mirror of
https://github.com/discourse/discourse.git
synced 2025-06-04 23:36:11 +08:00
DEV: Convert install-theme
modal to component-based API (#22939)
This commit is contained in:
@ -0,0 +1,229 @@
|
||||
import Component from "@glimmer/component";
|
||||
import { tracked } from "@glimmer/tracking";
|
||||
import { action } from "@ember/object";
|
||||
import { COMPONENTS, THEMES } from "admin/models/theme";
|
||||
import { POPULAR_THEMES } from "discourse-common/lib/popular-themes";
|
||||
import { ajax } from "discourse/lib/ajax";
|
||||
import I18n from "I18n";
|
||||
import { inject as service } from "@ember/service";
|
||||
import { popupAjaxError } from "discourse/lib/ajax-error";
|
||||
|
||||
const MIN_NAME_LENGTH = 4;
|
||||
|
||||
export default class InstallTheme extends Component {
|
||||
@service store;
|
||||
|
||||
@tracked selection = this.args.model.selection || "popular";
|
||||
@tracked uploadUrl = this.args.model.uploadUrl;
|
||||
@tracked uploadName = this.args.model.uploadName;
|
||||
@tracked selectedType = this.args.model.selectedType;
|
||||
@tracked advancedVisible = false;
|
||||
@tracked loading = false;
|
||||
@tracked localFile;
|
||||
@tracked publicKey;
|
||||
@tracked branch;
|
||||
@tracked duplicateRemoteThemeWarning;
|
||||
@tracked themeCannotBeInstalled;
|
||||
@tracked name;
|
||||
|
||||
recordType = "theme";
|
||||
|
||||
get createTypes() {
|
||||
return [
|
||||
{ name: I18n.t("admin.customize.theme.theme"), value: THEMES },
|
||||
{ name: I18n.t("admin.customize.theme.component"), value: COMPONENTS },
|
||||
];
|
||||
}
|
||||
|
||||
get showPublicKey() {
|
||||
return this.uploadUrl?.match?.(/^ssh:\/\/.+@.+$|.+@.+:.+$/);
|
||||
}
|
||||
|
||||
get submitLabel() {
|
||||
if (this.themeCannotBeInstalled) {
|
||||
return "admin.customize.theme.create_placeholder";
|
||||
}
|
||||
|
||||
return `admin.customize.theme.${this.create ? "create" : "install"}`;
|
||||
}
|
||||
|
||||
get component() {
|
||||
return this.selectedType === COMPONENTS;
|
||||
}
|
||||
|
||||
get local() {
|
||||
return this.selection === "local";
|
||||
}
|
||||
|
||||
get remote() {
|
||||
return this.selection === "remote";
|
||||
}
|
||||
|
||||
get create() {
|
||||
return this.selection === "create";
|
||||
}
|
||||
|
||||
get directRepoInstall() {
|
||||
return this.selection === "directRepoInstall";
|
||||
}
|
||||
|
||||
get popular() {
|
||||
return this.selection === "popular";
|
||||
}
|
||||
|
||||
get nameTooShort() {
|
||||
return !this.name || this.name.length < MIN_NAME_LENGTH;
|
||||
}
|
||||
|
||||
get installDisabled() {
|
||||
return (
|
||||
this.loading ||
|
||||
(this.remote && !this.uploadUrl) ||
|
||||
(this.local && !this.localFile) ||
|
||||
(this.create && this.nameTooShort)
|
||||
);
|
||||
}
|
||||
|
||||
get placeholder() {
|
||||
if (this.component) {
|
||||
return I18n.t("admin.customize.theme.component_name");
|
||||
} else {
|
||||
return I18n.t("admin.customize.theme.theme_name");
|
||||
}
|
||||
}
|
||||
|
||||
get themes() {
|
||||
return POPULAR_THEMES.map((t) => {
|
||||
if (
|
||||
this.args.model.installedThemes.some((theme) =>
|
||||
this.themeHasSameUrl(theme, t.value)
|
||||
)
|
||||
) {
|
||||
t.installed = true;
|
||||
}
|
||||
return t;
|
||||
});
|
||||
}
|
||||
|
||||
themeHasSameUrl(theme, url) {
|
||||
const themeUrl = theme.remote_theme && theme.remote_theme.remote_url;
|
||||
return (
|
||||
themeUrl &&
|
||||
url &&
|
||||
url.replace(/\.git$/, "") === themeUrl.replace(/\.git$/, "")
|
||||
);
|
||||
}
|
||||
|
||||
willDestroy() {
|
||||
this.args.model.clearParams?.();
|
||||
}
|
||||
|
||||
@action
|
||||
async generatePublicKey() {
|
||||
try {
|
||||
const pair = await ajax("/admin/themes/generate_key_pair", {
|
||||
type: "POST",
|
||||
});
|
||||
this.publicKey = pair.public_key;
|
||||
} catch (e) {
|
||||
popupAjaxError(e);
|
||||
}
|
||||
}
|
||||
|
||||
@action
|
||||
toggleAdvanced() {
|
||||
this.advancedVisible = !this.advancedVisible;
|
||||
}
|
||||
|
||||
@action
|
||||
uploadLocaleFile(event) {
|
||||
this.localFile = event.target.files[0];
|
||||
}
|
||||
|
||||
@action
|
||||
updateSelectedType(type) {
|
||||
this.args.model.updateSelectedType(type);
|
||||
this.selectedType = type;
|
||||
}
|
||||
|
||||
@action
|
||||
installThemeFromList(url) {
|
||||
this.uploadUrl = url;
|
||||
this.installTheme();
|
||||
}
|
||||
|
||||
@action
|
||||
async installTheme() {
|
||||
if (this.create) {
|
||||
this.loading = true;
|
||||
const theme = this.store.createRecord(this.recordType);
|
||||
try {
|
||||
await theme.save({ name: this.name, component: this.component });
|
||||
this.args.model.addTheme(theme);
|
||||
this.args.closeModal();
|
||||
} catch {
|
||||
popupAjaxError;
|
||||
} finally {
|
||||
this.loading = false;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
let options = {
|
||||
type: "POST",
|
||||
};
|
||||
|
||||
if (this.local) {
|
||||
options.processData = false;
|
||||
options.contentType = false;
|
||||
options.data = new FormData();
|
||||
options.data.append("theme", this.localFile);
|
||||
}
|
||||
|
||||
if (this.remote || this.popular || this.directRepoInstall) {
|
||||
const duplicate = this.args.model.content.find((theme) =>
|
||||
this.themeHasSameUrl(theme, this.uploadUrl)
|
||||
);
|
||||
if (duplicate && !this.duplicateRemoteThemeWarning) {
|
||||
const warning = I18n.t("admin.customize.theme.duplicate_remote_theme", {
|
||||
name: duplicate.name,
|
||||
});
|
||||
this.duplicateRemoteThemeWarning = warning;
|
||||
return;
|
||||
}
|
||||
options.data = {
|
||||
remote: this.uploadUrl,
|
||||
branch: this.branch,
|
||||
public_key: this.publicKey,
|
||||
};
|
||||
}
|
||||
|
||||
// User knows that theme cannot be installed, but they want to continue
|
||||
// to force install it.
|
||||
if (this.themeCannotBeInstalled) {
|
||||
options.data["force"] = true;
|
||||
}
|
||||
|
||||
// Used by theme-creator
|
||||
if (this.args.model.userId) {
|
||||
options.data["user_id"] = this.args.model.userId;
|
||||
}
|
||||
|
||||
try {
|
||||
this.loading = true;
|
||||
const result = await ajax("/admin/themes/import", options);
|
||||
const theme = this.store.createRecord(this.recordType, result.theme);
|
||||
this.args.model.addTheme(theme);
|
||||
this.args.closeModal();
|
||||
} catch (e) {
|
||||
if (!this.publicKey || this.themeCannotBeInstalled) {
|
||||
return popupAjaxError(e);
|
||||
}
|
||||
this.themeCannotBeInstalled = I18n.t(
|
||||
"admin.customize.theme.force_install"
|
||||
);
|
||||
} finally {
|
||||
this.loading = false;
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user