Fixed design menu re-rendering and losing input focus on first change

no issue

- `get settingGroups()` was always returning a new object which meant the template was re-rendering unexpectedly which created issues with form fields that lose their focus when re-rendered
- moved group handling into the `customThemeSettings` service as it makes more sense to keep it centralized, that gave us the ability to create a new `settingGroups` array only when the settings list changes keeping the tracked invalidation easier to reason about
This commit is contained in:
Kevin Ansfield 2021-10-14 14:15:11 +01:00
parent 122e9869ad
commit f4596a0add
3 changed files with 62 additions and 60 deletions

View File

@ -18,25 +18,23 @@
{{/if}}
{{/let}}
{{#if this.themeSettings}}
{{#each this.settingGroups as |group|}}
{{#let (eq this.openSection group.key) as |isOpen|}}
<button class="gh-nav-design-tab {{if isOpen "active"}}" type="button" {{on "click" (fn this.toggleSection group.key)}}>
<span class="gh-nav-button-expand">{{svg-jar (if isOpen "arrow-down-stroke" "arrow-right-stroke")}}</span>
{{svg-jar group.icon}} {{group.name}}
</button>
{{#each this.customThemeSettings.settingGroups as |group|}}
{{#let (eq this.openSection group.key) as |isOpen|}}
<button class="gh-nav-design-tab {{if isOpen "active"}}" type="button" {{on "click" (fn this.toggleSection group.key)}}>
<span class="gh-nav-button-expand">{{svg-jar (if isOpen "arrow-down-stroke" "arrow-right-stroke")}}</span>
{{svg-jar group.icon}} {{group.name}}
</button>
{{#if isOpen}}
<div class="gh-nav-design-settings">
<Settings::Design::ThemeSettingsForm
@themeSettings={{group.settings}}
@updatePreview={{perform this.themeManagement.updatePreviewHtmlTask}}
/>
</div>
{{/if}}
{{/let}}
{{/each}}
{{/if}}
{{#if isOpen}}
<div class="gh-nav-design-settings">
<Settings::Design::ThemeSettingsForm
@themeSettings={{group.settings}}
@updatePreview={{perform this.themeManagement.updatePreviewHtmlTask}}
/>
</div>
{{/if}}
{{/let}}
{{/each}}
</div>
</div>

View File

@ -15,18 +15,6 @@ export default class DesignMenuComponent extends Component {
@tracked openSection = null;
@tracked themes = this.store.peekAll('theme');
KNOWN_GROUPS = [{
key: 'homepage',
name: 'Homepage',
icon: 'house',
previewType: 'homepage'
}, {
key: 'post',
name: 'Post',
icon: 'post',
previewType: 'post'
}];
constructor() {
super(...arguments);
this.fetchThemeSettingsTask.perform();
@ -36,35 +24,6 @@ export default class DesignMenuComponent extends Component {
this.store.findAll('theme');
}
get themeSettings() {
return this.customThemeSettings.settings;
}
get settingGroups() {
const groupKeys = this.KNOWN_GROUPS.map(g => g.key);
const groups = [];
const siteWideSettings = this.themeSettings.filter(setting => !groupKeys.includes(setting.group));
if (siteWideSettings.length) {
groups.push({
key: 'site-wide',
name: 'Site-wide',
icon: 'view-site',
settings: siteWideSettings
});
}
this.KNOWN_GROUPS.forEach((knownGroup) => {
const settings = this.themeSettings.filter(setting => setting.group === knownGroup.key);
if (settings.length) {
groups.push(Object.assign({}, knownGroup, {settings}));
}
});
return groups;
}
get activeTheme() {
return this.themes.findBy('active', true);
}
@ -76,7 +35,7 @@ export default class DesignMenuComponent extends Component {
} else {
this.openSection = section;
const group = this.KNOWN_GROUPS.findBy('key', section);
const group = this.customThemeSettings.KNOWN_GROUPS.findBy('key', section);
if (group && group.previewType) {
this.themeManagement.setPreviewType(group.previewType);
} else {

View File

@ -8,6 +8,19 @@ export default class CustomThemeSettingsServices extends Service {
@service store;
@tracked settings = [];
@tracked settingGroups = [];
KNOWN_GROUPS = [{
key: 'homepage',
name: 'Homepage',
icon: 'house',
previewType: 'homepage'
}, {
key: 'post',
name: 'Post',
icon: 'post',
previewType: 'post'
}];
get isDirty() {
const dirtySetting = this.settings.find(setting => setting.hasDirtyAttributes);
@ -36,6 +49,7 @@ export default class CustomThemeSettingsServices extends Service {
const settings = yield this.store.findAll('custom-theme-setting');
this.settings = settings;
this.settingGroups = this._buildSettingGroups(settings);
return this.settings;
}
@ -51,6 +65,7 @@ export default class CustomThemeSettingsServices extends Service {
yield listRecord.save();
this.settings = listRecord.customThemeSettings.toArray();
this.settingGroups = this._buildSettingGroups(this.settings);
// don't keep references to lists and their children around
this.store.unloadRecord(listRecord);
@ -62,5 +77,35 @@ export default class CustomThemeSettingsServices extends Service {
run(() => this.store.unloadAll('custom-theme-setting'));
this.settings = [];
this.settingGroups = [];
}
_buildSettingGroups(settings) {
if (!settings || !settings.length) {
return [];
}
const groupKeys = this.KNOWN_GROUPS.map(g => g.key);
const groups = [];
const siteWideSettings = settings.filter(setting => !groupKeys.includes(setting.group));
if (siteWideSettings.length) {
groups.push({
key: 'site-wide',
name: 'Site-wide',
icon: 'view-site',
settings: siteWideSettings
});
}
this.KNOWN_GROUPS.forEach((knownGroup) => {
const groupSettings = settings.filter(setting => setting.group === knownGroup.key);
if (groupSettings.length) {
groups.push(Object.assign({}, knownGroup, {settings}));
}
});
return groups;
}
}