Release v2.18.0: template default content
This commit is contained in:
1 parent
48e8f3eb4b
commit
24f1603b43
54 files changed
+1421
-151
No files matched your search
@@ -29,6 +29,8 @@ test('extractTemplateRegions normalizes JSON regions and filters invalid rows',
|
||||
region_name: 'Hero',
|
||||
region_type: 'TEXT',
|
||||
lock_ratio: '16 : 9',
|
||||
default_content: '{"type":"text","value":"Template headline"}',
|
||||
read_only: 'true',
|
||||
animation_json: '{"intro":{"preset":"fadeIn"},"out":{"preset":"bounceOut"}}',
|
||||
x: '10',
|
||||
y: '20',
|
||||
@@ -48,6 +50,8 @@ test('extractTemplateRegions normalizes JSON regions and filters invalid rows',
|
||||
region_type: 'TEXT',
|
||||
label: 'Hero',
|
||||
lock_ratio: '16:9',
|
||||
default_content: { type: 'text', value: 'Template headline' },
|
||||
read_only: true,
|
||||
animation_json: {
|
||||
intro: { preset: 'fadeIn' },
|
||||
outro: { preset: 'bounceOut' },
|
||||
@@ -112,6 +116,8 @@ test('buildTemplatePayload resolves canvas size and rejects duplicate region nam
|
||||
region_type: 'text',
|
||||
label: 'Header',
|
||||
lock_ratio: '4:3',
|
||||
default_content: {},
|
||||
read_only: false,
|
||||
animation_json: {
|
||||
intro: { preset: 'none' },
|
||||
outro: { preset: 'none' },
|
||||
@@ -198,6 +204,26 @@ test('template create page renders the background remove control', () => {
|
||||
assert.match(html, /data-media-picker-hidden="existing-background-image-path"/);
|
||||
assert.match(html, /data-media-picker-file-input="background-image"/);
|
||||
assert.match(html, /id="background-image"/);
|
||||
assert.match(html, /data-region-default-content/);
|
||||
assert.match(html, /data-region-default-content-button/);
|
||||
assert.match(html, /data-region-read-only/);
|
||||
assert.match(html, /form-check form-switch d-inline-flex align-items-center gap-2 mb-0 ps-0 text-nowrap flex-shrink-0/);
|
||||
assert.match(html, /form-check-input m-0 flex-shrink-0/);
|
||||
assert.match(html, /<span class="form-check-label">Template-only<\/span>/);
|
||||
assert.match(html, /title="Hidden in the slide editor\. Edit this content on the template\."/);
|
||||
assert.match(html, /title="Edit template default content"><i class="bi bi-pencil-square me-1" aria-hidden="true"><\/i>Edit default/);
|
||||
assert.match(html, /id="region-default-content-modal"/);
|
||||
assert.match(html, /modal-xl modal-dialog-centered modal-dialog-scrollable template-default-content-dialog/);
|
||||
assert.match(html, /id="region-default-content-editor-host"/);
|
||||
assert.match(html, /id="region-default-content-preview-canvas"/);
|
||||
assert.match(html, /d-flex align-items-center gap-3 border-top/);
|
||||
assert.ok(html.indexOf('id="region-default-content-editor-host"') < html.indexOf('id="region-default-content-preview-stage"'));
|
||||
assert.ok(html.indexOf('id="region-default-content-save"') < html.lastIndexOf('>Cancel</button>'));
|
||||
assert.match(html, /class="btn btn-warning" data-bs-dismiss="modal">Cancel<\/button>/);
|
||||
assert.match(html, /template-default-content-editor\.js/);
|
||||
assert.match(html, /id="template-region-editor-data"/);
|
||||
assert.match(html, /vendor\/tinymce\/tinymce\.min\.js/);
|
||||
assert.ok(html.indexOf('name="region_width[]"') < html.indexOf('data-region-default-content-button'));
|
||||
assert.match(html, /placeholder="type_1"/);
|
||||
assert.match(html, /name="region_z\[\]" min="1" step="1" value="1" required/);
|
||||
assert.match(html, /Save and Close/);
|
||||
@@ -329,6 +355,8 @@ test('template animation durations use percent in the advanced modal', () => {
|
||||
|
||||
assert.match(modal, /signage\/templates\/animation-advanced-fields/);
|
||||
assert.match(modal, /data-animation-modal-title>Advanced animations:/);
|
||||
assert.ok(modal.indexOf('data-animation-modal-apply') < modal.lastIndexOf('>Cancel</button>'));
|
||||
assert.match(modal, /class="btn btn-warning" data-bs-dismiss="modal">Cancel<\/button>/);
|
||||
assert.ok(script.includes("title.textContent = 'Advanced animations: ' + (label ? label.textContent : 'Region');"));
|
||||
assert.doesNotMatch(modal, /modalBackdropStatic=true/);
|
||||
assert.match(advancedFields, /Duration %/);
|
||||
@@ -505,4 +533,55 @@ test('template snap toggle places its switch after the label', () => {
|
||||
const css = fs.readFileSync(require.resolve('../src/web/public/css/theme-custom.css'), 'utf8');
|
||||
assert.match(template, /class="form-check form-switch template-snap-control[^>]*"><label for="template-layout-snap"[^>]*>Snap to guides<\/label><input type="checkbox" id="template-layout-snap"/);
|
||||
assert.match(css, /\.template-snap-control \.form-check-input\s*\{[^}]*order:\s*2/);
|
||||
});
|
||||
|
||||
test('template default content adapter reuses slide region helpers and TinyMCE controller', () => {
|
||||
const source = fs.readFileSync(require.resolve('../src/web/public/js/templates/template-default-content-editor.js'), 'utf8');
|
||||
assert.match(source, /createSlideFormRegionHelpers/);
|
||||
assert.match(source, /getRegionEditorCardHtml/);
|
||||
assert.match(source, /getPreviewRegionContent/);
|
||||
assert.match(source, /template-default-content-preview-label/);
|
||||
assert.match(source, /createSlideFormEditorController/);
|
||||
});
|
||||
|
||||
test('template designer restores region default content and read-only state from saved data', () => {
|
||||
const source = fs.readFileSync(require.resolve('../src/web/public/js/templates/template-designer.js'), 'utf8');
|
||||
const match = source.match(/ function populateRegionCard\([^]*?\n }/);
|
||||
assert.ok(match);
|
||||
|
||||
const fields = {
|
||||
'[data-region-chip]': {},
|
||||
'[data-region-title]': {},
|
||||
'[name="region_name[]"]': {},
|
||||
'[name="region_type[]"]': {},
|
||||
'[name="region_key[]"]': {},
|
||||
'[name="region_label[]"]': {},
|
||||
'[data-region-default-content]': {},
|
||||
'[data-region-read-only]': {},
|
||||
'[name="region_lock_ratio[]"]': {},
|
||||
'[name="region_x[]"]': {},
|
||||
'[name="region_y[]"]': {},
|
||||
'[name="region_z[]"]': {},
|
||||
'[name="region_width[]"]': {},
|
||||
'[name="region_height[]"]': {}
|
||||
};
|
||||
const context = vm.createContext({
|
||||
getRegionChipLabel: () => 'HTML',
|
||||
normalizeLockRatio: value => value || '',
|
||||
writeAnimationConfig() {},
|
||||
valueOrDefault: (value, fallback) => value === undefined || value === null || value === '' ? fallback : value,
|
||||
updateRegionLockRatioState() {},
|
||||
updateRegionLockBadge() {}
|
||||
});
|
||||
vm.runInContext(match[0], context);
|
||||
context.populateRegionCard({ querySelector: selector => fields[selector] || null }, {
|
||||
region_key: 'brand_edge', region_type: 'html', label: 'brand_edge',
|
||||
default_content: { type: 'html', value: '<div>Template-owned</div>' },
|
||||
read_only: 1, x: 0, y: 0, width: 1920, height: 7, z_index: 1
|
||||
});
|
||||
|
||||
assert.deepEqual(JSON.parse(fields['[data-region-default-content]'].value), {
|
||||
type: 'html', value: '<div>Template-owned</div>'
|
||||
});
|
||||
assert.equal(fields['[data-region-read-only]'].checked, true);
|
||||
});
|
||||
Reference in new issue
Block a user