Skip to content

Commit

Permalink
theme-settings (#514)
Browse files Browse the repository at this point in the history
* Init for theme settings

* Re-render element on theme setting change

* - full page theme editor
- add breadcrumbs

* adding sub-menu styles for theme-settings

* add breadcrumbs for MODX 2

* fix broken dialog boxes in elfinder

* Saving & rendering

* add theme settings model for 2.x

* Saving & Rendering in 2.x

* Save to context settings for non-global theme settings

* working on twig output for theme settings

Signed-off-by: matdave <mat@matdave.com>

* more tweaks to theme-settings

Signed-off-by: matdave <mat@matdave.com>

* adjusting look of fred and adding some basic documentation for theme settings

Signed-off-by: matdave <mat@matdave.com>

* add global flag to the documentation.

Signed-off-by: matdave <mat@matdave.com>

* add global flag to the documentation.

Signed-off-by: matdave <mat@matdave.com>

* Remove comments

---------

Signed-off-by: matdave <mat@matdave.com>
Co-authored-by: Jan Peca <pecajan@gmail.com>
  • Loading branch information
matdave and theboxer authored Oct 22, 2024
1 parent 234b888 commit c4107a4
Show file tree
Hide file tree
Showing 70 changed files with 2,189 additions and 125 deletions.
51 changes: 48 additions & 3 deletions Writerside/topics/themer/cmp/cmp_themes.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,54 @@ When you create a Theme, Fred will automatically create a directory named for th

### Default Element

The default element setting allows you to chose a default Fred Element and target area for placing the content on existing documents. The setting is formatted as `ID|target` where ID is the identification number of the Fred Element and the target is the HTML object within containing a `data-fred-name` attribute. This is useful for converting a standard resource to Fred, as it will place the existing content in the default element.

If you aren't finding the identification number of the Fred Element, right-click on the top of the element grid and make sure the ID column is selected.
The default element setting allows you to choose a default Fred Element and target area for placing the content on existing documents. The setting is formatted as `UUID|target` where UUID is the universally unique identification number of the Fred Element and the target is the HTML object within containing a `data-fred-name` attribute. This is useful for converting a standard resource to Fred, as it will place the existing content in the default element.

If you aren't finding the UUID of the Fred Element, open an element and look for a display field labeled "UUID".

### Theme Settings

Themes can have settings that are used to configure the theme. These settings are stored in the "Settings" section of the Theme. The settings are stored as a JSON object and can be accessed in the theme's twig templates using the `theme_setting` object. For example, if you have a setting named `logo`, you can access it in a template like this:

```twig
<img src="{{ theme_setting.logo }}" />
```

Theme settings are saved in the system settings and can be accessed outside of fred using the theme's Setting Prefix. For example, if the theme's setting prefix is `my_theme`, you can access the setting `logo` in a chunk like this:

```html
<img src="[[++fred.theme.my_theme.setting.logo]]" alt="[[++site_name]]" />
```

Theme settings can use any of the [setting types](settings.md#available-settings-types) described in the option groups documentation.

#### Format

The theme settings are formatted as a JSON array. Here is an example of a theme setting:

```json
[
{
"group": "Look and Feel",
"settings": [
{
"name": "site_color",
"type": "colorswatch",
"options": [
"lightcoral",
"red",
"black"
]
},
{
"name": "site_logo",
"type": "image"
}
]
}
]
```

One additional option that is specific to Theme Settings is that each setting can have a `"global": false` flag. This flag will cause the setting to save to the context it is used in, rather than the system settings. This is useful for multi-context sites where you want to have different settings for different contexts.

### Elements

Expand Down
6 changes: 3 additions & 3 deletions Writerside/topics/themer/elements/attributes.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ The value of this attribute has to be unique in each Element, but you can have m
<p data-fred-name="description">Default value</p>

<!-- Editable image -->
<img src="http://via.placeholder.com/450x150" data-fred-name="header-image">
<img src="http://placehold.co/450x150" data-fred-name="header-image">
```

## data-fred-editable
Expand All @@ -48,7 +48,7 @@ Defines other HTML attributes (comma separated) to save with the content of the
### Example {id="example_3"}

```html
<img src="http://via.placeholder.com/450x150" alt="Default Alt" data-fred-name="header-image" data-fred-attrs="alt,title">
<img src="http://placehold.co/450x150" alt="Default Alt" data-fred-name="header-image" data-fred-attrs="alt,title">
```

## data-fred-render
Expand Down Expand Up @@ -124,7 +124,7 @@ Identical to `data-fred-media-source` but only for images.
### Example {id="example_8"}

```html
<img src="http://via.placeholder.com/450x150" data-fred-name="header-image" data-fred-image-media-source="Blogs,Images">
<img src="http://placehold.co/450x150" data-fred-name="header-image" data-fred-image-media-source="Blogs,Images">
```

## data-fred-block-class
Expand Down
2 changes: 1 addition & 1 deletion Writerside/topics/themer/elements/markup.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ Template Variables can be accessed in the element markup object with the prefix
<!-- Simple Element -->
<div class="panel">
<p data-fred-name="header_text">Default Value</p>
<img src="http://via.placeholder.com/450x150" data-fred-name="header_image">
<img src="http://placehold.co/450x150" data-fred-name="header_image">
</div>

<!-- Enhanced Element -->
Expand Down
2 changes: 1 addition & 1 deletion Writerside/topics/themer/themes.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Basic Tutorial Tutorial
# Basic Tutorial

Once you have created a design you are happy with, it is straightforward to build a Theme to share. To start creating a theme, follow the steps below:

Expand Down
1 change: 0 additions & 1 deletion _build/assets/js/Actions/blueprints.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@ export const createBlueprint = (name, description, category, rank, isPublic, dat
};

export const createBlueprintCategory = (name, rank, isPublic, templates) => {
console.log({name, rank, isPublic, templates});
return fetch(`${fredConfig.config.assetsUrl}endpoints/ajax.php?modx=${fredConfig.config.modxVersion}&action=blueprints-create-category`, {
method: "post",
headers: {
Expand Down
147 changes: 147 additions & 0 deletions _build/assets/js/Components/Sidebar/PageSettings.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,11 @@ export default class PageSettings extends SidebarPlugin {
this.setTVWithEmitter = this.setTVWithEmitter.bind(this);
this.setMultiTVWithEmitter = this.setMultiTVWithEmitter.bind(this);
this.addTVChangeListener = this.addTVChangeListener.bind(this);
this.setThemeSettingWithEmitter = this.setThemeSettingWithEmitter.bind(this);
this.setMultiThemeSettingWithEmitter = this.setMultiThemeSettingWithEmitter.bind(this);

this.pageSettings = fredConfig.pageSettings;
this.themeSettings = fredConfig.themeSettings;
this.content = this.render();
}

Expand All @@ -33,6 +36,8 @@ export default class PageSettings extends SidebarPlugin {

settingsForm.appendChild(this.getGeneralFields());

settingsForm.appendChild(this.getThemeSettingFields());

if (fredConfig.permission.fred_settings_advanced) {
settingsForm.appendChild(this.getAdvancedFields());
}
Expand Down Expand Up @@ -157,6 +162,122 @@ export default class PageSettings extends SidebarPlugin {
return advancedList;
}

getThemeSettingFields() {
const advancedList = dl();

const advancedTab = dt('fred.fe.page_settings.theme_settings', ['fred--accordion-cog'], e => {
const activeTabs = advancedList.parentElement.querySelectorAll('dt.active');

const isActive = advancedTab.classList.contains('active');

for (let tab of activeTabs) {
tab.classList.remove('active');
}

if (!isActive) {
advancedTab.classList.add('active');
e.stopPropagation();
emitter.emit('fred-sidebar-dt-active', advancedTab, advancedContent);
}

});

const advancedContent = dd();
const advancedHeader = h3('fred.fe.page_settings.theme_settings');
const fields = fieldSet(['fred--page_settings_form_theme_settings']);

this.themeSettings.forEach(setting => {
if (setting.group && setting.settings) {
const groupEl = this.renderThemeSettingsGroup(setting);
if (groupEl !== false) {
fields.appendChild(groupEl);
}
} else {
const settingEl = this.renderThemeSetting(setting);
if (settingEl !== false) {
fields.appendChild(settingEl);
}
}
});

advancedContent.appendChild(advancedHeader);
advancedContent.appendChild(fields);
advancedList.appendChild(advancedTab);
advancedList.appendChild(advancedContent);

return advancedList;
}

renderThemeSettingsGroup(group) {
const content = dl();

const settingGroup = dt(group.group, [], (e, el) => {
const activeTabs = content.parentElement.querySelectorAll('dt.active');

const isActive = el.classList.contains('active');

for (let tab of activeTabs) {
tab.classList.remove('active');
}

if (!isActive) {
el.classList.add('active');
e.stopPropagation();
}
});
const settingGroupContent = dd();

group.settings.forEach(setting => {
const settingEl = this.renderThemeSetting(setting);
if (settingEl !== false) {
settingGroupContent.appendChild(settingEl);
}
});

content.appendChild(settingGroup);
content.appendChild(settingGroupContent);

return content;
}

renderThemeSetting(setting) {
const defaultValue = setting.value;

switch (setting.type) {
case 'select':
return ui.select(setting, defaultValue, this.setThemeSettingWithEmitter);
case 'toggle':
return ui.toggle(setting, defaultValue, this.setThemeSettingWithEmitter);
case 'colorswatch':
return ui.colorSwatch(setting, defaultValue, this.setThemeSettingWithEmitter);
case 'colorpicker':
return ui.colorPicker(setting, defaultValue, this.setThemeSettingWithEmitter);
case 'slider':
return ui.slider(setting, defaultValue, this.setThemeSettingWithEmitter);
case 'page':
return ui.page(setting, defaultValue, this.setThemeSettingWithEmitter);
case 'chunk':
return ui.chunk(setting, defaultValue, this.setThemeSettingWithEmitter);
case 'tagger':
return ui.tagger(setting, defaultValue, this.setThemeSettingWithEmitter);
case 'image':
return ui.image(setting, defaultValue, this.setThemeSettingWithEmitter);
case 'file': {
return ui.file(setting, defaultValue, this.setThemeSettingWithEmitter);
}
case 'folder': {
return ui.folder(setting, defaultValue, this.setThemeSettingWithEmitter);
}
case 'togglegroup':
case 'checkbox':
return ui.toggleGroup(setting, defaultValue, this.setMultiThemeSettingWithEmitter);
case 'textarea':
return ui.area(setting, defaultValue, this.setThemeSettingWithEmitter);
default:
return ui.text(setting, defaultValue, this.setThemeSettingWithEmitter);
}
}

getTaggerFields() {
const taggerList = dl();

Expand Down Expand Up @@ -299,6 +420,11 @@ export default class PageSettings extends SidebarPlugin {
}
}

setThemeSetting(name, value) {
fredConfig.setThemeSettingValue(name, value);
emitter.emit('fred-content-changed');
}

getSetting(name, namespace = null) {
if (namespace) {
if (!this.pageSettings[namespace]) this.pageSettings[namespace] = {};
Expand All @@ -309,6 +435,27 @@ export default class PageSettings extends SidebarPlugin {
}
}

setThemeSettingWithEmitter(name, value, input) {
this.setThemeSetting(name, value);

emitter.emit('fred-theme-setting-change', name, value, valueParser(value), input);
}

setMultiThemeSettingWithEmitter(name, value, input) {
let oValue = this.themeSettings[name];
oValue = (oValue) ? oValue.split('||') : [];
let nValue = [value];
oValue.forEach((ov) => {
if(value !== ov){
nValue.push(ov);
}
});
nValue = this.trim(nValue.join('||'), '|');
this.setThemeSetting(name, nValue);

emitter.emit('fred-theme-setting-change', name, value, valueParser(value), input);
}

setSettingWithEmitter(name, value, input) {
this.setSetting(name, value);

Expand Down
Loading

0 comments on commit c4107a4

Please sign in to comment.