mirror of
https://github.com/TryGhost/Ghost.git
synced 2024-12-15 03:12:54 +03:00
715ee08100
refs https://github.com/TryGhost/Team/issues/1111 Extracted functionality for listing, downloading, activating, and deleting from the theme controller/template into separate components and services so that they are more composable/reusable in different situations. - moved theme activation to a new `theme-management` service that uses the `modals` service to open the theme warnings modal or limits upgrade modal as required - the activate process is a task so that consumers can store a reference to the task instance and cancel it to close any related warning/limit modals (eg, when navigating away from the route or closing the modal that kicked off the process) - created new-pattern modals for custom theme limit upgrade, theme errors, and delete confirmation so that we can treat them as promises and close where needed from parent - duplicated theme table component as `<GhThemeTableLabs>` with an actions redesign and a refactor to handle download, activation, and deletion itself making use of the new theme-management service and modals - fixed some oddities with design modal's transition/modal close handling by simplifying the async behaviour and being more explicit - added advanced design modal that contains the new theme table component and linked to it from footer of design modal's sidebar
100 lines
2.9 KiB
JavaScript
100 lines
2.9 KiB
JavaScript
import Component from '@glimmer/component';
|
|
import {action} from '@ember/object';
|
|
import {get} from '@ember/object';
|
|
import {inject as service} from '@ember/service';
|
|
|
|
export default class GhThemeTableComponent extends Component {
|
|
@service ghostPaths;
|
|
@service modals;
|
|
@service themeManagement;
|
|
@service utils;
|
|
|
|
activateTaskInstance = null;
|
|
confirmDeleteModal = null;
|
|
|
|
willDestroy() {
|
|
super.willDestroy(...arguments);
|
|
this.confirmDeleteModal?.close();
|
|
this.activateTaskInstance?.cancel();
|
|
}
|
|
|
|
get sortedThemes() {
|
|
let themes = this.args.themes.map((t) => {
|
|
let theme = {};
|
|
let themePackage = get(t, 'package');
|
|
|
|
theme.model = t;
|
|
theme.name = get(t, 'name');
|
|
theme.label = themePackage ? `${themePackage.name}` : theme.name;
|
|
theme.version = themePackage ? `${themePackage.version}` : '1.0';
|
|
theme.package = themePackage;
|
|
theme.active = get(t, 'active');
|
|
theme.isDeletable = !theme.active;
|
|
|
|
return theme;
|
|
});
|
|
let duplicateThemes = [];
|
|
|
|
themes.forEach((theme) => {
|
|
let duplicateLabels = themes.filterBy('label', theme.label);
|
|
|
|
if (duplicateLabels.length > 1) {
|
|
duplicateThemes.pushObject(theme);
|
|
}
|
|
});
|
|
|
|
duplicateThemes.forEach((theme) => {
|
|
if (theme.name !== 'casper') {
|
|
theme.label = `${theme.label} (${theme.name})`;
|
|
}
|
|
});
|
|
|
|
// "(default)" needs to be added to casper manually as it's always
|
|
// displayed and would mess up the duplicate checking if added earlier
|
|
let casper = themes.findBy('name', 'casper');
|
|
if (casper) {
|
|
casper.label = `${casper.label} (default)`;
|
|
casper.isDefault = true;
|
|
casper.isDeletable = false;
|
|
}
|
|
|
|
// sorting manually because .sortBy('label') has a different sorting
|
|
// algorithm to [...strings].sort()
|
|
return themes.sort((themeA, themeB) => {
|
|
let a = themeA.label.toLowerCase();
|
|
let b = themeB.label.toLowerCase();
|
|
|
|
if (a < b) {
|
|
return -1;
|
|
}
|
|
if (a > b) {
|
|
return 1;
|
|
}
|
|
return 0;
|
|
});
|
|
}
|
|
|
|
@action
|
|
downloadTheme(themeName, dropdown) {
|
|
dropdown?.actions.close();
|
|
this.utils.downloadFile(`${this.ghostPaths.apiRoot}/themes/${themeName}/download/`);
|
|
}
|
|
|
|
@action
|
|
activateTheme(theme, dropdown) {
|
|
dropdown?.actions.close();
|
|
this.activateTaskInstance = this.themeManagement.activateTask.perform(theme);
|
|
}
|
|
|
|
@action
|
|
deleteTheme(theme, dropdown) {
|
|
dropdown?.actions.close();
|
|
|
|
this.confirmDeleteModal = this.modals.open('modals/design/confirm-delete-theme', {
|
|
theme
|
|
}).finally(() => {
|
|
this.confirmDeleteModal = null;
|
|
});
|
|
}
|
|
}
|