1
0
Fork 0

Commits vergleichen

...

2 Commits

Autor SHA1 Nachricht Datum
angusmcleod 484bd464d2 Full rubocop run (safe only) 2021-02-24 18:50:42 +11:00
angusmcleod 6f977049fc Real run of prettier 2021-02-24 18:43:35 +11:00
194 geänderte Dateien mit 5467 neuen und 3472 gelöschten Zeilen

Datei anzeigen

@ -2,118 +2,127 @@ import Component from "@ember/component";
import discourseComputed, { observes } from "discourse-common/utils/decorators"; import discourseComputed, { observes } from "discourse-common/utils/decorators";
import { or, alias } from "@ember/object/computed"; import { or, alias } from "@ember/object/computed";
const generateContent = function(array, type) { const generateContent = function (array, type) {
return array.map(key => ({ return array.map((key) => ({
id: key, id: key,
name: I18n.t(`admin.wizard.custom_field.${type}.${key}`) name: I18n.t(`admin.wizard.custom_field.${type}.${key}`),
})); }));
} };
export default Component.extend({ export default Component.extend({
tagName: 'tr', tagName: "tr",
topicSerializers: ['topic_view', 'topic_list_item'], topicSerializers: ["topic_view", "topic_list_item"],
postSerializers: ['post'], postSerializers: ["post"],
groupSerializers: ['basic_group'], groupSerializers: ["basic_group"],
categorySerializers: ['basic_category'], categorySerializers: ["basic_category"],
klassContent: generateContent(['topic', 'post', 'group', 'category'], 'klass'), klassContent: generateContent(
typeContent: generateContent(['string', 'boolean', 'integer', 'json'], 'type'), ["topic", "post", "group", "category"],
showInputs: or('field.new', 'field.edit'), "klass"
classNames: ['custom-field-input'], ),
loading: or('saving', 'destroying'), typeContent: generateContent(
destroyDisabled: alias('loading'), ["string", "boolean", "integer", "json"],
closeDisabled: alias('loading'), "type"
),
showInputs: or("field.new", "field.edit"),
classNames: ["custom-field-input"],
loading: or("saving", "destroying"),
destroyDisabled: alias("loading"),
closeDisabled: alias("loading"),
didInsertElement() { didInsertElement() {
this.set('originalField', JSON.parse(JSON.stringify(this.field))); this.set("originalField", JSON.parse(JSON.stringify(this.field)));
}, },
@discourseComputed('field.klass') @discourseComputed("field.klass")
serializerContent(klass, p2) { serializerContent(klass, p2) {
const serializers = this.get(`${klass}Serializers`); const serializers = this.get(`${klass}Serializers`);
if (serializers) { if (serializers) {
return generateContent(serializers, 'serializers'); return generateContent(serializers, "serializers");
} else { } else {
return []; return [];
} }
}, },
@observes('field.klass') @observes("field.klass")
clearSerializersWhenClassChanges() { clearSerializersWhenClassChanges() {
this.set('field.serializers', null); this.set("field.serializers", null);
}, },
compareArrays(array1, array2) { compareArrays(array1, array2) {
return array1.length === array2.length && array1.every((value, index) => { return (
return value === array2[index]; array1.length === array2.length &&
}); array1.every((value, index) => {
return value === array2[index];
})
);
}, },
@discourseComputed( @discourseComputed(
'saving', "saving",
'field.name', "field.name",
'field.klass', "field.klass",
'field.type', "field.type",
'field.serializers' "field.serializers"
) )
saveDisabled(saving) { saveDisabled(saving) {
if (saving) return true; if (saving) return true;
const originalField = this.originalField; const originalField = this.originalField;
if (!originalField) return false; if (!originalField) return false;
return ['name', 'klass', 'type', 'serializers'].every(attr => { return ["name", "klass", "type", "serializers"].every((attr) => {
let current = this.get(attr); let current = this.get(attr);
let original = originalField[attr]; let original = originalField[attr];
if (!current) return false; if (!current) return false;
if (attr == 'serializers') { if (attr == "serializers") {
return this.compareArrays(current, original); return this.compareArrays(current, original);
} else { } else {
return current == original; return current == original;
} }
}); });
}, },
actions: { actions: {
edit() { edit() {
this.set('field.edit', true); this.set("field.edit", true);
}, },
close() { close() {
if (this.field.edit) { if (this.field.edit) {
this.set('field.edit', false); this.set("field.edit", false);
} }
}, },
destroy() { destroy() {
this.set('destroying', true); this.set("destroying", true);
this.removeField(this.field); this.removeField(this.field);
}, },
save() { save() {
this.set('saving', true); this.set("saving", true);
const field = this.field; const field = this.field;
let data = { let data = {
id: field.id, id: field.id,
klass: field.klass, klass: field.klass,
type: field.type, type: field.type,
serializers: field.serializers, serializers: field.serializers,
name: field.name name: field.name,
} };
this.saveField(data).then((result) => { this.saveField(data).then((result) => {
this.set('saving', false); this.set("saving", false);
if (result.success) { if (result.success) {
this.set('field.edit', false); this.set("field.edit", false);
} else { } else {
this.set('saveIcon', 'times'); this.set("saveIcon", "times");
} }
setTimeout(() => this.set('saveIcon', null), 10000); setTimeout(() => this.set("saveIcon", null), 10000);
}); });
} },
} },
}); });

Datei anzeigen

@ -1,19 +1,19 @@
import { default as discourseComputed } from 'discourse-common/utils/decorators'; import { default as discourseComputed } from "discourse-common/utils/decorators";
import Component from '@ember/component'; import Component from "@ember/component";
export default Component.extend({ export default Component.extend({
classNames: 'wizard-advanced-toggle', classNames: "wizard-advanced-toggle",
@discourseComputed('showAdvanced') @discourseComputed("showAdvanced")
toggleClass(showAdvanced) { toggleClass(showAdvanced) {
let classes = 'btn' let classes = "btn";
if (showAdvanced) classes += ' btn-primary'; if (showAdvanced) classes += " btn-primary";
return classes; return classes;
}, },
actions: { actions: {
toggleAdvanced() { toggleAdvanced() {
this.toggleProperty('showAdvanced'); this.toggleProperty("showAdvanced");
} },
} },
}) });

Datei anzeigen

@ -1,89 +1,98 @@
import { default as discourseComputed } from 'discourse-common/utils/decorators'; import { default as discourseComputed } from "discourse-common/utils/decorators";
import { equal, empty, or, and } from "@ember/object/computed"; import { equal, empty, or, and } from "@ember/object/computed";
import { generateName, selectKitContent } from '../lib/wizard'; import { generateName, selectKitContent } from "../lib/wizard";
import { computed } from "@ember/object"; import { computed } from "@ember/object";
import wizardSchema from '../lib/wizard-schema'; import wizardSchema from "../lib/wizard-schema";
import UndoChanges from '../mixins/undo-changes'; import UndoChanges from "../mixins/undo-changes";
import Component from "@ember/component"; import Component from "@ember/component";
import { notificationLevels } from '../lib/wizard'; import { notificationLevels } from "../lib/wizard";
import I18n from "I18n"; import I18n from "I18n";
export default Component.extend(UndoChanges, { export default Component.extend(UndoChanges, {
componentType: 'action', componentType: "action",
classNameBindings: [':wizard-custom-action', 'visible'], classNameBindings: [":wizard-custom-action", "visible"],
visible: computed('currentActionId', function() { return this.action.id === this.currentActionId }), visible: computed("currentActionId", function () {
createTopic: equal('action.type', 'create_topic'), return this.action.id === this.currentActionId;
updateProfile: equal('action.type', 'update_profile'), }),
watchCategories: equal('action.type', 'watch_categories'), createTopic: equal("action.type", "create_topic"),
sendMessage: equal('action.type', 'send_message'), updateProfile: equal("action.type", "update_profile"),
openComposer: equal('action.type', 'open_composer'), watchCategories: equal("action.type", "watch_categories"),
sendToApi: equal('action.type', 'send_to_api'), sendMessage: equal("action.type", "send_message"),
addToGroup: equal('action.type', 'add_to_group'), openComposer: equal("action.type", "open_composer"),
routeTo: equal('action.type', 'route_to'), sendToApi: equal("action.type", "send_to_api"),
createCategory: equal('action.type', 'create_category'), addToGroup: equal("action.type", "add_to_group"),
createGroup: equal('action.type', 'create_group'), routeTo: equal("action.type", "route_to"),
apiEmpty: empty('action.api'), createCategory: equal("action.type", "create_category"),
groupPropertyTypes: selectKitContent(['id', 'name']), createGroup: equal("action.type", "create_group"),
hasAdvanced: or('hasCustomFields', 'routeTo'), apiEmpty: empty("action.api"),
showAdvanced: and('hasAdvanced', 'action.type'), groupPropertyTypes: selectKitContent(["id", "name"]),
hasCustomFields: or('basicTopicFields', 'updateProfile', 'createGroup', 'createCategory'), hasAdvanced: or("hasCustomFields", "routeTo"),
basicTopicFields: or('createTopic', 'sendMessage', 'openComposer'), showAdvanced: and("hasAdvanced", "action.type"),
publicTopicFields: or('createTopic', 'openComposer'), hasCustomFields: or(
showPostAdvanced: or('createTopic', 'sendMessage'), "basicTopicFields",
actionTypes: Object.keys(wizardSchema.action.types).map(type => { "updateProfile",
"createGroup",
"createCategory"
),
basicTopicFields: or("createTopic", "sendMessage", "openComposer"),
publicTopicFields: or("createTopic", "openComposer"),
showPostAdvanced: or("createTopic", "sendMessage"),
actionTypes: Object.keys(wizardSchema.action.types).map((type) => {
return { return {
id: type, id: type,
name: I18n.t(`admin.wizard.action.${type}.label`) name: I18n.t(`admin.wizard.action.${type}.label`),
}; };
}), }),
availableNotificationLevels: notificationLevels.map((type, index) => { availableNotificationLevels: notificationLevels.map((type, index) => {
return { return {
id: type, id: type,
name: I18n.t(`admin.wizard.action.watch_categories.notification_level.${type}`) name: I18n.t(
`admin.wizard.action.watch_categories.notification_level.${type}`
),
}; };
}), }),
messageUrl: 'https://thepavilion.io/t/2810', messageUrl: "https://thepavilion.io/t/2810",
@discourseComputed('action.type') @discourseComputed("action.type")
messageKey(type) { messageKey(type) {
let key = 'type'; let key = "type";
if (type) { if (type) {
key = 'edit'; key = "edit";
} }
return key; return key;
}, },
@discourseComputed('wizard.steps') @discourseComputed("wizard.steps")
runAfterContent(steps) { runAfterContent(steps) {
let content = steps.map(function(step) { let content = steps.map(function (step) {
return { return {
id: step.id, id: step.id,
name: step.title || step.id name: step.title || step.id,
}; };
}); });
content.unshift({ content.unshift({
id: 'wizard_completion', id: "wizard_completion",
name: I18n.t('admin.wizard.action.run_after.wizard_completion') name: I18n.t("admin.wizard.action.run_after.wizard_completion"),
}); });
return content; return content;
}, },
@discourseComputed('apis') @discourseComputed("apis")
availableApis(apis) { availableApis(apis) {
return apis.map(a => { return apis.map((a) => {
return { return {
id: a.name, id: a.name,
name: a.title name: a.title,
}; };
}); });
}, },
@discourseComputed('apis', 'action.api') @discourseComputed("apis", "action.api")
availableEndpoints(apis, api) { availableEndpoints(apis, api) {
if (!api) return []; if (!api) return [];
return apis.find(a => a.name === api).endpoints; return apis.find((a) => a.name === api).endpoints;
} },
}); });

Datei anzeigen

@ -1,117 +1,119 @@
import { default as discourseComputed } from 'discourse-common/utils/decorators'; import { default as discourseComputed } from "discourse-common/utils/decorators";
import { equal, or, alias } from "@ember/object/computed"; import { equal, or, alias } from "@ember/object/computed";
import { computed } from "@ember/object"; import { computed } from "@ember/object";
import { selectKitContent } from '../lib/wizard'; import { selectKitContent } from "../lib/wizard";
import UndoChanges from '../mixins/undo-changes'; import UndoChanges from "../mixins/undo-changes";
import Component from "@ember/component"; import Component from "@ember/component";
import wizardSchema from '../lib/wizard-schema'; import wizardSchema from "../lib/wizard-schema";
export default Component.extend(UndoChanges, { export default Component.extend(UndoChanges, {
componentType: 'field', componentType: "field",
classNameBindings: [':wizard-custom-field', 'visible'], classNameBindings: [":wizard-custom-field", "visible"],
visible: computed('currentFieldId', function() { return this.field.id === this.currentFieldId }), visible: computed("currentFieldId", function () {
isDropdown: equal('field.type', 'dropdown'), return this.field.id === this.currentFieldId;
isUpload: equal('field.type', 'upload'), }),
isCategory: equal('field.type', 'category'), isDropdown: equal("field.type", "dropdown"),
isGroup: equal('field.type', 'group'), isUpload: equal("field.type", "upload"),
isTag: equal('field.type', 'tag'), isCategory: equal("field.type", "category"),
isText: equal('field.type', 'text'), isGroup: equal("field.type", "group"),
isTextarea: equal('field.type', 'textarea'), isTag: equal("field.type", "tag"),
isUrl: equal('field.type', 'url'), isText: equal("field.type", "text"),
isComposer: equal('field.type', 'composer'), isTextarea: equal("field.type", "textarea"),
showPrefill: or('isText', 'isCategory', 'isTag', 'isGroup', 'isDropdown'), isUrl: equal("field.type", "url"),
showContent: or('isCategory', 'isTag', 'isGroup', 'isDropdown'), isComposer: equal("field.type", "composer"),
showLimit: or('isCategory', 'isTag'), showPrefill: or("isText", "isCategory", "isTag", "isGroup", "isDropdown"),
isTextType: or('isText', 'isTextarea', 'isComposer'), showContent: or("isCategory", "isTag", "isGroup", "isDropdown"),
categoryPropertyTypes: selectKitContent(['id', 'slug']), showLimit: or("isCategory", "isTag"),
showAdvanced: alias('field.type'), isTextType: or("isText", "isTextarea", "isComposer"),
messageUrl: 'https://thepavilion.io/t/2809', categoryPropertyTypes: selectKitContent(["id", "slug"]),
showAdvanced: alias("field.type"),
@discourseComputed('field.type') messageUrl: "https://thepavilion.io/t/2809",
@discourseComputed("field.type")
validations(type) { validations(type) {
const applicableToField = []; const applicableToField = [];
for(let validation in wizardSchema.field.validations) { for (let validation in wizardSchema.field.validations) {
if ((wizardSchema.field.validations[validation]["types"]).includes(type)) { if (wizardSchema.field.validations[validation]["types"].includes(type)) {
applicableToField.push(validation) applicableToField.push(validation);
} }
} }
return applicableToField; return applicableToField;
}, },
@discourseComputed('field.type') @discourseComputed("field.type")
isDateTime(type) { isDateTime(type) {
return ['date_time', 'date', 'time'].indexOf(type) > -1; return ["date_time", "date", "time"].indexOf(type) > -1;
}, },
@discourseComputed('field.type') @discourseComputed("field.type")
messageKey(type) { messageKey(type) {
let key = 'type'; let key = "type";
if (type) { if (type) {
key = 'edit'; key = "edit";
} }
return key; return key;
}, },
setupTypeOutput(fieldType, options) { setupTypeOutput(fieldType, options) {
const selectionType = { const selectionType = {
category: 'category', category: "category",
tag: 'tag', tag: "tag",
group: 'group' group: "group",
}[fieldType]; }[fieldType];
if (selectionType) { if (selectionType) {
options[`${selectionType}Selection`] = 'output'; options[`${selectionType}Selection`] = "output";
options.outputDefaultSelection = selectionType; options.outputDefaultSelection = selectionType;
} }
return options; return options;
}, },
@discourseComputed('field.type') @discourseComputed("field.type")
contentOptions(fieldType) { contentOptions(fieldType) {
let options = { let options = {
wizardFieldSelection: true, wizardFieldSelection: true,
textSelection: 'key,value', textSelection: "key,value",
userFieldSelection: 'key,value', userFieldSelection: "key,value",
context: 'field' context: "field",
} };
options = this.setupTypeOutput(fieldType, options); options = this.setupTypeOutput(fieldType, options);
if (this.isDropdown) { if (this.isDropdown) {
options.wizardFieldSelection = 'key,value'; options.wizardFieldSelection = "key,value";
options.userFieldOptionsSelection = 'output'; options.userFieldOptionsSelection = "output";
options.textSelection = 'key,value,output'; options.textSelection = "key,value,output";
options.inputTypes = 'conditional,association,assignment'; options.inputTypes = "conditional,association,assignment";
options.pairConnector = 'association'; options.pairConnector = "association";
options.keyPlaceholder = 'admin.wizard.key'; options.keyPlaceholder = "admin.wizard.key";
options.valuePlaceholder = 'admin.wizard.value'; options.valuePlaceholder = "admin.wizard.value";
} }
return options; return options;
}, },
@discourseComputed('field.type') @discourseComputed("field.type")
prefillOptions(fieldType) { prefillOptions(fieldType) {
let options = { let options = {
wizardFieldSelection: true, wizardFieldSelection: true,
textSelection: true, textSelection: true,
userFieldSelection: 'key,value', userFieldSelection: "key,value",
context: 'field' context: "field",
} };
return this.setupTypeOutput(fieldType, options); return this.setupTypeOutput(fieldType, options);
}, },
actions: { actions: {
imageUploadDone(upload) { imageUploadDone(upload) {
this.set("field.image", upload.url); this.set("field.image", upload.url);
}, },
imageUploadDeleted() { imageUploadDeleted() {
this.set("field.image", null); this.set("field.image", null);
} },
} },
}); });

Datei anzeigen

@ -1,16 +1,16 @@
import Component from "@ember/component"; import Component from "@ember/component";
import { default as discourseComputed } from 'discourse-common/utils/decorators'; import { default as discourseComputed } from "discourse-common/utils/decorators";
export default Component.extend({ export default Component.extend({
classNames: 'wizard-custom-step', classNames: "wizard-custom-step",
actions: { actions: {
bannerUploadDone(upload) { bannerUploadDone(upload) {
this.set("step.banner", upload.url); this.set("step.banner", upload.url);
}, },
bannerUploadDeleted() { bannerUploadDeleted() {
this.set("step.banner", null); this.set("step.banner", null);
} },
} },
}); });

Datei anzeigen

