Skip to content

Commit

Permalink
Qol and docs (#510)
Browse files Browse the repository at this point in the history
* Initial updates to docs
Make chunks work with name
Make default_element work with UUID

* Initial updates to docs
Synchronize Element / TV setting options

* working on toggle group for element settings
* adding screenshots to the "Options" doc
  • Loading branch information
matdave authored Sep 11, 2024
1 parent 3375c82 commit 20ae6e7
Show file tree
Hide file tree
Showing 27 changed files with 3,238 additions and 1,210 deletions.
11 changes: 6 additions & 5 deletions TODO.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
# Documentation
- [ ] Include documentation on Template Variables
- [x] Include documentation on Template Variables
- [ ] Add screenshots to different Option Types
- [ ] Document **chunk** Element option
- [ ] New resource variable placeholders
- [x] Document **chunk** Element option
- [x] New resource variable placeholders
- [ ] Reference GPM in collaborative theme development

# Programming
- [ ] Make **chunk** option work without ID
- [ ] Make theme's **Default Element** work without ID
- [x] Make **chunk** option work without ID
- [x] Make theme's **Default Element** work without ID
- [ ] Add **Theme Options** using the theme's namespace in system settings
- Allow values to be context specific or global

1 change: 1 addition & 0 deletions Writerside/fd.tree
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
<toc-element topic="themes.md"/>
<toc-element topic="convert-to-fred.md"/>
<toc-element toc-title="Fred Templates">
<toc-element topic="Template-Variables-in-Fred.md"/>
<toc-element topic="templates_index.md"/>
</toc-element>
<toc-element toc-title="Fred Elements">
Expand Down
Binary file added Writerside/images/option_chunk.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Writerside/images/option_colorpicker.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Writerside/images/option_colorswatch.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Writerside/images/option_file.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Writerside/images/option_folder.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Writerside/images/option_image.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Writerside/images/option_page.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Writerside/images/option_select.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Writerside/images/option_slider.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Writerside/images/option_tagger.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Writerside/images/option_text.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Writerside/images/option_textarea.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Writerside/images/option_toggle.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Writerside/images/option_togglegroup.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Writerside/images/tv_properties.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
39 changes: 39 additions & 0 deletions Writerside/topics/Template-Variables-in-Fred.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# Template Variables in Fred

Fred allows you to expose Template Variables (TVs) to the user. When used in an Element, Fred will update the display when the variable changes. This allows you to create dynamic content that can be updated by the user.

## Creating Template Variables

You start by creating a TV the same way you would normally in MODX. You need to assign the TV to one or more of the Templates assigned in your Fred Theme.

### Configure Properties

To display a TV on the frontend, you will need to configure the variables properties. This works similar to Fred Options. You will go to the Properties tab on the TV and unlock the default properties.

![tv_properties.png](tv_properties.png)

At minimum, you will need to add the `fred` property. This will be the type "Yes/No" and the default value should be set to `Yes`.

TVs can have all the types that Fred Options have. You can find more information on the different types in the [Fred Options documentation](settings.md#available-settings-types).

To set a type just add the property `fred.type` with the value of the type you want to use. For example, to set a TV to an image input you would add the property `fred.type` with the value of `image`.

To set type-specific properties, you would add them with the prefix `fred.`. For example, to set the image TV to use a specific Media Source you would add the property `fred.mediaSource` with the value of the Media Source name.

## Using Template Variables in Elements

Once you have created a TV and assigned it to a Template, you can use it in an Element. You can reference the TV in the Element's settings by using the TV name as a Twig variable prefixed by `tv_`. For example, if you have a TV named `myTV`, you would reference it in the Element settings as `{{ tv_myTV }}`.

When you drag the Element onto a page, Fred will replace the Twig variable with the value of the TV. If the TV is an image, Fred will render the image. If the TV is a text input, Fred will render the text.

Additionally, you can use `data-fred-target` to allow the TV to be editable within an element. For example, in the case of the above image TV, you could have an element like:

```Twig
<img
src="{{ tv_myTV }}"
data-fred-target="tv_myTV"
data-fred-name="my-tv"
data-fred-media-source="Assets"
alt="{{ pagetitle }} Logo"
/>
```
11 changes: 10 additions & 1 deletion Writerside/topics/themer/elements/markup.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,19 @@ Fred Elements are made of HTML with specific attributes. The markup can be enhan

## Custom Tags

### themplate.theme_dir
### Template Theme Directory

To make themes more portable `{{template.theme_dir}}` can be used in an element as a dynamic placeholder reference to the template's theme directory (e.g. '/assets/theme/default/'.)

### Resource Fields

Resource fields can be accessed in the element markup object. For example, to access the pagetitle of the current resource, you would use `{{ pagetitle }}`.

### TV Fields

Template Variables can be accessed in the element markup object with the prefix `tv_`. For example, to access a TV named `myTV`, you would use `{{ tv_myTV }}`.


## Markup Examples

```html
Expand Down
52 changes: 46 additions & 6 deletions Writerside/topics/themer/options/settings.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,30 +50,46 @@ Note: for the best end-user experience, it is a good idea to set a default value
The following Settings types are used to configure Elements in Fred.

#### text
![option_text](option_text.png)

- A single-line HTML `<input type="text">` element
- Can have any text value
- **Returns** - A string

#### textarea
![option_textarea.png](option_textarea.png)

- A multie-line HTML `<textarea>` element
- Can have any text value
- Type specific properties:
- `rows` - The number of rows to show; Default: 4
- **Returns** - A string

#### select
![option_select.png](option_select.png)

- An HTML `<select>` list element
- Only supports a single select value
- Type specific properties:
- `options` - An object of `value:label` properties
- `options` - An object of `"value":"label"` properties
- **Returns** - A string with the selected value

#### toggle
![option_toggle.png](option_toggle.png)

- true/false checkbox
- returns logical `true` or `false`
- **Returns** - A logical `true` or `false` (`0` or `1` if output as a string)

#### togglegroup
![option_togglegroup.png](option_togglegroup.png)

- A checkbox group
- Type-specific properties:
- `options` - An object of `"value":"label"` properties
- **Returns** - A double-pipe `||` separated string of checked values

#### colorswatch
![option_colorswatch.png](option_colorswatch.png)

- Visual color picker, to choose from predefined values
- Type-specific properties:
Expand All @@ -85,62 +101,86 @@ The following Settings types are used to configure Elements in Fred.
- `colorAsClass` - if set to `true` the `color` value will be added as a class to the option, instead of setting as a background
- `label` - an arbitrary label for the swatch
- `width` - width of the color option, default is `1`
- **Returns** - A string of the color value

#### colorpicker
![option_colorpicker.png](option_colorpicker.png)

- A color picker that supports arbitrary color definitions including RGB, HSL or Hex values with optional opacity
- Type-specific properties:
- `showAlpha` - A boolean to show an alpha transparency slider; Default: `true`
- `options` - An array of colors; Example: `["lightcoral", "red", "black"]`
- **Returns** - A string of the color's hexadecimal value

#### slider
![option_slider.png](option_slider.png)

- An input slider for numbers
- Type-specific properties:
- `min` - **REQUIRED**: The minimum value of the slider
- `max` - **REQUIRED**: The maximum value of the slider
- `tooltipDecimals` – Number of decimals to show in the slider’s tooltip; Default: 0
- `step` – A number to increment the slider’s value; Default: 1
- **Notice:** To avoid issues with this option, set a default `value` within the range of `min` and `max`
- **Returns** - A number

#### page
![option_page.png](option_page.png)

- MODX Page select
- Value is returned as an object in format: `{"id": 1, "url": "fred.html"}`
- Refrencing ID or URL alone is done through the dot syntax: `{{ page-name-example.id}}`
- Type-specific properties:
- `clearButton` - If set to `true` an `x` button shows in the input field allowing a user to clear any set value
- `resources` - If set, only resource with specified IDs will show; Value can be string with a comma as a separator or an array
- `parents` - If set, only resource from these parents (including parents itself) will show; Value can be string with a comma as a separator or an array
- `depth` - Depth to look for children for specified `parents`; Default: 1
- **Returns** - An object with `id` and `url` properties
- Referencing ID or URL alone is done through the dot syntax: `{{ page-name-example.id}}`

#### chunk
![option_chunk.png](option_chunk.png)
- Chunk select
- Type-specific properties:
- `chunks` - Comma separated list of chunk names/ids to show
- `category` - Comma separated list of category names/ids to show chunks from
- **Returns** - An object with `id` and `name` properties
- Referencing ID or URL alone is done through the dot syntax: `{{ chunk-name-example.name}}`

#### file
![option_file.png](option_file.png)

- File picker
- Type-specific property:
- `mediaSource` - Optional name of the Media Source to use that overrides the top-level ```<a href="#mediasource">`mediaSource` global setting</a>```
- **Returns** - A string of the file path

#### folder
![option_folder.png](option_folder.png)

- Folder picker
- Type-specific property:
- `mediaSource` - Optional name of the Media Source to use that overrides the top-level ```<a href="#mediasource">`mediaSource` global setting</a>```
- `showOnlyFolders` - If set to `true` only folder will be visible in the elFinder; Default: false
- **Returns** - A string of the folder path

#### image
![option_image.png](option_image.png)

- Image select
- Type-specific properties:
- `showPreview` - If set to `false` preview won't appear under the text input
- `mediaSource` - Optional name of the Media Source to use that overrides the top-level ```<a href="#imagemediasource">`imageMediaSource` global setting</a>```
- **Returns** - A string of the image path

#### tagger

#### tagger
![option_tagger.png](option_tagger.png)
- Allows users to choose from preset Tagger tags
- Type-specific properties:
- `group` - **REQUIRED** An ID of the Tagger group to use
- `autoTag` - true/false to show/hide the auto tag
- `hideInput` - true/false to show/hide the input
- `group` - An ID of the Tagger group to use
- `limit` - Maximum limit of the number of tags that can be selected
- **Returns** - A string of comma-separated tag names

### Setting Groups

Expand Down
3 changes: 3 additions & 0 deletions _build/assets/js/Components/Sidebar/PageSettings.js
Original file line number Diff line number Diff line change
Expand Up @@ -261,9 +261,12 @@ export default class PageSettings extends SidebarPlugin {
const epoch = new Date(this.pageSettings.tvs[tv.name]).getTime()/1000;
fields.appendChild(ui.dateTime(tv, epoch, this.setTVWithEmitter, this.addTVChangeListener, 'Y-m-d H:i:s'));
break;
case 'togglegroup':
case 'checkbox':
fields.appendChild(ui.toggleGroup(tv, this.pageSettings.tvs[tv.name], this.setMultiTVWithEmitter, this.addTVChangeListener));
break;
case 'chunk':
fields.appendChild(ui.chunk(tv, this.pageSettings.tvs[tv.name], this.setTVWithEmitter, this.addTVChangeListener));
default:
fields.appendChild(ui.text(tv, this.pageSettings.tvs[tv.name], this.setTVWithEmitter, this.addTVChangeListener));
}
Expand Down
30 changes: 30 additions & 0 deletions _build/assets/js/Content/ElementSettings.js
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,9 @@ export class ElementSettings {

return ui.folder({mediaSource, ...setting}, defaultValue, this.setSetting.bind(this));
}
case 'togglegroup':
case 'checkbox':
return ui.toggleGroup(setting, defaultValue, this.setMultiSetting.bind(this));
case 'textarea':
return ui.area(setting, defaultValue, this.setSetting.bind(this));
default:
Expand All @@ -183,6 +186,20 @@ export class ElementSettings {
}
}

setMultiSetting(name, value) {
let oValue = this.el.settings[name];
oValue = (oValue) ? oValue.split('||') : [];
let nValue = [value];
oValue.forEach((ov) => {
if(value !== ov){
nValue.push(ov);
}
});
nValue = this.trim(nValue.join('||'), '|');
this.setSetting(name, nValue);

}

apply() {
this.el.render(true).then(() => {
emitter.emit('fred-content-changed');
Expand Down Expand Up @@ -246,6 +263,19 @@ export class ElementSettings {

utilitySidebar.close();
}

trim(str, ch) {
let start = 0,
end = str.length;

while(start < end && str[start] === ch)
++start;

while(end > start && str[end - 1] === ch)
--end;

return (start > 0 || end < str.length) ? str.substring(start, end) : str;
}
}

const elementSettings = new ElementSettings();
Expand Down
2 changes: 2 additions & 0 deletions core/components/fred/src/Endpoint/Ajax/GetChunks.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
namespace Fred\Endpoint\Ajax;

use Fred\Utils;
use MODX\Revolution\modCategory;
use MODX\Revolution\modChunk;

class GetChunks extends Endpoint
Expand All @@ -21,4 +22,5 @@ class GetChunks extends Endpoint
protected $allowedMethod = ['OPTIONS', 'GET'];
protected $chunks = [];
private $chunkClass = modChunk::class;
private $categoryClass = modCategory::class;
}
40 changes: 31 additions & 9 deletions core/components/fred/src/Traits/Endpoint/Ajax/GetChunks.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,31 @@ public function process()
$category = $_GET['category'] ?? '';
$chunks = $_GET['chunks'] ?? '';
$limit = isset($_GET['limit']) ? (int)$_GET['limit'] : 25;

$category = Utils::explodeAndClean($category, ',', 'intval', 0, 'strlen');
$chunks = Utils::explodeAndClean($chunks, ',', 'intval');
$catArr = [];
foreach(explode(",", $category) as $cat) {
if (is_numeric($cat)) {
$catArr[] = $cat;
} else {
$obj = $this->modx->getObject($this->categoryClass, ['name' => $cat]);
if (!empty($obj)) {
$catArr[] = $obj->get('id');
}
}
}
$category = $catArr;

$chunkArr = [];
foreach(explode(",", $chunks) as $chunk) {
if (is_numeric($chunk)) {
$chunkArr[] = $chunk;
} else {
$obj = $this->modx->getObject($this->chunkClass, ['name' => $chunk]);
if (!empty($obj) && !in_array($obj->get('id'), $chunkArr)) {
$chunkArr[] = $obj->get('id');
}
}
}
$chunks = $chunkArr;

$c = $this->modx->newQuery($this->chunkClass);

Expand All @@ -39,9 +61,9 @@ public function process()
$currentChunk = $this->modx->getObject($this->chunkClass, $current);
if ($currentChunk) {
$currentChunk = [
'id' => $currentChunk->id,
'value' => (string)$currentChunk->id,
'name' => $currentChunk->name,
'id' => $currentChunk->get('id'),
'value' => (string)$currentChunk->get('id'),
'name' => $currentChunk->get('name'),
];
$where['id:!='] = $current;
}
Expand Down Expand Up @@ -75,9 +97,9 @@ public function process()
continue;
}
$data[] = [
'id' => $chunk->id,
'value' => (string)$chunk->id,
'name' => $chunk->name,
'id' => $chunk->get('id'),
'value' => (string)$chunk->get('id'),
'name' => $chunk->get('name'),
];
}

Expand Down
18 changes: 17 additions & 1 deletion core/components/fred/src/Traits/RenderResource.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,23 @@ private function setDefaults()
if (!empty($defElement[0]) && is_numeric($defElement[0]) && !empty($defElement[1])) {
$defaultElement = $this->modx->getObject($this->elementClass, ['id' => $defElement[0]]);
if (!$defaultElement) {
$this->modx->log(\modX::LOG_LEVEL_ERROR, "[Fred] Element {$defElement[0]} wasn't found.");
if (!is_numeric($defElement[0])) {
$c = $this->modx->newQuery($this->elementClass);
$c->where(['uuid' => $defElement[0], 'OR:name' => $defElement[0]]);
$defaultElement = $this->modx->getObject($this->elementClass, $c);
if(!$defaultElement) {
$this->modx->log(\modX::LOG_LEVEL_ERROR, "[Fred] Default Element {$defElement[0]} wasn't found.");
return;
}
} else {
$this->modx->log(\modX::LOG_LEVEL_ERROR, "[Fred] Element {$defElement[0]} wasn't found.");
return;
}
}
// check if the element is part of the theme
$elementCategory = $defaultElement->getOne('Category');
if (!$elementCategory || $elementCategory->get('theme') !== $this->theme->id) {
$this->modx->log(\modX::LOG_LEVEL_ERROR, "[Fred] Default Element {$defElement[0]} is not part of the current theme.");
return;
}

Expand Down
1 change: 1 addition & 0 deletions core/components/fred/src/v2/Endpoint/Ajax/GetChunks.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,5 @@ class GetChunks extends Endpoint
protected $allowedMethod = ['OPTIONS', 'GET'];
protected $chunks = [];
private $chunkClass = 'modChunk';
private $categoryClass = 'modCategory';
}
Loading

0 comments on commit 20ae6e7

Please sign in to comment.