Spiegel von
https://github.com/paviliondev/discourse-custom-wizard.git
synchronisiert 2024-11-26 19:10:29 +01:00
329 Zeilen
10 KiB
JavaScript
329 Zeilen
10 KiB
JavaScript
import { default as computed } from "discourse-common/utils/decorators";
|
|
import { dasherize } from "@ember/string";
|
|
|
|
export default {
|
|
name: "custom-routes",
|
|
after: "sniff-capabilities",
|
|
initialize(app) {
|
|
if (window.location.pathname.indexOf("/w/") < 0) return;
|
|
|
|
const EmberObject = requirejs("@ember/object").default;
|
|
const Router = requirejs("wizard/router").default;
|
|
const ApplicationRoute = requirejs("wizard/routes/application").default;
|
|
const ajax = requirejs("wizard/lib/ajax").ajax;
|
|
const StepModel = requirejs("wizard/models/step").default;
|
|
const CustomWizard = requirejs(
|
|
"discourse/plugins/discourse-custom-wizard/wizard/models/custom"
|
|
).default;
|
|
const WizardStep = requirejs("wizard/components/wizard-step").default;
|
|
const WizardField = requirejs("wizard/components/wizard-field").default;
|
|
const getUrl = requirejs("discourse-common/lib/get-url").default;
|
|
const FieldModel = requirejs("wizard/models/wizard-field").default;
|
|
const autocomplete = requirejs("discourse/lib/autocomplete").default;
|
|
const cook = requirejs(
|
|
"discourse/plugins/discourse-custom-wizard/wizard/lib/text-lite"
|
|
).cook;
|
|
const Singleton = requirejs("discourse/mixins/singleton").default;
|
|
const Store = requirejs("discourse/models/store").default;
|
|
const registerRawHelpers = requirejs(
|
|
"discourse-common/lib/raw-handlebars-helpers"
|
|
).registerRawHelpers;
|
|
const createHelperContext = requirejs("discourse-common/lib/helpers")
|
|
.createHelperContext;
|
|
const RawHandlebars = requirejs("discourse-common/lib/raw-handlebars")
|
|
.default;
|
|
const Site = requirejs(
|
|
"discourse/plugins/discourse-custom-wizard/wizard/models/site"
|
|
).default;
|
|
const RestAdapter = requirejs("discourse/adapters/rest").default;
|
|
const Session = requirejs("discourse/models/session").default;
|
|
const setDefaultOwner = requirejs("discourse-common/lib/get-owner")
|
|
.setDefaultOwner;
|
|
const messageBus = requirejs("message-bus-client").default;
|
|
const container = app.__container__;
|
|
Discourse.Model = EmberObject.extend();
|
|
Discourse.__container__ = container;
|
|
setDefaultOwner(container);
|
|
registerRawHelpers(RawHandlebars, Handlebars);
|
|
|
|
// IE11 Polyfill - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/entries#Polyfill
|
|
if (!Object.entries)
|
|
Object.entries = function (obj) {
|
|
var ownProps = Object.keys(obj),
|
|
i = ownProps.length,
|
|
resArray = new Array(i); // preallocate the Array
|
|
while (i--) resArray[i] = [ownProps[i], obj[ownProps[i]]];
|
|
|
|
return resArray;
|
|
};
|
|
|
|
$.fn.autocomplete = autocomplete;
|
|
|
|
Object.keys(Ember.TEMPLATES).forEach((k) => {
|
|
if (k.indexOf("select-kit") === 0) {
|
|
let template = Ember.TEMPLATES[k];
|
|
define(k, () => template);
|
|
}
|
|
});
|
|
|
|
const targets = ["controller", "component", "route", "model", "adapter"];
|
|
|
|
const siteSettings = Wizard.SiteSettings;
|
|
app.register("site-settings:main", siteSettings, { instantiate: false });
|
|
createHelperContext({ siteSettings });
|
|
targets.forEach((t) => app.inject(t, "siteSettings", "site-settings:main"));
|
|
|
|
app.register("message-bus:main", messageBus, { instantiate: false });
|
|
targets.forEach((t) => app.inject(t, "messageBus", "message-bus:main"));
|
|
|
|
app.register("service:store", Store);
|
|
targets.forEach((t) => app.inject(t, "store", "service:store"));
|
|
targets.forEach((t) => app.inject(t, "appEvents", "service:app-events"));
|
|
|
|
app.register("adapter:rest", RestAdapter);
|
|
|
|
const site = Site.current();
|
|
app.register("site:main", site, { instantiate: false });
|
|
targets.forEach((t) => app.inject(t, "site", "site:main"));
|
|
|
|
site.set("can_create_tag", false);
|
|
app.register("session:main", Session.current(), { instantiate: false });
|
|
targets.forEach((t) => app.inject(t, "session", "session:main"));
|
|
let context = {
|
|
siteSettings: container.lookup("site-settings:main"),
|
|
currentUser: container.lookup("current-user:main"),
|
|
site: container.lookup("site:main"),
|
|
session: container.lookup("session:main"),
|
|
capabilities: container.lookup("capabilities:main"),
|
|
};
|
|
createHelperContext(context);
|
|
const session = container.lookup("session:main");
|
|
const setupData = document.getElementById("data-discourse-setup").dataset;
|
|
session.set("highlightJsPath", setupData.highlightJsPath);
|
|
Router.reopen({
|
|
rootURL: getUrl("/w/"),
|
|
});
|
|
|
|
Router.map(function () {
|
|
this.route("custom", { path: "/:wizard_id" }, function () {
|
|
this.route("steps");
|
|
this.route("step", { path: "/steps/:step_id" });
|
|
});
|
|
});
|
|
|
|
ApplicationRoute.reopen({
|
|
redirect() {
|
|
this.transitionTo("custom");
|
|
},
|
|
|
|
model() {},
|
|
});
|
|
|
|
WizardStep.reopen({
|
|
classNameBindings: ["step.id"],
|
|
|
|
animateInvalidFields() {
|
|
Ember.run.scheduleOnce("afterRender", () => {
|
|
let $element = $(
|
|
".invalid input[type=text], .invalid textarea, .invalid input[type=checkbox], .invalid .select-kit"
|
|
);
|
|
|
|
if ($element.length) {
|
|
$([document.documentElement, document.body]).animate(
|
|
{
|
|
scrollTop: $element.offset().top - 200,
|
|
},
|
|
400,
|
|
function () {
|
|
$element.wiggle(2, 100);
|
|
}
|
|
);
|
|
}
|
|
});
|
|
},
|
|
|
|
ensureStartsAtTop: function () {
|
|
window.scrollTo(0, 0);
|
|
}.observes("step.id"),
|
|
|
|
showQuitButton: function () {
|
|
const index = this.get("step.index");
|
|
const required = this.get("wizard.required");
|
|
return index === 0 && !required;
|
|
}.property("step.index", "wizard.required"),
|
|
|
|
cookedTitle: function () {
|
|
return cook(this.get("step.title"));
|
|
}.property("step.title"),
|
|
|
|
cookedDescription: function () {
|
|
return cook(this.get("step.description"));
|
|
}.property("step.description"),
|
|
|
|
bannerImage: function () {
|
|
const src = this.get("step.banner");
|
|
if (!src) return;
|
|
return getUrl(src);
|
|
}.property("step.banner"),
|
|
|
|
handleMessage: function () {
|
|
const message = this.get("step.message");
|
|
this.sendAction("showMessage", message);
|
|
}.observes("step.message"),
|
|
|
|
advance() {
|
|
this.set("saving", true);
|
|
this.get("step")
|
|
.save()
|
|
.then((response) => {
|
|
if (this.get("finalStep")) {
|
|
CustomWizard.finished(response);
|
|
} else {
|
|
this.sendAction("goNext", response);
|
|
}
|
|
})
|
|
.catch(() => this.animateInvalidFields())
|
|
.finally(() => this.set("saving", false));
|
|
},
|
|
|
|
keyPress(key) {},
|
|
|
|
actions: {
|
|
quit() {
|
|
this.get("wizard").skip();
|
|
},
|
|
|
|
done() {
|
|
this.set("finalStep", true);
|
|
this.send("nextStep");
|
|
},
|
|
|
|
showMessage(message) {
|
|
this.sendAction("showMessage", message);
|
|
},
|
|
},
|
|
});
|
|
|
|
StepModel.reopen({
|
|
save() {
|
|
const wizardId = this.get("wizardId");
|
|
const fields = {};
|
|
|
|
this.get("fields").forEach((f) => {
|
|
if (f.type !== "text_only") {
|
|
fields[f.id] = f.value;
|
|
}
|
|
});
|
|
|
|
return ajax({
|
|
url: `/w/${wizardId}/steps/${this.get("id")}`,
|
|
type: "PUT",
|
|
data: { fields },
|
|
}).catch((response) => {
|
|
if (
|
|
response &&
|
|
response.responseJSON &&
|
|
response.responseJSON.errors
|
|
) {
|
|
let wizardErrors = [];
|
|
response.responseJSON.errors.forEach((err) => {
|
|
if (err.field === wizardId) {
|
|
wizardErrors.push(err.description);
|
|
} else if (err.field) {
|
|
this.fieldError(err.field, err.description);
|
|
} else if (err) {
|
|
wizardErrors.push(err);
|
|
}
|
|
});
|
|
if (wizardErrors.length) {
|
|
this.handleWizardError(wizardErrors.join("\n"));
|
|
}
|
|
this.animateInvalidFields();
|
|
throw response;
|
|
}
|
|
|
|
if (response && response.responseText) {
|
|
const responseText = response.responseText;
|
|
const start = responseText.indexOf(">") + 1;
|
|
const end = responseText.indexOf("plugins");
|
|
const message = responseText.substring(start, end);
|
|
this.handleWizardError(message);
|
|
throw message;
|
|
}
|
|
});
|
|
},
|
|
|
|
handleWizardError(message) {
|
|
this.set("message", {
|
|
state: "error",
|
|
text: message,
|
|
});
|
|
Ember.run.later(() => this.set("message", null), 6000);
|
|
},
|
|
});
|
|
|
|
WizardField.reopen({
|
|
classNameBindings: ["field.id"],
|
|
|
|
cookedDescription: function () {
|
|
return cook(this.get("field.description"));
|
|
}.property("field.description"),
|
|
|
|
inputComponentName: function () {
|
|
const type = this.get("field.type");
|
|
const id = this.get("field.id");
|
|
if (["text_only"].includes(type)) return false;
|
|
return dasherize(type === "component" ? id : `wizard-field-${type}`);
|
|
}.property("field.type", "field.id"),
|
|
});
|
|
|
|
const StandardFieldValidation = [
|
|
"text",
|
|
"number",
|
|
"textarea",
|
|
"dropdown",
|
|
"tag",
|
|
"image",
|
|
"user_selector",
|
|
"text_only",
|
|
"composer",
|
|
"category",
|
|
"group",
|
|
"date",
|
|
"time",
|
|
"date_time",
|
|
];
|
|
|
|
FieldModel.reopen({
|
|
check() {
|
|
if (this.customCheck) {
|
|
return this.customCheck();
|
|
}
|
|
|
|
let valid = this.valid;
|
|
|
|
if (!this.required) {
|
|
this.setValid(true);
|
|
return true;
|
|
}
|
|
|
|
const val = this.get("value");
|
|
const type = this.get("type");
|
|
|
|
if (type === "checkbox") {
|
|
valid = val;
|
|
} else if (type === "upload") {
|
|
valid = val && val.id > 0;
|
|
} else if (StandardFieldValidation.indexOf(type) > -1) {
|
|
valid = val && val.toString().length > 0;
|
|
} else if (type === "url") {
|
|
valid = true;
|
|
}
|
|
|
|
this.setValid(valid);
|
|
|
|
return valid;
|
|
},
|
|
});
|
|
},
|
|
};
|