diff --git a/app/assets/javascripts/admin/addon/adapters/permalink.js b/app/assets/javascripts/admin/addon/adapters/permalink.js new file mode 100644 index 00000000000..44cca43b0e7 --- /dev/null +++ b/app/assets/javascripts/admin/addon/adapters/permalink.js @@ -0,0 +1,7 @@ +import RestAdapter from "discourse/adapters/rest"; + +export default class Permalink extends RestAdapter { + basePath() { + return "/admin/"; + } +} diff --git a/app/assets/javascripts/admin/addon/components/admin-permalink-form.gjs b/app/assets/javascripts/admin/addon/components/admin-permalink-form.gjs new file mode 100644 index 00000000000..7225fcb1278 --- /dev/null +++ b/app/assets/javascripts/admin/addon/components/admin-permalink-form.gjs @@ -0,0 +1,257 @@ +import Component from "@glimmer/component"; +import { cached } from "@glimmer/tracking"; +import { inject as controller } from "@ember/controller"; +import { action } from "@ember/object"; +import { service } from "@ember/service"; +import { isEmpty } from "@ember/utils"; +import { eq } from "truth-helpers"; +import BackButton from "discourse/components/back-button"; +import Form from "discourse/components/form"; +import { popupAjaxError } from "discourse/lib/ajax-error"; +import i18n from "discourse-common/helpers/i18n"; +import { bind } from "discourse-common/utils/decorators"; +import AdminConfigAreaCard from "admin/components/admin-config-area-card"; +import Permalink from "admin/models/permalink"; + +const TYPE_TO_FIELD_MAP = { + topic: "topicId", + post: "postId", + category: "categoryId", + tag: "tagName", + user: "userId", + external_url: "externalUrl", +}; + +export default class AdminFlagsForm extends Component { + @service router; + @service store; + @controller adminPermalinks; + + get isUpdate() { + return this.args.permalink; + } + + @cached + get formData() { + if (this.isUpdate) { + let permalinkType; + let permalinkValue; + if (!isEmpty(this.args.permalink.topic_id)) { + permalinkType = "topic"; + permalinkValue = this.args.permalink.topic_id; + } else if (!isEmpty(this.args.permalink.post_id)) { + permalinkType = "post"; + permalinkValue = this.args.permalink.post_id; + } else if (!isEmpty(this.args.permalink.category_id)) { + permalinkType = "category"; + permalinkValue = this.args.permalink.category_id; + } else if (!isEmpty(this.args.permalink.tag_name)) { + permalinkType = "tag"; + permalinkValue = this.args.permalink.tag_name; + } else if (!isEmpty(this.args.permalink.external_url)) { + permalinkType = "external_url"; + permalinkValue = this.args.permalink.external_url; + } else if (!isEmpty(this.args.permalink.user_id)) { + permalinkType = "user"; + permalinkValue = this.args.permalink.user_id; + } + + return { + url: this.args.permalink.url, + [TYPE_TO_FIELD_MAP[permalinkType]]: permalinkValue, + permalinkType, + }; + } else { + return { + permalinkType: "topic", + }; + } + } + + get header() { + return this.isUpdate + ? "admin.permalink.form.edit_header" + : "admin.permalink.form.add_header"; + } + + @action + save(data) { + const createOrUpdate = this.isUpdate ? this.update : this.create; + createOrUpdate(data); + } + + @bind + async create(data) { + try { + const result = await this.store.createRecord("permalink").save({ + url: data.url, + permalink_type: data.permalinkType, + permalink_type_value: this.valueForPermalinkType(data), + }); + this.adminPermalinks.model.unshiftObject( + Permalink.create(result.payload) + ); + this.router.transitionTo("adminPermalinks"); + } catch (error) { + popupAjaxError(error); + } + } + + @bind + async update(data) { + try { + const result = await this.store.update( + "permalink", + this.args.permalink.id, + { + url: data.url, + permalink_type: data.permalinkType, + permalink_type_value: this.valueForPermalinkType(data), + } + ); + const index = this.adminPermalinks.model.findIndex( + (permalink) => permalink.id === this.args.permalink.id + ); + this.adminPermalinks.model[index] = Permalink.create(result.payload); + this.router.transitionTo("adminPermalinks"); + } catch (error) { + popupAjaxError(error); + } + } + + valueForPermalinkType(data) { + return data[TYPE_TO_FIELD_MAP[data.permalinkType]]; + } + + validatePermalinkTypeValue(data, { removeError }) { + Object.keys(TYPE_TO_FIELD_MAP).forEach((type) => { + if (data.permalinkType !== type) { + removeError(TYPE_TO_FIELD_MAP[type]); + } + }); + } + + +} diff --git a/app/assets/javascripts/admin/addon/controllers/admin-permalinks.js b/app/assets/javascripts/admin/addon/controllers/admin-permalinks-index.js similarity index 63% rename from app/assets/javascripts/admin/addon/controllers/admin-permalinks.js rename to app/assets/javascripts/admin/addon/controllers/admin-permalinks-index.js index 854ccbe45b1..c7d183add03 100644 --- a/app/assets/javascripts/admin/addon/controllers/admin-permalinks.js +++ b/app/assets/javascripts/admin/addon/controllers/admin-permalinks-index.js @@ -9,8 +9,10 @@ import discourseDebounce from "discourse-common/lib/debounce"; import I18n from "discourse-i18n"; import Permalink from "admin/models/permalink"; -export default class AdminPermalinksController extends Controller { +export default class AdminPermalinksIndexController extends Controller { @service dialog; + @service router; + @service toasts; loading = false; filter = null; @@ -29,35 +31,35 @@ export default class AdminPermalinksController extends Controller { discourseDebounce(this, this._debouncedShow, INPUT_DELAY); } - @action - recordAdded(arg) { - this.model.unshiftObject(arg); - } - @action copyUrl(pl) { let linkElement = document.querySelector(`#admin-permalink-${pl.id}`); clipboardCopy(linkElement.textContent); - } - - @action - destroyRecord(record) { - return this.dialog.yesNoConfirm({ - message: I18n.t("admin.permalink.delete_confirm"), - didConfirm: () => { - return record.destroy().then( - (deleted) => { - if (deleted) { - this.model.removeObject(record); - } else { - this.dialog.alert(I18n.t("generic_error")); - } - }, - function () { - this.dialog.alert(I18n.t("generic_error")); - } - ); + this.toasts.success({ + duration: 3000, + data: { + message: I18n.t("admin.permalink.copy_success"), }, }); } + + @action + destroyRecord(permalink) { + this.dialog.yesNoConfirm({ + message: I18n.t("admin.permalink.delete_confirm"), + didConfirm: async () => { + try { + await this.store.destroyRecord("permalink", permalink); + this.model.removeObject(permalink); + } catch { + this.dialog.alert(I18n.t("generic_error")); + } + }, + }); + } + + @action + edit(record) { + this.router.transitionTo("adminPermalinks.edit", record); + } } diff --git a/app/assets/javascripts/admin/addon/models/permalink.js b/app/assets/javascripts/admin/addon/models/permalink.js index 21bafb83de9..af4ef5bdefd 100644 --- a/app/assets/javascripts/admin/addon/models/permalink.js +++ b/app/assets/javascripts/admin/addon/models/permalink.js @@ -1,10 +1,10 @@ -import EmberObject from "@ember/object"; import { ajax } from "discourse/lib/ajax"; import DiscourseURL from "discourse/lib/url"; import Category from "discourse/models/category"; +import RestModel from "discourse/models/rest"; import discourseComputed from "discourse-common/utils/decorators"; -export default class Permalink extends EmberObject { +export default class Permalink extends RestModel { static findAll(filter) { return ajax("/admin/permalinks.json", { data: { filter } }).then(function ( permalinks @@ -13,17 +13,6 @@ export default class Permalink extends EmberObject { }); } - save() { - return ajax("/admin/permalinks.json", { - type: "POST", - data: { - url: this.url, - permalink_type: this.permalink_type, - permalink_type_value: this.permalink_type_value, - }, - }); - } - @discourseComputed("category_id") category(category_id) { return Category.findById(category_id); @@ -34,9 +23,8 @@ export default class Permalink extends EmberObject { return !DiscourseURL.isInternal(external_url); } - destroy() { - return ajax("/admin/permalinks/" + this.id + ".json", { - type: "DELETE", - }); + @discourseComputed("url") + key(url) { + return url.replace("/", "_"); } } diff --git a/app/assets/javascripts/admin/addon/routes/admin-permalinks-edit.js b/app/assets/javascripts/admin/addon/routes/admin-permalinks-edit.js new file mode 100644 index 00000000000..49d77e1d42c --- /dev/null +++ b/app/assets/javascripts/admin/addon/routes/admin-permalinks-edit.js @@ -0,0 +1,10 @@ +import { service } from "@ember/service"; +import DiscourseRoute from "discourse/routes/discourse"; + +export default class AdminPermalinksEditRoute extends DiscourseRoute { + @service store; + + model(params) { + return this.store.find("permalink", params.permalink_id); + } +} diff --git a/app/assets/javascripts/admin/addon/routes/admin-route-map.js b/app/assets/javascripts/admin/addon/routes/admin-route-map.js index facec60a4f4..df898346b46 100644 --- a/app/assets/javascripts/admin/addon/routes/admin-route-map.js +++ b/app/assets/javascripts/admin/addon/routes/admin-route-map.js @@ -73,10 +73,16 @@ export default function () { resetNamespace: true, }); this.route("adminEmojis", { path: "/emojis", resetNamespace: true }); - this.route("adminPermalinks", { - path: "/permalinks", - resetNamespace: true, - }); + + this.route( + "adminPermalinks", + { path: "/permalinks", resetNamespace: true }, + function () { + this.route("new"); + this.route("edit", { path: "/:permalink_id" }); + } + ); + this.route("adminEmbedding", { path: "/embedding", resetNamespace: true, diff --git a/app/assets/javascripts/admin/addon/templates/permalinks-edit.hbs b/app/assets/javascripts/admin/addon/templates/permalinks-edit.hbs new file mode 100644 index 00000000000..f74b91cf898 --- /dev/null +++ b/app/assets/javascripts/admin/addon/templates/permalinks-edit.hbs @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/javascripts/admin/addon/templates/permalinks-index.hbs b/app/assets/javascripts/admin/addon/templates/permalinks-index.hbs new file mode 100644 index 00000000000..5d26eb8a7c5 --- /dev/null +++ b/app/assets/javascripts/admin/addon/templates/permalinks-index.hbs @@ -0,0 +1,118 @@ + + <:actions as |actions|> + + + + + + + + \ No newline at end of file diff --git a/app/assets/javascripts/admin/addon/templates/permalinks-new.hbs b/app/assets/javascripts/admin/addon/templates/permalinks-new.hbs new file mode 100644 index 00000000000..824a49fedef --- /dev/null +++ b/app/assets/javascripts/admin/addon/templates/permalinks-new.hbs @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/javascripts/admin/addon/templates/permalinks.hbs b/app/assets/javascripts/admin/addon/templates/permalinks.hbs index 135b614467f..d839ec147ef 100644 --- a/app/assets/javascripts/admin/addon/templates/permalinks.hbs +++ b/app/assets/javascripts/admin/addon/templates/permalinks.hbs @@ -1,88 +1,17 @@ -

{{i18n "admin.permalink.title"}}

+