@ -1,6 +1,13 @@
import { default as discourseComputed, on, observes } from 'discourse-common/utils/decorators'; import {
import { generateName } from '../lib/wizard'; default as discourseComputed,
import { default as wizardSchema, setWizardDefaults } from '../lib/wizard-schema'; on,
observes,
} from "discourse-common/utils/decorators";
import { generateName } from "../lib/wizard";
import {
default as wizardSchema,
setWizardDefaults,
} from "../lib/wizard-schema";
import { notEmpty } from "@ember/object/computed"; import { notEmpty } from "@ember/object/computed";
import { scheduleOnce, bind } from "@ember/runloop"; import { scheduleOnce, bind } from "@ember/runloop";
import EmberObject from "@ember/object"; import EmberObject from "@ember/object";
@ -8,56 +15,63 @@ import Component from "@ember/component";
import { A } from "@ember/array"; import { A } from "@ember/array";
export default Component.extend({ export default Component.extend({
classNameBindings: [':wizard-links', 'itemType'], classNameBindings: [":wizard-links", "itemType"],
items: A(), items: A(),
anyLinks: notEmpty('links'), anyLinks: notEmpty("links"),
@on('didInsertElement') @on("didInsertElement")
@observes('links.[]') @observes("links.[]")
setupSortable() { setupSortable() {
scheduleOnce('afterRender', () => (this.applySortable())); scheduleOnce("afterRender", () => this.applySortable());
}, },
applySortable() { applySortable() {
$(this.element).find(".link-list") $(this.element)
.sortable({ tolerance: 'pointer' }) .find(".link-list")
.on('sortupdate', (e, ui) => { .sortable({ tolerance: "pointer" })
this.updateItemOrder(ui.item.data('id'), ui.item.index()); .on("sortupdate", (e, ui) => {
this.updateItemOrder(ui.item.data("id"), ui.item.index());
}); });
}, },
updateItemOrder(itemId, newIndex) { updateItemOrder(itemId, newIndex) {
const items = this.items; const items = this.items;
const item = items.findBy('id', itemId); const item = items.findBy("id", itemId);
items.removeObject(item); items.removeObject(item);
items.insertAt(newIndex, item); items.insertAt(newIndex, item);
scheduleOnce('afterRender', this, () => this.applySortable()); scheduleOnce("afterRender", this, () => this.applySortable());
}, },
@discourseComputed('itemType') @discourseComputed("itemType")
header: (itemType) => `admin.wizard.${itemType}.header`, header: (itemType) => `admin.wizard.${itemType}.header`,
@discourseComputed('current', 'items.@each.id', 'items.@each.type', 'items.@each.label', 'items.@each.title') @discourseComputed(
"current",
"items.@each.id",
"items.@each.type",
"items.@each.label",
"items.@each.title"
)
links(current, items) { links(current, items) {
if (!items) return; if (!items) return;
return items.map((item) => { return items.map((item) => {
if (item) { if (item) {
let link = { let link = {
id: item.id id: item.id,
} };
let label = item.label || item.title || item.id; let label = item.label || item.title || item.id;
if (this.generateLabels && item.type) { if (this.generateLabels && item.type) {
label = generateName(item.type); label = generateName(item.type);
} }
link.label = `${label} (${item.id})`; link.label = `${label} (${item.id})`;
let classes = 'btn'; let classes = "btn";
if (current && item.id === current.id) { if (current && item.id === current.id) {
classes += ' btn-primary'; classes += " btn-primary";
}; }
link.classes = classes; link.classes = classes;
@ -68,69 +82,73 @@ export default Component.extend({
actions: { actions: {
add() { add() {
const items = this.get('items'); const items = this.get("items");
const itemType = this.itemType; const itemType = this.itemType;
let params = setWizardDefaults({}, itemType); let params = setWizardDefaults({}, itemType);
params.isNew = true; params.isNew = true;
let next = 1; let next = 1;
if (items.length) { if (items.length) {
next = Math.max.apply(Math, items.map((i) => { next =
let parts = i.id.split('_'); Math.max.apply(
let lastPart = parts[parts.length - 1]; Math,
return isNaN(lastPart) ? 0 : lastPart; items.map((i) => {
})) + 1; let parts = i.id.split("_");
let lastPart = parts[parts.length - 1];
return isNaN(lastPart) ? 0 : lastPart;
})
) + 1;
} }
let id = `${itemType}_${next}`; let id = `${itemType}_${next}`;
if (itemType === 'field') { if (itemType === "field") {
id = `${this.parentId}_${id}`; id = `${this.parentId}_${id}`;
} }
params.id = id; params.id = id;
let objectArrays = wizardSchema[itemType].objectArrays; let objectArrays = wizardSchema[itemType].objectArrays;
if (objectArrays) { if (objectArrays) {
Object.keys(objectArrays).forEach(objectType => { Object.keys(objectArrays).forEach((objectType) => {
params[objectArrays[objectType].property] = A(); params[objectArrays[objectType].property] = A();
}); });
}; }
const newItem = EmberObject.create(params); const newItem = EmberObject.create(params);
items.pushObject(newItem); items.pushObject(newItem);
this.set('current', newItem); this.set("current", newItem);
}, },
change(itemId) { change(itemId) {
this.set('current', this.items.findBy('id', itemId)); this.set("current", this.items.findBy("id", itemId));
}, },
remove(itemId) { remove(itemId) {
const items = this.items; const items = this.items;
let item; let item;
let index; let index;
items.forEach((it, ind) => { items.forEach((it, ind) => {
if (it.id === itemId) { if (it.id === itemId) {
item = it; item = it;
index = ind; index = ind;
} }
}); });
let nextIndex; let nextIndex;
if (this.current.id === itemId) { if (this.current.id === itemId) {
nextIndex = index < (items.length-2) ? (index+1) : (index-1); nextIndex = index < items.length - 2 ? index + 1 : index - 1;
} }
items.removeObject(item); items.removeObject(item);
if (nextIndex) { if (nextIndex) {
this.set('current', items[nextIndex]); this.set("current", items[nextIndex]);
} }
} },
} },
}); });

Datei anzeigen

@ -1,35 +1,39 @@
import Component from "@ember/component"; import Component from "@ember/component";
import { gt } from '@ember/object/computed'; import { gt } from "@ember/object/computed";
import { computed } from "@ember/object"; import { computed } from "@ember/object";
import { defaultConnector } from '../lib/wizard-mapper'; import { defaultConnector } from "../lib/wizard-mapper";
import { later } from "@ember/runloop"; import { later } from "@ember/runloop";
import { observes } from "discourse-common/utils/decorators"; import { observes } from "discourse-common/utils/decorators";
import I18n from "I18n"; import I18n from "I18n";
export default Component.extend({ export default Component.extend({
classNameBindings: [':mapper-connector', ':mapper-block', 'hasMultiple::single'], classNameBindings: [
hasMultiple: gt('connectors.length', 1), ":mapper-connector",
connectorLabel: computed(function() { ":mapper-block",
"hasMultiple::single",
],
hasMultiple: gt("connectors.length", 1),
connectorLabel: computed(function () {
let key = this.connector; let key = this.connector;
let path = this.inputTypes ? `input.${key}.name` : `connector.${key}`; let path = this.inputTypes ? `input.${key}.name` : `connector.${key}`;
return I18n.t(`admin.wizard.${path}`); return I18n.t(`admin.wizard.${path}`);
}), }),
didReceiveAttrs() { didReceiveAttrs() {
if (!this.connector) { if (!this.connector) {
later(() => { later(() => {
this.set( this.set(
'connector', "connector",
defaultConnector(this.connectorType, this.inputType, this.options) defaultConnector(this.connectorType, this.inputType, this.options)
); );
}); });
} }
}, },
actions: { actions: {
changeConnector(value) { changeConnector(value) {
this.set('connector', value); this.set("connector", value);
this.onUpdate('connector', this.connectorType); this.onUpdate("connector", this.connectorType);
} },
} },
}); });

Datei anzeigen

@ -1,69 +1,78 @@
import { computed, set } from "@ember/object"; import { computed, set } from "@ember/object";
import { alias, equal, or, not } from "@ember/object/computed"; import { alias, equal, or, not } from "@ember/object/computed";
import { newPair, connectorContent, inputTypesContent, defaultSelectionType, defaultConnector } from '../lib/wizard-mapper'; import {
newPair,
connectorContent,
inputTypesContent,
defaultSelectionType,
defaultConnector,
} from "../lib/wizard-mapper";
import Component from "@ember/component"; import Component from "@ember/component";
import { observes } from "discourse-common/utils/decorators"; import { observes } from "discourse-common/utils/decorators";
import { A } from "@ember/array"; import { A } from "@ember/array";
export default Component.extend({ export default Component.extend({
classNameBindings: [':mapper-input', 'inputType'], classNameBindings: [":mapper-input", "inputType"],
inputType: alias('input.type'), inputType: alias("input.type"),
isConditional: equal('inputType', 'conditional'), isConditional: equal("inputType", "conditional"),
isAssignment: equal('inputType', 'assignment'), isAssignment: equal("inputType", "assignment"),
isAssociation: equal('inputType', 'association'), isAssociation: equal("inputType", "association"),
isValidation: equal('inputType', 'validation'), isValidation: equal("inputType", "validation"),
hasOutput: or('isConditional', 'isAssignment'), hasOutput: or("isConditional", "isAssignment"),
hasPairs: or('isConditional', 'isAssociation', 'isValidation'), hasPairs: or("isConditional", "isAssociation", "isValidation"),
canAddPair: not('isAssignment'), canAddPair: not("isAssignment"),
connectors: computed(function() { return connectorContent('output', this.input.type, this.options) }), connectors: computed(function () {
inputTypes: computed(function() { return inputTypesContent(this.options) }), return connectorContent("output", this.input.type, this.options);
}),
@observes('input.type') inputTypes: computed(function () {
return inputTypesContent(this.options);
}),
@observes("input.type")
setupType() { setupType() {
if (this.hasPairs && (!this.input.pairs || this.input.pairs.length < 1)) { if (this.hasPairs && (!this.input.pairs || this.input.pairs.length < 1)) {
this.send('addPair'); this.send("addPair");
} }
if (this.hasOutput) { if (this.hasOutput) {
this.set('input.output', null); this.set("input.output", null);
if (!this.input.outputConnector) { if (!this.input.outputConnector) {
const options = this.options; const options = this.options;
this.set('input.output_type', defaultSelectionType('output', options)); this.set("input.output_type", defaultSelectionType("output", options));
this.set('input.output_connector', defaultConnector('output', this.inputType, options)); this.set(
"input.output_connector",
defaultConnector("output", this.inputType, options)
);
} }
} }
}, },
actions: { actions: {
addPair() { addPair() {
if (!this.input.pairs) { if (!this.input.pairs) {
this.set('input.pairs', A()); this.set("input.pairs", A());
} }
const pairs = this.input.pairs; const pairs = this.input.pairs;
const pairCount = pairs.length + 1; const pairCount = pairs.length + 1;
pairs.forEach(p => (set(p, 'pairCount', pairCount))); pairs.forEach((p) => set(p, "pairCount", pairCount));
pairs.pushObject( pairs.pushObject(
newPair( newPair(
this.input.type, this.input.type,
Object.assign( Object.assign({}, this.options, { index: pairs.length, pairCount })
{},
this.options,
{ index: pairs.length, pairCount }
)
) )
); );
}, },
removePair(pair) { removePair(pair) {
const pairs = this.input.pairs; const pairs = this.input.pairs;
const pairCount = pairs.length - 1; const pairCount = pairs.length - 1;
pairs.forEach(p => (set(p, 'pairCount', pairCount))); pairs.forEach((p) => set(p, "pairCount", pairCount));
pairs.removeObject(pair); pairs.removeObject(pair);
} },
} },
}); });

Datei anzeigen

@ -1,12 +1,16 @@
import { connectorContent } from '../lib/wizard-mapper'; import { connectorContent } from "../lib/wizard-mapper";
import { gt, or, alias } from "@ember/object/computed"; import { gt, or, alias } from "@ember/object/computed";
import { computed, observes } from "@ember/object"; import { computed, observes } from "@ember/object";
import Component from "@ember/component"; import Component from "@ember/component";
export default Component.extend({ export default Component.extend({
classNameBindings: [':mapper-pair', 'hasConnector::no-connector'], classNameBindings: [":mapper-pair", "hasConnector::no-connector"],
firstPair: gt('pair.index', 0), firstPair: gt("pair.index", 0),
showRemove: alias('firstPair'), showRemove: alias("firstPair"),
showJoin: computed('pair.pairCount', function() { return this.pair.index < (this.pair.pairCount - 1) }), showJoin: computed("pair.pairCount", function () {
connectors: computed(function() { return connectorContent('pair', this.inputType, this.options) }) return this.pair.index < this.pair.pairCount - 1;
}); }),
connectors: computed(function () {
return connectorContent("pair", this.inputType, this.options);
}),
});

Datei anzeigen

@ -1,14 +1,16 @@
import discourseComputed from 'discourse-common/utils/decorators'; import discourseComputed from "discourse-common/utils/decorators";
import Component from "@ember/component"; import Component from "@ember/component";
export default Component.extend({ export default Component.extend({
tagName: 'a', tagName: "a",
classNameBindings: ['active'], classNameBindings: ["active"],
@discourseComputed('item.type', 'activeType') @discourseComputed("item.type", "activeType")
active(type, activeType) { return type === activeType }, active(type, activeType) {
return type === activeType;
},
click() { click() {
this.toggle(this.item.type) this.toggle(this.item.type);
} },
}) });

Datei anzeigen

@ -1,51 +1,132 @@
import { alias, or, gt } from "@ember/object/computed"; import { alias, or, gt } from "@ember/object/computed";
import { computed } from "@ember/object"; import { computed } from "@ember/object";
import { default as discourseComputed, observes, on } from "discourse-common/utils/decorators"; import {
import { getOwner } from 'discourse-common/lib/get-owner'; default as discourseComputed,
import { defaultSelectionType, selectionTypes } from '../lib/wizard-mapper'; observes,
import { snakeCase, generateName, userProperties } from '../lib/wizard'; on,
} from "discourse-common/utils/decorators";
import { getOwner } from "discourse-common/lib/get-owner";
import { defaultSelectionType, selectionTypes } from "../lib/wizard-mapper";
import { snakeCase, generateName, userProperties } from "../lib/wizard";
import Component from "@ember/component"; import Component from "@ember/component";
import { bind, later } from "@ember/runloop"; import { bind, later } from "@ember/runloop";
import I18n from "I18n"; import I18n from "I18n";
export default Component.extend({ export default Component.extend({
classNameBindings: [':mapper-selector', 'activeType'], classNameBindings: [":mapper-selector", "activeType"],
showText: computed('activeType', function() { return this.showInput('text') }), showText: computed("activeType", function () {
showWizardField: computed('activeType', function() { return this.showInput('wizardField') }), return this.showInput("text");
showWizardAction: computed('activeType', function() { return this.showInput('wizardAction') }), }),
showUserField: computed('activeType', function() { return this.showInput('userField') }), showWizardField: computed("activeType", function () {
showUserFieldOptions: computed('activeType', function() { return this.showInput('userFieldOptions') }), return this.showInput("wizardField");
showCategory: computed('activeType', function() { return this.showInput('category') }), }),
showTag: computed('activeType', function() { return this.showInput('tag') }), showWizardAction: computed("activeType", function () {
showGroup: computed('activeType', function() { return this.showInput('group') }), return this.showInput("wizardAction");
showUser: computed('activeType', function() { return this.showInput('user') }), }),
showList: computed('activeType', function() { return this.showInput('list') }), showUserField: computed("activeType", function () {
showCustomField: computed('activeType', function() { return this.showInput('customField') }), return this.showInput("userField");
textEnabled: computed('options.textSelection', 'inputType', function() { return this.optionEnabled('textSelection') }), }),
wizardFieldEnabled: computed('options.wizardFieldSelection', 'inputType', function() { return this.optionEnabled('wizardFieldSelection') }), showUserFieldOptions: computed("activeType", function () {
wizardActionEnabled: computed('options.wizardActionSelection', 'inputType', function() { return this.optionEnabled('wizardActionSelection') }), return this.showInput("userFieldOptions");
customFieldEnabled: computed('options.customFieldSelection', 'inputType', function() { return this.optionEnabled('customFieldSelection') }), }),
userFieldEnabled: computed('options.userFieldSelection', 'inputType', function() { return this.optionEnabled('userFieldSelection') }), showCategory: computed("activeType", function () {
userFieldOptionsEnabled: computed('options.userFieldOptionsSelection', 'inputType', function() { return this.optionEnabled('userFieldOptionsSelection') }), return this.showInput("category");
categoryEnabled: computed('options.categorySelection', 'inputType', function() { return this.optionEnabled('categorySelection') }), }),
tagEnabled: computed('options.tagSelection', 'inputType', function() { return this.optionEnabled('tagSelection') }), showTag: computed("activeType", function () {
groupEnabled: computed('options.groupSelection', 'inputType', function() { return this.optionEnabled('groupSelection') }), return this.showInput("tag");
userEnabled: computed('options.userSelection', 'inputType', function() { return this.optionEnabled('userSelection') }), }),
listEnabled: computed('options.listSelection', 'inputType', function() { return this.optionEnabled('listSelection') }), showGroup: computed("activeType", function () {
return this.showInput("group");
groups: alias('site.groups'), }),
categories: alias('site.categories'), showUser: computed("activeType", function () {
showComboBox: or('showWizardField', 'showWizardAction', 'showUserField', 'showUserFieldOptions', 'showCustomField'), return this.showInput("user");
showMultiSelect: or('showCategory', 'showGroup'), }),
hasTypes: gt('selectorTypes.length', 1), showList: computed("activeType", function () {
return this.showInput("list");
}),
showCustomField: computed("activeType", function () {
return this.showInput("customField");
}),
textEnabled: computed("options.textSelection", "inputType", function () {
return this.optionEnabled("textSelection");
}),
wizardFieldEnabled: computed(
"options.wizardFieldSelection",
"inputType",
function () {
return this.optionEnabled("wizardFieldSelection");
}
),
wizardActionEnabled: computed(
"options.wizardActionSelection",
"inputType",
function () {
return this.optionEnabled("wizardActionSelection");
}
),
customFieldEnabled: computed(
"options.customFieldSelection",
"inputType",
function () {
return this.optionEnabled("customFieldSelection");
}
),
userFieldEnabled: computed(
"options.userFieldSelection",
"inputType",
function () {
return this.optionEnabled("userFieldSelection");
}
),
userFieldOptionsEnabled: computed(
"options.userFieldOptionsSelection",
"inputType",
function () {
return this.optionEnabled("userFieldOptionsSelection");
}
),
categoryEnabled: computed(
"options.categorySelection",
"inputType",
function () {
return this.optionEnabled("categorySelection");
}
),
tagEnabled: computed("options.tagSelection", "inputType", function () {
return this.optionEnabled("tagSelection");
}),
groupEnabled: computed("options.groupSelection", "inputType", function () {
return this.optionEnabled("groupSelection");
}),
userEnabled: computed("options.userSelection", "inputType", function () {
return this.optionEnabled("userSelection");
}),
listEnabled: computed("options.listSelection", "inputType", function () {
return this.optionEnabled("listSelection");
}),
groups: alias("site.groups"),
categories: alias("site.categories"),
showComboBox: or(
"showWizardField",
"showWizardAction",
"showUserField",
"showUserFieldOptions",
"showCustomField"
),
showMultiSelect: or("showCategory", "showGroup"),
hasTypes: gt("selectorTypes.length", 1),
showTypes: false, showTypes: false,
didInsertElement() { didInsertElement() {
if (!this.activeType || (this.activeType && !this[`${this.activeType}Enabled`])) { if (
!this.activeType ||
(this.activeType && !this[`${this.activeType}Enabled`])
) {
later(() => this.resetActiveType()); later(() => this.resetActiveType());
} }
$(document).on("click", bind(this, this.documentClick)); $(document).on("click", bind(this, this.documentClick));
}, },
@ -56,42 +137,45 @@ export default Component.extend({
documentClick(e) { documentClick(e) {
if (this._state == "destroying") return; if (this._state == "destroying") return;
let $target = $(e.target); let $target = $(e.target);
if (!$target.parents('.type-selector').length && this.showTypes) { if (!$target.parents(".type-selector").length && this.showTypes) {
this.set('showTypes', false); this.set("showTypes", false);
} }
}, },
@discourseComputed @discourseComputed
selectorTypes() { selectorTypes() {
return selectionTypes.filter(type => (this[`${type}Enabled`])) return selectionTypes
.map(type => ({ type, label: this.typeLabel(type) })); .filter((type) => this[`${type}Enabled`])
.map((type) => ({ type, label: this.typeLabel(type) }));
}, },
@discourseComputed('activeType') @discourseComputed("activeType")
activeTypeLabel(activeType) { activeTypeLabel(activeType) {
return this.typeLabel(activeType); return this.typeLabel(activeType);
}, },
typeLabel(type) { typeLabel(type) {
return type ? I18n.t(`admin.wizard.selector.label.${snakeCase(type)}`) : null; return type
? I18n.t(`admin.wizard.selector.label.${snakeCase(type)}`)
: null;
}, },
comboBoxAllowAny: or('showWizardField', 'showWizardAction'), comboBoxAllowAny: or("showWizardField", "showWizardAction"),
@discourseComputed @discourseComputed
showController() { showController() {
return getOwner(this).lookup('controller:admin-wizards-wizard-show'); return getOwner(this).lookup("controller:admin-wizards-wizard-show");
}, },
@discourseComputed( @discourseComputed(
'activeType', "activeType",
'showController.wizardFields.[]', "showController.wizardFields.[]",
'showController.wizard.actions.[]', "showController.wizard.actions.[]",
'showController.userFields.[]', "showController.userFields.[]",
'showController.currentField.id', "showController.currentField.id",
'showController.currentAction.id', "showController.currentAction.id",
'showController.customFields' "showController.customFields"
) )
comboBoxContent( comboBoxContent(
activeType, activeType,
@ -103,133 +187,144 @@ export default Component.extend({
customFields customFields
) { ) {
let content; let content;
if (activeType === 'wizardField') { if (activeType === "wizardField") {
content = wizardFields; content = wizardFields;
if (this.options.context === 'field') { if (this.options.context === "field") {
content = content.filter(field => field.id !== currentFieldId); content = content.filter((field) => field.id !== currentFieldId);
} }
} }
if (activeType === 'wizardAction') { if (activeType === "wizardAction") {
content = wizardActions.map(a => ({ content = wizardActions.map((a) => ({
id: a.id, id: a.id,
label: `${generateName(a.type)} (${a.id})`, label: `${generateName(a.type)} (${a.id})`,
type: a.type type: a.type,
})); }));
if (this.options.context === 'action') { if (this.options.context === "action") {
content = content.filter(a => a.id !== currentActionId); content = content.filter((a) => a.id !== currentActionId);
} }
} }
if (activeType === 'userField') { if (activeType === "userField") {
content = userProperties.map((f) => ({ content = userProperties
id: f, .map((f) => ({
name: generateName(f) id: f,
})).concat((userFields || [])); name: generateName(f),
}))
if (this.options.context === 'action' && .concat(userFields || []);
this.inputType === 'association' &&
this.selectorType === 'key') { if (
this.options.context === "action" &&
const excludedFields = ['username','email', 'trust_level']; this.inputType === "association" &&
content = content.filter(userField => excludedFields.indexOf(userField.id) === -1); this.selectorType === "key"
) {
const excludedFields = ["username", "email", "trust_level"];
content = content.filter(
(userField) => excludedFields.indexOf(userField.id) === -1
);
} }
} }
if (activeType === 'userFieldOptions') { if (activeType === "userFieldOptions") {
content = userFields; content = userFields;
} }
if (activeType === 'customField') { if (activeType === "customField") {
content = customFields; content = customFields;
} }
return content; return content;
}, },
@discourseComputed('activeType') @discourseComputed("activeType")
multiSelectContent(activeType) { multiSelectContent(activeType) {
return { return {
category: this.categories, category: this.categories,
group: this.groups, group: this.groups,
list: '' list: "",
}[activeType]; }[activeType];
}, },
@discourseComputed('activeType', 'inputType') @discourseComputed("activeType", "inputType")
placeholderKey(activeType, inputType) { placeholderKey(activeType, inputType) {
if (activeType === 'text' && this.options[`${this.selectorType}Placeholder`]) { if (
activeType === "text" &&
this.options[`${this.selectorType}Placeholder`]
) {
return this.options[`${this.selectorType}Placeholder`]; return this.options[`${this.selectorType}Placeholder`];
} else { } else {
return `admin.wizard.selector.placeholder.${snakeCase(activeType)}`; return `admin.wizard.selector.placeholder.${snakeCase(activeType)}`;
} }
}, },
@discourseComputed('activeType') @discourseComputed("activeType")
multiSelectOptions(activeType) { multiSelectOptions(activeType) {
let result = { let result = {
none: this.placeholderKey none: this.placeholderKey,
}; };
if (activeType === 'list') { if (activeType === "list") {
result.allowAny = true; result.allowAny = true;
} }
return result; return result;
}, },
optionEnabled(type) { optionEnabled(type) {
const options = this.options; const options = this.options;
if (!options) return false; if (!options) return false;
const option = options[type]; const option = options[type];
if (option === true) return true; if (option === true) return true;
if (typeof option !== 'string') return false; if (typeof option !== "string") return false;
return option.split(',').filter(option => { return option.split(",").filter((option) => {
return [this.selectorType, this.inputType].indexOf(option) !== -1; return [this.selectorType, this.inputType].indexOf(option) !== -1;
}).length; }).length;
}, },
showInput(type) { showInput(type) {
return this.activeType === type && this[`${type}Enabled`]; return this.activeType === type && this[`${type}Enabled`];
}, },
changeValue(value) { changeValue(value) {
this.set('value', value); this.set("value", value);
this.onUpdate('selector', this.activeType); this.onUpdate("selector", this.activeType);
}, },
@observes('inputType') @observes("inputType")
resetActiveType() { resetActiveType() {
this.set('activeType', defaultSelectionType(this.selectorType, this.options)); this.set(
"activeType",
defaultSelectionType(this.selectorType, this.options)
);
}, },
actions: { actions: {
toggleType(type) { toggleType(type) {
this.set('activeType', type); this.set("activeType", type);
this.set('showTypes', false); this.set("showTypes", false);
this.set('value', null); this.set("value", null);
this.onUpdate('selector'); this.onUpdate("selector");
}, },
toggleTypes() { toggleTypes() {
this.toggleProperty('showTypes'); this.toggleProperty("showTypes");
}, },
changeValue(value) { changeValue(value) {
this.changeValue(value); this.changeValue(value);
}, },
changeInputValue(event) { changeInputValue(event) {
this.changeValue(event.target.value); this.changeValue(event.target.value);
}, },
changeUserValue(previousValue, value) { changeUserValue(previousValue, value) {
this.changeValue(value); this.changeValue(value);
} },
} },
}) });

Datei anzeigen

@ -1,84 +1,90 @@
import { getOwner } from 'discourse-common/lib/get-owner'; import { getOwner } from "discourse-common/lib/get-owner";
import { newInput, selectionTypes } from '../lib/wizard-mapper'; import { newInput, selectionTypes } from "../lib/wizard-mapper";
import { default as discourseComputed, observes, on } from 'discourse-common/utils/decorators'; import {
default as discourseComputed,
observes,
on,
} from "discourse-common/utils/decorators";
import { later } from "@ember/runloop"; import { later } from "@ember/runloop";
import Component from "@ember/component"; import Component from "@ember/component";
import { A } from "@ember/array"; import { A } from "@ember/array";
export default Component.extend({ export default Component.extend({
classNames: 'wizard-mapper', classNames: "wizard-mapper",
didReceiveAttrs() { didReceiveAttrs() {
if (this.inputs && this.inputs.constructor !== Array) { if (this.inputs && this.inputs.constructor !== Array) {
later(() => this.set('inputs', null)); later(() => this.set("inputs", null));
} }
}, },
@discourseComputed('inputs.@each.type') @discourseComputed("inputs.@each.type")
canAdd(inputs) { canAdd(inputs) {
return !inputs || return (
inputs.constructor !== Array || !inputs ||
inputs.every(i => { inputs.constructor !== Array ||
return ['assignment','association'].indexOf(i.type) === -1; inputs.every((i) => {
}); return ["assignment", "association"].indexOf(i.type) === -1;
})
);
}, },
@discourseComputed('options.@each.inputType') @discourseComputed("options.@each.inputType")
inputOptions(options) { inputOptions(options) {
let result = { let result = {
inputTypes: options.inputTypes || 'assignment,conditional', inputTypes: options.inputTypes || "assignment,conditional",
inputConnector: options.inputConnector || 'or', inputConnector: options.inputConnector || "or",
pairConnector: options.pairConnector || null, pairConnector: options.pairConnector || null,
outputConnector: options.outputConnector || null, outputConnector: options.outputConnector || null,
context: options.context || null context: options.context || null,
} };
let inputTypes = ['key', 'value', 'output']; let inputTypes = ["key", "value", "output"];
inputTypes.forEach(type => { inputTypes.forEach((type) => {
result[`${type}Placeholder`] = options[`${type}Placeholder`] || null; result[`${type}Placeholder`] = options[`${type}Placeholder`] || null;
result[`${type}DefaultSelection`] = options[`${type}DefaultSelection`] || null; result[`${type}DefaultSelection`] =
options[`${type}DefaultSelection`] || null;
}); });
selectionTypes.forEach(type => { selectionTypes.forEach((type) => {
if (options[`${type}Selection`] !== undefined) { if (options[`${type}Selection`] !== undefined) {
result[`${type}Selection`] = options[`${type}Selection`] result[`${type}Selection`] = options[`${type}Selection`];
} else { } else {
result[`${type}Selection`] = type === 'text' ? true : false; result[`${type}Selection`] = type === "text" ? true : false;
} }
}); });
return result; return result;
}, },
onUpdate() { onUpdate() {},
},
actions: { actions: {
add() { add() {
if (!this.get('inputs')) { if (!this.get("inputs")) {
this.set('inputs', A()); this.set("inputs", A());
} }
this.get('inputs').pushObject( this.get("inputs").pushObject(
newInput(this.inputOptions, this.inputs.length) newInput(this.inputOptions, this.inputs.length)
); );
this.onUpdate(this.property, 'input'); this.onUpdate(this.property, "input");
}, },
remove(input) { remove(input) {
const inputs = this.inputs; const inputs = this.inputs;
inputs.removeObject(input); inputs.removeObject(input);
if (inputs.length) { if (inputs.length) {
inputs[0].set('connector', null); inputs[0].set("connector", null);
} }
this.onUpdate(this.property, 'input'); this.onUpdate(this.property, "input");
}, },
inputUpdated(component, type) { inputUpdated(component, type) {
this.onUpdate(this.property, component, type); this.onUpdate(this.property, component, type);
} },
} },
}); });

Datei anzeigen

@ -1,32 +1,32 @@
import { default as discourseComputed } from 'discourse-common/utils/decorators'; import { default as discourseComputed } from "discourse-common/utils/decorators";
import { not, notEmpty } from "@ember/object/computed"; import { not, notEmpty } from "@ember/object/computed";
import Component from "@ember/component"; import Component from "@ember/component";
import I18n from "I18n"; import I18n from "I18n";
const icons = { const icons = {
error: 'times-circle', error: "times-circle",
success: 'check-circle', success: "check-circle",
info: 'info-circle' info: "info-circle",
} };
export default Component.extend({ export default Component.extend({
classNameBindings: [':wizard-message', 'type', 'loading'], classNameBindings: [":wizard-message", "type", "loading"],
showDocumentation: not('loading'), showDocumentation: not("loading"),
showIcon: not('loading'), showIcon: not("loading"),
hasItems: notEmpty('items'), hasItems: notEmpty("items"),
@discourseComputed('type') @discourseComputed("type")
icon(type) { icon(type) {
return icons[type] || 'info-circle'; return icons[type] || "info-circle";
}, },
@discourseComputed('key', 'component', 'opts') @discourseComputed("key", "component", "opts")
message(key, component, opts) { message(key, component, opts) {
return I18n.t(`admin.wizard.message.${component}.${key}`, opts || {}); return I18n.t(`admin.wizard.message.${component}.${key}`, opts || {});
}, },
@discourseComputed('component') @discourseComputed("component")
documentation(component) { documentation(component) {
return I18n.t(`admin.wizard.message.${component}.documentation`); return I18n.t(`admin.wizard.message.${component}.documentation`);
} },
}) });

Datei anzeigen

@ -12,7 +12,7 @@ export default Component.extend({
if (!this.field.validations) { if (!this.field.validations) {
const validations = {}; const validations = {};
this.validations.forEach((validation) => { this.validations.forEach((validation) => {
validations[validation] = {}; validations[validation] = {};
}); });

Datei anzeigen

@ -1,64 +1,67 @@
import { default as discourseComputed, on } from 'discourse-common/utils/decorators'; import {
default as discourseComputed,
on,
} from "discourse-common/utils/decorators";
import { notEmpty } from "@ember/object/computed"; import { notEmpty } from "@ember/object/computed";
import { userProperties } from '../lib/wizard'; import { userProperties } from "../lib/wizard";
import { scheduleOnce } from "@ember/runloop"; import { scheduleOnce } from "@ember/runloop";
import Component from "@ember/component"; import Component from "@ember/component";
import I18n from "I18n"; import I18n from "I18n";
export default Component.extend({ export default Component.extend({
classNames: 'wizard-text-editor', classNames: "wizard-text-editor",
barEnabled: true, barEnabled: true,
previewEnabled: true, previewEnabled: true,
fieldsEnabled: true, fieldsEnabled: true,
hasWizardFields: notEmpty('wizardFieldList'), hasWizardFields: notEmpty("wizardFieldList"),
hasWizardActions: notEmpty('wizardActionList'), hasWizardActions: notEmpty("wizardActionList"),
didReceiveAttrs() { didReceiveAttrs() {
this._super(...arguments); this._super(...arguments);
if (!this.barEnabled) { if (!this.barEnabled) {
scheduleOnce('afterRender', () => { scheduleOnce("afterRender", () => {
$(this.element).find('.d-editor-button-bar').addClass('hidden'); $(this.element).find(".d-editor-button-bar").addClass("hidden");
}); });
} }
}, },
@discourseComputed('forcePreview') @discourseComputed("forcePreview")
previewLabel(forcePreview) { previewLabel(forcePreview) {
return I18n.t("admin.wizard.editor.preview", { return I18n.t("admin.wizard.editor.preview", {
action: I18n.t(`admin.wizard.editor.${forcePreview ? 'hide' : 'show'}`) action: I18n.t(`admin.wizard.editor.${forcePreview ? "hide" : "show"}`),
}); });
}, },
@discourseComputed('showPopover') @discourseComputed("showPopover")
popoverLabel(showPopover) { popoverLabel(showPopover) {
return I18n.t("admin.wizard.editor.popover", { return I18n.t("admin.wizard.editor.popover", {
action: I18n.t(`admin.wizard.editor.${showPopover ? 'hide' : 'show'}`) action: I18n.t(`admin.wizard.editor.${showPopover ? "hide" : "show"}`),
}); });
}, },
@discourseComputed() @discourseComputed()
userPropertyList() { userPropertyList() {
return userProperties.map((f) => ` u{${f}}`); return userProperties.map((f) => ` u{${f}}`);
}, },
@discourseComputed('wizardFields') @discourseComputed("wizardFields")
wizardFieldList(wizardFields) { wizardFieldList(wizardFields) {
return wizardFields.map((f) => ` w{${f.id}}`); return wizardFields.map((f) => ` w{${f.id}}`);
}, },
@discourseComputed('wizardActions') @discourseComputed("wizardActions")
wizardActionList(wizardActions) { wizardActionList(wizardActions) {
return wizardActions.map((a) => ` w{${a.id}}`); return wizardActions.map((a) => ` w{${a.id}}`);
}, },
actions: { actions: {
togglePreview() { togglePreview() {
this.toggleProperty('forcePreview'); this.toggleProperty("forcePreview");
}, },
togglePopover() { togglePopover() {
this.toggleProperty('showPopover'); this.toggleProperty("showPopover");
} },
} },
}); });

Datei anzeigen

@ -1,4 +1,4 @@
import ValueList from 'admin/components/value-list'; import ValueList from "admin/components/value-list";
export default ValueList.extend({ export default ValueList.extend({
_saveValues() { _saveValues() {
@ -8,5 +8,5 @@ export default ValueList.extend({
} }
this.onChange(this.collection.join(this.inputDelimiter || "\n")); this.onChange(this.collection.join(this.inputDelimiter || "\n"));
} },
}) });

Datei anzeigen

@ -1,6 +1,7 @@
export default { export default {
shouldRender(_, ctx) { shouldRender(_, ctx) {
return ctx.siteSettings.custom_wizard_enabled && return (
ctx.site.complete_custom_wizard; ctx.siteSettings.custom_wizard_enabled && ctx.site.complete_custom_wizard
} );
} },
};

Datei anzeigen

@ -1,93 +1,139 @@
import { ajax } from 'discourse/lib/ajax'; import { ajax } from "discourse/lib/ajax";
import { popupAjaxError } from 'discourse/lib/ajax-error'; import { popupAjaxError } from "discourse/lib/ajax-error";
import CustomWizardApi from '../models/custom-wizard-api'; import CustomWizardApi from "../models/custom-wizard-api";
import { default as discourseComputed } from 'discourse-common/utils/decorators'; import { default as discourseComputed } from "discourse-common/utils/decorators";
import { not, and, equal } from "@ember/object/computed"; import { not, and, equal } from "@ember/object/computed";
import { selectKitContent } from '../lib/wizard'; import { selectKitContent } from "../lib/wizard";
import Controller from "@ember/controller"; import Controller from "@ember/controller";
import I18n from "I18n"; import I18n from "I18n";
export default Controller.extend({ export default Controller.extend({
queryParams: ['refresh_list'], queryParams: ["refresh_list"],
loadingSubscriptions: false, loadingSubscriptions: false,
notAuthorized: not('api.authorized'), notAuthorized: not("api.authorized"),
endpointMethods: selectKitContent(['GET', 'PUT', 'POST', 'PATCH', 'DELETE']), endpointMethods: selectKitContent(["GET", "PUT", "POST", "PATCH", "DELETE"]),
showRemove: not('isNew'), showRemove: not("isNew"),
showRedirectUri: and('threeLeggedOauth', 'api.name'), showRedirectUri: and("threeLeggedOauth", "api.name"),
responseIcon: null, responseIcon: null,
contentTypes: selectKitContent(['application/json', 'application/x-www-form-urlencoded']), contentTypes: selectKitContent([
successCodes: selectKitContent([100, 101, 102, 200, 201, 202, 203, 204, 205, 206, 207, 208, 226, 300, 301, 302, 303, 303, 304, 305, 306, 307, 308]), "application/json",
"application/x-www-form-urlencoded",
]),
successCodes: selectKitContent([
100,
101,
102,
200,
201,
202,
203,
204,
205,
206,
207,
208,
226,
300,
301,
302,
303,
303,
304,
305,
306,
307,
308,
]),
@discourseComputed('saveDisabled', 'api.authType', 'api.authUrl', 'api.tokenUrl', 'api.clientId', 'api.clientSecret', 'threeLeggedOauth') @discourseComputed(
authDisabled(saveDisabled, authType, authUrl, tokenUrl, clientId, clientSecret, threeLeggedOauth) { "saveDisabled",
if (saveDisabled || !authType || !tokenUrl || !clientId || !clientSecret) return true; "api.authType",
"api.authUrl",
"api.tokenUrl",
"api.clientId",
"api.clientSecret",
"threeLeggedOauth"
)
authDisabled(
saveDisabled,
authType,
authUrl,
tokenUrl,
clientId,
clientSecret,
threeLeggedOauth
) {
if (saveDisabled || !authType || !tokenUrl || !clientId || !clientSecret)
return true;
if (threeLeggedOauth) return !authUrl; if (threeLeggedOauth) return !authUrl;
return false; return false;
}, },
@discourseComputed('api.name', 'api.authType') @discourseComputed("api.name", "api.authType")
saveDisabled(name, authType) { saveDisabled(name, authType) {
return !name || !authType; return !name || !authType;
}, },
authorizationTypes: selectKitContent(['none', 'basic', 'oauth_2', 'oauth_3']), authorizationTypes: selectKitContent(["none", "basic", "oauth_2", "oauth_3"]),
isBasicAuth: equal('api.authType', 'basic'), isBasicAuth: equal("api.authType", "basic"),
@discourseComputed('api.authType') @discourseComputed("api.authType")
isOauth(authType) { isOauth(authType) {
return authType && authType.indexOf('oauth') > -1; return authType && authType.indexOf("oauth") > -1;
}, },
twoLeggedOauth: equal('api.authType', 'oauth_2'), twoLeggedOauth: equal("api.authType", "oauth_2"),
threeLeggedOauth: equal('api.authType', 'oauth_3'), threeLeggedOauth: equal("api.authType", "oauth_3"),
actions: { actions: {
addParam() { addParam() {
this.get('api.authParams').pushObject({}); this.get("api.authParams").pushObject({});
}, },
removeParam(param) { removeParam(param) {
this.get('api.authParams').removeObject(param); this.get("api.authParams").removeObject(param);
}, },
addEndpoint() { addEndpoint() {
this.get('api.endpoints').pushObject({}); this.get("api.endpoints").pushObject({});
}, },
removeEndpoint(endpoint) { removeEndpoint(endpoint) {
this.get('api.endpoints').removeObject(endpoint); this.get("api.endpoints").removeObject(endpoint);
}, },
authorize() { authorize() {
const api = this.get('api'); const api = this.get("api");
const { name, authType, authUrl, authParams } = api; const { name, authType, authUrl, authParams } = api;
this.set('authErrorMessage', ''); this.set("authErrorMessage", "");
if (authType === 'oauth_2') { if (authType === "oauth_2") {
this.set('authorizing', true); this.set("authorizing", true);
ajax(`/admin/wizards/apis/${name.underscore()}/authorize`).catch(popupAjaxError) ajax(`/admin/wizards/apis/${name.underscore()}/authorize`)
.then(result => { .catch(popupAjaxError)
.then((result) => {
if (result.success) { if (result.success) {
this.set('api', CustomWizardApi.create(result.api)); this.set("api", CustomWizardApi.create(result.api));
} else if (result.failed && result.message) { } else if (result.failed && result.message) {
this.set('authErrorMessage', result.message); this.set("authErrorMessage", result.message);
} else { } else {
this.set('authErrorMessage', 'Authorization Failed'); this.set("authErrorMessage", "Authorization Failed");
} }
setTimeout(() => { setTimeout(() => {
this.set('authErrorMessage', ''); this.set("authErrorMessage", "");
}, 6000); }, 6000);
}).finally(() => this.set('authorizing', false)); })
} else if (authType === 'oauth_3') { .finally(() => this.set("authorizing", false));
let query = '?'; } else if (authType === "oauth_3") {
let query = "?";
query += `client_id=${api.clientId}`; query += `client_id=${api.clientId}`;
query += `&redirect_uri=${encodeURIComponent(api.redirectUri)}`; query += `&redirect_uri=${encodeURIComponent(api.redirectUri)}`;
query += `&response_type=code`; query += `&response_type=code`;
if (authParams) { if (authParams) {
authParams.forEach(p => { authParams.forEach((p) => {
query += `&${p.key}=${encodeURIComponent(p.value)}`; query += `&${p.key}=${encodeURIComponent(p.value)}`;
}); });
} }
@ -97,7 +143,7 @@ export default Controller.extend({
}, },
save() { save() {
const api = this.get('api'); const api = this.get("api");
const name = api.name; const name = api.name;
const authType = api.authType; const authType = api.authType;
let refreshList = false; let refreshList = false;
@ -106,35 +152,37 @@ export default Controller.extend({
if (!name || !authType) return; if (!name || !authType) return;
let data = { let data = {
auth_type: authType auth_type: authType,
}; };
if (api.title) data['title'] = api.title; if (api.title) data["title"] = api.title;
const originalTitle = this.get('api.originalTitle'); const originalTitle = this.get("api.originalTitle");
if (api.get('isNew') || (originalTitle && (api.title !== originalTitle))) { if (api.get("isNew") || (originalTitle && api.title !== originalTitle)) {
refreshList = true; refreshList = true;
} }
if (api.get('isNew')) { if (api.get("isNew")) {
data['new'] = true; data["new"] = true;
}; }
let requiredParams; let requiredParams;
if (authType === 'basic') { if (authType === "basic") {
requiredParams = ['username', 'password']; requiredParams = ["username", "password"];
} else if (authType === 'oauth_2') { } else if (authType === "oauth_2") {
requiredParams = ['tokenUrl', 'clientId', 'clientSecret']; requiredParams = ["tokenUrl", "clientId", "clientSecret"];
} else if (authType === 'oauth_3') { } else if (authType === "oauth_3") {
requiredParams = ['authUrl', 'tokenUrl', 'clientId', 'clientSecret']; requiredParams = ["authUrl", "tokenUrl", "clientId", "clientSecret"];
} }
if (requiredParams) { if (requiredParams) {
for (let rp of requiredParams) { for (let rp of requiredParams) {
if (!api[rp]) { if (!api[rp]) {
let key = rp.replace('auth', ''); let key = rp.replace("auth", "");
error = `${I18n.t(`admin.wizard.api.auth.${key.underscore()}`)} is required for ${authType}`; error = `${I18n.t(
`admin.wizard.api.auth.${key.underscore()}`
)} is required for ${authType}`;
break; break;
} }
data[rp.underscore()] = api[rp]; data[rp.underscore()] = api[rp];
@ -143,73 +191,79 @@ export default Controller.extend({
const params = api.authParams; const params = api.authParams;
if (params.length) { if (params.length) {
data['auth_params'] = JSON.stringify(params); data["auth_params"] = JSON.stringify(params);
} }
const endpoints = api.endpoints; const endpoints = api.endpoints;
if (endpoints.length) { if (endpoints.length) {
for (let e of endpoints) { for (let e of endpoints) {
if (!e.name) { if (!e.name) {
error = 'Every endpoint must have a name'; error = "Every endpoint must have a name";
break; break;
} }
} }
data['endpoints'] = JSON.stringify(endpoints); data["endpoints"] = JSON.stringify(endpoints);
} }
if (error) { if (error) {
this.set('error', error); this.set("error", error);
setTimeout(() => { setTimeout(() => {
this.set('error', ''); this.set("error", "");
}, 6000); }, 6000);
return; return;
} }
this.set('updating', true); this.set("updating", true);
ajax(`/admin/wizards/api/${name.underscore()}`, { ajax(`/admin/wizards/api/${name.underscore()}`, {
type: 'PUT', type: "PUT",
data data,
}).catch(popupAjaxError) })
.then(result => { .catch(popupAjaxError)
.then((result) => {
if (result.success) { if (result.success) {
this.send('afterSave', result.api.name); this.send("afterSave", result.api.name);
} else { } else {
this.set('responseIcon', 'times'); this.set("responseIcon", "times");
} }
}).finally(() => this.set('updating', false)); })
.finally(() => this.set("updating", false));
}, },
remove() { remove() {
const name = this.get('api.name'); const name = this.get("api.name");
if (!name) return; if (!name) return;
this.set('updating', true); this.set("updating", true);
ajax(`/admin/wizards/api/${name.underscore()}`, { ajax(`/admin/wizards/api/${name.underscore()}`, {
type: 'DELETE' type: "DELETE",
}).catch(popupAjaxError) })
.then(result => { .catch(popupAjaxError)
.then((result) => {
if (result.success) { if (result.success) {
this.send('afterDestroy'); this.send("afterDestroy");
} }
}).finally(() => this.set('updating', false)); })
.finally(() => this.set("updating", false));
}, },
clearLogs() { clearLogs() {
const name = this.get('api.name'); const name = this.get("api.name");
if (!name) return; if (!name) return;
ajax(`/admin/wizards/api/${name.underscore()}/logs`, { ajax(`/admin/wizards/api/${name.underscore()}/logs`, {
type: 'DELETE' type: "DELETE",
}).catch(popupAjaxError) })
.then(result => { .catch(popupAjaxError)
.then((result) => {
if (result.success) { if (result.success) {
this.transitionToRoute('adminWizardsApis').then(() => { this.transitionToRoute("adminWizardsApis").then(() => {
this.send('refreshModel'); this.send("refreshModel");
}); });
} }
}).finally(() => this.set('updating', false)); })
} .finally(() => this.set("updating", false));
} },
},
}); });

Datei anzeigen

@ -1,55 +1,57 @@
import Controller from "@ember/controller"; import Controller from "@ember/controller";
import EmberObject from '@ember/object'; import EmberObject from "@ember/object";
import { ajax } from 'discourse/lib/ajax'; import { ajax } from "discourse/lib/ajax";
import { popupAjaxError } from 'discourse/lib/ajax-error'; import { popupAjaxError } from "discourse/lib/ajax-error";
import CustomWizardCustomField from "../models/custom-wizard-custom-field"; import CustomWizardCustomField from "../models/custom-wizard-custom-field";
import { default as discourseComputed } from 'discourse-common/utils/decorators'; import { default as discourseComputed } from "discourse-common/utils/decorators";
export default Controller.extend({ export default Controller.extend({
messageKey: 'create', messageKey: "create",
fieldKeys: ['klass', 'type', 'serializers', 'name'], fieldKeys: ["klass", "type", "serializers", "name"],
documentationUrl: "https://thepavilion.io/t/3572", documentationUrl: "https://thepavilion.io/t/3572",
actions: { actions: {
addField() { addField() {
this.get('customFields').pushObject( this.get("customFields").pushObject(
CustomWizardCustomField.create({ edit: true }) CustomWizardCustomField.create({ edit: true })
); );
}, },
saveField(field) { saveField(field) {
return CustomWizardCustomField.saveField(field) return CustomWizardCustomField.saveField(field).then((result) => {
.then(result => { if (result.success) {
if (result.success) { this.setProperties({
messageKey: "saved",
messageType: "success",
});
} else {
if (result.messages) {
this.setProperties({ this.setProperties({
messageKey: 'saved', messageKey: "error",
messageType: 'success' messageType: "error",
messageOpts: { messages: result.messages },
}); });
} else {
if (result.messages) {
this.setProperties({
messageKey: 'error',
messageType: 'error',
messageOpts: { messages: result.messages }
})
}
} }
}
setTimeout(() => this.setProperties({
messageKey: 'create', setTimeout(
messageType: null, () =>
messageOpts: null this.setProperties({
}), 10000); messageKey: "create",
messageType: null,
return result; messageOpts: null,
}); }),
10000
);
return result;
});
}, },
removeField(field) { removeField(field) {
return CustomWizardCustomField.destroyField(field) return CustomWizardCustomField.destroyField(field).then((result) => {
.then(result => { this.get("customFields").removeObject(field);
this.get('customFields').removeObject(field); });
}); },
} },
} });
});

Datei anzeigen

@ -1,8 +1,8 @@
import { default as computed } from 'discourse-common/utils/decorators'; import { default as computed } from "discourse-common/utils/decorators";
import { popupAjaxError } from 'discourse/lib/ajax-error'; import { popupAjaxError } from "discourse/lib/ajax-error";
import { ajax } from 'discourse/lib/ajax'; import { ajax } from "discourse/lib/ajax";
import { notEmpty } from "@ember/object/computed"; import { notEmpty } from "@ember/object/computed";
import CustomWizardLogs from '../models/custom-wizard-logs'; import CustomWizardLogs from "../models/custom-wizard-logs";
import Controller from "@ember/controller"; import Controller from "@ember/controller";
export default Controller.extend({ export default Controller.extend({
@ -11,40 +11,40 @@ export default Controller.extend({
page: 0, page: 0,
canLoadMore: true, canLoadMore: true,
logs: [], logs: [],
loadLogs() { loadLogs() {
if (!this.canLoadMore) return; if (!this.canLoadMore) return;
this.set("refreshing", true); this.set("refreshing", true);
CustomWizardLogs.list() CustomWizardLogs.list()
.then(result => { .then((result) => {
if (!result || result.length === 0) { if (!result || result.length === 0) {
this.set('canLoadMore', false); this.set("canLoadMore", false);
} }
this.set("logs", this.logs.concat(result)); this.set("logs", this.logs.concat(result));
}) })
.finally(() => this.set("refreshing", false)); .finally(() => this.set("refreshing", false));
}, },
@computed('hasLogs', 'refreshing') @computed("hasLogs", "refreshing")
noResults(hasLogs, refreshing) { noResults(hasLogs, refreshing) {
return !hasLogs && !refreshing; return !hasLogs && !refreshing;
}, },
actions: { actions: {
loadMore() { loadMore() {
this.set('page', this.page += 1); this.set("page", (this.page += 1));
this.loadLogs(); this.loadLogs();
}, },
refresh() { refresh() {
this.setProperties({ this.setProperties({
canLoadMore: true, canLoadMore: true,
page: 0, page: 0,
logs: [] logs: [],
}) });
this.loadLogs(); this.loadLogs();
} },
} },
}); });

Datei anzeigen

@ -1,76 +1,80 @@
import Controller from "@ember/controller"; import Controller from "@ember/controller";
import { import {
default as discourseComputed, default as discourseComputed,
observes observes,
} from 'discourse-common/utils/decorators'; } from "discourse-common/utils/decorators";
import { empty } from "@ember/object/computed"; import { empty } from "@ember/object/computed";
import CustomWizardManager from '../models/custom-wizard-manager'; import CustomWizardManager from "../models/custom-wizard-manager";
import { A } from "@ember/array"; import { A } from "@ember/array";
import I18n from "I18n"; import I18n from "I18n";
import { underscore } from "@ember/string"; import { underscore } from "@ember/string";
export default Controller.extend({ export default Controller.extend({
messageUrl: 'https://thepavilion.io/t/3652', messageUrl: "https://thepavilion.io/t/3652",
messageKey: 'info', messageKey: "info",
messageIcon: 'info-circle', messageIcon: "info-circle",
messageClass: 'info', messageClass: "info",
importDisabled: empty('file'), importDisabled: empty("file"),
exportWizards: A(), exportWizards: A(),
destroyWizards: A(), destroyWizards: A(),
exportDisabled: empty('exportWizards'), exportDisabled: empty("exportWizards"),
destoryDisabled: empty('destroyWizards'), destoryDisabled: empty("destroyWizards"),
setMessage(type, key, opts={}, items=[]) { setMessage(type, key, opts = {}, items = []) {
this.setProperties({ this.setProperties({
messageKey: key, messageKey: key,
messageOpts: opts, messageOpts: opts,
messageType: type, messageType: type,
messageItems: items messageItems: items,
}); });
setTimeout(() => { setTimeout(() => {
this.setProperties({ this.setProperties({
messageKey: 'info', messageKey: "info",
messageOpts: null, messageOpts: null,
messageType: null, messageType: null,
messageItems: null messageItems: null,
}) });
}, 10000); }, 10000);
}, },
buildWizardLink(wizard) { buildWizardLink(wizard) {
let html = `<a href='/admin/wizards/wizard/${wizard.id}'>${wizard.name}</a>`; let html = `<a href='/admin/wizards/wizard/${wizard.id}'>${wizard.name}</a>`;
html += `<span class='action'>${I18n.t('admin.wizard.manager.imported')}</span>`; html += `<span class='action'>${I18n.t(
"admin.wizard.manager.imported"
)}</span>`;
return { return {
icon: 'check-circle', icon: "check-circle",
html html,
}; };
}, },
buildDestroyedItem(destroyed) { buildDestroyedItem(destroyed) {
let html = `<span data-wizard-id="${destroyed.id}">${destroyed.name}</span>`; let html = `<span data-wizard-id="${destroyed.id}">${destroyed.name}</span>`;
html += `<span class='action'>${I18n.t('admin.wizard.manager.destroyed')}</span>`; html += `<span class='action'>${I18n.t(
"admin.wizard.manager.destroyed"
)}</span>`;
return { return {
icon: 'check-circle', icon: "check-circle",
html html,
}; };
}, },
buildFailureItem(failure) { buildFailureItem(failure) {
return { return {
icon: 'times-circle', icon: "times-circle",
html: `${failure.id}: ${failure.messages}` html: `${failure.id}: ${failure.messages}`,
}; };
}, },
clearFile() { clearFile() {
this.setProperties({ this.setProperties({
file: null, file: null,
filename: null filename: null,
}); });
$('#file-upload').val(''); $("#file-upload").val("");
}, },
@observes('importing', 'destroying') @observes("importing", "destroying")
setLoadingMessages() { setLoadingMessages() {
if (this.importing) { if (this.importing) {
this.setMessage("loading", "importing"); this.setMessage("loading", "importing");
@ -82,47 +86,49 @@ export default Controller.extend({
actions: { actions: {
upload() { upload() {
$('#file-upload').click(); $("#file-upload").click();
}, },
clearFile() { clearFile() {
this.clearFile(); this.clearFile();
}, },
setFile(event) { setFile(event) {
let maxFileSize = 512 * 1024; let maxFileSize = 512 * 1024;
const file = event.target.files[0]; const file = event.target.files[0];
if (file === undefined) { if (file === undefined) {
this.set('file', null); this.set("file", null);
return; return;
} }
if (maxFileSize < file.size) { if (maxFileSize < file.size) {
this.setMessage("error", "file_size_error"); this.setMessage("error", "file_size_error");
this.set("file", null); this.set("file", null);
$('#file-upload').val(''); $("#file-upload").val("");
} else { } else {
this.setProperties({ this.setProperties({
file, file,
filename: file.name filename: file.name,
}); });
} }
}, },
selectWizard(event) { selectWizard(event) {
const type = event.target.classList.contains('export') ? 'export' : 'destroy'; const type = event.target.classList.contains("export")
? "export"
: "destroy";
const wizards = this.get(`${type}Wizards`); const wizards = this.get(`${type}Wizards`);
const checked = event.target.checked; const checked = event.target.checked;
let wizardId = event.target.closest('tr').getAttribute('data-wizard-id'); let wizardId = event.target.closest("tr").getAttribute("data-wizard-id");
if (wizardId) { if (wizardId) {
wizardId = underscore(wizardId); wizardId = underscore(wizardId);
} else { } else {
return false; return false;
} }
if (checked) { if (checked) {
wizards.addObject(wizardId); wizards.addObject(wizardId);
} else { } else {
@ -131,99 +137,113 @@ export default Controller.extend({
}, },
import() { import() {
const file = this.get('file'); const file = this.get("file");
if (!file) { if (!file) {
this.setMessage("error", 'no_file'); this.setMessage("error", "no_file");
return; return;
} }
let $formData = new FormData(); let $formData = new FormData();
$formData.append('file', file); $formData.append("file", file);
this.set('importing', true); this.set("importing", true);
this.setMessage("loading", "importing"); this.setMessage("loading", "importing");
CustomWizardManager.import($formData).then(result => { CustomWizardManager.import($formData)
if (result.error) { .then((result) => {
this.setMessage("error", "server_error", { if (result.error) {
message: result.error this.setMessage("error", "server_error", {
}); message: result.error,
} else { });
this.setMessage("success", "import_complete", {}, } else {
result.imported.map(imported => { this.setMessage(
return this.buildWizardLink(imported); "success",
}).concat( "import_complete",
result.failures.map(failure => { {},
return this.buildFailureItem(failure); result.imported
}) .map((imported) => {
) return this.buildWizardLink(imported);
); })
.concat(
if (result.imported.length) { result.failures.map((failure) => {
this.get('wizards').addObjects(result.imported); return this.buildFailureItem(failure);
})
)
);
if (result.imported.length) {
this.get("wizards").addObjects(result.imported);
}
} }
} this.clearFile();
this.clearFile(); })
}).finally(() => { .finally(() => {
this.set('importing', false); this.set("importing", false);
}); });
}, },
export() { export() {
const exportWizards = this.get('exportWizards'); const exportWizards = this.get("exportWizards");
if (!exportWizards.length) { if (!exportWizards.length) {
this.setMessage("error", 'none_selected'); this.setMessage("error", "none_selected");
} else { } else {
CustomWizardManager.export(exportWizards); CustomWizardManager.export(exportWizards);
exportWizards.clear(); exportWizards.clear();
$('input.export').prop("checked", false); $("input.export").prop("checked", false);
} }
}, },
destroy() { destroy() {
const destroyWizards = this.get('destroyWizards'); const destroyWizards = this.get("destroyWizards");
if (!destroyWizards.length) { if (!destroyWizards.length) {
this.setMessage("error", 'none_selected'); this.setMessage("error", "none_selected");
} else { } else {
this.set('destroying', true); this.set("destroying", true);
CustomWizardManager.destroy(destroyWizards).then((result) => { CustomWizardManager.destroy(destroyWizards)
if (result.error) { .then((result) => {
this.setMessage("error", "server_error", { if (result.error) {
message: result.error this.setMessage("error", "server_error", {
}); message: result.error,
} else { });
this.setMessage("success", "destroy_complete", {}, } else {
result.destroyed.map(destroyed => { this.setMessage(
return this.buildDestroyedItem(destroyed); "success",
}).concat( "destroy_complete",
result.failures.map(failure => { {},
return this.buildFailureItem(failure); result.destroyed
}) .map((destroyed) => {
) return this.buildDestroyedItem(destroyed);
); })
.concat(
if (result.destroyed.length) { result.failures.map((failure) => {
const destroyedIds = result.destroyed.map(d => d.id); return this.buildFailureItem(failure);
const destroyWizards = this.get('destroyWizards'); })
const wizards = this.get('wizards'); )
wizards.removeObjects(
wizards.filter(w => {
return destroyedIds.includes(w.id);
})
); );
destroyWizards.removeObjects(destroyedIds); if (result.destroyed.length) {
const destroyedIds = result.destroyed.map((d) => d.id);
const destroyWizards = this.get("destroyWizards");
const wizards = this.get("wizards");
wizards.removeObjects(
wizards.filter((w) => {
return destroyedIds.includes(w.id);
})
);
destroyWizards.removeObjects(destroyedIds);
}
} }
} })
}).finally(() => { .finally(() => {
this.set('destroying', false); this.set("destroying", false);
}); });
} }
} },
} },
}); });

Datei anzeigen

@ -2,5 +2,5 @@ import Controller from "@ember/controller";
import { fmt } from "discourse/lib/computed"; import { fmt } from "discourse/lib/computed";
export default Controller.extend({ export default Controller.extend({
downloadUrl: fmt("wizard.id", "/admin/wizards/submissions/%@/download") downloadUrl: fmt("wizard.id", "/admin/wizards/submissions/%@/download"),
}); });

Datei anzeigen

@ -1,123 +1,139 @@
import { default as discourseComputed, observes, on } from 'discourse-common/utils/decorators'; import {
default as discourseComputed,
observes,
on,
} from "discourse-common/utils/decorators";
import { notEmpty, alias } from "@ember/object/computed"; import { notEmpty, alias } from "@ember/object/computed";
import showModal from 'discourse/lib/show-modal'; import showModal from "discourse/lib/show-modal";
import { generateId, wizardFieldList } from '../lib/wizard'; import { generateId, wizardFieldList } from "../lib/wizard";
import { buildProperties } from '../lib/wizard-json'; import { buildProperties } from "../lib/wizard-json";
import { dasherize } from "@ember/string"; import { dasherize } from "@ember/string";
import EmberObject from "@ember/object"; import EmberObject from "@ember/object";
import { scheduleOnce, later } from "@ember/runloop"; import { scheduleOnce, later } from "@ember/runloop";
import Controller from "@ember/controller"; import Controller from "@ember/controller";
import copyText from "discourse/lib/copy-text"; import copyText from "discourse/lib/copy-text";
import CustomWizard from '../models/custom-wizard'; import CustomWizard from "../models/custom-wizard";
import I18n from "I18n"; import I18n from "I18n";
export default Controller.extend({ export default Controller.extend({
hasName: notEmpty('wizard.name'), hasName: notEmpty("wizard.name"),
@observes('currentStep') @observes("currentStep")
resetCurrentObjects() { resetCurrentObjects() {
const currentStep = this.currentStep; const currentStep = this.currentStep;
if (currentStep) { if (currentStep) {
const fields = currentStep.fields; const fields = currentStep.fields;
this.set('currentField', fields && fields.length ? fields[0] : null) this.set("currentField", fields && fields.length ? fields[0] : null);
} }
scheduleOnce('afterRender', () => ($("body").addClass('admin-wizard'))); scheduleOnce("afterRender", () => $("body").addClass("admin-wizard"));
},
@observes('wizard.name')
setId() {
const wizard = this.wizard;
if (wizard && !wizard.existingId) {
this.set('wizard.id', generateId(wizard.name));
}
},
@discourseComputed('wizard.id')
wizardUrl(wizardId) {
return window.location.origin + '/w/' + dasherize(wizardId);
}, },
@discourseComputed('wizard.after_time_scheduled') @observes("wizard.name")
nextSessionScheduledLabel(scheduled) { setId() {
return scheduled ? const wizard = this.wizard;
moment(scheduled).format('MMMM Do, HH:mm') : if (wizard && !wizard.existingId) {
I18n.t('admin.wizard.after_time_time_label'); this.set("wizard.id", generateId(wizard.name));
}
}, },
@discourseComputed('currentStep.id', 'wizard.save_submissions', 'currentStep.fields.@each.label') @discourseComputed("wizard.id")
wizardUrl(wizardId) {
return window.location.origin + "/w/" + dasherize(wizardId);
},
@discourseComputed("wizard.after_time_scheduled")
nextSessionScheduledLabel(scheduled) {
return scheduled
? moment(scheduled).format("MMMM Do, HH:mm")
: I18n.t("admin.wizard.after_time_time_label");
},
@discourseComputed(
"currentStep.id",
"wizard.save_submissions",
"currentStep.fields.@each.label"
)
wizardFields(currentStepId, saveSubmissions) { wizardFields(currentStepId, saveSubmissions) {
let steps = this.wizard.steps; let steps = this.wizard.steps;
if (!saveSubmissions) { if (!saveSubmissions) {
steps = [steps.findBy('id', currentStepId)]; steps = [steps.findBy("id", currentStepId)];
} }
return wizardFieldList(steps); return wizardFieldList(steps);
}, },
actions: { actions: {
save() { save() {
this.setProperties({ this.setProperties({
saving: true, saving: true,
error: null error: null,
}); });
const wizard = this.wizard; const wizard = this.wizard;
const creating = this.creating; const creating = this.creating;
let opts = {}; let opts = {};
if (creating) { if (creating) {
opts.create = true; opts.create = true;
} }
wizard.save(opts).then((result) => { wizard
this.send('afterSave', result.wizard_id); .save(opts)
}).catch((result) => { .then((result) => {
let errorType = 'failed'; this.send("afterSave", result.wizard_id);
let errorParams = {}; })
.catch((result) => {
if (result.error) { let errorType = "failed";
errorType = result.error.type; let errorParams = {};
errorParams = result.error.params;
} if (result.error) {
errorType = result.error.type;
this.set('error', I18n.t(`admin.wizard.error.${errorType}`, errorParams)); errorParams = result.error.params;
}
later(() => this.set('error', null), 10000);
}).finally(() => this.set('saving', false)); this.set(
"error",
I18n.t(`admin.wizard.error.${errorType}`, errorParams)
);
later(() => this.set("error", null), 10000);
})
.finally(() => this.set("saving", false));
}, },
remove() { remove() {
this.wizard.remove().then(() => this.send('afterDestroy')); this.wizard.remove().then(() => this.send("afterDestroy"));
}, },
setNextSessionScheduled() { setNextSessionScheduled() {
let controller = showModal('next-session-scheduled', { let controller = showModal("next-session-scheduled", {
model: { model: {
dateTime: this.wizard.after_time_scheduled, dateTime: this.wizard.after_time_scheduled,
update: (dateTime) => this.set('wizard.after_time_scheduled', dateTime) update: (dateTime) =>
} this.set("wizard.after_time_scheduled", dateTime),
},
}); });
controller.setup(); controller.setup();
}, },
toggleAdvanced() { toggleAdvanced() {
this.toggleProperty('wizard.showAdvanced'); this.toggleProperty("wizard.showAdvanced");
}, },
copyUrl() { copyUrl() {
const $copyRange = $('<p id="copy-range"></p>'); const $copyRange = $('<p id="copy-range"></p>');
$copyRange.html(this.wizardUrl); $copyRange.html(this.wizardUrl);
$(document.body).append($copyRange); $(document.body).append($copyRange);
if (copyText(this.wizardUrl, $copyRange[0])) { if (copyText(this.wizardUrl, $copyRange[0])) {
this.set("copiedUrl", true); this.set("copiedUrl", true);
later(() => this.set("copiedUrl", false), 2000); later(() => this.set("copiedUrl", false), 2000);
} }
$copyRange.remove(); $copyRange.remove();
} },
} },
}); });

Datei anzeigen

@ -1,25 +1,25 @@
import Controller from "@ember/controller"; import Controller from "@ember/controller";
import { default as discourseComputed } from 'discourse-common/utils/decorators'; import { default as discourseComputed } from "discourse-common/utils/decorators";
import { equal } from '@ember/object/computed'; import { equal } from "@ember/object/computed";
export default Controller.extend({ export default Controller.extend({
creating: equal('wizardId', 'create'), creating: equal("wizardId", "create"),
@discourseComputed('creating', 'wizardId') @discourseComputed("creating", "wizardId")
wizardListVal(creating, wizardId) { wizardListVal(creating, wizardId) {
return creating ? null : wizardId; return creating ? null : wizardId;
}, },
@discourseComputed('creating', 'wizardId') @discourseComputed("creating", "wizardId")
messageKey(creating, wizardId) { messageKey(creating, wizardId) {
let key = 'select'; let key = "select";
if (creating) { if (creating) {
key = 'create'; key = "create";
} else if (wizardId) { } else if (wizardId) {
key = 'edit'; key = "edit";
} }
return key; return key;
}, },
messageUrl: "https://thepavilion.io/c/knowledge/discourse/custom-wizard" messageUrl: "https://thepavilion.io/c/knowledge/discourse/custom-wizard",
}); });

Datei anzeigen

@ -1,27 +1,27 @@
import { default as discourseComputed } from 'discourse-common/utils/decorators'; import { default as discourseComputed } from "discourse-common/utils/decorators";
import Controller from "@ember/controller"; import Controller from "@ember/controller";
export default Controller.extend({ export default Controller.extend({
title: 'admin.wizard.after_time_modal.title', title: "admin.wizard.after_time_modal.title",
setup() { setup() {
this.set('bufferedDateTime', moment(this.model.dateTime)); this.set("bufferedDateTime", moment(this.model.dateTime));
}, },
@discourseComputed('bufferedDateTime') @discourseComputed("bufferedDateTime")
submitDisabled(dateTime) { submitDisabled(dateTime) {
return moment().isAfter(dateTime); return moment().isAfter(dateTime);
}, },
actions: { actions: {
submit() { submit() {
const dateTime = this.get('bufferedDateTime'); const dateTime = this.get("bufferedDateTime");
this.get('model.update')(moment(dateTime).utc().toISOString()); this.get("model.update")(moment(dateTime).utc().toISOString());
this.send("closeModal"); this.send("closeModal");
}, },
dateTimeChanged(dateTime) { dateTimeChanged(dateTime) {
this.set('bufferedDateTime', dateTime); this.set("bufferedDateTime", dateTime);
} },
} },
}); });

Datei anzeigen

@ -1,25 +1,55 @@
export default { export default {
resource: 'admin', resource: "admin",
map() { map() {
this.route('adminWizards', { path: '/wizards', resetNamespace: true }, function() { this.route(
"adminWizards",
this.route('adminWizardsWizard', { path: '/wizard/', resetNamespace: true }, function() { { path: "/wizards", resetNamespace: true },
this.route('adminWizardsWizardShow', { path: '/:wizardId/', resetNamespace: true }); function () {
}); this.route(
"adminWizardsWizard",
this.route('adminWizardsCustomFields', { path: '/custom-fields', resetNamespace: true }); { path: "/wizard/", resetNamespace: true },
function () {
this.route('adminWizardsSubmissions', { path: '/submissions', resetNamespace: true }, function() { this.route("adminWizardsWizardShow", {
this.route('adminWizardsSubmissionsShow', { path: '/:wizardId/', resetNamespace: true }); path: "/:wizardId/",
}) resetNamespace: true,
});
this.route('adminWizardsApi', { path: '/api', resetNamespace: true }, function() { }
this.route('adminWizardsApiShow', { path: '/:name', resetNamespace: true }); );
});
this.route('adminWizardsLogs', { path: '/logs', resetNamespace: true });
this.route('adminWizardsManager', { path: '/manager', resetNamespace: true }); this.route("adminWizardsCustomFields", {
}); path: "/custom-fields",
} resetNamespace: true,
});
this.route(
"adminWizardsSubmissions",
{ path: "/submissions", resetNamespace: true },
function () {
this.route("adminWizardsSubmissionsShow", {
path: "/:wizardId/",
resetNamespace: true,
});
}
);
this.route(
"adminWizardsApi",
{ path: "/api", resetNamespace: true },
function () {
this.route("adminWizardsApiShow", {
path: "/:name",
resetNamespace: true,
});
}
);
this.route("adminWizardsLogs", { path: "/logs", resetNamespace: true });
this.route("adminWizardsManager", {
path: "/manager",
resetNamespace: true,
});
}
);
},
}; };

Datei anzeigen

@ -1,6 +1,6 @@
import { registerUnbound } from 'discourse-common/lib/helpers'; import { registerUnbound } from "discourse-common/lib/helpers";
import { dasherize } from "@ember/string"; import { dasherize } from "@ember/string";
registerUnbound('dasherize', function(string) { registerUnbound("dasherize", function (string) {
return dasherize(string); return dasherize(string);
}); });

Datei anzeigen

@ -1,19 +1,19 @@
import { withPluginApi } from 'discourse/lib/plugin-api'; import { withPluginApi } from "discourse/lib/plugin-api";
import DiscourseURL from 'discourse/lib/url'; import DiscourseURL from "discourse/lib/url";
export default { export default {
name: 'custom-wizard-edits', name: "custom-wizard-edits",
initialize(container) { initialize(container) {
const siteSettings = container.lookup('site-settings:main'); const siteSettings = container.lookup("site-settings:main");
if (!siteSettings.custom_wizard_enabled) return; if (!siteSettings.custom_wizard_enabled) return;
const existing = DiscourseURL.routeTo; const existing = DiscourseURL.routeTo;
DiscourseURL.routeTo = function(path, opts) { DiscourseURL.routeTo = function (path, opts) {
if (path && path.indexOf('/w/') > -1) { if (path && path.indexOf("/w/") > -1) {
return window.location = path; return (window.location = path);
} }
return existing.apply(this, [path, opts]); return existing.apply(this, [path, opts]);
}; };
} },
}; };

Datei anzeigen

@ -1,36 +1,42 @@
import ApplicationRoute from 'discourse/routes/application'; import ApplicationRoute from "discourse/routes/application";
export default { export default {
name: "custom-wizard-redirect", name: "custom-wizard-redirect",
after: "message-bus", after: "message-bus",
initialize: function (container) { initialize: function (container) {
const messageBus = container.lookup('message-bus:main'); const messageBus = container.lookup("message-bus:main");
const siteSettings = container.lookup('site-settings:main'); const siteSettings = container.lookup("site-settings:main");
if (!siteSettings.custom_wizard_enabled || !messageBus) return; if (!siteSettings.custom_wizard_enabled || !messageBus) return;
messageBus.subscribe("/redirect_to_wizard", function (wizardId) { messageBus.subscribe("/redirect_to_wizard", function (wizardId) {
const wizardUrl = window.location.origin + '/w/' + wizardId; const wizardUrl = window.location.origin + "/w/" + wizardId;
window.location.href = wizardUrl; window.location.href = wizardUrl;
}); });
ApplicationRoute.reopen({ ApplicationRoute.reopen({
actions: { actions: {
willTransition(transition) { willTransition(transition) {
const redirectToWizard = this.get('currentUser.redirect_to_wizard'); const redirectToWizard = this.get("currentUser.redirect_to_wizard");
const excludedPaths = Discourse.SiteSettings.wizard_redirect_exclude_paths.split('|').concat(['loading']); const excludedPaths = Discourse.SiteSettings.wizard_redirect_exclude_paths
.split("|")
.concat(["loading"]);
if (redirectToWizard && (!transition.intent.name || !excludedPaths.find((p) => { if (
return transition.intent.name.indexOf(p) > -1; redirectToWizard &&
}))) { (!transition.intent.name ||
!excludedPaths.find((p) => {
return transition.intent.name.indexOf(p) > -1;
}))
) {
transition.abort(); transition.abort();
window.location = '/w/' + redirectToWizard.dasherize(); window.location = "/w/" + redirectToWizard.dasherize();
} }
return this._super(transition); return this._super(transition);
} },
} },
}) });
} },
}; };

Datei anzeigen

@ -1,14 +1,14 @@
import { listProperties, camelCase, snakeCase } from '../lib/wizard'; import { listProperties, camelCase, snakeCase } from "../lib/wizard";
import wizardSchema from '../lib/wizard-schema'; import wizardSchema from "../lib/wizard-schema";
import EmberObject from '@ember/object'; import EmberObject from "@ember/object";
import { A } from "@ember/array"; import { A } from "@ember/array";
function present(val) { function present(val) {
if (val === null || val === undefined) { if (val === null || val === undefined) {
return false; return false;
} else if (typeof val === 'object') { } else if (typeof val === "object") {
return Object.keys(val).length !== 0; return Object.keys(val).length !== 0;
} else if (typeof val === 'string' || val.constructor === Array) { } else if (typeof val === "string" || val.constructor === Array) {
return val && val.length; return val && val.length;
} else { } else {
return false; return false;
@ -20,51 +20,44 @@ function mapped(property, type) {
} }
function castCase(property, value) { function castCase(property, value) {
return property.indexOf('_type') > -1 ? camelCase(value) : value; return property.indexOf("_type") > -1 ? camelCase(value) : value;
} }
function buildProperty(json, property, type) { function buildProperty(json, property, type) {
let value = json[property]; let value = json[property];
if (mapped(property, type) && if (mapped(property, type) && present(value) && value.constructor === Array) {
present(value) &&
value.constructor === Array) {
let inputs = []; let inputs = [];
value.forEach(inputJson => { value.forEach((inputJson) => {
let input = {} let input = {};
Object.keys(inputJson).forEach(inputKey => { Object.keys(inputJson).forEach((inputKey) => {
if (inputKey === 'pairs') { if (inputKey === "pairs") {
let pairs = []; let pairs = [];
let pairCount = inputJson.pairs.length; let pairCount = inputJson.pairs.length;
inputJson.pairs.forEach(pairJson => { inputJson.pairs.forEach((pairJson) => {
let pair = {}; let pair = {};
Object.keys(pairJson).forEach(pairKey => { Object.keys(pairJson).forEach((pairKey) => {
pair[pairKey] = castCase(pairKey, pairJson[pairKey]); pair[pairKey] = castCase(pairKey, pairJson[pairKey]);
}); });
pair.pairCount = pairCount; pair.pairCount = pairCount;
pairs.push( pairs.push(EmberObject.create(pair));
EmberObject.create(pair)
);
}); });
input.pairs = pairs; input.pairs = pairs;
} else { } else {
input[inputKey] = castCase(inputKey, inputJson[inputKey]); input[inputKey] = castCase(inputKey, inputJson[inputKey]);
} }
}); });
inputs.push( inputs.push(EmberObject.create(input));
EmberObject.create(input)
);
}); });
return A(inputs); return A(inputs);
} else { } else {
return value; return value;
@ -73,48 +66,48 @@ function buildProperty(json, property, type) {
function buildObject(json, type) { function buildObject(json, type) {
let props = { let props = {
isNew: false isNew: false,
} };
Object.keys(json).forEach(prop => { Object.keys(json).forEach((prop) => {
props[prop] = buildProperty(json, prop, type) props[prop] = buildProperty(json, prop, type);
}); });
return EmberObject.create(props); return EmberObject.create(props);
} }
function buildObjectArray(json, type) { function buildObjectArray(json, type) {
let array = A(); let array = A();
if (present(json)) { if (present(json)) {
json.forEach((objJson) => { json.forEach((objJson) => {
let object = buildObject(objJson, type); let object = buildObject(objJson, type);
if (hasAdvancedProperties(object, type)) { if (hasAdvancedProperties(object, type)) {
object.set('showAdvanced', true); object.set("showAdvanced", true);
} }
array.pushObject(object); array.pushObject(object);
}); });
} }
return array; return array;
} }
function buildBasicProperties(json, type, props) { function buildBasicProperties(json, type, props) {
listProperties(type).forEach((p) => { listProperties(type).forEach((p) => {
props[p] = buildProperty(json, p, type); props[p] = buildProperty(json, p, type);
if (hasAdvancedProperties(json, type)) { if (hasAdvancedProperties(json, type)) {
props.showAdvanced = true; props.showAdvanced = true;
} }
}); });
return props; return props;
} }
function hasAdvancedProperties(object, type) { function hasAdvancedProperties(object, type) {
return Object.keys(object).some(p => { return Object.keys(object).some((p) => {
return wizardSchema[type].advanced.indexOf(p) > -1 && present(object[p]); return wizardSchema[type].advanced.indexOf(p) > -1 && present(object[p]);
}); });
} }
@ -122,59 +115,55 @@ function hasAdvancedProperties(object, type) {
/// to be removed: necessary due to action array being moved from step to wizard /// to be removed: necessary due to action array being moved from step to wizard
function actionPatch(json) { function actionPatch(json) {
let actions = json.actions || []; let actions = json.actions || [];
json.steps.forEach(step => { json.steps.forEach((step) => {
if (step.actions && step.actions.length) { if (step.actions && step.actions.length) {
step.actions.forEach(action => { step.actions.forEach((action) => {
action.run_after = 'wizard_completion'; action.run_after = "wizard_completion";
actions.push(action); actions.push(action);
}); });
} }
}); });
json.actions = actions; json.actions = actions;
return json; return json;
} }
/// ///
function buildProperties(json) { function buildProperties(json) {
let props = { let props = {
steps: A(), steps: A(),
actions: A() actions: A(),
}; };
if (present(json)) { if (present(json)) {
props.existingId = true; props.existingId = true;
props = buildBasicProperties(json, 'wizard', props); props = buildBasicProperties(json, "wizard", props);
if (present(json.steps)) { if (present(json.steps)) {
json.steps.forEach((stepJson) => { json.steps.forEach((stepJson) => {
let stepProps = { let stepProps = {
isNew: false isNew: false,
}; };
stepProps = buildBasicProperties(stepJson, 'step', stepProps); stepProps = buildBasicProperties(stepJson, "step", stepProps);
stepProps.fields = buildObjectArray(stepJson.fields, 'field'); stepProps.fields = buildObjectArray(stepJson.fields, "field");
props.steps.pushObject(EmberObject.create(stepProps)); props.steps.pushObject(EmberObject.create(stepProps));
}); });
}; }
json = actionPatch(json); // to be removed - see above json = actionPatch(json); // to be removed - see above
props.actions = buildObjectArray(json.actions, 'action'); props.actions = buildObjectArray(json.actions, "action");
} else { } else {
listProperties('wizard').forEach(prop => { listProperties("wizard").forEach((prop) => {
props[prop] = wizardSchema.wizard.basic[prop]; props[prop] = wizardSchema.wizard.basic[prop];
}); });
} }
return props; return props;
} }
export { export { buildProperties, present, mapped };
buildProperties,
present,
mapped
}

Datei anzeigen

@ -5,71 +5,71 @@ import I18n from "I18n";
// Inputs // Inputs
function defaultInputType(options = {}) { function defaultInputType(options = {}) {
return options.inputTypes.split(',')[0]; return options.inputTypes.split(",")[0];
} }
function mapInputTypes(types) { function mapInputTypes(types) {
return types.map(function(type) { return types.map(function (type) {
return { return {
id: type, id: type,
name: I18n.t(`admin.wizard.input.${type}.name`) name: I18n.t(`admin.wizard.input.${type}.name`),
}; };
}); });
} }
function inputTypesContent(options = {}) { function inputTypesContent(options = {}) {
return options.inputTypes ? return options.inputTypes
mapInputTypes(options.inputTypes.split(',')) : ? mapInputTypes(options.inputTypes.split(","))
mapInputTypes(selectableInputTypes); : mapInputTypes(selectableInputTypes);
} }
// connectorTypes // connectorTypes
const connectors = { const connectors = {
pair: [ pair: [
'equal', "equal",
'greater', "greater",
'less', "less",
'greater_or_equal', "greater_or_equal",
'less_or_equal', "less_or_equal",
'regex', "regex",
'is' "is",
], ],
output: [ output: ["then", "set"],
'then', };
'set',
],
}
function defaultConnector(connectorType, inputType, options={}) { function defaultConnector(connectorType, inputType, options = {}) {
if (connectorType === 'input') { if (connectorType === "input") {
return defaultInputType(options); return defaultInputType(options);
} }
if (connectorType === 'pair') { if (connectorType === "pair") {
if (inputType === 'conditional') return 'equal'; if (inputType === "conditional") return "equal";
if (inputType === 'association') return 'association'; if (inputType === "association") return "association";
if (inputType === 'validation') return 'equal'; if (inputType === "validation") return "equal";
} }
if (connectorType === 'output') { if (connectorType === "output") {
if (inputType === 'conditional') return 'then'; if (inputType === "conditional") return "then";
if (inputType === 'assignment') return 'set'; if (inputType === "assignment") return "set";
} }
return 'equal'; return "equal";
} }
function connectorContent(connectorType, inputType, opts) { function connectorContent(connectorType, inputType, opts) {
let connector = opts[`${connectorType}Connector`]; let connector = opts[`${connectorType}Connector`];
if ((!connector && connectorType === 'output') || inputType === 'association') { if (
(!connector && connectorType === "output") ||
inputType === "association"
) {
connector = defaultConnector(connectorType, inputType); connector = defaultConnector(connectorType, inputType);
} }
let content = connector ? [connector] : connectors[connectorType]; let content = connector ? [connector] : connectors[connectorType];
return content.map(function(item) { return content.map(function (item) {
return { return {
id: item, id: item,
name: I18n.t(`admin.wizard.connector.${item}`) name: I18n.t(`admin.wizard.connector.${item}`),
}; };
}); });
} }
@ -77,38 +77,39 @@ function connectorContent(connectorType, inputType, opts) {
// Selectors // Selectors
const selectionTypes = [ const selectionTypes = [
'text', "text",
'list', "list",
'wizardField', "wizardField",
'wizardAction', "wizardAction",
'userField', "userField",
'userFieldOptions', "userFieldOptions",
'group', "group",
'category', "category",
'tag', "tag",
'user', "user",
'customField' "customField",
] ];
function defaultSelectionType(inputType, options = {}) { function defaultSelectionType(inputType, options = {}) {
if (options[`${inputType}DefaultSelection`]) { if (options[`${inputType}DefaultSelection`]) {
return options[`${inputType}DefaultSelection`]; return options[`${inputType}DefaultSelection`];
} }
let type = selectionTypes[0]; let type = selectionTypes[0];
for (let t of selectionTypes) { for (let t of selectionTypes) {
let inputTypes = options[`${t}Selection`]; let inputTypes = options[`${t}Selection`];
if (inputTypes === true || if (
((typeof inputTypes === 'string') && inputTypes === true ||
inputTypes.split(',').indexOf(inputType) > -1)) { (typeof inputTypes === "string" &&
inputTypes.split(",").indexOf(inputType) > -1)
) {
type = t; type = t;
break; break;
} }
} }
return type; return type;
} }
@ -118,46 +119,42 @@ function newPair(inputType, options = {}) {
let params = { let params = {
index: options.index, index: options.index,
pairCount: options.pairCount, pairCount: options.pairCount,
key: '', key: "",
key_type: defaultSelectionType('key', options), key_type: defaultSelectionType("key", options),
value: '', value: "",
value_type: defaultSelectionType('value', options), value_type: defaultSelectionType("value", options),
connector: defaultConnector('pair', inputType, options) connector: defaultConnector("pair", inputType, options),
} };
return EmberObject.create(params); return EmberObject.create(params);
} }
function newInput(options = {}, count) { function newInput(options = {}, count) {
const inputType = defaultInputType(options); const inputType = defaultInputType(options);
let params = { let params = {
type: inputType, type: inputType,
pairs: A( pairs: A([
[ newPair(
newPair( inputType,
inputType, Object.assign({}, options, { index: 0, pairCount: 1 })
Object.assign({}, ),
options, ]),
{ index: 0, pairCount: 1 } };
)
)
]
)
}
if (count > 0) { if (count > 0) {
params.connector = options.inputConnector; params.connector = options.inputConnector;
} }
if (['conditional', 'assignment'].indexOf(inputType) > -1 || if (
options.outputDefaultSelection || ["conditional", "assignment"].indexOf(inputType) > -1 ||
options.outputConnector) { options.outputDefaultSelection ||
options.outputConnector
params['output_type'] = defaultSelectionType('output', options); ) {
params['output_connector'] = defaultConnector('output', inputType, options); params["output_type"] = defaultSelectionType("output", options);
params["output_connector"] = defaultConnector("output", inputType, options);
} }
return EmberObject.create(params); return EmberObject.create(params);
} }
@ -169,5 +166,5 @@ export {
inputTypesContent, inputTypesContent,
selectionTypes, selectionTypes,
newInput, newInput,
newPair newPair,
} };

Datei anzeigen

@ -14,30 +14,24 @@ const wizard = {
prompt_completion: null, prompt_completion: null,
restart_on_revisit: null, restart_on_revisit: null,
theme_id: null, theme_id: null,
permitted: null permitted: null,
}, },
mapped: [ mapped: ["permitted"],
'permitted' advanced: ["restart_on_revisit"],
], required: ["id"],
advanced: [
'restart_on_revisit',
],
required: [
'id',
],
dependent: { dependent: {
after_time: 'after_time_scheduled' after_time: "after_time_scheduled",
}, },
objectArrays: { objectArrays: {
step: { step: {
property: 'steps', property: "steps",
required: false required: false,
}, },
action: { action: {
property: 'actions', property: "actions",
required: false required: false,
} },
} },
}; };
const step = { const step = {
@ -49,28 +43,19 @@ const step = {
raw_description: null, raw_description: null,
required_data: null, required_data: null,
required_data_message: null, required_data_message: null,
permitted_params: null permitted_params: null,
},
mapped: [
'required_data',
'permitted_params'
],
advanced: [
'required_data',
'permitted_params'
],
required: [
'id'
],
dependent: {
}, },
mapped: ["required_data", "permitted_params"],
advanced: ["required_data", "permitted_params"],
required: ["id"],
dependent: {},
objectArrays: { objectArrays: {
field: { field: {
property: 'fields', property: "fields",
required: false required: false,
} },
} },
} };
const field = { const field = {
basic: { basic: {
@ -80,32 +65,21 @@ const field = {
description: null, description: null,
required: null, required: null,
key: null, key: null,
type: null type: null,
}, },
types: {}, types: {},
mapped: [ mapped: ["prefill", "content"],
'prefill', advanced: ["property", "key"],
'content' required: ["id", "type"],
], dependent: {},
advanced: [ objectArrays: {},
'property', };
'key'
],
required: [
'id',
'type'
],
dependent: {
},
objectArrays: {
}
}
const action = { const action = {
basic: { basic: {
id: null, id: null,
run_after: 'wizard_completion', run_after: "wizard_completion",
type: null type: null,
}, },
types: { types: {
create_topic: { create_topic: {
@ -129,7 +103,7 @@ const action = {
custom_fields: null, custom_fields: null,
required: null, required: null,
recipient: null, recipient: null,
suppress_notifications: null suppress_notifications: null,
}, },
open_composer: { open_composer: {
title: null, title: null,
@ -138,30 +112,30 @@ const action = {
post_template: null, post_template: null,
category: null, category: null,
tags: null, tags: null,
custom_fields: null custom_fields: null,
}, },
update_profile: { update_profile: {
profile_updates: null, profile_updates: null,
custom_fields: null custom_fields: null,
}, },
watch_categories: { watch_categories: {
categories: null, categories: null,
notification_level: null, notification_level: null,
mute_remainder: null, mute_remainder: null,
wizard_user: true, wizard_user: true,
usernames: null usernames: null,
}, },
send_to_api: { send_to_api: {
api: null, api: null,
api_endpoint: null, api_endpoint: null,
api_body: null api_body: null,
}, },
add_to_group: { add_to_group: {
group: null group: null,
}, },
route_to: { route_to: {
url: null, url: null,
code: null code: null,
}, },
create_category: { create_category: {
name: null, name: null,
@ -170,7 +144,7 @@ const action = {
text_color: "FFFFFF", text_color: "FFFFFF",
parent_category_id: null, parent_category_id: null,
permissions: null, permissions: null,
custom_fields: null custom_fields: null,
}, },
create_group: { create_group: {
name: null, name: null,
@ -184,61 +158,56 @@ const action = {
messageable_level: null, messageable_level: null,
visibility_level: null, visibility_level: null,
members_visibility_level: null, members_visibility_level: null,
custom_fields: null custom_fields: null,
} },
}, },
mapped: [ mapped: [
'title', "title",
'category', "category",
'tags', "tags",
'visible', "visible",
'custom_fields', "custom_fields",
'required', "required",
'recipient', "recipient",
'profile_updates', "profile_updates",
'group', "group",
'url', "url",
'categories', "categories",
'mute_remainder', "mute_remainder",
'name', "name",
'slug', "slug",
'color', "color",
'text_color', "text_color",
'parent_category_id', "parent_category_id",
'permissions', "permissions",
'full_name', "full_name",
'bio_raw', "bio_raw",
'owner_usernames', "owner_usernames",
'usernames', "usernames",
'grant_trust_level', "grant_trust_level",
'mentionable_level', "mentionable_level",
'messageable_level', "messageable_level",
'visibility_level', "visibility_level",
'members_visibility_level' "members_visibility_level",
], ],
advanced: [ advanced: [
'code', "code",
'custom_fields', "custom_fields",
'skip_redirect', "skip_redirect",
'suppress_notifications', "suppress_notifications",
'required' "required",
], ],
required: [ required: ["id", "type"],
'id', dependent: {},
'type' objectArrays: {},
], };
dependent: {
},
objectArrays: {
}
}
const wizardSchema = { const wizardSchema = {
wizard, wizard,
step, step,
field, field,
action action,
} };
export function buildFieldTypes(types) { export function buildFieldTypes(types) {
wizardSchema.field.types = types; wizardSchema.field.types = types;
@ -252,34 +221,34 @@ if (Discourse.SiteSettings.wizard_apis_enabled) {
wizardSchema.action.types.send_to_api = { wizardSchema.action.types.send_to_api = {
api: null, api: null,
api_endpoint: null, api_endpoint: null,
api_body: null api_body: null,
} };
} }
export function setWizardDefaults(obj, itemType, opts={}) { export function setWizardDefaults(obj, itemType, opts = {}) {
const objSchema = wizardSchema[itemType]; const objSchema = wizardSchema[itemType];
const basicDefaults = objSchema.basic; const basicDefaults = objSchema.basic;
Object.keys(basicDefaults).forEach(property => { Object.keys(basicDefaults).forEach((property) => {
let defaultValue = get(basicDefaults, property); let defaultValue = get(basicDefaults, property);
if (defaultValue) { if (defaultValue) {
set(obj, property, defaultValue); set(obj, property, defaultValue);
} }
}); });
if (objSchema.types) { if (objSchema.types) {
const typeDefaults = objSchema.types[obj.type]; const typeDefaults = objSchema.types[obj.type];
if (typeDefaults) { if (typeDefaults) {
Object.keys(typeDefaults).forEach(property => { Object.keys(typeDefaults).forEach((property) => {
if (typeDefaults.hasOwnProperty(property)) { if (typeDefaults.hasOwnProperty(property)) {
set(obj, property, get(typeDefaults, property)); set(obj, property, get(typeDefaults, property));
} }
}); });
} }
} }
return obj; return obj;
} }
export default wizardSchema; export default wizardSchema;

Datei anzeigen

@ -1,110 +1,111 @@
import EmberObject from "@ember/object"; import EmberObject from "@ember/object";
import wizardSchema from './wizard-schema'; import wizardSchema from "./wizard-schema";
function selectKitContent(content) { function selectKitContent(content) {
return content.map(i => ({id: i, name: i})); return content.map((i) => ({ id: i, name: i }));
} }
function generateName(id) { function generateName(id) {
return id ? sentenceCase(id) : ''; return id ? sentenceCase(id) : "";
} }
function generateId(name, opts={}) { function generateId(name, opts = {}) {
return name ? snakeCase(name) : ''; return name ? snakeCase(name) : "";
} }
function sentenceCase(string) { function sentenceCase(string) {
return string.replace(/[_\-]+/g, ' ') return string
.replace(/[_\-]+/g, " ")
.toLowerCase() .toLowerCase()
.replace(/(^\w|\b\w)/g, (m) => m.toUpperCase()); .replace(/(^\w|\b\w)/g, (m) => m.toUpperCase());
} }
function snakeCase(string) { function snakeCase(string) {
return string.match(/[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+/g) return string
.map(x => x.toLowerCase()) .match(/[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+/g)
.join('_'); .map((x) => x.toLowerCase())
.join("_");
} }
function camelCase(string) { function camelCase(string) {
return string.replace(/([-_][a-z])/ig, ($1) => { return string.replace(/([-_][a-z])/gi, ($1) => {
return $1.toUpperCase() return $1.toUpperCase().replace("-", "").replace("_", "");
.replace('-', '')
.replace('_', '');
}); });
} }
const userProperties = [ const userProperties = [
'name', "name",
'username', "username",
'email', "email",
'avatar', "avatar",
'date_of_birth', "date_of_birth",
'title', "title",
'profile_background', "profile_background",
'card_background', "card_background",
'locale', "locale",
'location', "location",
'website', "website",
'bio_raw', "bio_raw",
'trust_level', "trust_level",
'email_level', "email_level",
'email_messages_level', "email_messages_level",
'email_digests' "email_digests",
]; ];
const notificationLevels = [ const notificationLevels = [
'regular', "regular",
'watching', "watching",
'tracking', "tracking",
'watching_first_post', "watching_first_post",
'muted' "muted",
]; ];
function listProperties(type, opts={}) { function listProperties(type, opts = {}) {
let properties = Object.keys(wizardSchema[type].basic); let properties = Object.keys(wizardSchema[type].basic);
const types = wizardSchema[type].types; const types = wizardSchema[type].types;
if (types) { if (types) {
let typeProperties = []; let typeProperties = [];
if (opts.allTypes) { if (opts.allTypes) {
Object.keys(types).forEach(type => { Object.keys(types).forEach((type) => {
typeProperties = typeProperties.concat(Object.keys(types[type])); typeProperties = typeProperties.concat(Object.keys(types[type]));
}); });
} else if (opts.objectType && types[opts.objectType]) { } else if (opts.objectType && types[opts.objectType]) {
typeProperties = Object.keys(types[opts.objectType]); typeProperties = Object.keys(types[opts.objectType]);
} }
properties = properties.concat(typeProperties); properties = properties.concat(typeProperties);
} }
return properties; return properties;
} }
function wizardFieldList(steps = [], opts = {}) { function wizardFieldList(steps = [], opts = {}) {
let upToIndex = null; let upToIndex = null;
if (opts.upTo) { if (opts.upTo) {
upToIndex = steps.map((s) => (s.id)).indexOf(opts.upTo); upToIndex = steps.map((s) => s.id).indexOf(opts.upTo);
} }
return steps.reduce((result, step, index) => { return steps.reduce((result, step, index) => {
let fields = step.fields; let fields = step.fields;
if (fields && fields.length > 0) { if (fields && fields.length > 0) {
if (upToIndex === null || index < upToIndex) { if (upToIndex === null || index < upToIndex) {
result.push(...fields.map((field) => { result.push(
return EmberObject.create({ ...fields.map((field) => {
id: field.id, return EmberObject.create({
label: `${field.label} (${field.id})`, id: field.id,
type: field.type label: `${field.label} (${field.id})`,
}); type: field.type,
})); });
})
);
} }
} }
return result; return result;
}, []); }, []);
} }
@ -118,5 +119,5 @@ export {
userProperties, userProperties,
listProperties, listProperties,
notificationLevels, notificationLevels,
wizardFieldList wizardFieldList,
}; };

Datei anzeigen

@ -1,9 +1,9 @@
import { listProperties } from '../lib/wizard'; import { listProperties } from "../lib/wizard";
import { default as wizardSchema } from '../lib/wizard-schema'; import { default as wizardSchema } from "../lib/wizard-schema";
import { set, get } from "@ember/object"; import { set, get } from "@ember/object";
import Mixin from "@ember/object/mixin"; import Mixin from "@ember/object/mixin";
import { observes } from 'discourse-common/utils/decorators'; import { observes } from "discourse-common/utils/decorators";
import { deepEqual } from 'discourse-common/lib/object'; import { deepEqual } from "discourse-common/lib/object";
export default Mixin.create({ export default Mixin.create({
didInsertElement() { didInsertElement() {
@ -14,9 +14,9 @@ export default Mixin.create({
this.setProperties({ this.setProperties({
originalObject: JSON.parse(JSON.stringify(obj)), originalObject: JSON.parse(JSON.stringify(obj)),
undoIcon: obj.isNew ? 'times' : 'undo', undoIcon: obj.isNew ? "times" : "undo",
undoKey: `admin.wizard.${obj.isNew ? 'clear' : 'undo'}` undoKey: `admin.wizard.${obj.isNew ? "clear" : "undo"}`,
}) });
}, },
willDestroyElement() { willDestroyElement() {
@ -24,33 +24,33 @@ export default Mixin.create({
this.removeObservers(); this.removeObservers();
}, },
removeObservers(objType=null) { removeObservers(objType = null) {
const componentType = this.componentType; const componentType = this.componentType;
const obj = this.get(componentType); const obj = this.get(componentType);
let opts = { let opts = {
objectType: objType || obj.type objectType: objType || obj.type,
} };
listProperties(componentType, opts).forEach(property => { listProperties(componentType, opts).forEach((property) => {
obj.removeObserver(property, this, this.toggleUndo); obj.removeObserver(property, this, this.toggleUndo);
}); });
}, },
setupObservers(objType=null) { setupObservers(objType = null) {
const componentType = this.componentType; const componentType = this.componentType;
const obj = this.get(componentType); const obj = this.get(componentType);
let opts = { let opts = {
objectType: objType || obj.type objectType: objType || obj.type,
} };
listProperties(componentType, opts).forEach(property => { listProperties(componentType, opts).forEach((property) => {
obj.addObserver(property, this, this.toggleUndo); obj.addObserver(property, this, this.toggleUndo);
}); });
}, },
revertToOriginal(revertBasic=false) { revertToOriginal(revertBasic = false) {
const original = JSON.parse(JSON.stringify(this.originalObject)); const original = JSON.parse(JSON.stringify(this.originalObject));
const componentType = this.componentType; const componentType = this.componentType;
const obj = this.get(componentType); const obj = this.get(componentType);
@ -58,7 +58,7 @@ export default Mixin.create({
const basicDefaults = objSchema.basic; const basicDefaults = objSchema.basic;
if (revertBasic) { if (revertBasic) {
Object.keys(basicDefaults).forEach(property => { Object.keys(basicDefaults).forEach((property) => {
let value; let value;
if (original.hasOwnProperty(property)) { if (original.hasOwnProperty(property)) {
@ -74,7 +74,7 @@ export default Mixin.create({
if (objSchema.types && obj.type) { if (objSchema.types && obj.type) {
let typeDefaults = objSchema.types[obj.type]; let typeDefaults = objSchema.types[obj.type];
Object.keys(typeDefaults).forEach(property => { Object.keys(typeDefaults).forEach((property) => {
let value; let value;
if (original.type === obj.type && original.hasOwnProperty(property)) { if (original.type === obj.type && original.hasOwnProperty(property)) {
@ -91,36 +91,36 @@ export default Mixin.create({
toggleUndo() { toggleUndo() {
const current = this.get(this.componentType); const current = this.get(this.componentType);
const original = this.originalObject; const original = this.originalObject;
this.set('showUndo', !deepEqual(current, original)); this.set("showUndo", !deepEqual(current, original));
}, },
actions: { actions: {
undoChanges() { undoChanges() {
const componentType = this.componentType; const componentType = this.componentType;
const original = this.get('originalObject'); const original = this.get("originalObject");
const obj = this.get(componentType); const obj = this.get(componentType);
this.removeObservers(obj.type); this.removeObservers(obj.type);
this.revertToOriginal(true); this.revertToOriginal(true);
this.set('showUndo', false); this.set("showUndo", false);
this.setupObservers(this.get(componentType).type); this.setupObservers(this.get(componentType).type);
}, },
changeType(type) { changeType(type) {
const componentType = this.componentType; const componentType = this.componentType;
const original = this.get('originalObject'); const original = this.get("originalObject");
const obj = this.get(componentType); const obj = this.get(componentType);
this.removeObservers(obj.type); this.removeObservers(obj.type);
obj.set('type', type); obj.set("type", type);
this.revertToOriginal(); this.revertToOriginal();
this.set('showUndo', type !== original.type); this.set("showUndo", type !== original.type);
this.setupObservers(type); this.setupObservers(type);
}, },
mappedFieldUpdated(property, mappedComponent, type) { mappedFieldUpdated(property, mappedComponent, type) {
const obj = this.get(this.componentType); const obj = this.get(this.componentType);
obj.notifyPropertyChange(property); obj.notifyPropertyChange(property);
} },
} },
}) });

Datei anzeigen

@ -1,15 +1,19 @@
import { ajax } from 'discourse/lib/ajax'; import { ajax } from "discourse/lib/ajax";
import { default as discourseComputed } from 'discourse-common/utils/decorators'; import { default as discourseComputed } from "discourse-common/utils/decorators";
import EmberObject from "@ember/object"; import EmberObject from "@ember/object";
import { A } from "@ember/array"; import { A } from "@ember/array";
const CustomWizardApi = EmberObject.extend({ const CustomWizardApi = EmberObject.extend({
@discourseComputed('name') @discourseComputed("name")
redirectUri(name) { redirectUri(name) {
let nameParam = name.toString().dasherize(); let nameParam = name.toString().dasherize();
const baseUrl = location.protocol+'//'+location.hostname+(location.port ? ':'+location.port: ''); const baseUrl =
location.protocol +
"//" +
location.hostname +
(location.port ? ":" + location.port : "");
return baseUrl + `/admin/wizards/apis/${nameParam}/redirect`; return baseUrl + `/admin/wizards/apis/${nameParam}/redirect`;
} },
}); });
CustomWizardApi.reopenClass({ CustomWizardApi.reopenClass({
@ -38,7 +42,7 @@ CustomWizardApi.reopenClass({
tokenRefreshAt: authorization.token_refresh_at, tokenRefreshAt: authorization.token_refresh_at,
endpoints: A(endpoints), endpoints: A(endpoints),
isNew: params.isNew, isNew: params.isNew,
log: params.log log: params.log,
}); });
return api; return api;
@ -46,19 +50,19 @@ CustomWizardApi.reopenClass({
find(name) { find(name) {
return ajax(`/admin/wizards/api/${name}`, { return ajax(`/admin/wizards/api/${name}`, {
type: 'GET' type: "GET",
}).then(result => { }).then((result) => {
return CustomWizardApi.create(result); return CustomWizardApi.create(result);
}); });
}, },
list() { list() {
return ajax("/admin/wizards/api", { return ajax("/admin/wizards/api", {
type: 'GET' type: "GET",
}).then(result => { }).then((result) => {
return result; return result;
}); });
} },
}); });
export default CustomWizardApi; export default CustomWizardApi;

Datei anzeigen

@ -1,33 +1,33 @@
import { ajax } from 'discourse/lib/ajax'; import { ajax } from "discourse/lib/ajax";
import { popupAjaxError } from 'discourse/lib/ajax-error'; import { popupAjaxError } from "discourse/lib/ajax-error";
import EmberObject from "@ember/object"; import EmberObject from "@ember/object";
import { isEmpty } from "@ember/utils"; import { isEmpty } from "@ember/utils";
const CustomWizardCustomField = EmberObject.extend({ const CustomWizardCustomField = EmberObject.extend({
isNew: isEmpty('id') isNew: isEmpty("id"),
}); });
const basePath = '/admin/wizards/custom-fields'; const basePath = "/admin/wizards/custom-fields";
CustomWizardCustomField.reopenClass({ CustomWizardCustomField.reopenClass({
listFields() { listFields() {
return ajax(basePath).catch(popupAjaxError); return ajax(basePath).catch(popupAjaxError);
}, },
saveField(customField) { saveField(customField) {
return ajax(basePath, { return ajax(basePath, {
type: 'PUT', type: "PUT",
data: { data: {
custom_field: customField custom_field: customField,
} },
}).catch(popupAjaxError); }).catch(popupAjaxError);
}, },
destroyField(field) { destroyField(field) {
return ajax(`${basePath}/${field.name}`, { return ajax(`${basePath}/${field.name}`, {
type: 'DELETE' type: "DELETE",
}).catch(popupAjaxError); }).catch(popupAjaxError);
} },
}); });
export default CustomWizardCustomField; export default CustomWizardCustomField;

Datei anzeigen

@ -1,17 +1,17 @@
import { ajax } from 'discourse/lib/ajax'; import { ajax } from "discourse/lib/ajax";
import { popupAjaxError } from 'discourse/lib/ajax-error'; import { popupAjaxError } from "discourse/lib/ajax-error";
import EmberObject from "@ember/object"; import EmberObject from "@ember/object";
const CustomWizardLogs = EmberObject.extend(); const CustomWizardLogs = EmberObject.extend();
CustomWizardLogs.reopenClass({ CustomWizardLogs.reopenClass({
list(page = 0) { list(page = 0) {
return ajax('/admin/wizards/logs', { return ajax("/admin/wizards/logs", {
data: { data: {
page page,
} },
}).catch(popupAjaxError); }).catch(popupAjaxError);
} },
}); });
export default CustomWizardLogs; export default CustomWizardLogs;

Datei anzeigen

@ -1,5 +1,5 @@
import { ajax } from 'discourse/lib/ajax'; import { ajax } from "discourse/lib/ajax";
import { popupAjaxError } from 'discourse/lib/ajax-error'; import { popupAjaxError } from "discourse/lib/ajax-error";
import EmberObject from "@ember/object"; import EmberObject from "@ember/object";
const CustomWizardManager = EmberObject.extend(); const CustomWizardManager = EmberObject.extend();
@ -9,35 +9,35 @@ const basePath = "admin/wizards/manager";
CustomWizardManager.reopenClass({ CustomWizardManager.reopenClass({
import($formData) { import($formData) {
return ajax(`/${basePath}/import`, { return ajax(`/${basePath}/import`, {
type: 'POST', type: "POST",
data: $formData, data: $formData,
processData: false, processData: false,
contentType: false, contentType: false,
}).catch(popupAjaxError); }).catch(popupAjaxError);
}, },
export(wizardIds) { export(wizardIds) {
let url = `${Discourse.BaseUrl}/${basePath}/export?`; let url = `${Discourse.BaseUrl}/${basePath}/export?`;
wizardIds.forEach((wizardId, index) => { wizardIds.forEach((wizardId, index) => {
let step = 'wizard_ids[]=' + wizardId; let step = "wizard_ids[]=" + wizardId;
if (index !== wizardIds[wizardIds.length - 1]) { if (index !== wizardIds[wizardIds.length - 1]) {
step += '&'; step += "&";
} }
url += step; url += step;
}); });
location.href = url; location.href = url;
}, },
destroy(wizardIds) { destroy(wizardIds) {
return ajax(`/${basePath}/destroy`, { return ajax(`/${basePath}/destroy`, {
type: "DELETE", type: "DELETE",
data: { data: {
wizard_ids: wizardIds wizard_ids: wizardIds,
} },
}).catch(popupAjaxError); }).catch(popupAjaxError);
} },
}); });
export default CustomWizardManager; export default CustomWizardManager;

Datei anzeigen

@ -1,32 +1,32 @@
import { ajax } from 'discourse/lib/ajax'; import { ajax } from "discourse/lib/ajax";
import EmberObject from "@ember/object"; import EmberObject from "@ember/object";
import { buildProperties, present, mapped } from '../lib/wizard-json'; import { buildProperties, present, mapped } from "../lib/wizard-json";
import { listProperties, camelCase, snakeCase } from '../lib/wizard'; import { listProperties, camelCase, snakeCase } from "../lib/wizard";
import wizardSchema from '../lib/wizard-schema'; import wizardSchema from "../lib/wizard-schema";
import { Promise } from "rsvp"; import { Promise } from "rsvp";
import { popupAjaxError } from 'discourse/lib/ajax-error'; import { popupAjaxError } from "discourse/lib/ajax-error";
const CustomWizard = EmberObject.extend({ const CustomWizard = EmberObject.extend({
save(opts) { save(opts) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
let wizard = this.buildJson(this, 'wizard'); let wizard = this.buildJson(this, "wizard");
if (wizard.error) { if (wizard.error) {
reject(wizard); reject(wizard);
} }
let data = { let data = {
wizard wizard,
}; };
if (opts.create) { if (opts.create) {
data.create = true; data.create = true;
} }
ajax(`/admin/wizards/wizard/${wizard.id}`, { ajax(`/admin/wizards/wizard/${wizard.id}`, {
type: 'PUT', type: "PUT",
contentType: "application/json", contentType: "application/json",
data: JSON.stringify(data) data: JSON.stringify(data),
}).then((result) => { }).then((result) => {
if (result.error) { if (result.error) {
reject(result); reject(result);
@ -39,53 +39,55 @@ const CustomWizard = EmberObject.extend({
buildJson(object, type, result = {}) { buildJson(object, type, result = {}) {
let objectType = object.type || null; let objectType = object.type || null;
if (wizardSchema[type].types) { if (wizardSchema[type].types) {
if (!objectType) { if (!objectType) {
result.error = { result.error = {
type: 'required', type: "required",
params: { type, property: 'type' } params: { type, property: "type" },
} };
return result; return result;
} }
} }
for (let property of listProperties(type, { objectType })) { for (let property of listProperties(type, { objectType })) {
let value = object.get(property); let value = object.get(property);
result = this.validateValue(property, value, object, type, result); result = this.validateValue(property, value, object, type, result);
if (result.error) { if (result.error) {
break; break;
} }
if (mapped(property, type)) { if (mapped(property, type)) {
value = this.buildMappedJson(value); value = this.buildMappedJson(value);
} }
if (value !== undefined && value !== null) { if (value !== undefined && value !== null) {
result[property] = value; result[property] = value;
} }
}; }
if (!result.error) { if (!result.error) {
for (let arrayObjectType of Object.keys(wizardSchema[type].objectArrays)) { for (let arrayObjectType of Object.keys(
wizardSchema[type].objectArrays
)) {
let arraySchema = wizardSchema[type].objectArrays[arrayObjectType]; let arraySchema = wizardSchema[type].objectArrays[arrayObjectType];
let objectArray = object.get(arraySchema.property); let objectArray = object.get(arraySchema.property);
if (arraySchema.required && !present(objectArray)) { if (arraySchema.required && !present(objectArray)) {
result.error = { result.error = {
type: 'required', type: "required",
params: { type, property: arraySchema.property } params: { type, property: arraySchema.property },
} };
break; break;
} }
result[arraySchema.property] = []; result[arraySchema.property] = [];
for (let item of objectArray) { for (let item of objectArray) {
let itemProps = this.buildJson(item, arrayObjectType); let itemProps = this.buildJson(item, arrayObjectType);
if (itemProps.error) { if (itemProps.error) {
result.error = itemProps.error; result.error = itemProps.error;
break; break;
@ -93,115 +95,119 @@ const CustomWizard = EmberObject.extend({
result[arraySchema.property].push(itemProps); result[arraySchema.property].push(itemProps);
} }
} }
}; }
} }
return result; return result;
}, },
validateValue(property, value, object, type, result) { validateValue(property, value, object, type, result) {
if (wizardSchema[type].required.indexOf(property) > -1 && !value) { if (wizardSchema[type].required.indexOf(property) > -1 && !value) {
result.error = { result.error = {
type: 'required', type: "required",
params: { type, property } params: { type, property },
} };
} }
let dependent = wizardSchema[type].dependent[property]; let dependent = wizardSchema[type].dependent[property];
if (dependent && value && !object[dependent]) { if (dependent && value && !object[dependent]) {
result.error = { result.error = {
type: 'dependent', type: "dependent",
params: { property, dependent } params: { property, dependent },
} };
} }
if (property === 'api_body') { if (property === "api_body") {
try { try {
value = JSON.parse(value); value = JSON.parse(value);
} catch (e) { } catch (e) {
result.error = { result.error = {
type: 'invalid', type: "invalid",
params: { type, property } params: { type, property },
} };
} }
} }
return result; return result;
}, },
buildMappedJson(inputs) { buildMappedJson(inputs) {
if (!inputs || !inputs.length) return false; if (!inputs || !inputs.length) return false;
let result = []; let result = [];
inputs.forEach(inpt => { inputs.forEach((inpt) => {
let input = { let input = {
type: inpt.type, type: inpt.type,
}; };
if (inpt.connector) { if (inpt.connector) {
input.connector = inpt.connector; input.connector = inpt.connector;
} }
if (present(inpt.output)) { if (present(inpt.output)) {
input.output = inpt.output; input.output = inpt.output;
input.output_type = snakeCase(inpt.output_type); input.output_type = snakeCase(inpt.output_type);
input.output_connector = inpt.output_connector; input.output_connector = inpt.output_connector;
} }
if (present(inpt.pairs)) { if (present(inpt.pairs)) {
input.pairs = []; input.pairs = [];
inpt.pairs.forEach(pr => { inpt.pairs.forEach((pr) => {
if (present(pr.key) && present(pr.value)) { if (present(pr.key) && present(pr.value)) {
let pairParams = { let pairParams = {
index: pr.index, index: pr.index,
key: pr.key, key: pr.key,
key_type: snakeCase(pr.key_type), key_type: snakeCase(pr.key_type),
value: pr.value, value: pr.value,
value_type: snakeCase(pr.value_type), value_type: snakeCase(pr.value_type),
connector: pr.connector connector: pr.connector,
} };
input.pairs.push(pairParams); input.pairs.push(pairParams);
} }
}); });
} }
if ((input.type === 'assignment' && present(input.output)) || if (
present(input.pairs)) { (input.type === "assignment" && present(input.output)) ||
present(input.pairs)
) {
result.push(input); result.push(input);
} }
}); });
if (!result.length) { if (!result.length) {
result = false; result = false;
} }
return result; return result;
}, },
remove() { remove() {
return ajax(`/admin/wizards/wizard/${this.id}`, { return ajax(`/admin/wizards/wizard/${this.id}`, {
type: 'DELETE' type: "DELETE",
}).then(() => this.destroy()).catch(popupAjaxError); })
} .then(() => this.destroy())
.catch(popupAjaxError);
},
}); });
CustomWizard.reopenClass({ CustomWizard.reopenClass({
all() { all() {
return ajax("/admin/wizards/wizard", { return ajax("/admin/wizards/wizard", {
type: 'GET' type: "GET",
}).then(result => { })
return result.wizard_list; .then((result) => {
}).catch(popupAjaxError); return result.wizard_list;
})
.catch(popupAjaxError);
}, },
submissions(wizardId) { submissions(wizardId) {
return ajax(`/admin/wizards/submissions/${wizardId}`, { return ajax(`/admin/wizards/submissions/${wizardId}`, {
type: "GET" type: "GET",
}).catch(popupAjaxError); }).catch(popupAjaxError);
}, },
@ -209,7 +215,7 @@ CustomWizard.reopenClass({
const wizard = this._super.apply(this); const wizard = this._super.apply(this);
wizard.setProperties(buildProperties(wizardJson)); wizard.setProperties(buildProperties(wizardJson));
return wizard; return wizard;
} },
}); });
export default CustomWizard; export default CustomWizard;

Datei anzeigen

@ -1,16 +1,16 @@
import CustomWizardApi from '../models/custom-wizard-api'; import CustomWizardApi from "../models/custom-wizard-api";
import DiscourseRoute from "discourse/routes/discourse"; import DiscourseRoute from "discourse/routes/discourse";
export default DiscourseRoute.extend({ export default DiscourseRoute.extend({
model(params) { model(params) {
if (params.name === 'create') { if (params.name === "create") {
return CustomWizardApi.create({ isNew: true }); return CustomWizardApi.create({ isNew: true });
} else { } else {
return CustomWizardApi.find(params.name); return CustomWizardApi.find(params.name);
} }
}, },
setupController(controller, model){ setupController(controller, model) {
controller.set("api", model); controller.set("api", model);
} },
}); });

Datei anzeigen

@ -1,45 +1,44 @@
import DiscourseRoute from "discourse/routes/discourse"; import DiscourseRoute from "discourse/routes/discourse";
import CustomWizardApi from '../models/custom-wizard-api'; import CustomWizardApi from "../models/custom-wizard-api";
export default DiscourseRoute.extend({ export default DiscourseRoute.extend({
model() { model() {
return CustomWizardApi.list(); return CustomWizardApi.list();
}, },
setupController(controller, model) { setupController(controller, model) {
const showParams = this.paramsFor('adminWizardsApiShow'); const showParams = this.paramsFor("adminWizardsApiShow");
const apiName = showParams.name == 'create' ? null : showParams.name; const apiName = showParams.name == "create" ? null : showParams.name;
const apiList = (model || []).map(api => { const apiList = (model || []).map((api) => {
return { return {
id: api.name, id: api.name,
name: api.title name: api.title,
} };
}); });
controller.setProperties({ controller.setProperties({
apiName, apiName,
apiList apiList,
}) });
}, },
actions: { actions: {
changeApi(apiName) { changeApi(apiName) {
this.controllerFor('adminWizardsApi').set('apiName', apiName); this.controllerFor("adminWizardsApi").set("apiName", apiName);
this.transitionTo('adminWizardsApiShow', apiName); this.transitionTo("adminWizardsApiShow", apiName);
}, },
afterDestroy() { afterDestroy() {
this.transitionTo('adminWizardsApi').then(() => this.refresh()); this.transitionTo("adminWizardsApi").then(() => this.refresh());
}, },
afterSave(apiName) { afterSave(apiName) {
this.refresh().then(() => this.send('changeApi', apiName)); this.refresh().then(() => this.send("changeApi", apiName));
}, },
createApi() { createApi() {
this.controllerFor('adminWizardsApi').set('apiName', 'create'); this.controllerFor("adminWizardsApi").set("apiName", "create");
this.transitionTo('adminWizardsApiShow', 'create'); this.transitionTo("adminWizardsApiShow", "create");
} },
} },
});
});

Datei anzeigen

@ -6,9 +6,9 @@ export default DiscourseRoute.extend({
model() { model() {
return CustomWizardCustomField.listFields(); return CustomWizardCustomField.listFields();
}, },
setupController(controller, model) { setupController(controller, model) {
const customFields = A(model || []); const customFields = A(model || []);
controller.set('customFields', customFields); controller.set("customFields", customFields);
} },
}); });

Datei anzeigen

@ -1,4 +1,4 @@
import CustomWizardLogs from '../models/custom-wizard-logs'; import CustomWizardLogs from "../models/custom-wizard-logs";
import DiscourseRoute from "discourse/routes/discourse"; import DiscourseRoute from "discourse/routes/discourse";
export default DiscourseRoute.extend({ export default DiscourseRoute.extend({
@ -7,6 +7,6 @@ export default DiscourseRoute.extend({
}, },
setupController(controller, model) { setupController(controller, model) {
controller.set('logs', model); controller.set("logs", model);
} },
}) });

Datei anzeigen

@ -1,12 +1,12 @@
import CustomWizard from '../models/custom-wizard'; import CustomWizard from "../models/custom-wizard";
import DiscourseRoute from "discourse/routes/discourse"; import DiscourseRoute from "discourse/routes/discourse";
export default DiscourseRoute.extend({ export default DiscourseRoute.extend({
model() { model() {
return CustomWizard.all(); return CustomWizard.all();
}, },
setupController(controller, model) { setupController(controller, model) {
controller.set('wizards', model) controller.set("wizards", model);
} },
}); });

Datei anzeigen

@ -1,4 +1,4 @@
import CustomWizard from '../models/custom-wizard'; import CustomWizard from "../models/custom-wizard";
import DiscourseRoute from "discourse/routes/discourse"; import DiscourseRoute from "discourse/routes/discourse";
export default DiscourseRoute.extend({ export default DiscourseRoute.extend({
@ -25,12 +25,12 @@ export default DiscourseRoute.extend({
}); });
submissions.push(submission); submissions.push(submission);
}); });
controller.setProperties({ controller.setProperties({
wizard: model.wizard, wizard: model.wizard,
submissions, submissions,
fields fields,
}); });
} }
} },
}); });

Datei anzeigen

@ -1,24 +1,24 @@
import DiscourseRoute from "discourse/routes/discourse"; import DiscourseRoute from "discourse/routes/discourse";
import { ajax } from 'discourse/lib/ajax'; import { ajax } from "discourse/lib/ajax";
export default DiscourseRoute.extend({ export default DiscourseRoute.extend({
model() { model() {
return ajax(`/admin/wizards/wizard`); return ajax(`/admin/wizards/wizard`);
}, },
setupController(controller, model) { setupController(controller, model) {
const showParams = this.paramsFor('adminWizardsSubmissionsShow'); const showParams = this.paramsFor("adminWizardsSubmissionsShow");
controller.setProperties({ controller.setProperties({
wizardId: showParams.wizardId, wizardId: showParams.wizardId,
wizardList: model.wizard_list wizardList: model.wizard_list,
}) });
}, },
actions: { actions: {
changeWizard(wizardId) { changeWizard(wizardId) {
this.controllerFor('adminWizardsSubmissions').set('wizardId', wizardId); this.controllerFor("adminWizardsSubmissions").set("wizardId", wizardId);
this.transitionTo('adminWizardsSubmissionsShow', wizardId); this.transitionTo("adminWizardsSubmissionsShow", wizardId);
} },
} },
}); });

Datei anzeigen

@ -1,47 +1,49 @@
import CustomWizard from '../models/custom-wizard'; import CustomWizard from "../models/custom-wizard";
import { ajax } from 'discourse/lib/ajax'; import { ajax } from "discourse/lib/ajax";
import DiscourseRoute from "discourse/routes/discourse"; import DiscourseRoute from "discourse/routes/discourse";
import I18n from "I18n"; import I18n from "I18n";
import { selectKitContent } from '../lib/wizard'; import { selectKitContent } from "../lib/wizard";
export default DiscourseRoute.extend({ export default DiscourseRoute.extend({
model(params) { model(params) {
if (params.wizardId === 'create') { if (params.wizardId === "create") {
return { create: true }; return { create: true };
} else { } else {
return ajax(`/admin/wizards/wizard/${params.wizardId}`); return ajax(`/admin/wizards/wizard/${params.wizardId}`);
} }
}, },
afterModel(model) { afterModel(model) {
if (model.none) { if (model.none) {
return this.transitionTo('adminWizardsWizard'); return this.transitionTo("adminWizardsWizard");
} }
}, },
setupController(controller, model) { setupController(controller, model) {
const parentModel = this.modelFor('adminWizardsWizard'); const parentModel = this.modelFor("adminWizardsWizard");
const wizard = CustomWizard.create((!model || model.create) ? {} : model); const wizard = CustomWizard.create(!model || model.create ? {} : model);
const fieldTypes = Object.keys(parentModel.field_types).map(type => { const fieldTypes = Object.keys(parentModel.field_types).map((type) => {
return { return {
id: type, id: type,
name: I18n.t(`admin.wizard.field.type.${type}`) name: I18n.t(`admin.wizard.field.type.${type}`),
}; };
}) });
let props = { let props = {
wizardList: parentModel.wizard_list, wizardList: parentModel.wizard_list,
fieldTypes, fieldTypes,
userFields: parentModel.userFields, userFields: parentModel.userFields,
customFields: selectKitContent(parentModel.custom_fields.map(f => f.name)), customFields: selectKitContent(
parentModel.custom_fields.map((f) => f.name)
),
apis: parentModel.apis, apis: parentModel.apis,
themes: parentModel.themes, themes: parentModel.themes,
wizard, wizard,
currentStep: wizard.steps[0], currentStep: wizard.steps[0],
currentAction: wizard.actions[0], currentAction: wizard.actions[0],
creating: model.create creating: model.create,
}; };
controller.setProperties(props); controller.setProperties(props);
} },
}); });

Datei anzeigen

@ -1,15 +1,15 @@
import DiscourseRoute from "discourse/routes/discourse"; import DiscourseRoute from "discourse/routes/discourse";
import { buildFieldTypes, buildFieldValidations } from '../lib/wizard-schema'; import { buildFieldTypes, buildFieldValidations } from "../lib/wizard-schema";
import EmberObject, { set } from "@ember/object"; import EmberObject, { set } from "@ember/object";
import { A } from "@ember/array"; import { A } from "@ember/array";
import { all } from "rsvp"; import { all } from "rsvp";
import { ajax } from 'discourse/lib/ajax'; import { ajax } from "discourse/lib/ajax";
export default DiscourseRoute.extend({ export default DiscourseRoute.extend({
model() { model() {
return ajax("/admin/wizards/wizard"); return ajax("/admin/wizards/wizard");
}, },
afterModel(model) { afterModel(model) {
buildFieldTypes(model.field_types); buildFieldTypes(model.field_types);
buildFieldValidations(model.realtime_validations); buildFieldValidations(model.realtime_validations);
@ -17,80 +17,86 @@ export default DiscourseRoute.extend({
return all([ return all([
this._getThemes(model), this._getThemes(model),
this._getApis(model), this._getApis(model),
this._getUserFields(model) this._getUserFields(model),
]); ]);
}, },
_getThemes(model) { _getThemes(model) {
return ajax('/admin/themes') return ajax("/admin/themes").then((result) => {
.then((result) => { set(
set(model, 'themes', result.themes.map(t => { model,
"themes",
result.themes.map((t) => {
return { return {
id: t.id, id: t.id,
name: t.name name: t.name,
} };
})); })
}); );
});
}, },
_getApis(model) { _getApis(model) {
return ajax('/admin/wizards/api') return ajax("/admin/wizards/api").then((result) =>
.then((result) => set(model, 'apis', result)); set(model, "apis", result)
);
}, },
_getUserFields(model) { _getUserFields(model) {
return this.store.findAll('user-field').then((result) => { return this.store.findAll("user-field").then((result) => {
if (result && result.content) { if (result && result.content) {
set(model, 'userFields', set(
model,
"userFields",
result.content.map((f) => ({ result.content.map((f) => ({
id: `user_field_${f.id}`, id: `user_field_${f.id}`,
name: f.name name: f.name,
})) }))
); );
} }
}); });
}, },
currentWizard() { currentWizard() {
const params = this.paramsFor('adminWizardsWizardShow'); const params = this.paramsFor("adminWizardsWizardShow");
if (params && params.wizardId) { if (params && params.wizardId) {
return params.wizardId; return params.wizardId;
} else { } else {
return null; return null;
} }
}, },
setupController(controller, model) { setupController(controller, model) {
controller.setProperties({ controller.setProperties({
wizardList: model.wizard_list, wizardList: model.wizard_list,
wizardId: this.currentWizard(), wizardId: this.currentWizard(),
custom_fields: A(model.custom_fields.map(f => EmberObject.create(f))) custom_fields: A(model.custom_fields.map((f) => EmberObject.create(f))),
}); });
}, },
actions: { actions: {
changeWizard(wizardId) { changeWizard(wizardId) {
this.controllerFor('adminWizardsWizard').set('wizardId', wizardId); this.controllerFor("adminWizardsWizard").set("wizardId", wizardId);
if (wizardId) { if (wizardId) {
this.transitionTo('adminWizardsWizardShow', wizardId); this.transitionTo("adminWizardsWizardShow", wizardId);
} else { } else {
this.transitionTo('adminWizardsWizard'); this.transitionTo("adminWizardsWizard");
} }
}, },
afterDestroy() { afterDestroy() {
this.transitionTo('adminWizardsWizard').then(() => this.refresh()); this.transitionTo("adminWizardsWizard").then(() => this.refresh());
}, },
afterSave(wizardId) { afterSave(wizardId) {
this.refresh().then(() => this.send('changeWizard', wizardId)); this.refresh().then(() => this.send("changeWizard", wizardId));
}, },
createWizard() { createWizard() {
this.controllerFor('adminWizardsWizard').set('wizardId', 'create'); this.controllerFor("adminWizardsWizard").set("wizardId", "create");
this.transitionTo('adminWizardsWizardShow', 'create'); this.transitionTo("adminWizardsWizardShow", "create");
} },
} },
}); });

Datei anzeigen

@ -3,7 +3,7 @@ import DiscourseRoute from "discourse/routes/discourse";
export default DiscourseRoute.extend({ export default DiscourseRoute.extend({
beforeModel(transition) { beforeModel(transition) {
if (transition.targetName === "adminWizards.index") { if (transition.targetName === "adminWizards.index") {
this.transitionTo('adminWizardsWizard'); this.transitionTo("adminWizardsWizard");
} }
}, },
}); });

Datei anzeigen

@ -1,5 +1,5 @@
window.Discourse = {} window.Discourse = {};
window.Wizard = {}; window.Wizard = {};
Wizard.SiteSettings = {}; Wizard.SiteSettings = {};
Discourse.__widget_helpers = {}; Discourse.__widget_helpers = {};
Discourse.SiteSettings = Wizard.SiteSettings; Discourse.SiteSettings = Wizard.SiteSettings;

Datei anzeigen

@ -1,4 +1,4 @@
(function () { (function () {
document.cookie = 'destination_url=' + window.location.href + ';path=/'; document.cookie = "destination_url=" + window.location.href + ";path=/";
window.location.href = '/login' window.location.href = "/login";
})() })();

Datei anzeigen

@ -1,4 +1,4 @@
(function() { (function () {
var wizard = require('discourse/plugins/discourse-custom-wizard/wizard/custom-wizard').default.create(); var wizard = require("discourse/plugins/discourse-custom-wizard/wizard/custom-wizard").default.create();
wizard.start(); wizard.start();
})(); })();

Datei anzeigen

@ -1,9 +1,12 @@
import { default as computed, observes } from 'discourse-common/utils/decorators'; import {
import { renderAvatar } from 'discourse/helpers/user-avatar'; default as computed,
import userSearch from '../lib/user-search'; observes,
} from "discourse-common/utils/decorators";
import { renderAvatar } from "discourse/helpers/user-avatar";
import userSearch from "../lib/user-search";
import WizardI18n from "../lib/wizard-i18n"; import WizardI18n from "../lib/wizard-i18n";
const template = function(params) { const template = function (params) {
const options = params.options; const options = params.options;
let html = "<div class='autocomplete'>"; let html = "<div class='autocomplete'>";
@ -11,7 +14,7 @@ const template = function(params) {
html += "<ul>"; html += "<ul>";
options.users.forEach((u) => { options.users.forEach((u) => {
html += `<li><a href title="${u.name}">`; html += `<li><a href title="${u.name}">`;
html += renderAvatar(u, { imageSize: 'tiny' }); html += renderAvatar(u, { imageSize: "tiny" });
html += `<span class='username'>${u.username}</span>`; html += `<span class='username'>${u.username}</span>`;
if (u.name) { if (u.name) {
html += `<span class='name'>${u.name}</span>`; html += `<span class='name'>${u.name}</span>`;
@ -19,7 +22,7 @@ const template = function(params) {
html += `</a></li>`; html += `</a></li>`;
}); });
html += "</ul>"; html += "</ul>";
}; }
html += "</div>"; html += "</div>";
@ -27,10 +30,10 @@ const template = function(params) {
}; };
export default Ember.TextField.extend({ export default Ember.TextField.extend({
attributeBindings: ['autofocus', 'maxLength'], attributeBindings: ["autofocus", "maxLength"],
autocorrect: false, autocorrect: false,
autocapitalize: false, autocapitalize: false,
name: 'user-selector', name: "user-selector",
id: "custom-member-selector", id: "custom-member-selector",
@computed("placeholderKey") @computed("placeholderKey")
@ -38,101 +41,107 @@ export default Ember.TextField.extend({
return placeholderKey ? WizardI18n(placeholderKey) : ""; return placeholderKey ? WizardI18n(placeholderKey) : "";
}, },
@observes('usernames') @observes("usernames")
_update() { _update() {
if (this.get('canReceiveUpdates') === 'true') if (this.get("canReceiveUpdates") === "true")
this.didInsertElement({updateData: true}); this.didInsertElement({ updateData: true });
}, },
didInsertElement(opts) { didInsertElement(opts) {
this._super(); this._super();
var self = this, var self = this,
selected = [], selected = [],
groups = [], groups = [],
currentUser = this.currentUser, currentUser = this.currentUser,
includeMentionableGroups = this.get('includeMentionableGroups') === 'true', includeMentionableGroups =
includeMessageableGroups = this.get('includeMessageableGroups') === 'true', this.get("includeMentionableGroups") === "true",
includeGroups = this.get('includeGroups') === 'true', includeMessageableGroups =
allowedUsers = this.get('allowedUsers') === 'true'; this.get("includeMessageableGroups") === "true",
includeGroups = this.get("includeGroups") === "true",
allowedUsers = this.get("allowedUsers") === "true";
function excludedUsernames() { function excludedUsernames() {
// hack works around some issues with allowAny eventing // hack works around some issues with allowAny eventing
const usernames = self.get('single') ? [] : selected; const usernames = self.get("single") ? [] : selected;
if (currentUser && self.get('excludeCurrentUser')) { if (currentUser && self.get("excludeCurrentUser")) {
return usernames.concat([currentUser.get('username')]); return usernames.concat([currentUser.get("username")]);
} }
return usernames; return usernames;
} }
$(this.element).val(this.get('usernames')).autocomplete({ $(this.element)
template, .val(this.get("usernames"))
disabled: this.get('disabled'), .autocomplete({
single: this.get('single'), template,
allowAny: this.get('allowAny'), disabled: this.get("disabled"),
updateData: (opts && opts.updateData) ? opts.updateData : false, single: this.get("single"),
allowAny: this.get("allowAny"),
updateData: opts && opts.updateData ? opts.updateData : false,
dataSource(term) { dataSource(term) {
const termRegex = /[^a-zA-Z0-9_\-\.@\+]/; const termRegex = /[^a-zA-Z0-9_\-\.@\+]/;
var results = userSearch({ var results = userSearch({
term: term.replace(termRegex, ''), term: term.replace(termRegex, ""),
topicId: self.get('topicId'), topicId: self.get("topicId"),
exclude: excludedUsernames(), exclude: excludedUsernames(),
includeGroups, includeGroups,
allowedUsers, allowedUsers,
includeMentionableGroups, includeMentionableGroups,
includeMessageableGroups includeMessageableGroups,
});
return results;
},
transformComplete(v) {
if (v.username || v.name) {
if (!v.username) { groups.push(v.name); }
return v.username || v.name;
} else {
var excludes = excludedUsernames();
return v.usernames.filter(function(item){
return excludes.indexOf(item) === -1;
}); });
}
},
onChangeItems(items) { return results;
var hasGroups = false; },
items = items.map(function(i) {
if (groups.indexOf(i) > -1) { hasGroups = true; }
return i.username ? i.username : i;
});
self.set('usernames', items.join(","));
self.set('hasGroups', hasGroups);
selected = items; transformComplete(v) {
if (self.get('onChangeCallback')) self.sendAction('onChangeCallback'); if (v.username || v.name) {
}, if (!v.username) {
groups.push(v.name);
}
return v.username || v.name;
} else {
var excludes = excludedUsernames();
return v.usernames.filter(function (item) {
return excludes.indexOf(item) === -1;
});
}
},
reverseTransform(i) { onChangeItems(items) {
return { username: i }; var hasGroups = false;
} items = items.map(function (i) {
if (groups.indexOf(i) > -1) {
hasGroups = true;
}
return i.username ? i.username : i;
});
self.set("usernames", items.join(","));
self.set("hasGroups", hasGroups);
}); selected = items;
if (self.get("onChangeCallback")) self.sendAction("onChangeCallback");
},
reverseTransform(i) {
return { username: i };
},
});
}, },
willDestroyElement() { willDestroyElement() {
this._super(); this._super();
$(this.element).autocomplete('destroy'); $(this.element).autocomplete("destroy");
}, },
// THIS IS A HUGE HACK TO SUPPORT CLEARING THE INPUT // THIS IS A HUGE HACK TO SUPPORT CLEARING THE INPUT
@observes('usernames') @observes("usernames")
_clearInput: function() { _clearInput: function () {
if (arguments.length > 1) { if (arguments.length > 1) {
if (Em.isEmpty(this.get("usernames"))) { if (Em.isEmpty(this.get("usernames"))) {
$(this.element).parent().find("a").click(); $(this.element).parent().find("a").click();
} }
} }
} },
}); });

Datei anzeigen

@ -10,44 +10,45 @@ import { categoryBadgeHTML } from "discourse/helpers/category-link";
import { dasherize } from "@ember/string"; import { dasherize } from "@ember/string";
export default WizardFieldValidator.extend({ export default WizardFieldValidator.extend({
classNames: ['similar-topics-validator'], classNames: ["similar-topics-validator"],
similarTopics: null, similarTopics: null,
hasInput: notEmpty('field.value'), hasInput: notEmpty("field.value"),
hasSimilarTopics: notEmpty('similarTopics'), hasSimilarTopics: notEmpty("similarTopics"),
hasNotSearched: equal('similarTopics', null), hasNotSearched: equal("similarTopics", null),
noSimilarTopics: computed('similarTopics', function() { noSimilarTopics: computed("similarTopics", function () {
return this.similarTopics !== null && this.similarTopics.length == 0; return this.similarTopics !== null && this.similarTopics.length == 0;
}), }),
showDefault: computed('hasNotSearched', 'hasInput', 'typing', function() { showDefault: computed("hasNotSearched", "hasInput", "typing", function () {
return this.hasInput && (this.hasNotSearched || this.typing); return this.hasInput && (this.hasNotSearched || this.typing);
}), }),
showSimilarTopics: computed('typing', 'hasSimilarTopics', function() { showSimilarTopics: computed("typing", "hasSimilarTopics", function () {
return this.hasSimilarTopics && !this.typing; return this.hasSimilarTopics && !this.typing;
}), }),
showNoSimilarTopics: computed('typing', 'noSimilarTopics', function() { showNoSimilarTopics: computed("typing", "noSimilarTopics", function () {
return this.noSimilarTopics && !this.typing; return this.noSimilarTopics && !this.typing;
}), }),
hasValidationCategories: notEmpty('validationCategories'), hasValidationCategories: notEmpty("validationCategories"),
showValidationCategories: and('showDefault', 'hasValidationCategories'), showValidationCategories: and("showDefault", "hasValidationCategories"),
@discourseComputed('validation.categories') @discourseComputed("validation.categories")
validationCategories(categoryIds) { validationCategories(categoryIds) {
if (categoryIds) return categoryIds.map(id => this.site.categoriesById[id]); if (categoryIds)
return categoryIds.map((id) => this.site.categoriesById[id]);
return A(); return A();
}, },
@discourseComputed('validationCategories') @discourseComputed("validationCategories")
catLinks(categories) { catLinks(categories) {
return categories.map(category => categoryBadgeHTML(category)).join(""); return categories.map((category) => categoryBadgeHTML(category)).join("");
}, },
@discourseComputed( @discourseComputed(
'loading', "loading",
'showSimilarTopics', "showSimilarTopics",
'showNoSimilarTopics', "showNoSimilarTopics",
'showValidationCategories', "showValidationCategories",
'showDefault' "showDefault"
) )
currentState( currentState(
loading, loading,
@ -58,30 +59,31 @@ export default WizardFieldValidator.extend({
) { ) {
switch (true) { switch (true) {
case loading: case loading:
return 'loading'; return "loading";
case showSimilarTopics: case showSimilarTopics:
return 'results'; return "results";
case showNoSimilarTopics: case showNoSimilarTopics:
return 'no_results'; return "no_results";
case showValidationCategories: case showValidationCategories:
return 'default_categories'; return "default_categories";
case showDefault: case showDefault:
return 'default'; return "default";
default: default:
return false; return false;
} }
}, },
@discourseComputed('currentState') @discourseComputed("currentState")
currentStateClass (currentState) { currentStateClass(currentState) {
if (currentState) return `similar-topics-${dasherize(currentState)}`; if (currentState) return `similar-topics-${dasherize(currentState)}`;
return "similar-topics"; return "similar-topics";
}, },
@discourseComputed('currentState') @discourseComputed("currentState")
currentStateKey (currentState) { currentStateKey(currentState) {
if (currentState) return `realtime_validations.similar_topics.${currentState}`; if (currentState)
return `realtime_validations.similar_topics.${currentState}`;
return false; return false;
}, },
@ -91,17 +93,17 @@ export default WizardFieldValidator.extend({
@observes("field.value") @observes("field.value")
customValidate() { customValidate() {
const field = this.field; const field = this.field;
if (!field.value) return; if (!field.value) return;
const value = field.value; const value = field.value;
this.set("typing", true); this.set("typing", true);
if (value && value.length < 5) { if (value && value.length < 5) {
this.set('similarTopics', null); this.set("similarTopics", null);
return; return;
} }
const lastKeyUp = new Date(); const lastKeyUp = new Date();
this._lastKeyUp = lastKeyUp; this._lastKeyUp = lastKeyUp;
@ -113,28 +115,30 @@ export default WizardFieldValidator.extend({
return; return;
} }
this.set("typing", false); this.set("typing", false);
this.updateSimilarTopics(); this.updateSimilarTopics();
}, 1000); }, 1000);
}, },
updateSimilarTopics() { updateSimilarTopics() {
this.set('updating', true); this.set("updating", true);
this.backendValidate({ this.backendValidate({
title: this.get("field.value"), title: this.get("field.value"),
categories: this.get("validation.categories"), categories: this.get("validation.categories"),
date_after: this.get("validation.date_after"), date_after: this.get("validation.date_after"),
}).then((result) => { })
const similarTopics = A( .then((result) => {
deepMerge(result["topics"], result["similar_topics"]) const similarTopics = A(
); deepMerge(result["topics"], result["similar_topics"])
similarTopics.forEach(function (topic, index) { );
similarTopics[index] = EmberObject.create(topic); similarTopics.forEach(function (topic, index) {
}); similarTopics[index] = EmberObject.create(topic);
});
this.set("similarTopics", similarTopics); this.set("similarTopics", similarTopics);
}).finally(() => this.set('updating', false)); })
.finally(() => this.set("updating", false));
}, },
actions: { actions: {

Datei anzeigen

@ -4,14 +4,14 @@ import { ajax } from "discourse/lib/ajax";
import { getToken } from "wizard/lib/ajax"; import { getToken } from "wizard/lib/ajax";
export default Component.extend({ export default Component.extend({
classNames: ['validator'], classNames: ["validator"],
classNameBindings: ["isValid", "isInvalid"], classNameBindings: ["isValid", "isInvalid"],
validMessageKey: null, validMessageKey: null,
invalidMessageKey: null, invalidMessageKey: null,
isValid: null, isValid: null,
isInvalid: equal("isValid", false), isInvalid: equal("isValid", false),
layoutName: "components/validator", // useful for sharing the template with extending components layoutName: "components/validator", // useful for sharing the template with extending components
init() { init() {
this._super(...arguments); this._super(...arguments);

Datei anzeigen

@ -1,12 +1,17 @@
import CategorySelector from 'select-kit/components/category-selector'; import CategorySelector from "select-kit/components/category-selector";
import { computed } from "@ember/object"; import { computed } from "@ember/object";
import { makeArray } from "discourse-common/lib/helpers"; import { makeArray } from "discourse-common/lib/helpers";
export default CategorySelector.extend({ export default CategorySelector.extend({
content: computed("categories.[]", "blacklist.[]", "whitelist.[]", function() { content: computed(
return this._super().filter(category => { "categories.[]",
const whitelist = makeArray(this.whitelist); "blacklist.[]",
return !whitelist.length || whitelist.indexOf(category.id) > -1; "whitelist.[]",
}); function () {
}) return this._super().filter((category) => {
}) const whitelist = makeArray(this.whitelist);
return !whitelist.length || whitelist.indexOf(category.id) > -1;
});
}
),
});

Datei anzeigen

@ -20,7 +20,7 @@ import {
import { cacheShortUploadUrl } from "pretty-text/upload-short-url"; import { cacheShortUploadUrl } from "pretty-text/upload-short-url";
import { alias } from "@ember/object/computed"; import { alias } from "@ember/object/computed";
import { uploadIcon } from "discourse/lib/uploads"; import { uploadIcon } from "discourse/lib/uploads";
import WizardI18n from '../lib/wizard-i18n'; import WizardI18n from "../lib/wizard-i18n";
const uploadMarkdownResolvers = []; const uploadMarkdownResolvers = [];

Datei anzeigen

@ -1,15 +1,15 @@
import Component from "@ember/component"; import Component from "@ember/component";
export default Component.extend({ export default Component.extend({
classNames: ['wizard-composer-hyperlink'], classNames: ["wizard-composer-hyperlink"],
actions: { actions: {
addLink() { addLink() {
this.addLink(this.linkName, this.linkUrl); this.addLink(this.linkName, this.linkUrl);
}, },
hideBox() { hideBox() {
this.hideBox(); this.hideBox();
} },
}, },
}); });

Datei anzeigen

@ -1,3 +1,3 @@
import DateInput from "discourse/components/date-input"; import DateInput from "discourse/components/date-input";
export default DateInput.extend(); export default DateInput.extend();

Datei anzeigen

@ -1,14 +1,14 @@
import DateTimeInput from "discourse/components/date-time-input"; import DateTimeInput from "discourse/components/date-time-input";
import discourseComputed from 'discourse-common/utils/decorators'; import discourseComputed from "discourse-common/utils/decorators";
export default DateTimeInput.extend({ export default DateTimeInput.extend({
@discourseComputed('timeFirst', 'tabindex') @discourseComputed("timeFirst", "tabindex")
timeTabindex(timeFirst, tabindex) { timeTabindex(timeFirst, tabindex) {
return timeFirst ? tabindex : tabindex + 1; return timeFirst ? tabindex : tabindex + 1;
}, },
@discourseComputed('timeFirst', 'tabindex') @discourseComputed("timeFirst", "tabindex")
dateTabindex(timeFirst, tabindex) { dateTabindex(timeFirst, tabindex) {
return timeFirst ? tabindex + 1 : tabindex; return timeFirst ? tabindex + 1 : tabindex;
} },
}); });

Datei anzeigen

@ -1,32 +1,39 @@
import { observes } from 'discourse-common/utils/decorators'; import { observes } from "discourse-common/utils/decorators";
import Category from 'discourse/models/category'; import Category from "discourse/models/category";
export default Ember.Component.extend({ export default Ember.Component.extend({
didInsertElement() { didInsertElement() {
const property = this.field.property || 'id'; const property = this.field.property || "id";
const value = this.field.value; const value = this.field.value;
if (value) { if (value) {
this.set('categories', [...value].reduce((result, v) => { this.set(
let val = property === 'id' ? Category.findById(v) : Category.findBySlug(v); "categories",
if (val) result.push(val); [...value].reduce((result, v) => {
return result; let val =
}, [])); property === "id" ? Category.findById(v) : Category.findBySlug(v);
if (val) result.push(val);
return result;
}, [])
);
} }
}, },
@observes('categories') @observes("categories")
setValue() { setValue() {
const categories = (this.categories || []).filter(c => !!c); const categories = (this.categories || []).filter((c) => !!c);
const property = this.field.property || 'id'; const property = this.field.property || "id";
if (categories.length) { if (categories.length) {
this.set('field.value', categories.reduce((result, c) => { this.set(
if (c && c[property]) { "field.value",
result.push(c[property]) categories.reduce((result, c) => {
} if (c && c[property]) {
return result; result.push(c[property]);
}, [])); }
return result;
}, [])
);
} }
} },
}); });

Datei anzeigen

@ -1,41 +1,47 @@
import { default as computed, observes } from 'discourse-common/utils/decorators'; import {
default as computed,
observes,
} from "discourse-common/utils/decorators";
import EmberObject from "@ember/object"; import EmberObject from "@ember/object";
export default Ember.Component.extend({ export default Ember.Component.extend({
showPreview: false, showPreview: false,
classNameBindings: [":wizard-field-composer", "showPreview:show-preview:hide-preview"], classNameBindings: [
":wizard-field-composer",
"showPreview:show-preview:hide-preview",
],
didInsertElement() { didInsertElement() {
this.set('composer', EmberObject.create({ this.set(
loading: false, "composer",
reply: this.get('field.value') EmberObject.create({
})) loading: false,
reply: this.get("field.value"),
})
);
}, },
@observes('composer.reply') @observes("composer.reply")
setField() { setField() {
this.set('field.value', this.get('composer.reply')); this.set("field.value", this.get("composer.reply"));
}, },
@computed('showPreview') @computed("showPreview")
togglePreviewLabel(showPreview) { togglePreviewLabel(showPreview) {
return showPreview ? 'wizard_composer.hide_preview' : 'wizard_composer.show_preview'; return showPreview
? "wizard_composer.hide_preview"
: "wizard_composer.show_preview";
}, },
actions: { actions: {
togglePreview() { togglePreview() {
this.toggleProperty('showPreview'); this.toggleProperty("showPreview");
}, },
groupsMentioned() { groupsMentioned() {},
}, afterRefresh() {},
afterRefresh() { cannotSeeMention() {},
}, importQuote() {},
cannotSeeMention() { showUploadSelector() {},
}, },
importQuote() {
},
showUploadSelector() {
}
}
}); });

Datei anzeigen

@ -1,15 +1,15 @@
import Component from "@ember/component"; import Component from "@ember/component";
import { observes } from 'discourse-common/utils/decorators'; import { observes } from "discourse-common/utils/decorators";
export default Component.extend({ export default Component.extend({
@observes('dateTime') @observes("dateTime")
setValue() { setValue() {
this.set('field.value', this.dateTime.format(this.field.format)); this.set("field.value", this.dateTime.format(this.field.format));
}, },
actions: { actions: {
onChange(value) { onChange(value) {
this.set('dateTime', moment(value)); this.set("dateTime", moment(value));
} },
} },
}); });

Datei anzeigen

@ -1,15 +1,15 @@
import Component from "@ember/component"; import Component from "@ember/component";
import { observes } from 'discourse-common/utils/decorators'; import { observes } from "discourse-common/utils/decorators";
export default Component.extend({ export default Component.extend({
@observes('date') @observes("date")
setValue() { setValue() {
this.set('field.value', this.date.format(this.field.format)); this.set("field.value", this.date.format(this.field.format));
}, },
actions: { actions: {
onChange(value) { onChange(value) {
this.set('date', moment(value)); this.set("date", moment(value));
} },
} },
}); });

Datei anzeigen

@ -1,20 +1,21 @@
import Component from "@ember/component"; import Component from "@ember/component";
import { observes } from 'discourse-common/utils/decorators'; import { observes } from "discourse-common/utils/decorators";
export default Component.extend({ export default Component.extend({
@observes('time') @observes("time")
setValue() { setValue() {
this.set('field.value', this.time.format(this.field.format)); this.set("field.value", this.time.format(this.field.format));
}, },
actions: { actions: {
onChange(value) { onChange(value) {
this.set('time', this.set(
"time",
moment({ moment({
hours: value.hours, hours: value.hours,
minutes: value.minutes minutes: value.minutes,
}) })
) );
} },
} },
}); });

Datei anzeigen

@ -20,10 +20,10 @@ export default Ember.Component.extend({
formData: { formData: {
synchronous: true, synchronous: true,
type: `wizard_${id}`, type: `wizard_${id}`,
authenticity_token: getToken() authenticity_token: getToken(),
}, },
dataType: "json", dataType: "json",
dropZone: $upload dropZone: $upload,
}); });
$upload.on("fileuploadsubmit", () => this.set("uploading", true)); $upload.on("fileuploadsubmit", () => this.set("uploading", true));
@ -31,12 +31,16 @@ export default Ember.Component.extend({
$upload.on("fileuploaddone", (e, response) => { $upload.on("fileuploaddone", (e, response) => {
this.setProperties({ this.setProperties({
"field.value": response.result, "field.value": response.result,
"uploading": false uploading: false,
}); });
if ( Discourse.SiteSettings.wizard_recognised_image_upload_formats.split('|').includes(response.result.extension)) { if (
Discourse.SiteSettings.wizard_recognised_image_upload_formats
.split("|")
.includes(response.result.extension)
) {
this.setProperties({ this.setProperties({
"isImage": true isImage: true,
}) });
} }
}); });
@ -51,9 +55,9 @@ export default Ember.Component.extend({
title: "", title: "",
text: message, text: message,
type: "warning", type: "warning",
confirmButtonColor: "#6699ff" confirmButtonColor: "#6699ff",
}); });
this.set("uploading", false); this.set("uploading", false);
}); });
} },
}); });

Datei anzeigen

@ -1,17 +1,19 @@
import ComboBox from 'select-kit/components/combo-box'; import ComboBox from "select-kit/components/combo-box";
import { computed } from "@ember/object"; import { computed } from "@ember/object";
import { makeArray } from "discourse-common/lib/helpers"; import { makeArray } from "discourse-common/lib/helpers";
export default ComboBox.extend({ export default ComboBox.extend({
content: computed("groups.[]", "field.content.[]", function() { content: computed("groups.[]", "field.content.[]", function () {
const whitelist = makeArray(this.field.content); const whitelist = makeArray(this.field.content);
return this.groups.filter(group => { return this.groups
return !whitelist.length || whitelist.indexOf(group.id) > -1; .filter((group) => {
}).map(g => { return !whitelist.length || whitelist.indexOf(group.id) > -1;
return { })
id: g.id, .map((g) => {
name: g.full_name ? g.full_name : g.name return {
} id: g.id,
}); name: g.full_name ? g.full_name : g.name,
}) };
}) });
}),
});

Datei anzeigen

@ -1,13 +1,13 @@
import CustomWizard from '../models/custom'; import CustomWizard from "../models/custom";
export default Ember.Component.extend({ export default Ember.Component.extend({
siteName: function() { siteName: function () {
return Wizard.SiteSettings.title; return Wizard.SiteSettings.title;
}.property(), }.property(),
actions: { actions: {
skip() { skip() {
CustomWizard.skip(this.get('wizardId')); CustomWizard.skip(this.get("wizardId"));
} },
} },
}); });

Datei anzeigen

@ -2,10 +2,10 @@ import Component from "@ember/component";
import { bind } from "@ember/runloop"; import { bind } from "@ember/runloop";
import { observes } from "discourse-common/utils/decorators"; import { observes } from "discourse-common/utils/decorators";
export default Component.extend({ export default Component.extend({
classNames: ['wizard-similar-topics'], classNames: ["wizard-similar-topics"],
showTopics: true, showTopics: true,
didInsertElement() { didInsertElement() {
$(document).on("click", bind(this, this.documentClick)); $(document).on("click", bind(this, this.documentClick));
}, },
@ -18,19 +18,19 @@ export default Component.extend({
if (this._state == "destroying") return; if (this._state == "destroying") return;
let $target = $(e.target); let $target = $(e.target);
if (!$target.hasClass('show-topics')) { if (!$target.hasClass("show-topics")) {
this.set('showTopics', false); this.set("showTopics", false);
} }
}, },
@observes('topics') @observes("topics")
toggleShowWhenTopicsChange() { toggleShowWhenTopicsChange() {
this.set('showTopics', true); this.set("showTopics", true);
}, },
actions: { actions: {
toggleShowTopics() { toggleShowTopics() {
this.set('showTopics', true); this.set("showTopics", true);
} },
} },
}) });

Datei anzeigen

@ -1,4 +1,4 @@
import TagChooser from 'select-kit/components/tag-chooser'; import TagChooser from "select-kit/components/tag-chooser";
import { makeArray } from "discourse-common/lib/helpers"; import { makeArray } from "discourse-common/lib/helpers";
export default TagChooser.extend({ export default TagChooser.extend({
@ -7,5 +7,5 @@ export default TagChooser.extend({
const whitelist = makeArray(context.whitelist); const whitelist = makeArray(context.whitelist);
return !whitelist.length || whitelist.indexOf(tag.id) > 1; return !whitelist.length || whitelist.indexOf(tag.id) > 1;
}); });
} },
}) });

Datei anzeigen

@ -5,14 +5,20 @@ import { siteDir, isRTL, isLTR } from "discourse/lib/text-direction";
import WizardI18n from "../lib/wizard-i18n"; import WizardI18n from "../lib/wizard-i18n";
export default Ember.TextField.extend({ export default Ember.TextField.extend({
attributeBindings: ['autocorrect', 'autocapitalize', 'autofocus', 'maxLength', 'dir'], attributeBindings: [
"autocorrect",
"autocapitalize",
"autofocus",
"maxLength",
"dir",
],
@computed @computed
dir() { dir() {
if (Wizard.SiteSettings.support_mixed_text_direction) { if (Wizard.SiteSettings.support_mixed_text_direction) {
let val = this.value; let val = this.value;
if (val) { if (val) {
return isRTL(val) ? 'rtl' : 'ltr'; return isRTL(val) ? "rtl" : "ltr";
} else { } else {
return siteDir(); return siteDir();
} }
@ -23,11 +29,11 @@ export default Ember.TextField.extend({
if (Wizard.SiteSettings.support_mixed_text_direction) { if (Wizard.SiteSettings.support_mixed_text_direction) {
let val = this.value; let val = this.value;
if (isRTL(val)) { if (isRTL(val)) {
this.set('dir', 'rtl'); this.set("dir", "rtl");
} else if (isLTR(val)) { } else if (isLTR(val)) {
this.set('dir', 'ltr'); this.set("dir", "ltr");
} else { } else {
this.set('dir', siteDir()); this.set("dir", siteDir());
} }
} }
}, },
@ -35,5 +41,5 @@ export default Ember.TextField.extend({
@computed("placeholderKey") @computed("placeholderKey")
placeholder(placeholderKey) { placeholder(placeholderKey) {
return placeholderKey ? WizardI18n(placeholderKey) : ""; return placeholderKey ? WizardI18n(placeholderKey) : "";
} },
}); });

Datei anzeigen

@ -1,3 +1,3 @@
import TimeInput from "discourse/components/time-input"; import TimeInput from "discourse/components/time-input";
export default TimeInput.extend(); export default TimeInput.extend();

Datei anzeigen

@ -1,32 +1,32 @@
import StepController from 'wizard/controllers/step'; import StepController from "wizard/controllers/step";
import getUrl from 'discourse-common/lib/get-url'; import getUrl from "discourse-common/lib/get-url";
export default StepController.extend({ export default StepController.extend({
actions: { actions: {
goNext(response) { goNext(response) {
const next = this.get('step.next'); const next = this.get("step.next");
if (response.redirect_on_next) { if (response.redirect_on_next) {
window.location.href = response.redirect_on_next; window.location.href = response.redirect_on_next;
} else if (response.refresh_required) { } else if (response.refresh_required) {
const id = this.get('wizard.id'); const id = this.get("wizard.id");
window.location.href = getUrl(`/w/${id}/steps/${next}`); window.location.href = getUrl(`/w/${id}/steps/${next}`);
} else { } else {
this.transitionToRoute('custom.step', next); this.transitionToRoute("custom.step", next);
} }
}, },
goBack() { goBack() {
this.transitionToRoute('custom.step', this.get('step.previous')); this.transitionToRoute("custom.step", this.get("step.previous"));
}, },
showMessage(message) { showMessage(message) {
this.set('stepMessage', message); this.set("stepMessage", message);
}, },
resetWizard() { resetWizard() {
const id = this.get('wizard.id'); const id = this.get("wizard.id");
const stepId = this.get('step.id'); const stepId = this.get("step.id");
window.location.href = getUrl(`/w/${id}/steps/${stepId}?reset=true`); window.location.href = getUrl(`/w/${id}/steps/${stepId}?reset=true`);
} },
} },
}); });

Datei anzeigen

@ -1,3 +1,3 @@
export default Ember.Controller.extend({ export default Ember.Controller.extend({
queryParams: ['reset'] queryParams: ["reset"],
}); });

Datei anzeigen

@ -1,7 +1,7 @@
import { buildResolver } from "discourse-common/resolver"; import { buildResolver } from "discourse-common/resolver";
export default Ember.Application.extend({ export default Ember.Application.extend({
rootElement: '#custom-wizard-main', rootElement: "#custom-wizard-main",
Resolver: buildResolver("wizard"), Resolver: buildResolver("wizard"),
start() { start() {
@ -11,7 +11,7 @@ export default Ember.Application.extend({
if (!module) { if (!module) {
throw new Error(key + " must export an initializer."); throw new Error(key + " must export an initializer.");
} }
const init = module.default; const init = module.default;
const oldInitialize = init.initialize; const oldInitialize = init.initialize;
init.initialize = () => { init.initialize = () => {
@ -21,8 +21,8 @@ export default Ember.Application.extend({
this.initializer(init); this.initializer(init);
} }
}); });
Object.keys(requirejs._eak_seen).forEach(key => { Object.keys(requirejs._eak_seen).forEach((key) => {
if (/\/initializers\//.test(key)) { if (/\/initializers\//.test(key)) {
const module = requirejs(key, null, null, true); const module = requirejs(key, null, null, true);
if (!module) { if (!module) {
@ -31,5 +31,5 @@ export default Ember.Application.extend({
this.initializer(module.default); this.initializer(module.default);
} }
}); });
} },
}); });

Datei anzeigen

@ -1,16 +1,21 @@
import { registerUnbound } from "discourse-common/lib/helpers"; import { registerUnbound } from "discourse-common/lib/helpers";
import I18n from "I18n"; import I18n from "I18n";
export default registerUnbound("char-counter", function(body, maxLength) { export default registerUnbound("char-counter", function (body, maxLength) {
let bodyLength = body ? body.length : 0; let bodyLength = body ? body.length : 0;
let finalString; let finalString;
if (maxLength) { if (maxLength) {
let isOverMax = bodyLength > maxLength ? "true" : "false"; let isOverMax = bodyLength > maxLength ? "true" : "false";
finalString = `<div class="body-length" data-length=${bodyLength} data-over-max=${isOverMax}>${bodyLength} / ${I18n.t('wizard.x_characters', { count: parseInt(maxLength) })}</div>`; finalString = `<div class="body-length" data-length=${bodyLength} data-over-max=${isOverMax}>${bodyLength} / ${I18n.t(
} else { "wizard.x_characters",
finalString = `<div class="body-length">${I18n.t('wizard.x_characters', { count: parseInt(bodyLength) })}</div>`; { count: parseInt(maxLength) }
} )}</div>`;
} else {
finalString = `<div class="body-length">${I18n.t("wizard.x_characters", {
count: parseInt(bodyLength),
})}</div>`;
}
return new Handlebars.SafeString(finalString); return new Handlebars.SafeString(finalString);
}); });

Datei anzeigen

@ -1,5 +1,5 @@
import { registerUnbound } from "discourse-common/lib/helpers"; import { registerUnbound } from "discourse-common/lib/helpers";
export default registerUnbound("dir-span", function(str) { export default registerUnbound("dir-span", function (str) {
return new Handlebars.SafeString(str); return new Handlebars.SafeString(str);
}); });

Datei anzeigen

@ -1,15 +1,17 @@
import { htmlHelper } from 'discourse-common/lib/helpers'; import { htmlHelper } from "discourse-common/lib/helpers";
function renderSpinner(cssClass) { function renderSpinner(cssClass) {
var html = "<div class='spinner"; var html = "<div class='spinner";
if (cssClass) { html += ' ' + cssClass; } if (cssClass) {
html += " " + cssClass;
}
return html + "'></div>"; return html + "'></div>";
} }
var spinnerHTML = renderSpinner(); var spinnerHTML = renderSpinner();
export default htmlHelper(params => { export default htmlHelper((params) => {
const hash = params.hash; const hash = params.hash;
return renderSpinner((hash && hash.size) ? hash.size : undefined); return renderSpinner(hash && hash.size ? hash.size : undefined);
}); });
export { spinnerHTML, renderSpinner }; export { spinnerHTML, renderSpinner };

Datei anzeigen

@ -1,5 +1,5 @@
import { registerUnbound } from "discourse-common/lib/helpers"; import { registerUnbound } from "discourse-common/lib/helpers";
export default registerUnbound("plugin-outlet", function(attrs) { export default registerUnbound("plugin-outlet", function (attrs) {
return new Handlebars.SafeString(''); return new Handlebars.SafeString("");
}); });

Datei anzeigen

@ -1,6 +1,6 @@
import { registerUnbound } from 'discourse-common/lib/helpers'; import { registerUnbound } from "discourse-common/lib/helpers";
import WizardI18n from '../lib/wizard-i18n'; import WizardI18n from "../lib/wizard-i18n";
export default registerUnbound("wizard-i18n", (key, params) => { export default registerUnbound("wizard-i18n", (key, params) => {
return WizardI18n(key, params); return WizardI18n(key, params);
}); });

Datei anzeigen

@ -5,20 +5,22 @@ export default {
name: "custom-wizard-field", name: "custom-wizard-field",
initialize(app) { initialize(app) {
if (window.location.pathname.indexOf("/w/") < 0) return; if (window.location.pathname.indexOf("/w/") < 0) return;
const FieldComponent = requirejs("wizard/components/wizard-field").default; const FieldComponent = requirejs("wizard/components/wizard-field").default;
const FieldModel = requirejs("wizard/models/wizard-field").default; const FieldModel = requirejs("wizard/models/wizard-field").default;
const { cook } = requirejs("discourse/plugins/discourse-custom-wizard/wizard/lib/text-lite"); const { cook } = requirejs(
"discourse/plugins/discourse-custom-wizard/wizard/lib/text-lite"
);
const DEditor = requirejs("discourse/components/d-editor").default; const DEditor = requirejs("discourse/components/d-editor").default;
const { clipboardHelpers } = requirejs("discourse/lib/utilities"); const { clipboardHelpers } = requirejs("discourse/lib/utilities");
const { toMarkdown } = requirejs("discourse/lib/to-markdown"); const { toMarkdown } = requirejs("discourse/lib/to-markdown");
FieldComponent.reopen({ FieldComponent.reopen({
classNameBindings: ["field.id"], classNameBindings: ["field.id"],
@discourseComputed("field.type") @discourseComputed("field.type")
textType(fieldType) { textType(fieldType) {
return ['text', 'textarea'].includes(fieldType); return ["text", "textarea"].includes(fieldType);
}, },
cookedDescription: function () { cookedDescription: function () {
@ -81,35 +83,43 @@ export default {
return valid; return valid;
}, },
}); });
const isInside = (text, regex) => { const isInside = (text, regex) => {
const matches = text.match(regex); const matches = text.match(regex);
return matches && matches.length % 2; return matches && matches.length % 2;
}; };
DEditor.reopen({ DEditor.reopen({
isComposer: true, isComposer: true,
didInsertElement() { didInsertElement() {
this._super(); this._super();
if (this.wizardComposerEvents) { if (this.wizardComposerEvents) {
this.appEvents.on("wizard-editor:insert-text", this, "_wizardInsertText"); this.appEvents.on(
this.appEvents.on("wizard-editor:replace-text", this, "_wizardReplaceText"); "wizard-editor:insert-text",
this,
"_wizardInsertText"
);
this.appEvents.on(
"wizard-editor:replace-text",
this,
"_wizardReplaceText"
);
} }
}, },
_wizardInsertText(args = {}) { _wizardInsertText(args = {}) {
if (args.fieldId === this.fieldId) { if (args.fieldId === this.fieldId) {
this._insertText(args.text, args.options); this._insertText(args.text, args.options);
} }
}, },
_wizardReplaceText(args = {}) { _wizardReplaceText(args = {}) {
if (args.fieldId === this.fieldId) { if (args.fieldId === this.fieldId) {
this._replaceText(args.oldVal, args.newVal, args.opts = {}); this._replaceText(args.oldVal, args.newVal, (args.opts = {}));
} }
}, },
paste(e) { paste(e) {
if (!$(".d-editor-input").is(":focus")) { if (!$(".d-editor-input").is(":focus")) {
return; return;
@ -140,7 +150,7 @@ export default {
if (table) { if (table) {
this.appEvents.trigger("wizard-editor:insert-text", { this.appEvents.trigger("wizard-editor:insert-text", {
fieldId: this.fieldId, fieldId: this.fieldId,
text: table text: table,
}); });
handled = true; handled = true;
} }
@ -169,7 +179,7 @@ export default {
this.appEvents.trigger("composer:insert-text", { this.appEvents.trigger("composer:insert-text", {
fieldId: this.fieldId, fieldId: this.fieldId,
text: markdown text: markdown,
}); });
handled = true; handled = true;
} }
@ -180,5 +190,5 @@ export default {
} }
}, },
}); });
} },
} };

Datei anzeigen

@ -2,15 +2,20 @@ export default {
name: "custom-wizard-step", name: "custom-wizard-step",
initialize(app) { initialize(app) {
if (window.location.pathname.indexOf("/w/") < 0) return; if (window.location.pathname.indexOf("/w/") < 0) return;
const CustomWizard = requirejs("discourse/plugins/discourse-custom-wizard/wizard/models/custom").default; const CustomWizard = requirejs(
"discourse/plugins/discourse-custom-wizard/wizard/models/custom"
).default;
const StepModel = requirejs("wizard/models/step").default; const StepModel = requirejs("wizard/models/step").default;
const StepComponent = requirejs("wizard/components/wizard-step").default; const StepComponent = requirejs("wizard/components/wizard-step").default;
const ajax = requirejs("wizard/lib/ajax").ajax; const ajax = requirejs("wizard/lib/ajax").ajax;
const getUrl = requirejs("discourse-common/lib/get-url").default; const getUrl = requirejs("discourse-common/lib/get-url").default;
const discourseComputed = requirejs("discourse-common/utils/decorators").default; const discourseComputed = requirejs("discourse-common/utils/decorators")
const cook = requirejs("discourse/plugins/discourse-custom-wizard/wizard/lib/text-lite").cook; .default;
const cook = requirejs(
"discourse/plugins/discourse-custom-wizard/wizard/lib/text-lite"
).cook;
StepModel.reopen({ StepModel.reopen({
save() { save() {
const wizardId = this.get("wizardId"); const wizardId = this.get("wizardId");
@ -68,13 +73,15 @@ export default {
Ember.run.later(() => this.set("message", null), 6000); Ember.run.later(() => this.set("message", null), 6000);
}, },
}); });
StepComponent.reopen({ StepComponent.reopen({
classNameBindings: ["step.id"], classNameBindings: ["step.id"],
animateInvalidFields() { animateInvalidFields() {
Ember.run.scheduleOnce("afterRender", () => { Ember.run.scheduleOnce("afterRender", () => {
let $element = $(".invalid input[type=text],.invalid textarea,.invalid input[type=checkbox],.invalid .select-kit"); let $element = $(
".invalid input[type=text],.invalid textarea,.invalid input[type=checkbox],.invalid .select-kit"
);
if ($element.length) { if ($element.length) {
$([document.documentElement, document.body]).animate( $([document.documentElement, document.body]).animate(
@ -113,13 +120,13 @@ export default {
if (!src) return; if (!src) return;
return getUrl(src); return getUrl(src);
}.property("step.banner"), }.property("step.banner"),
@discourseComputed('step.fields.[]') @discourseComputed("step.fields.[]")
primaryButtonIndex(fields) { primaryButtonIndex(fields) {
return fields.length + 1; return fields.length + 1;
}, },
@discourseComputed('step.fields.[]') @discourseComputed("step.fields.[]")
secondaryButtonIndex(fields) { secondaryButtonIndex(fields) {
return fields.length + 2; return fields.length + 2;
}, },
@ -161,5 +168,5 @@ export default {
}, },
}, },
}); });
} },
} };

Datei anzeigen

@ -6,18 +6,27 @@ export default {
const EmberObject = requirejs("@ember/object").default; const EmberObject = requirejs("@ember/object").default;
const Router = requirejs("wizard/router").default; const Router = requirejs("wizard/router").default;
const ApplicationRoute = requirejs("wizard/routes/application").default; const ApplicationRoute = requirejs("wizard/routes/application").default;
const CustomWizard = requirejs("discourse/plugins/discourse-custom-wizard/wizard/models/custom").default; const CustomWizard = requirejs(
"discourse/plugins/discourse-custom-wizard/wizard/models/custom"
).default;
const getUrl = requirejs("discourse-common/lib/get-url").default; const getUrl = requirejs("discourse-common/lib/get-url").default;
const Store = requirejs("discourse/models/store").default; const Store = requirejs("discourse/models/store").default;
const registerRawHelpers = requirejs("discourse-common/lib/raw-handlebars-helpers").registerRawHelpers; const registerRawHelpers = requirejs(
const createHelperContext = requirejs("discourse-common/lib/helpers").createHelperContext; "discourse-common/lib/raw-handlebars-helpers"
const RawHandlebars = requirejs("discourse-common/lib/raw-handlebars").default; ).registerRawHelpers;
const Site = requirejs("discourse/plugins/discourse-custom-wizard/wizard/models/site").default; 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 RestAdapter = requirejs("discourse/adapters/rest").default;
const Session = requirejs("discourse/models/session").default; const Session = requirejs("discourse/models/session").default;
const setDefaultOwner = requirejs("discourse-common/lib/get-owner").setDefaultOwner; const setDefaultOwner = requirejs("discourse-common/lib/get-owner")
.setDefaultOwner;
const messageBus = requirejs("message-bus-client").default; const messageBus = requirejs("message-bus-client").default;
const container = app.__container__; const container = app.__container__;
Discourse.Model = EmberObject.extend(); Discourse.Model = EmberObject.extend();
Discourse.__container__ = container; Discourse.__container__ = container;
@ -66,7 +75,7 @@ export default {
site.set("can_create_tag", false); site.set("can_create_tag", false);
app.register("session:main", Session.current(), { instantiate: false }); app.register("session:main", Session.current(), { instantiate: false });
targets.forEach((t) => app.inject(t, "session", "session:main")); targets.forEach((t) => app.inject(t, "session", "session:main"));
createHelperContext({ createHelperContext({
siteSettings: container.lookup("site-settings:main"), siteSettings: container.lookup("site-settings:main"),
currentUser: container.lookup("current-user:main"), currentUser: container.lookup("current-user:main"),
@ -74,13 +83,13 @@ export default {
session: container.lookup("session:main"), session: container.lookup("session:main"),
capabilities: container.lookup("capabilities:main"), capabilities: container.lookup("capabilities:main"),
}); });
const session = container.lookup("session:main"); const session = container.lookup("session:main");
const setupData = document.getElementById("data-discourse-setup").dataset; const setupData = document.getElementById("data-discourse-setup").dataset;
session.set("highlightJsPath", setupData.highlightJsPath); session.set("highlightJsPath", setupData.highlightJsPath);
Router.reopen({ Router.reopen({
rootURL: getUrl("/w/") rootURL: getUrl("/w/"),
}); });
Router.map(function () { Router.map(function () {

Dateidiff unterdrückt, weil mindestens eine Zeile zu lang ist

Datei anzeigen

@ -1,23 +1,28 @@
import { ajax } from 'wizard/lib/ajax'; import { ajax } from "wizard/lib/ajax";
import getURL from "discourse-common/lib/get-url"; import getURL from "discourse-common/lib/get-url";
const _loaded = {}; const _loaded = {};
const _loading = {}; const _loading = {};
function loadWithTag(path, cb) { function loadWithTag(path, cb) {
const head = document.getElementsByTagName('head')[0]; const head = document.getElementsByTagName("head")[0];
let finished = false; let finished = false;
let s = document.createElement('script'); let s = document.createElement("script");
s.src = path; s.src = path;
if (Ember.Test) { if (Ember.Test) {
Ember.Test.registerWaiter(() => finished); Ember.Test.registerWaiter(() => finished);
} }
head.appendChild(s); head.appendChild(s);
s.onload = s.onreadystatechange = function(_, abort) { s.onload = s.onreadystatechange = function (_, abort) {
finished = true; finished = true;
if (abort || !s.readyState || s.readyState === "loaded" || s.readyState === "complete") { if (
abort ||
!s.readyState ||
s.readyState === "loaded" ||
s.readyState === "complete"
) {
s = s.onload = s.onreadystatechange = null; s = s.onload = s.onreadystatechange = null;
if (!abort) { if (!abort) {
Ember.run(null, cb); Ember.run(null, cb);
@ -31,38 +36,42 @@ export function loadCSS(url) {
} }
export default function loadScript(url, opts) { export default function loadScript(url, opts) {
// TODO: Remove this once plugins have been updated not to use it: // TODO: Remove this once plugins have been updated not to use it:
if (url === "defer/html-sanitizer-bundle") { return Ember.RSVP.Promise.resolve(); } if (url === "defer/html-sanitizer-bundle") {
return Ember.RSVP.Promise.resolve();
}
opts = opts || {}; opts = opts || {};
$('script').each((i, tag) => { $("script").each((i, tag) => {
const src = tag.getAttribute('src'); const src = tag.getAttribute("src");
if (src && (opts.scriptTag || src !== url)) { if (src && (opts.scriptTag || src !== url)) {
_loaded[tag.getAttribute('src')] = true; _loaded[tag.getAttribute("src")] = true;
} }
}); });
return new Ember.RSVP.Promise(function (resolve) {
return new Ember.RSVP.Promise(function(resolve) {
url = getURL(url); url = getURL(url);
// If we already loaded this url // If we already loaded this url
if (_loaded[url]) { return resolve(); } if (_loaded[url]) {
if (_loading[url]) { return _loading[url].then(resolve);} return resolve();
}
if (_loading[url]) {
return _loading[url].then(resolve);
}
let done; let done;
_loading[url] = new Ember.RSVP.Promise(function(_done){ _loading[url] = new Ember.RSVP.Promise(function (_done) {
done = _done; done = _done;
}); });
_loading[url].then(function(){ _loading[url].then(function () {
delete _loading[url]; delete _loading[url];
}); });
const cb = function(data) { const cb = function (data) {
if (opts && opts.css) { if (opts && opts.css) {
$("head").append("<style>" + data + "</style>"); $("head").append("<style>" + data + "</style>");
} }
@ -76,7 +85,7 @@ export default function loadScript(url, opts) {
// Scripts should always load from CDN // Scripts should always load from CDN
// CSS is type text, to accept it from a CDN we would need to handle CORS // CSS is type text, to accept it from a CDN we would need to handle CORS
if (!opts.css && Discourse.CDN && url[0] === "/" && url[1] !== "/") { if (!opts.css && Discourse.CDN && url[0] === "/" && url[1] !== "/") {
cdnUrl = Discourse.CDN.replace(/\/$/,"") + url; cdnUrl = Discourse.CDN.replace(/\/$/, "") + url;
} }
// Some javascript depends on the path of where it is loaded (ace editor) // Some javascript depends on the path of where it is loaded (ace editor)
@ -88,7 +97,11 @@ export default function loadScript(url, opts) {
} }
loadWithTag(cdnUrl, cb); loadWithTag(cdnUrl, cb);
} else { } else {
ajax({url: cdnUrl, dataType: opts.css ? "text": "script", cache: true}).then(cb); ajax({
url: cdnUrl,
dataType: opts.css ? "text" : "script",
cache: true,
}).then(cb);
} }
}); });
} }

Datei anzeigen

@ -1,5 +1,5 @@
import loadScript from './load-script'; import loadScript from "./load-script";
import { default as PrettyText } from 'pretty-text/pretty-text'; import { default as PrettyText } from "pretty-text/pretty-text";
export function cook(text, options) { export function cook(text, options) {
return new Handlebars.SafeString(new PrettyText(options).cook(text)); return new Handlebars.SafeString(new PrettyText(options).cook(text));
@ -10,8 +10,8 @@ export function cook(text, options) {
export function cookAsync(text, options) { export function cookAsync(text, options) {
if (Discourse.MarkdownItURL) { if (Discourse.MarkdownItURL) {
return loadScript(Discourse.MarkdownItURL) return loadScript(Discourse.MarkdownItURL)
.then(()=>cook(text, options)) .then(() => cook(text, options))
.catch(e => Ember.Logger.error(e)); .catch((e) => Ember.Logger.error(e));
} else { } else {
return Ember.RSVP.Promise.resolve(cook(text)); return Ember.RSVP.Promise.resolve(cook(text));
} }

Datei anzeigen

@ -1,14 +1,23 @@
import { CANCELLED_STATUS } from 'discourse/lib/autocomplete'; import { CANCELLED_STATUS } from "discourse/lib/autocomplete";
import { debounce } from "@ember/runloop"; import { debounce } from "@ember/runloop";
import getUrl from 'discourse-common/lib/get-url'; import getUrl from "discourse-common/lib/get-url";
var cache = {}, var cache = {},
cacheTopicId, cacheTopicId,
cacheTime, cacheTime,
currentTerm, currentTerm,
oldSearch; oldSearch;
function performSearch(term, topicId, includeGroups, includeMentionableGroups, includeMessageableGroups, allowedUsers, group, resultsFn) { function performSearch(
term,
topicId,
includeGroups,
includeMentionableGroups,
includeMessageableGroups,
allowedUsers,
group,
resultsFn
) {
var cached = cache[term]; var cached = cache[term];
if (cached) { if (cached) {
resultsFn(cached); resultsFn(cached);
@ -16,42 +25,49 @@ function performSearch(term, topicId, includeGroups, includeMentionableGroups, i
} }
// need to be able to cancel this // need to be able to cancel this
oldSearch = $.ajax(getUrl('/u/search/users'), { oldSearch = $.ajax(getUrl("/u/search/users"), {
data: { term: term, data: {
topic_id: topicId, term: term,
include_groups: includeGroups, topic_id: topicId,
include_mentionable_groups: includeMentionableGroups, include_groups: includeGroups,
include_messageable_groups: includeMessageableGroups, include_mentionable_groups: includeMentionableGroups,
group: group, include_messageable_groups: includeMessageableGroups,
topic_allowed_users: allowedUsers } group: group,
topic_allowed_users: allowedUsers,
},
}); });
var returnVal = CANCELLED_STATUS; var returnVal = CANCELLED_STATUS;
oldSearch.then(function (r) { oldSearch
cache[term] = r; .then(function (r) {
cacheTime = new Date(); cache[term] = r;
// If there is a newer search term, return null cacheTime = new Date();
if (term === currentTerm) { returnVal = r; } // If there is a newer search term, return null
if (term === currentTerm) {
}).always(function(){ returnVal = r;
oldSearch = null; }
resultsFn(returnVal); })
}); .always(function () {
oldSearch = null;
resultsFn(returnVal);
});
} }
function organizeResults(r, options) { function organizeResults(r, options) {
if (r === CANCELLED_STATUS) { return r; } if (r === CANCELLED_STATUS) {
return r;
}
var exclude = options.exclude || [], var exclude = options.exclude || [],
limit = options.limit || 5, limit = options.limit || 5,
users = [], users = [],
emails = [], emails = [],
groups = [], groups = [],
results = []; results = [];
if (r.users) { if (r.users) {
r.users.every(function(u) { r.users.every(function (u) {
if (exclude.indexOf(u.username) === -1) { if (exclude.indexOf(u.username) === -1) {
users.push(u); users.push(u);
results.push(u); results.push(u);
@ -62,13 +78,17 @@ function organizeResults(r, options) {
if (options.term.match(/@/)) { if (options.term.match(/@/)) {
let e = { username: options.term }; let e = { username: options.term };
emails = [ e ]; emails = [e];
results.push(e); results.push(e);
} }
if (r.groups) { if (r.groups) {
r.groups.every(function(g) { r.groups.every(function (g) {
if (results.length > limit && options.term.toLowerCase() !== g.name.toLowerCase()) return false; if (
results.length > limit &&
options.term.toLowerCase() !== g.name.toLowerCase()
)
return false;
if (exclude.indexOf(g.name) === -1) { if (exclude.indexOf(g.name) === -1) {
groups.push(g); groups.push(g);
results.push(g); results.push(g);
@ -83,16 +103,14 @@ function organizeResults(r, options) {
return results; return results;
} }
export default function userSearch(options) { export default function userSearch(options) {
var term = options.term || "", var term = options.term || "",
includeGroups = options.includeGroups, includeGroups = options.includeGroups,
includeMentionableGroups = options.includeMentionableGroups, includeMentionableGroups = options.includeMentionableGroups,
includeMessageableGroups = options.includeMessageableGroups, includeMessageableGroups = options.includeMessageableGroups,
allowedUsers = options.allowedUsers, allowedUsers = options.allowedUsers,
topicId = options.topicId, topicId = options.topicId,
group = options.group; group = options.group;
if (oldSearch) { if (oldSearch) {
oldSearch.abort(); oldSearch.abort();
@ -101,26 +119,26 @@ export default function userSearch(options) {
currentTerm = term; currentTerm = term;
return new Ember.RSVP.Promise(function(resolve) { return new Ember.RSVP.Promise(function (resolve) {
// TODO site setting for allowed regex in username // TODO site setting for allowed regex in username
if (term.match(/[^\w_\-\.@\+]/)) { if (term.match(/[^\w_\-\.@\+]/)) {
resolve([]); resolve([]);
return; return;
} }
if (((new Date() - cacheTime) > 30000) || (cacheTopicId !== topicId)) { if (new Date() - cacheTime > 30000 || cacheTopicId !== topicId) {
cache = {}; cache = {};
} }
cacheTopicId = topicId; cacheTopicId = topicId;
var clearPromise = setTimeout(function(){ var clearPromise = setTimeout(function () {
resolve(CANCELLED_STATUS); resolve(CANCELLED_STATUS);
}, 5000); }, 5000);
// TODO: Use discouseDebounce after it is available on stable. // TODO: Use discouseDebounce after it is available on stable.
debounce( debounce(
this, this,
function() { function () {
performSearch( performSearch(
term, term,
topicId, topicId,
@ -129,13 +147,13 @@ export default function userSearch(options) {
includeMessageableGroups, includeMessageableGroups,
allowedUsers, allowedUsers,
group, group,
function(r) { function (r) {
clearTimeout(clearPromise); clearTimeout(clearPromise);
resolve(organizeResults(r, options)); resolve(organizeResults(r, options));
} }
) );
}, },
300 300
) );
}); });
} }

Datei anzeigen

@ -1,7 +1,12 @@
// lite version of discourse/lib/utilities // lite version of discourse/lib/utilities
export function determinePostReplaceSelection({ selection, needle, replacement }) { export function determinePostReplaceSelection({
const diff = (replacement.end - replacement.start) - (needle.end - needle.start); selection,
needle,
replacement,
}) {
const diff =
replacement.end - replacement.start - (needle.end - needle.start);
if (selection.end <= needle.start) { if (selection.end <= needle.start) {
// Selection ends (and starts) before needle. // Selection ends (and starts) before needle.
@ -30,7 +35,7 @@ export function determinePostReplaceSelection({ selection, needle, replacement }
} }
} }
const toArray = items => { const toArray = (items) => {
items = items || []; items = items || [];
if (!Array.isArray(items)) { if (!Array.isArray(items)) {
@ -41,20 +46,26 @@ const toArray = items => {
}; };
export function clipboardData(e, canUpload) { export function clipboardData(e, canUpload) {
const clipboard = e.clipboardData || const clipboard =
e.originalEvent.clipboardData || e.clipboardData ||
e.delegatedEvent.originalEvent.clipboardData; e.originalEvent.clipboardData ||
e.delegatedEvent.originalEvent.clipboardData;
const types = toArray(clipboard.types); const types = toArray(clipboard.types);
let files = toArray(clipboard.files); let files = toArray(clipboard.files);
if (types.includes("Files") && files.length === 0) { // for IE if (types.includes("Files") && files.length === 0) {
files = toArray(clipboard.items).filter(i => i.kind === "file"); // for IE
files = toArray(clipboard.items).filter((i) => i.kind === "file");
} }
canUpload = files && canUpload && !types.includes("text/plain"); canUpload = files && canUpload && !types.includes("text/plain");
const canUploadImage = canUpload && files.filter(f => f.type.match('^image/'))[0]; const canUploadImage =
const canPasteHtml = Discourse.SiteSettings.enable_rich_text_paste && types.includes("text/html") && !canUploadImage; canUpload && files.filter((f) => f.type.match("^image/"))[0];
const canPasteHtml =
Discourse.SiteSettings.enable_rich_text_paste &&
types.includes("text/html") &&
!canUploadImage;
return { clipboard, types, canUpload, canPasteHtml }; return { clipboard, types, canUpload, canPasteHtml };
} }

Datei anzeigen

@ -2,30 +2,32 @@ import I18n from "I18n";
const getThemeId = () => { const getThemeId = () => {
let themeId = parseInt($("meta[name=discourse_theme_ids]")[0].content, 10); let themeId = parseInt($("meta[name=discourse_theme_ids]")[0].content, 10);
if (!isNaN(themeId)) { if (!isNaN(themeId)) {
return themeId.toString(); return themeId.toString();
} else { } else {
return null; return null;
} }
} };
const translationExists = (key) => { const translationExists = (key) => {
return I18n.findTranslation(key, { locale: I18n.locale }) || return (
I18n.findTranslation(key, { locale: I18n.defaultLocale }); I18n.findTranslation(key, { locale: I18n.locale }) ||
} I18n.findTranslation(key, { locale: I18n.defaultLocale })
);
};
const WizardI18n = (key, params={}) => { const WizardI18n = (key, params = {}) => {
const themeId = getThemeId(); const themeId = getThemeId();
if (!themeId) return I18n.t(key, params); if (!themeId) return I18n.t(key, params);
const themeKey = `theme_translations.${themeId}.${key}`; const themeKey = `theme_translations.${themeId}.${key}`;
if (translationExists(themeKey)) { if (translationExists(themeKey)) {
return I18n.t(themeKey, params); return I18n.t(themeKey, params);
} else { } else {
return I18n.t(key, params); return I18n.t(key, params);
} }
} };
export default WizardI18n; export default WizardI18n;

Datei anzeigen

@ -1,23 +1,23 @@
import { default as computed } from 'discourse-common/utils/decorators'; import { default as computed } from "discourse-common/utils/decorators";
import getUrl from 'discourse-common/lib/get-url'; import getUrl from "discourse-common/lib/get-url";
import WizardField from 'wizard/models/wizard-field'; import WizardField from "wizard/models/wizard-field";
import { ajax } from 'wizard/lib/ajax'; import { ajax } from "wizard/lib/ajax";
import Step from 'wizard/models/step'; import Step from "wizard/models/step";
import EmberObject from "@ember/object"; import EmberObject from "@ember/object";
const CustomWizard = EmberObject.extend({ const CustomWizard = EmberObject.extend({
@computed('steps.length') @computed("steps.length")
totalSteps: length => length, totalSteps: (length) => length,
skip() { skip() {
if (this.required && (!this.completed && this.permitted)) return; if (this.required && !this.completed && this.permitted) return;
CustomWizard.skip(this.id); CustomWizard.skip(this.id);
}, },
}); });
CustomWizard.reopenClass({ CustomWizard.reopenClass({
skip(wizardId) { skip(wizardId) {
ajax({ url: `/w/${wizardId}/skip`, type: 'PUT' }).then((result) => { ajax({ url: `/w/${wizardId}/skip`, type: "PUT" }).then((result) => {
CustomWizard.finished(result); CustomWizard.finished(result);
}); });
}, },
@ -28,52 +28,52 @@ CustomWizard.reopenClass({
url = result.redirect_on_complete; url = result.redirect_on_complete;
} }
window.location.href = getUrl(url); window.location.href = getUrl(url);
} },
}); });
export function findCustomWizard(wizardId, params = {}) { export function findCustomWizard(wizardId, params = {}) {
let url = `/w/${wizardId}`; let url = `/w/${wizardId}`;
let paramKeys = Object.keys(params).filter(k => { let paramKeys = Object.keys(params).filter((k) => {
if (k === 'wizard_id') return false; if (k === "wizard_id") return false;
return !!params[k]; return !!params[k];
}); });
if (paramKeys.length) { if (paramKeys.length) {
url += '?'; url += "?";
paramKeys.forEach((k,i) => { paramKeys.forEach((k, i) => {
if (i > 0) { if (i > 0) {
url += '&'; url += "&";
} }
url += `${k}=${params[k]}`; url += `${k}=${params[k]}`;
}); });
} }
return ajax({ url, cache: false, dataType: 'json' }).then(result => { return ajax({ url, cache: false, dataType: "json" }).then((result) => {
const wizard = result; const wizard = result;
if (!wizard) return null; if (!wizard) return null;
if (!wizard.completed) { if (!wizard.completed) {
wizard.steps = wizard.steps.map(step => { wizard.steps = wizard.steps.map((step) => {
const stepObj = Step.create(step); const stepObj = Step.create(step);
stepObj.fields.sort((a, b) => { stepObj.fields.sort((a, b) => {
return parseFloat(a.number) - parseFloat(b.number); return parseFloat(a.number) - parseFloat(b.number);
}); });
let tabindex = 1; let tabindex = 1;
stepObj.fields.forEach((f, i) => { stepObj.fields.forEach((f, i) => {
f.tabindex = tabindex; f.tabindex = tabindex;
if (['date_time'].includes(f.type)) { if (["date_time"].includes(f.type)) {
tabindex = tabindex + 2; tabindex = tabindex + 2;
} else { } else {
tabindex++; tabindex++;
} }
}); });
stepObj.fields = stepObj.fields.map(f => WizardField.create(f)); stepObj.fields = stepObj.fields.map((f) => WizardField.create(f));
return stepObj; return stepObj;
}); });
} }
@ -81,7 +81,7 @@ export function findCustomWizard(wizardId, params = {}) {
if (wizard.categories) { if (wizard.categories) {
let subcatMap = {}; let subcatMap = {};
let categoriesById = {}; let categoriesById = {};
let categories = wizard.categories.map(c => { let categories = wizard.categories.map((c) => {
if (c.parent_category_id) { if (c.parent_category_id) {
subcatMap[c.parent_category_id] = subcatMap[c.parent_category_id] =
subcatMap[c.parent_category_id] || []; subcatMap[c.parent_category_id] || [];
@ -91,25 +91,31 @@ export function findCustomWizard(wizardId, params = {}) {
}); });
// Associate the categories with their parents // Associate the categories with their parents
categories.forEach(c => { categories.forEach((c) => {
let subcategoryIds = subcatMap[c.get("id")]; let subcategoryIds = subcatMap[c.get("id")];
if (subcategoryIds) { if (subcategoryIds) {
c.set("subcategories", subcategoryIds.map(id => categoriesById[id])); c.set(
"subcategories",
subcategoryIds.map((id) => categoriesById[id])
);
} }
if (c.get("parent_category_id")) { if (c.get("parent_category_id")) {
c.set("parentCategory", categoriesById[c.get("parent_category_id")]); c.set("parentCategory", categoriesById[c.get("parent_category_id")]);
} }
}); });
Discourse.Site.currentProp('categoriesList', categories); Discourse.Site.currentProp("categoriesList", categories);
Discourse.Site.currentProp('sortedCategories', categories); Discourse.Site.currentProp("sortedCategories", categories);
Discourse.Site.currentProp('listByActivity', categories); Discourse.Site.currentProp("listByActivity", categories);
Discourse.Site.currentProp('categoriesById', categoriesById); Discourse.Site.currentProp("categoriesById", categoriesById);
Discourse.Site.currentProp('uncategorized_category_id', wizard.uncategorized_category_id); Discourse.Site.currentProp(
"uncategorized_category_id",
wizard.uncategorized_category_id
);
} }
return CustomWizard.create(wizard); return CustomWizard.create(wizard);
}); });
}; }
export default CustomWizard; export default CustomWizard;

Datei anzeigen

@ -7,4 +7,4 @@ export default Site.reopenClass({
const store = Discourse.__container__.lookup("service:store"); const store = Discourse.__container__.lookup("service:store");
return store.createRecord("site", {}); return store.createRecord("site", {});
}, },
}) });

Datei anzeigen

@ -1,22 +1,27 @@
export default Ember.Route.extend({ export default Ember.Route.extend({
beforeModel() { beforeModel() {
const appModel = this.modelFor('custom'); const appModel = this.modelFor("custom");
if (appModel && appModel.permitted && !appModel.completed && appModel.start) { if (
this.replaceWith('custom.step', appModel.start); appModel &&
appModel.permitted &&
!appModel.completed &&
appModel.start
) {
this.replaceWith("custom.step", appModel.start);
} }
}, },
model() { model() {
return this.modelFor('custom'); return this.modelFor("custom");
}, },
setupController(controller, model) { setupController(controller, model) {
if (model) { if (model) {
const completed = model.get('completed'); const completed = model.get("completed");
const permitted = model.get('permitted'); const permitted = model.get("permitted");
const wizardId = model.get('id'); const wizardId = model.get("id");
const user = model.get('user'); const user = model.get("user");
const name = model.get('name'); const name = model.get("name");
controller.setProperties({ controller.setProperties({
requiresLogin: !user, requiresLogin: !user,
@ -24,10 +29,10 @@ export default Ember.Route.extend({
name, name,
completed, completed,
notPermitted: !permitted, notPermitted: !permitted,
wizardId wizardId,
}); });
} else { } else {
controller.set('noWizard', true); controller.set("noWizard", true);
} }
} },
}); });

Datei anzeigen

@ -2,37 +2,38 @@ import WizardI18n from "../lib/wizard-i18n";
export default Ember.Route.extend({ export default Ember.Route.extend({
model(params) { model(params) {
const appModel = this.modelFor('custom'); const appModel = this.modelFor("custom");
const allSteps = appModel.steps; const allSteps = appModel.steps;
if (allSteps) { if (allSteps) {
const step = allSteps.findBy('id', params.step_id); const step = allSteps.findBy("id", params.step_id);
return step ? step : allSteps[0]; return step ? step : allSteps[0];
}; }
return appModel; return appModel;
}, },
afterModel(model) { afterModel(model) {
if (model.completed) return this.transitionTo('index'); if (model.completed) return this.transitionTo("index");
return model.set("wizardId", this.modelFor('custom').id); return model.set("wizardId", this.modelFor("custom").id);
}, },
setupController(controller, model) { setupController(controller, model) {
let props = { let props = {
step: model, step: model,
wizard: this.modelFor('custom') wizard: this.modelFor("custom"),
}; };
if (!model.permitted) { if (!model.permitted) {
props['stepMessage'] = { props["stepMessage"] = {
state: 'not-permitted', state: "not-permitted",
text: model.permitted_message || WizardI18n('wizard.step_not_permitted') text:
model.permitted_message || WizardI18n("wizard.step_not_permitted"),
}; };
if (model.index > 0) { if (model.index > 0) {
props['showReset'] = true; props["showReset"] = true;
} }
} }
controller.setProperties(props); controller.setProperties(props);
} },
}); });

Datei anzeigen

@ -1,5 +1,5 @@
export default Ember.Route.extend({ export default Ember.Route.extend({
redirect() { redirect() {
this.transitionTo('custom.index'); this.transitionTo("custom.index");
} },
}); });

Datei anzeigen

@ -1,39 +1,39 @@
/* eslint no-undef: 0 */ /* eslint no-undef: 0 */
import { findCustomWizard } from '../models/custom'; import { findCustomWizard } from "../models/custom";
import { ajax } from 'wizard/lib/ajax'; import { ajax } from "wizard/lib/ajax";
export default Ember.Route.extend({ export default Ember.Route.extend({
beforeModel(transition) { beforeModel(transition) {
this.set('queryParams', transition.intent.queryParams); this.set("queryParams", transition.intent.queryParams);
}, },
model(params) { model(params) {
return findCustomWizard(params.wizard_id, this.get('queryParams')); return findCustomWizard(params.wizard_id, this.get("queryParams"));
}, },
afterModel() { afterModel() {
return ajax({ return ajax({
url: `/site/settings`, url: `/site/settings`,
type: 'GET', type: "GET",
}).then((result) => { }).then((result) => {
$.extend(Wizard.SiteSettings, result); $.extend(Wizard.SiteSettings, result);
}); });
}, },
setupController(controller, model) { setupController(controller, model) {
const background = model ? model.get('background') : 'AliceBlue'; const background = model ? model.get("background") : "AliceBlue";
Ember.run.scheduleOnce('afterRender', this, function(){ Ember.run.scheduleOnce("afterRender", this, function () {
$('body.custom-wizard').css('background', background); $("body.custom-wizard").css("background", background);
if (model) { if (model) {
$('#custom-wizard-main').addClass(model.get('id').dasherize()); $("#custom-wizard-main").addClass(model.get("id").dasherize());
} }
}); });
controller.setProperties({ controller.setProperties({
customWizard: true, customWizard: true,
logoUrl: Wizard.SiteSettings.logo_small, logoUrl: Wizard.SiteSettings.logo_small,
reset: null reset: null,
}); });
} },
}); });

Dateidiff unterdrückt, weil mindestens eine Zeile zu lang ist

Datei anzeigen

@ -1,72 +1,75 @@
.ui-timepicker-wrapper { .ui-timepicker-wrapper {
overflow-y: auto; overflow-y: auto;
max-height: 150px; max-height: 150px;
width: 6.5em; width: 6.5em;
background: #fff; background: #fff;
border: 1px solid #ddd; border: 1px solid #ddd;
-webkit-box-shadow:0 5px 10px rgba(0,0,0,0.2); -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);
-moz-box-shadow:0 5px 10px rgba(0,0,0,0.2); -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);
box-shadow:0 5px 10px rgba(0,0,0,0.2); box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);
outline: none; outline: none;
z-index: 10001; z-index: 10001;
margin: 0; margin: 0;
} }
.ui-timepicker-wrapper.ui-timepicker-with-duration { .ui-timepicker-wrapper.ui-timepicker-with-duration {
width: 13em; width: 13em;
} }
.ui-timepicker-wrapper.ui-timepicker-with-duration.ui-timepicker-step-30, .ui-timepicker-wrapper.ui-timepicker-with-duration.ui-timepicker-step-30,
.ui-timepicker-wrapper.ui-timepicker-with-duration.ui-timepicker-step-60 { .ui-timepicker-wrapper.ui-timepicker-with-duration.ui-timepicker-step-60 {
width: 11em; width: 11em;
} }
.ui-timepicker-list { .ui-timepicker-list {
margin: 0; margin: 0;
padding: 0; padding: 0;
list-style: none; list-style: none;
} }
.ui-timepicker-duration { .ui-timepicker-duration {
margin-left: 5px; color: #888; margin-left: 5px;
color: #888;
} }
.ui-timepicker-list:hover .ui-timepicker-duration { .ui-timepicker-list:hover .ui-timepicker-duration {
color: #888; color: #888;
} }
.ui-timepicker-list li { .ui-timepicker-list li {
padding: 3px 0 3px 5px; padding: 3px 0 3px 5px;
cursor: pointer; cursor: pointer;
white-space: nowrap; white-space: nowrap;
color: #000; color: #000;
list-style: none; list-style: none;
margin: 0; margin: 0;
} }
.ui-timepicker-list:hover .ui-timepicker-selected { .ui-timepicker-list:hover .ui-timepicker-selected {
background: #fff; color: #000; background: #fff;
color: #000;
} }
li.ui-timepicker-selected, li.ui-timepicker-selected,
.ui-timepicker-list li:hover, .ui-timepicker-list li:hover,
.ui-timepicker-list .ui-timepicker-selected:hover { .ui-timepicker-list .ui-timepicker-selected:hover {
background: #1980EC; color: #fff; background: #1980ec;
color: #fff;
} }
li.ui-timepicker-selected .ui-timepicker-duration, li.ui-timepicker-selected .ui-timepicker-duration,
.ui-timepicker-list li:hover .ui-timepicker-duration { .ui-timepicker-list li:hover .ui-timepicker-duration {
color: #ccc; color: #ccc;
} }
.ui-timepicker-list li.ui-timepicker-disabled, .ui-timepicker-list li.ui-timepicker-disabled,
.ui-timepicker-list li.ui-timepicker-disabled:hover, .ui-timepicker-list li.ui-timepicker-disabled:hover,
.ui-timepicker-list li.ui-timepicker-selected.ui-timepicker-disabled { .ui-timepicker-list li.ui-timepicker-selected.ui-timepicker-disabled {
color: #888; color: #888;
cursor: default; cursor: default;
} }
.ui-timepicker-list li.ui-timepicker-disabled:hover, .ui-timepicker-list li.ui-timepicker-disabled:hover,
.ui-timepicker-list li.ui-timepicker-selected.ui-timepicker-disabled { .ui-timepicker-list li.ui-timepicker-selected.ui-timepicker-disabled {
background: #f2f2f2; background: #f2f2f2;
} }

Datei anzeigen

@ -1,15 +1,15 @@
@import 'wizard-mapper'; @import "wizard-mapper";
@import 'wizard-manager'; @import "wizard-manager";
@import 'wizard-api'; @import "wizard-api";
@import 'common/components/buttons'; @import "common/components/buttons";
.admin-wizard-controls { .admin-wizard-controls {
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: space-between; justify-content: space-between;
margin-bottom: 20px; margin-bottom: 20px;
&+ .wizard-message + div { & + .wizard-message + div {
margin-top: 20px; margin-top: 20px;
} }
} }
@ -22,54 +22,52 @@
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
align-items: flex-start; align-items: flex-start;
.message-block { .message-block {
.d-icon { .d-icon {
margin-right: 4px; margin-right: 4px;
} }
.d-icon-check-circle { .d-icon-check-circle {
color: var(--success); color: var(--success);
} }
.d-icon-times-circle { .d-icon-times-circle {
color: var(--danger); color: var(--danger);
} }
a + a { a + a {
border-left: 1px solid $primary-medium; border-left: 1px solid $primary-medium;
padding-left: 5px; padding-left: 5px;
margin-left: 5px; margin-left: 5px;
} }
.message { .message {
white-space: nowrap; white-space: nowrap;
} }
.list-colon { .list-colon {
margin-right: 5px; margin-right: 5px;
} }
ul { ul {
list-style: none; list-style: none;
margin: 0; margin: 0;
span.action { span.action {
margin-left: 5px; margin-left: 5px;
} }
} }
} }
& + div { & + div {
margin-top: 30px; margin-top: 30px;
} }
} }
.wizard-submissions { .wizard-submissions {
overflow: scroll; overflow: scroll;
table td { table td {
min-width: 150px; min-width: 150px;
} }
@ -81,7 +79,7 @@
margin: 0 7px; margin: 0 7px;
} }
} }
.wizard-logs { .wizard-logs {
.date { .date {
width: 100px; width: 100px;
@ -125,11 +123,11 @@
.wizard-custom-action { .wizard-custom-action {
position: relative; position: relative;
display: none; display: none;
&.visible { &.visible {
display: flex; display: flex;
} }
.undo-changes { .undo-changes {
position: absolute; position: absolute;
top: 0; top: 0;
@ -139,11 +137,11 @@
.admin-wizard-container.settings .wizard-basic-details { .admin-wizard-container.settings .wizard-basic-details {
justify-content: initial; justify-content: initial;
.setting { .setting {
width: auto; width: auto;
margin-right: 20px; margin-right: 20px;
.setting-label { .setting-label {
width: initial; width: initial;
min-width: initial; min-width: initial;
@ -153,7 +151,7 @@
.wizard-header { .wizard-header {
margin-bottom: 20px; margin-bottom: 20px;
&.large { &.large {
font-size: 1.5em; font-size: 1.5em;
min-height: 31px; min-height: 31px;
@ -161,32 +159,32 @@
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
align-items: flex-start; align-items: flex-start;
input { input {
margin-bottom: 0; margin-bottom: 0;
width: 400px; width: 400px;
} }
label { label {
margin-bottom: 0; margin-bottom: 0;
} }
.download-link { .download-link {
font-size: 1rem; font-size: 1rem;
line-height: 20px; line-height: 20px;
} }
.wizard-url { .wizard-url {
display: inline-flex; display: inline-flex;
margin-left: 20px; margin-left: 20px;
max-width: 50%; max-width: 50%;
a { a {
padding: 6px 12px; padding: 6px 12px;
font-size: 1rem; font-size: 1rem;
background-color: $primary-low; background-color: $primary-low;
} }
button { button {
font-size: 1rem; font-size: 1rem;
} }
@ -210,22 +208,21 @@
.admin-wizard-buttons { .admin-wizard-buttons {
margin-top: 20px; margin-top: 20px;
display: flex; display: flex;
.btn { .btn {
margin-right: 1em; margin-right: 1em;
} }
} }
.admin-wizard-container.settings { .admin-wizard-container.settings {
[class~="setting"] {
[class~='setting'] {
display: inline-flex; display: inline-flex;
align-items: flex-start; align-items: flex-start;
width: 48%; width: 48%;
margin-bottom: 30px; margin-bottom: 30px;
padding-bottom: 0; padding-bottom: 0;
position: relative; position: relative;
&:last-of-type { &:last-of-type {
margin-bottom: 0; margin-bottom: 0;
} }
@ -241,7 +238,7 @@
float: initial; float: initial;
width: initial; width: initial;
padding: 0; padding: 0;
label { label {
font-size: 0.85em; font-size: 0.85em;
} }
@ -253,97 +250,100 @@
button { button {
display: block; display: block;
} }
input[type="text"], textarea { input[type="text"],
textarea {
width: 100%; width: 100%;
box-sizing: border-box; box-sizing: border-box;
margin-bottom: 0; margin-bottom: 0;
} }
input[type="number"] { input[type="number"] {
margin-bottom: 0; margin-bottom: 0;
} }
input[disabled] { input[disabled] {
background-color: $primary-low; background-color: $primary-low;
cursor: not-allowed; cursor: not-allowed;
} }
input.medium { input.medium {
width: 200px; width: 200px;
} }
input.small { input.small {
width: 100px; width: 100px;
} }
.uploaded-image-preview { .uploaded-image-preview {
width: 100%; width: 100%;
max-height: 100px; max-height: 100px;
margin-bottom: 0; margin-bottom: 0;
} }
.image-upload-controls { .image-upload-controls {
label { label {
font-size: 1em; font-size: 1em;
margin: 0 5px 0 0; margin: 0 5px 0 0;
} }
} }
> textarea { > textarea {
min-height: 100px; min-height: 100px;
resize: vertical; resize: vertical;
} }
input[type="checkbox"] { input[type="checkbox"] {
float: left; float: left;
margin: 5px 7px 0 0; margin: 5px 7px 0 0;
} }
.input .select-kit, > .select-kit { .input .select-kit,
> .select-kit {
max-width: 250px !important; max-width: 250px !important;
min-width: 250px !important; min-width: 250px !important;
} }
} }
&.full, &.full-inline { &.full,
&.full-inline {
width: 100%; width: 100%;
.setting-value { .setting-value {
width: initial; width: initial;
float: none; float: none;
&.editor { &.editor {
.d-editor { .d-editor {
margin-bottom: 5px; margin-bottom: 5px;
} }
} }
.uploaded-image-preview { .uploaded-image-preview {
max-height: 200px; max-height: 200px;
} }
} }
} }
&.full-inline { &.full-inline {
.setting-value { .setting-value {
display: flex; display: flex;
align-items: center; align-items: center;
input { input {
margin: 0 7px 0 0; margin: 0 7px 0 0;
} }
button { button {
margin: 0 0 0 20px; margin: 0 0 0 20px;
} }
} }
} }
&.field-mapper-setting { &.field-mapper-setting {
.setting-value { .setting-value {
max-width: calc(100% - 80px); max-width: calc(100% - 80px);
.mapper-input { .mapper-input {
max-width: 100%; max-width: 100%;
box-sizing: border-box; box-sizing: border-box;
@ -359,17 +359,17 @@
margin-top: 5px; margin-top: 5px;
} }
} }
.advanced-settings { .advanced-settings {
width: 100%; width: 100%;
margin-top: 30px; margin-top: 30px;
[class~='setting']:first-of-type { [class~="setting"]:first-of-type {
border-top: none; border-top: none;
} }
} }
.wizard-custom-action > [class~='setting']:first-of-type { .wizard-custom-action > [class~="setting"]:first-of-type {
margin-bottom: 0; margin-bottom: 0;
} }
@ -406,20 +406,20 @@
.d-editor-input { .d-editor-input {
min-height: 150px; min-height: 150px;
} }
.d-editor-container { .d-editor-container {
display: block; display: block;
} }
.d-editor-textarea-wrapper { .d-editor-textarea-wrapper {
display: grid; display: grid;
margin-bottom: 10px; margin-bottom: 10px;
textarea { textarea {
resize: vertical; resize: vertical;
} }
} }
.d-editor-preview-wrapper { .d-editor-preview-wrapper {
display: none; display: none;
margin: 0 0 10px 0; margin: 0 0 10px 0;
@ -427,7 +427,7 @@
background-color: $secondary; background-color: $secondary;
border: 1px solid $primary-medium; border: 1px solid $primary-medium;
max-width: 100%; max-width: 100%;
&.force-preview { &.force-preview {
display: block; display: block;
} }
@ -437,20 +437,20 @@
margin: 0; margin: 0;
} }
} }
.wizard-editor-gutter { .wizard-editor-gutter {
position: relative; position: relative;
display: flex; display: flex;
.btn { .btn {
margin-right: 10px; margin-right: 10px;
} }
.wizard-editor-gutter-popover { .wizard-editor-gutter-popover {
position: absolute; position: absolute;
padding: 10px; padding: 10px;
background-color: $secondary; background-color: $secondary;
box-shadow: shadow('card'); box-shadow: shadow("card");
z-index: 200; z-index: 200;
top: 40px; top: 40px;
} }
@ -476,7 +476,7 @@
margin-bottom: 10px; margin-bottom: 10px;
margin-right: 10px; margin-right: 10px;
} }
.btn { .btn {
height: 32px; height: 32px;
} }
@ -500,11 +500,11 @@
.required-data-message { .required-data-message {
display: inline-block; display: inline-block;
margin-top: 20px; margin-top: 20px;
.label { .label {
margin-bottom: 5px; margin-bottom: 5px;
} }
input { input {
margin-bottom: 0; margin-bottom: 0;
} }
@ -517,7 +517,7 @@
.modal .modal-body.next-session-time-modal { .modal .modal-body.next-session-time-modal {
overflow: visible; overflow: visible;
.picker-container { .picker-container {
position: absolute; position: absolute;
top: 30px; top: 30px;
@ -569,7 +569,9 @@
width: 100%; width: 100%;
} }
.add-mapper-input .btn, .btn-after-time, .wizard-editor-gutter .btn { .add-mapper-input .btn,
.btn-after-time,
.wizard-editor-gutter .btn {
background-color: $secondary; background-color: $secondary;
border: 1px solid $primary-medium; border: 1px solid $primary-medium;
} }
@ -579,47 +581,47 @@
.buttons { .buttons {
display: flex; display: flex;
align-items: center; align-items: center;
button.btn { button.btn {
margin-left: 10px; margin-left: 10px;
} }
} }
} }
.btn.save:enabled { .btn.save:enabled {
@extend .btn-primary; @extend .btn-primary;
} }
.btn.destroy { .btn.destroy {
@extend .btn-danger; @extend .btn-danger;
} }
h3 { h3 {
margin-bottom: 0; margin-bottom: 0;
} }
.select-kit { .select-kit {
width: 150px; width: 150px;
} }
.select-kit.multi-select { .select-kit.multi-select {
width: 300px; width: 300px;
.choices .choice, .choices .choice,
.select-kit-filter .filter-input { .select-kit-filter .filter-input {
height: 25px; height: 25px;
min-height: 25px; min-height: 25px;
} }
} }
input[type="text"] { input[type="text"] {
margin: 0; margin: 0;
} }
table { table {
td { td {
vertical-align: top; vertical-align: top;
label { label {
margin: 0; margin: 0;
line-height: 30px; line-height: 30px;
@ -627,25 +629,25 @@
margin-right: 10px; margin-right: 10px;
} }
} }
td { td {
min-width: 170px; min-width: 170px;
width: 170px; width: 170px;
} }
td.multi-select { td.multi-select {
min-width: 300px; min-width: 300px;
} }
td.input { td.input {
min-width: 210px; min-width: 210px;
width: 210px; width: 210px;
} }
td.actions { td.actions {
min-width: 100px; min-width: 100px;
text-align: right; text-align: right;
button.btn { button.btn {
margin-left: 5px !important; margin-left: 5px !important;
} }
@ -661,7 +663,7 @@
background-color: var(--primary-low); background-color: var(--primary-low);
padding: 1em; padding: 1em;
margin: 0 0 1em 0; margin: 0 0 1em 0;
input { input {
margin-bottom: 0; margin-bottom: 0;
} }
@ -671,7 +673,7 @@
.validation-container { .validation-container {
display: flex; display: flex;
padding: 1em 0; padding: 1em 0;
.validation-section { .validation-section {
width: 250px; width: 250px;
} }

Datei anzeigen

@ -17,7 +17,8 @@
text-align: right; text-align: right;
vertical-align: middle; vertical-align: middle;
> .d-icon, > .spinner { > .d-icon,
> .spinner {
margin-right: 7px; margin-right: 7px;
} }
@ -30,7 +31,7 @@
.wizard-api-header { .wizard-api-header {
margin-top: 20px; margin-top: 20px;
&.page { &.page {
margin-bottom: 20px; margin-bottom: 20px;
} }
@ -103,15 +104,16 @@
.endpoint { .endpoint {
margin-top: 20px; margin-top: 20px;
.top, .bottom { .top,
.bottom {
display: flex; display: flex;
} }
.top { .top {
margin-bottom: 15px; margin-bottom: 15px;
} }
.combo-box { .combo-box {
margin-right: 10px; margin-right: 10px;
width: 210px; width: 210px;
@ -138,6 +140,6 @@
margin-bottom: 20px; margin-bottom: 20px;
} }
.wizard-step-contents{ .wizard-step-contents {
height: unset !important; height: unset !important;
} }

Datei anzeigen

@ -1,42 +1,42 @@
.admin-wizards-manager .admin-wizard-controls { .admin-wizards-manager .admin-wizard-controls {
display: flex; display: flex;
justify-content: flex-start; justify-content: flex-start;
h3 { h3 {
margin-bottom: 0; margin-bottom: 0;
} }
.buttons { .buttons {
display: flex; display: flex;
margin-left: auto; margin-left: auto;
> * { > * {
margin-left: 10px; margin-left: 10px;
} }
#import-button:enabled, #import-button:enabled,
#export-button:enabled { #export-button:enabled {
background-color: $tertiary; background-color: $tertiary;
color: $secondary; color: $secondary;
} }
#destroy-button:enabled { #destroy-button:enabled {
background-color: $danger; background-color: $danger;
color: $secondary; color: $secondary;
} }
} }
#file-upload { #file-upload {
display: none; display: none;
} }
.filename { .filename {
padding: 0 10px; padding: 0 10px;
border: 1px solid $primary; border: 1px solid $primary;
display: inline-flex; display: inline-flex;
height: 28px; height: 28px;
line-height: 28px; line-height: 28px;
a { a {
color: $primary; color: $primary;
margin-right: 5px; margin-right: 5px;

Einige Dateien werden nicht angezeigt, da zu viele Dateien in diesem Diff geändert wurden Mehr anzeigen