mirror of
https://github.com/discourse/discourse.git
synced 2025-02-22 14:20:13 +08:00
DEV: Move modal hide/show logic into a service (#21748)
For now, state is still stored in the modal controller. Eventually the controller will be replaced with a component, and the state will be stored in the service. (extracted from https://github.com/discourse/discourse/pull/21304)
This commit is contained in:
parent
db54b80275
commit
d460309f89
@ -1,5 +1,3 @@
|
|||||||
import I18n from "I18n";
|
|
||||||
import { dasherize } from "@ember/string";
|
|
||||||
import { getOwner } from "discourse-common/lib/get-owner";
|
import { getOwner } from "discourse-common/lib/get-owner";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -26,80 +24,6 @@ export default function showModal(name, opts) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// We use the container here because modals are like singletons
|
const modalService = container.lookup("service:modal");
|
||||||
// in Discourse. Only one can be shown with a particular state.
|
return modalService.show(name, opts);
|
||||||
const route = container.lookup("route:application");
|
|
||||||
const modalController = route.controllerFor("modal");
|
|
||||||
|
|
||||||
modalController.set(
|
|
||||||
"modalClass",
|
|
||||||
opts.modalClass || `${dasherize(name).toLowerCase()}-modal`
|
|
||||||
);
|
|
||||||
|
|
||||||
const controllerName = opts.admin ? `modals/${name}` : name;
|
|
||||||
modalController.set("name", controllerName);
|
|
||||||
|
|
||||||
let controller = container.lookup("controller:" + controllerName);
|
|
||||||
const templateName = opts.templateName || dasherize(name);
|
|
||||||
|
|
||||||
const renderArgs = { into: "modal", outlet: "modalBody" };
|
|
||||||
if (controller) {
|
|
||||||
renderArgs.controller = controllerName;
|
|
||||||
} else {
|
|
||||||
// use a basic controller
|
|
||||||
renderArgs.controller = "basic-modal-body";
|
|
||||||
controller = container.lookup(`controller:${renderArgs.controller}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (opts.addModalBodyView) {
|
|
||||||
renderArgs.view = "modal-body";
|
|
||||||
}
|
|
||||||
|
|
||||||
const modalName = `modal/${templateName}`;
|
|
||||||
const fullName = opts.admin ? `admin/templates/${modalName}` : modalName;
|
|
||||||
route.render(fullName, renderArgs);
|
|
||||||
if (opts.title) {
|
|
||||||
modalController.set("title", I18n.t(opts.title));
|
|
||||||
} else if (opts.titleTranslated) {
|
|
||||||
modalController.set("title", opts.titleTranslated);
|
|
||||||
} else {
|
|
||||||
modalController.set("title", null);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (opts.titleAriaElementId) {
|
|
||||||
modalController.set("titleAriaElementId", opts.titleAriaElementId);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (opts.panels) {
|
|
||||||
modalController.setProperties({
|
|
||||||
panels: opts.panels,
|
|
||||||
selectedPanel: opts.panels[0],
|
|
||||||
});
|
|
||||||
|
|
||||||
if (controller.actions.onSelectPanel) {
|
|
||||||
modalController.set(
|
|
||||||
"onSelectPanel",
|
|
||||||
controller.actions.onSelectPanel.bind(controller)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
modalController.set(
|
|
||||||
"modalClass",
|
|
||||||
`${modalController.get("modalClass")} has-tabs`
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
modalController.setProperties({ panels: [], selectedPanel: null });
|
|
||||||
}
|
|
||||||
|
|
||||||
controller.set("modal", modalController);
|
|
||||||
const model = opts.model;
|
|
||||||
if (model) {
|
|
||||||
controller.set("model", model);
|
|
||||||
}
|
|
||||||
if (controller.onShow) {
|
|
||||||
controller.onShow();
|
|
||||||
}
|
|
||||||
controller.set("flashMessage", null);
|
|
||||||
|
|
||||||
return controller;
|
|
||||||
}
|
}
|
||||||
|
@ -40,6 +40,7 @@ const ApplicationRoute = DiscourseRoute.extend(OpenComposer, {
|
|||||||
documentTitle: service(),
|
documentTitle: service(),
|
||||||
dialog: service(),
|
dialog: service(),
|
||||||
composer: service(),
|
composer: service(),
|
||||||
|
modal: service(),
|
||||||
|
|
||||||
actions: {
|
actions: {
|
||||||
toggleAnonymous() {
|
toggleAnonymous() {
|
||||||
@ -152,46 +153,7 @@ const ApplicationRoute = DiscourseRoute.extend(OpenComposer, {
|
|||||||
|
|
||||||
// Close the current modal, and destroy its state.
|
// Close the current modal, and destroy its state.
|
||||||
closeModal(initiatedBy) {
|
closeModal(initiatedBy) {
|
||||||
const route = getOwner(this).lookup("route:application");
|
return this.modal.close(initiatedBy);
|
||||||
let modalController = route.controllerFor("modal");
|
|
||||||
const controllerName = modalController.get("name");
|
|
||||||
|
|
||||||
if (controllerName) {
|
|
||||||
const controller = getOwner(this).lookup(
|
|
||||||
`controller:${controllerName}`
|
|
||||||
);
|
|
||||||
if (controller && controller.beforeClose) {
|
|
||||||
if (false === controller.beforeClose()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this.render("hide-modal", { into: "modal", outlet: "modalBody" });
|
|
||||||
$(".d-modal.fixed-modal").modal("hide");
|
|
||||||
|
|
||||||
if (controllerName) {
|
|
||||||
const controller = getOwner(this).lookup(
|
|
||||||
`controller:${controllerName}`
|
|
||||||
);
|
|
||||||
|
|
||||||
if (controller) {
|
|
||||||
this.appEvents.trigger("modal:closed", {
|
|
||||||
name: controllerName,
|
|
||||||
controller,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (controller.onClose) {
|
|
||||||
controller.onClose({
|
|
||||||
initiatedByCloseButton: initiatedBy === "initiatedByCloseButton",
|
|
||||||
initiatedByClickOut: initiatedBy === "initiatedByClickOut",
|
|
||||||
initiatedByESC: initiatedBy === "initiatedByESC",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
modalController.set("name", null);
|
|
||||||
}
|
|
||||||
modalController.hidden = true;
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -200,11 +162,11 @@ const ApplicationRoute = DiscourseRoute.extend(OpenComposer, {
|
|||||||
user clicks "No", reopenModal. If user clicks "Yes", be sure to call closeModal.
|
user clicks "No", reopenModal. If user clicks "Yes", be sure to call closeModal.
|
||||||
**/
|
**/
|
||||||
hideModal() {
|
hideModal() {
|
||||||
$(".d-modal.fixed-modal").modal("hide");
|
return this.modal.hide();
|
||||||
},
|
},
|
||||||
|
|
||||||
reopenModal() {
|
reopenModal() {
|
||||||
$(".d-modal.fixed-modal").modal("show");
|
return this.modal.reopen();
|
||||||
},
|
},
|
||||||
|
|
||||||
editCategory(category) {
|
editCategory(category) {
|
||||||
|
137
app/assets/javascripts/discourse/app/services/modal.js
Normal file
137
app/assets/javascripts/discourse/app/services/modal.js
Normal file
@ -0,0 +1,137 @@
|
|||||||
|
import Service, { inject as service } from "@ember/service";
|
||||||
|
import { getOwner } from "@ember/application";
|
||||||
|
import I18n from "I18n";
|
||||||
|
import { dasherize } from "@ember/string";
|
||||||
|
import { disableImplicitInjections } from "discourse/lib/implicit-injections";
|
||||||
|
|
||||||
|
@disableImplicitInjections
|
||||||
|
export default class ModalService extends Service {
|
||||||
|
@service appEvents;
|
||||||
|
|
||||||
|
show(name, opts = {}) {
|
||||||
|
const container = getOwner(this);
|
||||||
|
const route = container.lookup("route:application");
|
||||||
|
const modalController = route.controllerFor("modal");
|
||||||
|
|
||||||
|
modalController.set(
|
||||||
|
"modalClass",
|
||||||
|
opts.modalClass || `${dasherize(name).toLowerCase()}-modal`
|
||||||
|
);
|
||||||
|
|
||||||
|
const controllerName = opts.admin ? `modals/${name}` : name;
|
||||||
|
modalController.set("name", controllerName);
|
||||||
|
|
||||||
|
let controller = container.lookup("controller:" + controllerName);
|
||||||
|
const templateName = opts.templateName || dasherize(name);
|
||||||
|
|
||||||
|
const renderArgs = { into: "modal", outlet: "modalBody" };
|
||||||
|
if (controller) {
|
||||||
|
renderArgs.controller = controllerName;
|
||||||
|
} else {
|
||||||
|
// use a basic controller
|
||||||
|
renderArgs.controller = "basic-modal-body";
|
||||||
|
controller = container.lookup(`controller:${renderArgs.controller}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (opts.addModalBodyView) {
|
||||||
|
renderArgs.view = "modal-body";
|
||||||
|
}
|
||||||
|
|
||||||
|
const modalName = `modal/${templateName}`;
|
||||||
|
const fullName = opts.admin ? `admin/templates/${modalName}` : modalName;
|
||||||
|
route.render(fullName, renderArgs);
|
||||||
|
if (opts.title) {
|
||||||
|
modalController.set("title", I18n.t(opts.title));
|
||||||
|
} else if (opts.titleTranslated) {
|
||||||
|
modalController.set("title", opts.titleTranslated);
|
||||||
|
} else {
|
||||||
|
modalController.set("title", null);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (opts.titleAriaElementId) {
|
||||||
|
modalController.set("titleAriaElementId", opts.titleAriaElementId);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (opts.panels) {
|
||||||
|
modalController.setProperties({
|
||||||
|
panels: opts.panels,
|
||||||
|
selectedPanel: opts.panels[0],
|
||||||
|
});
|
||||||
|
|
||||||
|
if (controller.actions.onSelectPanel) {
|
||||||
|
modalController.set(
|
||||||
|
"onSelectPanel",
|
||||||
|
controller.actions.onSelectPanel.bind(controller)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
modalController.set(
|
||||||
|
"modalClass",
|
||||||
|
`${modalController.get("modalClass")} has-tabs`
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
modalController.setProperties({ panels: [], selectedPanel: null });
|
||||||
|
}
|
||||||
|
|
||||||
|
controller.set("modal", modalController);
|
||||||
|
const model = opts.model;
|
||||||
|
if (model) {
|
||||||
|
controller.set("model", model);
|
||||||
|
}
|
||||||
|
if (controller.onShow) {
|
||||||
|
controller.onShow();
|
||||||
|
}
|
||||||
|
controller.set("flashMessage", null);
|
||||||
|
|
||||||
|
return controller;
|
||||||
|
}
|
||||||
|
|
||||||
|
close(initiatedBy) {
|
||||||
|
const route = getOwner(this).lookup("route:application");
|
||||||
|
let modalController = route.controllerFor("modal");
|
||||||
|
const controllerName = modalController.get("name");
|
||||||
|
|
||||||
|
if (controllerName) {
|
||||||
|
const controller = getOwner(this).lookup(`controller:${controllerName}`);
|
||||||
|
if (controller && controller.beforeClose) {
|
||||||
|
if (false === controller.beforeClose()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getOwner(this)
|
||||||
|
.lookup("route:application")
|
||||||
|
.render("hide-modal", { into: "modal", outlet: "modalBody" });
|
||||||
|
$(".d-modal.fixed-modal").modal("hide");
|
||||||
|
|
||||||
|
if (controllerName) {
|
||||||
|
const controller = getOwner(this).lookup(`controller:${controllerName}`);
|
||||||
|
|
||||||
|
if (controller) {
|
||||||
|
this.appEvents.trigger("modal:closed", {
|
||||||
|
name: controllerName,
|
||||||
|
controller,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (controller.onClose) {
|
||||||
|
controller.onClose({
|
||||||
|
initiatedByCloseButton: initiatedBy === "initiatedByCloseButton",
|
||||||
|
initiatedByClickOut: initiatedBy === "initiatedByClickOut",
|
||||||
|
initiatedByESC: initiatedBy === "initiatedByESC",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
modalController.set("name", null);
|
||||||
|
}
|
||||||
|
modalController.hidden = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
hide() {
|
||||||
|
$(".d-modal.fixed-modal").modal("hide");
|
||||||
|
}
|
||||||
|
|
||||||
|
reopen() {
|
||||||
|
$(".d-modal.fixed-modal").modal("show");
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user