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 { or, alias } from "@ember/object/computed";
const generateContent = function(array, type) {
return array.map(key => ({
const generateContent = function (array, type) {
return array.map((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({
tagName: 'tr',
topicSerializers: ['topic_view', 'topic_list_item'],
postSerializers: ['post'],
groupSerializers: ['basic_group'],
categorySerializers: ['basic_category'],
klassContent: generateContent(['topic', 'post', 'group', 'category'], 'klass'),
typeContent: generateContent(['string', 'boolean', 'integer', 'json'], 'type'),
showInputs: or('field.new', 'field.edit'),
classNames: ['custom-field-input'],
loading: or('saving', 'destroying'),
destroyDisabled: alias('loading'),
closeDisabled: alias('loading'),
tagName: "tr",
topicSerializers: ["topic_view", "topic_list_item"],
postSerializers: ["post"],
groupSerializers: ["basic_group"],
categorySerializers: ["basic_category"],
klassContent: generateContent(
["topic", "post", "group", "category"],
"klass"
),
typeContent: generateContent(
["string", "boolean", "integer", "json"],
"type"
),
showInputs: or("field.new", "field.edit"),
classNames: ["custom-field-input"],
loading: or("saving", "destroying"),
destroyDisabled: alias("loading"),
closeDisabled: alias("loading"),
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) {
const serializers = this.get(`${klass}Serializers`);
if (serializers) {
return generateContent(serializers, 'serializers');
return generateContent(serializers, "serializers");
} else {
return [];
}
},
@observes('field.klass')
@observes("field.klass")
clearSerializersWhenClassChanges() {
this.set('field.serializers', null);
this.set("field.serializers", null);
},
compareArrays(array1, array2) {
return array1.length === array2.length && array1.every((value, index) => {
return value === array2[index];
});
return (
array1.length === array2.length &&
array1.every((value, index) => {
return value === array2[index];
})
);
},
@discourseComputed(
'saving',
'field.name',
'field.klass',
'field.type',
'field.serializers'
"saving",
"field.name",
"field.klass",
"field.type",
"field.serializers"
)
saveDisabled(saving) {
if (saving) return true;
const originalField = this.originalField;
if (!originalField) return false;
return ['name', 'klass', 'type', 'serializers'].every(attr => {
return ["name", "klass", "type", "serializers"].every((attr) => {
let current = this.get(attr);
let original = originalField[attr];
if (!current) return false;
if (attr == 'serializers') {
if (attr == "serializers") {
return this.compareArrays(current, original);
} else {
return current == original;
}
});
},
actions: {
edit() {
this.set('field.edit', true);
this.set("field.edit", true);
},
close() {
if (this.field.edit) {
this.set('field.edit', false);
this.set("field.edit", false);
}
},
destroy() {
this.set('destroying', true);
this.set("destroying", true);
this.removeField(this.field);
},
save() {
this.set('saving', true);
this.set("saving", true);
const field = this.field;
let data = {
id: field.id,
klass: field.klass,
type: field.type,
serializers: field.serializers,
name: field.name
}
name: field.name,
};
this.saveField(data).then((result) => {
this.set('saving', false);
this.set("saving", false);
if (result.success) {
this.set('field.edit', false);
this.set("field.edit", false);
} 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 Component from '@ember/component';
import { default as discourseComputed } from "discourse-common/utils/decorators";
import Component from "@ember/component";
export default Component.extend({
classNames: 'wizard-advanced-toggle',
@discourseComputed('showAdvanced')
classNames: "wizard-advanced-toggle",
@discourseComputed("showAdvanced")
toggleClass(showAdvanced) {
let classes = 'btn'
if (showAdvanced) classes += ' btn-primary';
let classes = "btn";
if (showAdvanced) classes += " btn-primary";
return classes;
},
actions: {
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 { generateName, selectKitContent } from '../lib/wizard';
import { generateName, selectKitContent } from "../lib/wizard";
import { computed } from "@ember/object";
import wizardSchema from '../lib/wizard-schema';
import UndoChanges from '../mixins/undo-changes';
import wizardSchema from "../lib/wizard-schema";
import UndoChanges from "../mixins/undo-changes";
import Component from "@ember/component";
import { notificationLevels } from '../lib/wizard';
import { notificationLevels } from "../lib/wizard";
import I18n from "I18n";
export default Component.extend(UndoChanges, {
componentType: 'action',
classNameBindings: [':wizard-custom-action', 'visible'],
visible: computed('currentActionId', function() { return this.action.id === this.currentActionId }),
createTopic: equal('action.type', 'create_topic'),
updateProfile: equal('action.type', 'update_profile'),
watchCategories: equal('action.type', 'watch_categories'),
sendMessage: equal('action.type', 'send_message'),
openComposer: equal('action.type', 'open_composer'),
sendToApi: equal('action.type', 'send_to_api'),
addToGroup: equal('action.type', 'add_to_group'),
routeTo: equal('action.type', 'route_to'),
createCategory: equal('action.type', 'create_category'),
createGroup: equal('action.type', 'create_group'),
apiEmpty: empty('action.api'),
groupPropertyTypes: selectKitContent(['id', 'name']),
hasAdvanced: or('hasCustomFields', 'routeTo'),
showAdvanced: and('hasAdvanced', 'action.type'),
hasCustomFields: or('basicTopicFields', 'updateProfile', 'createGroup', 'createCategory'),
basicTopicFields: or('createTopic', 'sendMessage', 'openComposer'),
publicTopicFields: or('createTopic', 'openComposer'),
showPostAdvanced: or('createTopic', 'sendMessage'),
actionTypes: Object.keys(wizardSchema.action.types).map(type => {
componentType: "action",
classNameBindings: [":wizard-custom-action", "visible"],
visible: computed("currentActionId", function () {
return this.action.id === this.currentActionId;
}),
createTopic: equal("action.type", "create_topic"),
updateProfile: equal("action.type", "update_profile"),
watchCategories: equal("action.type", "watch_categories"),
sendMessage: equal("action.type", "send_message"),
openComposer: equal("action.type", "open_composer"),
sendToApi: equal("action.type", "send_to_api"),
addToGroup: equal("action.type", "add_to_group"),
routeTo: equal("action.type", "route_to"),
createCategory: equal("action.type", "create_category"),
createGroup: equal("action.type", "create_group"),
apiEmpty: empty("action.api"),
groupPropertyTypes: selectKitContent(["id", "name"]),
hasAdvanced: or("hasCustomFields", "routeTo"),
showAdvanced: and("hasAdvanced", "action.type"),
hasCustomFields: or(
"basicTopicFields",
"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 {
id: type,
name: I18n.t(`admin.wizard.action.${type}.label`)
name: I18n.t(`admin.wizard.action.${type}.label`),
};
}),
availableNotificationLevels: notificationLevels.map((type, index) => {
return {
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',
@discourseComputed('action.type')
messageUrl: "https://thepavilion.io/t/2810",
@discourseComputed("action.type")
messageKey(type) {
let key = 'type';
let key = "type";
if (type) {
key = 'edit';
key = "edit";
}
return key;
},
@discourseComputed('wizard.steps')
@discourseComputed("wizard.steps")
runAfterContent(steps) {
let content = steps.map(function(step) {
let content = steps.map(function (step) {
return {
id: step.id,
name: step.title || step.id
name: step.title || step.id,
};
});
content.unshift({
id: 'wizard_completion',
name: I18n.t('admin.wizard.action.run_after.wizard_completion')
id: "wizard_completion",
name: I18n.t("admin.wizard.action.run_after.wizard_completion"),
});
return content;
},
@discourseComputed('apis')
@discourseComputed("apis")
availableApis(apis) {
return apis.map(a => {
return apis.map((a) => {
return {
id: a.name,
name: a.title
name: a.title,
};
});
},
@discourseComputed('apis', 'action.api')
@discourseComputed("apis", "action.api")
availableEndpoints(apis, api) {
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 { computed } from "@ember/object";
import { selectKitContent } from '../lib/wizard';
import UndoChanges from '../mixins/undo-changes';
import { selectKitContent } from "../lib/wizard";
import UndoChanges from "../mixins/undo-changes";
import Component from "@ember/component";
import wizardSchema from '../lib/wizard-schema';
import wizardSchema from "../lib/wizard-schema";
export default Component.extend(UndoChanges, {
componentType: 'field',
classNameBindings: [':wizard-custom-field', 'visible'],
visible: computed('currentFieldId', function() { return this.field.id === this.currentFieldId }),
isDropdown: equal('field.type', 'dropdown'),
isUpload: equal('field.type', 'upload'),
isCategory: equal('field.type', 'category'),
isGroup: equal('field.type', 'group'),
isTag: equal('field.type', 'tag'),
isText: equal('field.type', 'text'),
isTextarea: equal('field.type', 'textarea'),
isUrl: equal('field.type', 'url'),
isComposer: equal('field.type', 'composer'),
showPrefill: or('isText', 'isCategory', 'isTag', 'isGroup', 'isDropdown'),
showContent: or('isCategory', 'isTag', 'isGroup', 'isDropdown'),
showLimit: or('isCategory', 'isTag'),
isTextType: or('isText', 'isTextarea', 'isComposer'),
categoryPropertyTypes: selectKitContent(['id', 'slug']),
showAdvanced: alias('field.type'),
messageUrl: 'https://thepavilion.io/t/2809',
@discourseComputed('field.type')
componentType: "field",
classNameBindings: [":wizard-custom-field", "visible"],
visible: computed("currentFieldId", function () {
return this.field.id === this.currentFieldId;
}),
isDropdown: equal("field.type", "dropdown"),
isUpload: equal("field.type", "upload"),
isCategory: equal("field.type", "category"),
isGroup: equal("field.type", "group"),
isTag: equal("field.type", "tag"),
isText: equal("field.type", "text"),
isTextarea: equal("field.type", "textarea"),
isUrl: equal("field.type", "url"),
isComposer: equal("field.type", "composer"),
showPrefill: or("isText", "isCategory", "isTag", "isGroup", "isDropdown"),
showContent: or("isCategory", "isTag", "isGroup", "isDropdown"),
showLimit: or("isCategory", "isTag"),
isTextType: or("isText", "isTextarea", "isComposer"),
categoryPropertyTypes: selectKitContent(["id", "slug"]),
showAdvanced: alias("field.type"),
messageUrl: "https://thepavilion.io/t/2809",
@discourseComputed("field.type")
validations(type) {
const applicableToField = [];
for(let validation in wizardSchema.field.validations) {
if ((wizardSchema.field.validations[validation]["types"]).includes(type)) {
applicableToField.push(validation)
for (let validation in wizardSchema.field.validations) {
if (wizardSchema.field.validations[validation]["types"].includes(type)) {
applicableToField.push(validation);
}
}
return applicableToField;
},
@discourseComputed('field.type')
@discourseComputed("field.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) {
let key = 'type';
let key = "type";
if (type) {
key = 'edit';
key = "edit";
}
return key;
},
setupTypeOutput(fieldType, options) {
setupTypeOutput(fieldType, options) {
const selectionType = {
category: 'category',
tag: 'tag',
group: 'group'
category: "category",
tag: "tag",
group: "group",
}[fieldType];
if (selectionType) {
options[`${selectionType}Selection`] = 'output';
options[`${selectionType}Selection`] = "output";
options.outputDefaultSelection = selectionType;
}
return options;
},
@discourseComputed('field.type')
@discourseComputed("field.type")
contentOptions(fieldType) {
let options = {
wizardFieldSelection: true,
textSelection: 'key,value',
userFieldSelection: 'key,value',
context: 'field'
}
textSelection: "key,value",
userFieldSelection: "key,value",
context: "field",
};
options = this.setupTypeOutput(fieldType, options);
if (this.isDropdown) {
options.wizardFieldSelection = 'key,value';
options.userFieldOptionsSelection = 'output';
options.textSelection = 'key,value,output';
options.inputTypes = 'conditional,association,assignment';
options.pairConnector = 'association';
options.keyPlaceholder = 'admin.wizard.key';
options.valuePlaceholder = 'admin.wizard.value';
options.wizardFieldSelection = "key,value";
options.userFieldOptionsSelection = "output";
options.textSelection = "key,value,output";
options.inputTypes = "conditional,association,assignment";
options.pairConnector = "association";
options.keyPlaceholder = "admin.wizard.key";
options.valuePlaceholder = "admin.wizard.value";
}
return options;
},
@discourseComputed('field.type')
@discourseComputed("field.type")
prefillOptions(fieldType) {
let options = {
wizardFieldSelection: true,
textSelection: true,
userFieldSelection: 'key,value',
context: 'field'
}
userFieldSelection: "key,value",
context: "field",
};
return this.setupTypeOutput(fieldType, options);
},
actions: {
actions: {
imageUploadDone(upload) {
this.set("field.image", upload.url);
},
imageUploadDeleted() {
this.set("field.image", null);
}
}
},
},
});

Datei anzeigen

@ -1,16 +1,16 @@
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({
classNames: 'wizard-custom-step',
classNames: "wizard-custom-step",
actions: {
bannerUploadDone(upload) {
this.set("step.banner", upload.url);
},
bannerUploadDeleted() {
this.set("step.banner", null);
}
}
},
},
});

Datei anzeigen

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

Datei anzeigen

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

Datei anzeigen

@ -1,69 +1,78 @@
import { computed, set } from "@ember/object";
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 { observes } from "discourse-common/utils/decorators";
import { A } from "@ember/array";
export default Component.extend({
classNameBindings: [':mapper-input', 'inputType'],
inputType: alias('input.type'),
isConditional: equal('inputType', 'conditional'),
isAssignment: equal('inputType', 'assignment'),
isAssociation: equal('inputType', 'association'),
isValidation: equal('inputType', 'validation'),
hasOutput: or('isConditional', 'isAssignment'),
hasPairs: or('isConditional', 'isAssociation', 'isValidation'),
canAddPair: not('isAssignment'),
connectors: computed(function() { return connectorContent('output', this.input.type, this.options) }),
inputTypes: computed(function() { return inputTypesContent(this.options) }),
@observes('input.type')
classNameBindings: [":mapper-input", "inputType"],
inputType: alias("input.type"),
isConditional: equal("inputType", "conditional"),
isAssignment: equal("inputType", "assignment"),
isAssociation: equal("inputType", "association"),
isValidation: equal("inputType", "validation"),
hasOutput: or("isConditional", "isAssignment"),
hasPairs: or("isConditional", "isAssociation", "isValidation"),
canAddPair: not("isAssignment"),
connectors: computed(function () {
return connectorContent("output", this.input.type, this.options);
}),
inputTypes: computed(function () {
return inputTypesContent(this.options);
}),
@observes("input.type")
setupType() {
if (this.hasPairs && (!this.input.pairs || this.input.pairs.length < 1)) {
this.send('addPair');
this.send("addPair");
}
if (this.hasOutput) {
this.set('input.output', null);
this.set("input.output", null);
if (!this.input.outputConnector) {
const options = this.options;
this.set('input.output_type', defaultSelectionType('output', options));
this.set('input.output_connector', defaultConnector('output', this.inputType, options));
this.set("input.output_type", defaultSelectionType("output", options));
this.set(
"input.output_connector",
defaultConnector("output", this.inputType, options)
);
}
}
},
actions: {
addPair() {
if (!this.input.pairs) {
this.set('input.pairs', A());
this.set("input.pairs", A());
}
const pairs = this.input.pairs;
const pairCount = pairs.length + 1;
pairs.forEach(p => (set(p, 'pairCount', pairCount)));
pairs.forEach((p) => set(p, "pairCount", pairCount));
pairs.pushObject(
newPair(
this.input.type,
Object.assign(
{},
this.options,
{ index: pairs.length, pairCount }
)
this.input.type,
Object.assign({}, this.options, { index: pairs.length, pairCount })
)
);
},
removePair(pair) {
const pairs = this.input.pairs;
const pairCount = pairs.length - 1;
pairs.forEach(p => (set(p, 'pairCount', pairCount)));
pairs.forEach((p) => set(p, "pairCount", pairCount));
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 { computed, observes } from "@ember/object";
import { computed, observes } from "@ember/object";
import Component from "@ember/component";
export default Component.extend({
classNameBindings: [':mapper-pair', 'hasConnector::no-connector'],
firstPair: gt('pair.index', 0),
showRemove: alias('firstPair'),
showJoin: computed('pair.pairCount', function() { return this.pair.index < (this.pair.pairCount - 1) }),
connectors: computed(function() { return connectorContent('pair', this.inputType, this.options) })
});
classNameBindings: [":mapper-pair", "hasConnector::no-connector"],
firstPair: gt("pair.index", 0),
showRemove: alias("firstPair"),
showJoin: computed("pair.pairCount", function () {
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";
export default Component.extend({
tagName: 'a',
classNameBindings: ['active'],
@discourseComputed('item.type', 'activeType')
active(type, activeType) { return type === activeType },
tagName: "a",
classNameBindings: ["active"],
@discourseComputed("item.type", "activeType")
active(type, activeType) {
return type === activeType;
},
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 { computed } from "@ember/object";
import { default as discourseComputed, observes, 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 {
default as discourseComputed,
observes,
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 { bind, later } from "@ember/runloop";
import I18n from "I18n";
export default Component.extend({
classNameBindings: [':mapper-selector', 'activeType'],
showText: computed('activeType', function() { return this.showInput('text') }),
showWizardField: computed('activeType', function() { return this.showInput('wizardField') }),
showWizardAction: computed('activeType', function() { return this.showInput('wizardAction') }),
showUserField: computed('activeType', function() { return this.showInput('userField') }),
showUserFieldOptions: computed('activeType', function() { return this.showInput('userFieldOptions') }),
showCategory: computed('activeType', function() { return this.showInput('category') }),
showTag: computed('activeType', function() { return this.showInput('tag') }),
showGroup: computed('activeType', function() { return this.showInput('group') }),
showUser: computed('activeType', function() { return this.showInput('user') }),
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),
classNameBindings: [":mapper-selector", "activeType"],
showText: computed("activeType", function () {
return this.showInput("text");
}),
showWizardField: computed("activeType", function () {
return this.showInput("wizardField");
}),
showWizardAction: computed("activeType", function () {
return this.showInput("wizardAction");
}),
showUserField: computed("activeType", function () {
return this.showInput("userField");
}),
showUserFieldOptions: computed("activeType", function () {
return this.showInput("userFieldOptions");
}),
showCategory: computed("activeType", function () {
return this.showInput("category");
}),
showTag: computed("activeType", function () {
return this.showInput("tag");
}),
showGroup: computed("activeType", function () {
return this.showInput("group");
}),
showUser: computed("activeType", function () {
return this.showInput("user");
}),
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,
didInsertElement() {
if (!this.activeType || (this.activeType && !this[`${this.activeType}Enabled`])) {
if (
!this.activeType ||
(this.activeType && !this[`${this.activeType}Enabled`])
) {
later(() => this.resetActiveType());
}
$(document).on("click", bind(this, this.documentClick));
},
@ -56,42 +137,45 @@ export default Component.extend({
documentClick(e) {
if (this._state == "destroying") return;
let $target = $(e.target);
if (!$target.parents('.type-selector').length && this.showTypes) {
this.set('showTypes', false);
if (!$target.parents(".type-selector").length && this.showTypes) {
this.set("showTypes", false);
}
},
@discourseComputed
selectorTypes() {
return selectionTypes.filter(type => (this[`${type}Enabled`]))
.map(type => ({ type, label: this.typeLabel(type) }));
return selectionTypes
.filter((type) => this[`${type}Enabled`])
.map((type) => ({ type, label: this.typeLabel(type) }));
},
@discourseComputed('activeType')
@discourseComputed("activeType")
activeTypeLabel(activeType) {
return this.typeLabel(activeType);
},
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
showController() {
return getOwner(this).lookup('controller:admin-wizards-wizard-show');
return getOwner(this).lookup("controller:admin-wizards-wizard-show");
},
@discourseComputed(
'activeType',
'showController.wizardFields.[]',
'showController.wizard.actions.[]',
'showController.userFields.[]',
'showController.currentField.id',
'showController.currentAction.id',
'showController.customFields'
"activeType",
"showController.wizardFields.[]",
"showController.wizard.actions.[]",
"showController.userFields.[]",
"showController.currentField.id",
"showController.currentAction.id",
"showController.customFields"
)
comboBoxContent(
activeType,
@ -103,133 +187,144 @@ export default Component.extend({
customFields
) {
let content;
if (activeType === 'wizardField') {
if (activeType === "wizardField") {
content = wizardFields;
if (this.options.context === 'field') {
content = content.filter(field => field.id !== currentFieldId);
if (this.options.context === "field") {
content = content.filter((field) => field.id !== currentFieldId);
}
}
if (activeType === 'wizardAction') {
content = wizardActions.map(a => ({
if (activeType === "wizardAction") {
content = wizardActions.map((a) => ({
id: a.id,
label: `${generateName(a.type)} (${a.id})`,
type: a.type
type: a.type,
}));
if (this.options.context === 'action') {
content = content.filter(a => a.id !== currentActionId);
if (this.options.context === "action") {
content = content.filter((a) => a.id !== currentActionId);
}
}
if (activeType === 'userField') {
content = userProperties.map((f) => ({
id: f,
name: generateName(f)
})).concat((userFields || []));
if (this.options.context === 'action' &&
this.inputType === 'association' &&
this.selectorType === 'key') {
const excludedFields = ['username','email', 'trust_level'];
content = content.filter(userField => excludedFields.indexOf(userField.id) === -1);
if (activeType === "userField") {
content = userProperties
.map((f) => ({
id: f,
name: generateName(f),
}))
.concat(userFields || []);
if (
this.options.context === "action" &&
this.inputType === "association" &&
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;
}
if (activeType === 'customField') {
if (activeType === "customField") {
content = customFields;
}
return content;
},
@discourseComputed('activeType')
@discourseComputed("activeType")
multiSelectContent(activeType) {
return {
category: this.categories,
group: this.groups,
list: ''
list: "",
}[activeType];
},
@discourseComputed('activeType', 'inputType')
@discourseComputed("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`];
} else {
return `admin.wizard.selector.placeholder.${snakeCase(activeType)}`;
}
}
},
@discourseComputed('activeType')
@discourseComputed("activeType")
multiSelectOptions(activeType) {
let result = {
none: this.placeholderKey
none: this.placeholderKey,
};
if (activeType === 'list') {
if (activeType === "list") {
result.allowAny = true;
}
return result;
},
optionEnabled(type) {
const options = this.options;
if (!options) return false;
const option = options[type];
if (option === true) return true;
if (typeof option !== 'string') return false;
return option.split(',').filter(option => {
if (typeof option !== "string") return false;
return option.split(",").filter((option) => {
return [this.selectorType, this.inputType].indexOf(option) !== -1;
}).length;
},
showInput(type) {
return this.activeType === type && this[`${type}Enabled`];
},
changeValue(value) {
this.set('value', value);
this.onUpdate('selector', this.activeType);
this.set("value", value);
this.onUpdate("selector", this.activeType);
},
@observes('inputType')
@observes("inputType")
resetActiveType() {
this.set('activeType', defaultSelectionType(this.selectorType, this.options));
this.set(
"activeType",
defaultSelectionType(this.selectorType, this.options)
);
},
actions: {
toggleType(type) {
this.set('activeType', type);
this.set('showTypes', false);
this.set('value', null);
this.onUpdate('selector');
this.set("activeType", type);
this.set("showTypes", false);
this.set("value", null);
this.onUpdate("selector");
},
toggleTypes() {
this.toggleProperty('showTypes');
this.toggleProperty("showTypes");
},
changeValue(value) {
this.changeValue(value);
},
changeInputValue(event) {
this.changeValue(event.target.value);
},
changeUserValue(previousValue, value) {
this.changeValue(value);
}
}
})
},
},
});

Datei anzeigen

@ -1,84 +1,90 @@
import { getOwner } from 'discourse-common/lib/get-owner';
import { newInput, selectionTypes } from '../lib/wizard-mapper';
import { default as discourseComputed, observes, on } from 'discourse-common/utils/decorators';
import { getOwner } from "discourse-common/lib/get-owner";
import { newInput, selectionTypes } from "../lib/wizard-mapper";
import {
default as discourseComputed,
observes,
on,
} from "discourse-common/utils/decorators";
import { later } from "@ember/runloop";
import Component from "@ember/component";
import { A } from "@ember/array";
export default Component.extend({
classNames: 'wizard-mapper',
classNames: "wizard-mapper",
didReceiveAttrs() {
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) {
return !inputs ||
inputs.constructor !== Array ||
inputs.every(i => {
return ['assignment','association'].indexOf(i.type) === -1;
});
return (
!inputs ||
inputs.constructor !== Array ||
inputs.every((i) => {
return ["assignment", "association"].indexOf(i.type) === -1;
})
);
},
@discourseComputed('options.@each.inputType')
@discourseComputed("options.@each.inputType")
inputOptions(options) {
let result = {
inputTypes: options.inputTypes || 'assignment,conditional',
inputConnector: options.inputConnector || 'or',
inputTypes: options.inputTypes || "assignment,conditional",
inputConnector: options.inputConnector || "or",
pairConnector: options.pairConnector || null,
outputConnector: options.outputConnector || null,
context: options.context || null
}
let inputTypes = ['key', 'value', 'output'];
inputTypes.forEach(type => {
context: options.context || null,
};
let inputTypes = ["key", "value", "output"];
inputTypes.forEach((type) => {
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) {
result[`${type}Selection`] = options[`${type}Selection`]
result[`${type}Selection`] = options[`${type}Selection`];
} else {
result[`${type}Selection`] = type === 'text' ? true : false;
result[`${type}Selection`] = type === "text" ? true : false;
}
});
return result;
},
onUpdate() {
},
onUpdate() {},
actions: {
add() {
if (!this.get('inputs')) {
this.set('inputs', A());
if (!this.get("inputs")) {
this.set("inputs", A());
}
this.get('inputs').pushObject(
this.get("inputs").pushObject(
newInput(this.inputOptions, this.inputs.length)
);
this.onUpdate(this.property, 'input');
this.onUpdate(this.property, "input");
},
remove(input) {
const inputs = this.inputs;
inputs.removeObject(input);
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) {
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 Component from "@ember/component";
import I18n from "I18n";
const icons = {
error: 'times-circle',
success: 'check-circle',
info: 'info-circle'
}
error: "times-circle",
success: "check-circle",
info: "info-circle",
};
export default Component.extend({
classNameBindings: [':wizard-message', 'type', 'loading'],
showDocumentation: not('loading'),
showIcon: not('loading'),
hasItems: notEmpty('items'),
@discourseComputed('type')
classNameBindings: [":wizard-message", "type", "loading"],
showDocumentation: not("loading"),
showIcon: not("loading"),
hasItems: notEmpty("items"),
@discourseComputed("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) {
return I18n.t(`admin.wizard.message.${component}.${key}`, opts || {});
},
@discourseComputed('component')
@discourseComputed("component")
documentation(component) {
return I18n.t(`admin.wizard.message.${component}.documentation`);
}
})
},
});

Datei anzeigen

@ -12,7 +12,7 @@ export default Component.extend({
if (!this.field.validations) {
const validations = {};
this.validations.forEach((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 { userProperties } from '../lib/wizard';
import { userProperties } from "../lib/wizard";
import { scheduleOnce } from "@ember/runloop";
import Component from "@ember/component";
import I18n from "I18n";
export default Component.extend({
classNames: 'wizard-text-editor',
classNames: "wizard-text-editor",
barEnabled: true,
previewEnabled: true,
fieldsEnabled: true,
hasWizardFields: notEmpty('wizardFieldList'),
hasWizardActions: notEmpty('wizardActionList'),
hasWizardFields: notEmpty("wizardFieldList"),
hasWizardActions: notEmpty("wizardActionList"),
didReceiveAttrs() {
this._super(...arguments);
if (!this.barEnabled) {
scheduleOnce('afterRender', () => {
$(this.element).find('.d-editor-button-bar').addClass('hidden');
scheduleOnce("afterRender", () => {
$(this.element).find(".d-editor-button-bar").addClass("hidden");
});
}
},
@discourseComputed('forcePreview')
@discourseComputed("forcePreview")
previewLabel(forcePreview) {
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) {
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()
userPropertyList() {
return userProperties.map((f) => ` u{${f}}`);
},
@discourseComputed('wizardFields')
@discourseComputed("wizardFields")
wizardFieldList(wizardFields) {
return wizardFields.map((f) => ` w{${f.id}}`);
},
@discourseComputed('wizardActions')
@discourseComputed("wizardActions")
wizardActionList(wizardActions) {
return wizardActions.map((a) => ` w{${a.id}}`);
},
actions: {
togglePreview() {
this.toggleProperty('forcePreview');
this.toggleProperty("forcePreview");
},
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({
_saveValues() {
@ -8,5 +8,5 @@ export default ValueList.extend({
}
this.onChange(this.collection.join(this.inputDelimiter || "\n"));
}
})
},
});

Datei anzeigen

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

Datei anzeigen

@ -1,93 +1,139 @@
import { ajax } from 'discourse/lib/ajax';
import { popupAjaxError } from 'discourse/lib/ajax-error';
import CustomWizardApi from '../models/custom-wizard-api';
import { default as discourseComputed } from 'discourse-common/utils/decorators';
import { ajax } from "discourse/lib/ajax";
import { popupAjaxError } from "discourse/lib/ajax-error";
import CustomWizardApi from "../models/custom-wizard-api";
import { default as discourseComputed } from "discourse-common/utils/decorators";
import { not, and, equal } from "@ember/object/computed";
import { selectKitContent } from '../lib/wizard';
import { selectKitContent } from "../lib/wizard";
import Controller from "@ember/controller";
import I18n from "I18n";
export default Controller.extend({
queryParams: ['refresh_list'],
queryParams: ["refresh_list"],
loadingSubscriptions: false,
notAuthorized: not('api.authorized'),
endpointMethods: selectKitContent(['GET', 'PUT', 'POST', 'PATCH', 'DELETE']),
showRemove: not('isNew'),
showRedirectUri: and('threeLeggedOauth', 'api.name'),
notAuthorized: not("api.authorized"),
endpointMethods: selectKitContent(["GET", "PUT", "POST", "PATCH", "DELETE"]),
showRemove: not("isNew"),
showRedirectUri: and("threeLeggedOauth", "api.name"),
responseIcon: null,
contentTypes: selectKitContent(['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]),
contentTypes: selectKitContent([
"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')
authDisabled(saveDisabled, authType, authUrl, tokenUrl, clientId, clientSecret, threeLeggedOauth) {
if (saveDisabled || !authType || !tokenUrl || !clientId || !clientSecret) return true;
@discourseComputed(
"saveDisabled",
"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;
return false;
},
@discourseComputed('api.name', 'api.authType')
@discourseComputed("api.name", "api.authType")
saveDisabled(name, authType) {
return !name || !authType;
},
authorizationTypes: selectKitContent(['none', 'basic', 'oauth_2', 'oauth_3']),
isBasicAuth: equal('api.authType', 'basic'),
authorizationTypes: selectKitContent(["none", "basic", "oauth_2", "oauth_3"]),
isBasicAuth: equal("api.authType", "basic"),
@discourseComputed('api.authType')
@discourseComputed("api.authType")
isOauth(authType) {
return authType && authType.indexOf('oauth') > -1;
return authType && authType.indexOf("oauth") > -1;
},
twoLeggedOauth: equal('api.authType', 'oauth_2'),
threeLeggedOauth: equal('api.authType', 'oauth_3'),
twoLeggedOauth: equal("api.authType", "oauth_2"),
threeLeggedOauth: equal("api.authType", "oauth_3"),
actions: {
addParam() {
this.get('api.authParams').pushObject({});
this.get("api.authParams").pushObject({});
},
removeParam(param) {
this.get('api.authParams').removeObject(param);
this.get("api.authParams").removeObject(param);
},
addEndpoint() {
this.get('api.endpoints').pushObject({});
this.get("api.endpoints").pushObject({});
},
removeEndpoint(endpoint) {
this.get('api.endpoints').removeObject(endpoint);
this.get("api.endpoints").removeObject(endpoint);
},
authorize() {
const api = this.get('api');
const api = this.get("api");
const { name, authType, authUrl, authParams } = api;
this.set('authErrorMessage', '');
this.set("authErrorMessage", "");
if (authType === 'oauth_2') {
this.set('authorizing', true);
ajax(`/admin/wizards/apis/${name.underscore()}/authorize`).catch(popupAjaxError)
.then(result => {
if (authType === "oauth_2") {
this.set("authorizing", true);
ajax(`/admin/wizards/apis/${name.underscore()}/authorize`)
.catch(popupAjaxError)
.then((result) => {
if (result.success) {
this.set('api', CustomWizardApi.create(result.api));
this.set("api", CustomWizardApi.create(result.api));
} else if (result.failed && result.message) {
this.set('authErrorMessage', result.message);
this.set("authErrorMessage", result.message);
} else {
this.set('authErrorMessage', 'Authorization Failed');
this.set("authErrorMessage", "Authorization Failed");
}
setTimeout(() => {
this.set('authErrorMessage', '');
this.set("authErrorMessage", "");
}, 6000);
}).finally(() => this.set('authorizing', false));
} else if (authType === 'oauth_3') {
let query = '?';
})
.finally(() => this.set("authorizing", false));
} else if (authType === "oauth_3") {
let query = "?";
query += `client_id=${api.clientId}`;
query += `&redirect_uri=${encodeURIComponent(api.redirectUri)}`;
query += `&response_type=code`;
if (authParams) {
authParams.forEach(p => {
authParams.forEach((p) => {
query += `&${p.key}=${encodeURIComponent(p.value)}`;
});
}
@ -97,7 +143,7 @@ export default Controller.extend({
},
save() {
const api = this.get('api');
const api = this.get("api");
const name = api.name;
const authType = api.authType;
let refreshList = false;
@ -106,35 +152,37 @@ export default Controller.extend({
if (!name || !authType) return;
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');
if (api.get('isNew') || (originalTitle && (api.title !== originalTitle))) {
const originalTitle = this.get("api.originalTitle");
if (api.get("isNew") || (originalTitle && api.title !== originalTitle)) {
refreshList = true;
}
if (api.get('isNew')) {
data['new'] = true;
};
if (api.get("isNew")) {
data["new"] = true;
}
let requiredParams;
if (authType === 'basic') {
requiredParams = ['username', 'password'];
} else if (authType === 'oauth_2') {
requiredParams = ['tokenUrl', 'clientId', 'clientSecret'];
} else if (authType === 'oauth_3') {
requiredParams = ['authUrl', 'tokenUrl', 'clientId', 'clientSecret'];
if (authType === "basic") {
requiredParams = ["username", "password"];
} else if (authType === "oauth_2") {
requiredParams = ["tokenUrl", "clientId", "clientSecret"];
} else if (authType === "oauth_3") {
requiredParams = ["authUrl", "tokenUrl", "clientId", "clientSecret"];
}
if (requiredParams) {
for (let rp of requiredParams) {
if (!api[rp]) {
let key = rp.replace('auth', '');
error = `${I18n.t(`admin.wizard.api.auth.${key.underscore()}`)} is required for ${authType}`;
let key = rp.replace("auth", "");
error = `${I18n.t(
`admin.wizard.api.auth.${key.underscore()}`
)} is required for ${authType}`;
break;
}
data[rp.underscore()] = api[rp];
@ -143,73 +191,79 @@ export default Controller.extend({
const params = api.authParams;
if (params.length) {
data['auth_params'] = JSON.stringify(params);
data["auth_params"] = JSON.stringify(params);
}
const endpoints = api.endpoints;
if (endpoints.length) {
for (let e of endpoints) {
if (!e.name) {
error = 'Every endpoint must have a name';
error = "Every endpoint must have a name";
break;
}
}
data['endpoints'] = JSON.stringify(endpoints);
data["endpoints"] = JSON.stringify(endpoints);
}
if (error) {
this.set('error', error);
this.set("error", error);
setTimeout(() => {
this.set('error', '');
this.set("error", "");
}, 6000);
return;
}
this.set('updating', true);
this.set("updating", true);
ajax(`/admin/wizards/api/${name.underscore()}`, {
type: 'PUT',
data
}).catch(popupAjaxError)
.then(result => {
type: "PUT",
data,
})
.catch(popupAjaxError)
.then((result) => {
if (result.success) {
this.send('afterSave', result.api.name);
this.send("afterSave", result.api.name);
} else {
this.set('responseIcon', 'times');
this.set("responseIcon", "times");
}
}).finally(() => this.set('updating', false));
})
.finally(() => this.set("updating", false));
},
remove() {
const name = this.get('api.name');
const name = this.get("api.name");
if (!name) return;
this.set('updating', true);
this.set("updating", true);
ajax(`/admin/wizards/api/${name.underscore()}`, {
type: 'DELETE'
}).catch(popupAjaxError)
.then(result => {
type: "DELETE",
})
.catch(popupAjaxError)
.then((result) => {
if (result.success) {
this.send('afterDestroy');
this.send("afterDestroy");
}
}).finally(() => this.set('updating', false));
})
.finally(() => this.set("updating", false));
},
clearLogs() {
const name = this.get('api.name');
const name = this.get("api.name");
if (!name) return;
ajax(`/admin/wizards/api/${name.underscore()}/logs`, {
type: 'DELETE'
}).catch(popupAjaxError)
.then(result => {
type: "DELETE",
})
.catch(popupAjaxError)
.then((result) => {
if (result.success) {
this.transitionToRoute('adminWizardsApis').then(() => {
this.send('refreshModel');
this.transitionToRoute("adminWizardsApis").then(() => {
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 EmberObject from '@ember/object';
import { ajax } from 'discourse/lib/ajax';
import { popupAjaxError } from 'discourse/lib/ajax-error';
import EmberObject from "@ember/object";
import { ajax } from "discourse/lib/ajax";
import { popupAjaxError } from "discourse/lib/ajax-error";
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({
messageKey: 'create',
fieldKeys: ['klass', 'type', 'serializers', 'name'],
messageKey: "create",
fieldKeys: ["klass", "type", "serializers", "name"],
documentationUrl: "https://thepavilion.io/t/3572",
actions: {
addField() {
this.get('customFields').pushObject(
this.get("customFields").pushObject(
CustomWizardCustomField.create({ edit: true })
);
},
saveField(field) {
return CustomWizardCustomField.saveField(field)
.then(result => {
if (result.success) {
return CustomWizardCustomField.saveField(field).then((result) => {
if (result.success) {
this.setProperties({
messageKey: "saved",
messageType: "success",
});
} else {
if (result.messages) {
this.setProperties({
messageKey: 'saved',
messageType: 'success'
messageKey: "error",
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',
messageType: null,
messageOpts: null
}), 10000);
return result;
});
}
setTimeout(
() =>
this.setProperties({
messageKey: "create",
messageType: null,
messageOpts: null,
}),
10000
);
return result;
});
},
removeField(field) {
return CustomWizardCustomField.destroyField(field)
.then(result => {
this.get('customFields').removeObject(field);
});
}
}
});
return CustomWizardCustomField.destroyField(field).then((result) => {
this.get("customFields").removeObject(field);
});
},
},
});

Datei anzeigen

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

Datei anzeigen

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

Datei anzeigen

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

Datei anzeigen

@ -1,25 +1,25 @@
import Controller from "@ember/controller";
import { default as discourseComputed } from 'discourse-common/utils/decorators';
import { equal } from '@ember/object/computed';
import { default as discourseComputed } from "discourse-common/utils/decorators";
import { equal } from "@ember/object/computed";
export default Controller.extend({
creating: equal('wizardId', 'create'),
@discourseComputed('creating', 'wizardId')
creating: equal("wizardId", "create"),
@discourseComputed("creating", "wizardId")
wizardListVal(creating, wizardId) {
return creating ? null : wizardId;
},
@discourseComputed('creating', 'wizardId')
@discourseComputed("creating", "wizardId")
messageKey(creating, wizardId) {
let key = 'select';
let key = "select";
if (creating) {
key = 'create';
key = "create";
} 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";
export default Controller.extend({
title: 'admin.wizard.after_time_modal.title',
title: "admin.wizard.after_time_modal.title",
setup() {
this.set('bufferedDateTime', moment(this.model.dateTime));
this.set("bufferedDateTime", moment(this.model.dateTime));
},
@discourseComputed('bufferedDateTime')
@discourseComputed("bufferedDateTime")
submitDisabled(dateTime) {
return moment().isAfter(dateTime);
},
actions: {
submit() {
const dateTime = this.get('bufferedDateTime');
this.get('model.update')(moment(dateTime).utc().toISOString());
const dateTime = this.get("bufferedDateTime");
this.get("model.update")(moment(dateTime).utc().toISOString());
this.send("closeModal");
},
dateTimeChanged(dateTime) {
this.set('bufferedDateTime', dateTime);
}
}
this.set("bufferedDateTime", dateTime);
},
},
});

Datei anzeigen

@ -1,25 +1,55 @@
export default {
resource: 'admin',
resource: "admin",
map() {
this.route('adminWizards', { path: '/wizards', resetNamespace: true }, function() {
this.route('adminWizardsWizard', { path: '/wizard/', resetNamespace: true }, function() {
this.route('adminWizardsWizardShow', { path: '/:wizardId/', 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(
"adminWizards",
{ path: "/wizards", resetNamespace: true },
function () {
this.route(
"adminWizardsWizard",
{ path: "/wizard/", resetNamespace: true },
function () {
this.route("adminWizardsWizardShow", {
path: "/:wizardId/",
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";
registerUnbound('dasherize', function(string) {
registerUnbound("dasherize", function (string) {
return dasherize(string);
});

Datei anzeigen

@ -1,19 +1,19 @@
import { withPluginApi } from 'discourse/lib/plugin-api';
import DiscourseURL from 'discourse/lib/url';
import { withPluginApi } from "discourse/lib/plugin-api";
import DiscourseURL from "discourse/lib/url";
export default {
name: 'custom-wizard-edits',
name: "custom-wizard-edits",
initialize(container) {
const siteSettings = container.lookup('site-settings:main');
const siteSettings = container.lookup("site-settings:main");
if (!siteSettings.custom_wizard_enabled) return;
const existing = DiscourseURL.routeTo;
DiscourseURL.routeTo = function(path, opts) {
if (path && path.indexOf('/w/') > -1) {
return window.location = path;
DiscourseURL.routeTo = function (path, opts) {
if (path && path.indexOf("/w/") > -1) {
return (window.location = path);
}
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 {
name: "custom-wizard-redirect",
after: "message-bus",
initialize: function (container) {
const messageBus = container.lookup('message-bus:main');
const siteSettings = container.lookup('site-settings:main');
const messageBus = container.lookup("message-bus:main");
const siteSettings = container.lookup("site-settings:main");
if (!siteSettings.custom_wizard_enabled || !messageBus) return;
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;
});
ApplicationRoute.reopen({
actions: {
willTransition(transition) {
const redirectToWizard = this.get('currentUser.redirect_to_wizard');
const excludedPaths = Discourse.SiteSettings.wizard_redirect_exclude_paths.split('|').concat(['loading']);
const redirectToWizard = this.get("currentUser.redirect_to_wizard");
const excludedPaths = Discourse.SiteSettings.wizard_redirect_exclude_paths
.split("|")
.concat(["loading"]);
if (redirectToWizard && (!transition.intent.name || !excludedPaths.find((p) => {
return transition.intent.name.indexOf(p) > -1;
}))) {
if (
redirectToWizard &&
(!transition.intent.name ||
!excludedPaths.find((p) => {
return transition.intent.name.indexOf(p) > -1;
}))
) {
transition.abort();
window.location = '/w/' + redirectToWizard.dasherize();
window.location = "/w/" + redirectToWizard.dasherize();
}
return this._super(transition);
}
}
})
}
},
},
});
},
};

Datei anzeigen

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

Datei anzeigen

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

Datei anzeigen

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

Datei anzeigen

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

Datei anzeigen

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

Datei anzeigen

@ -1,15 +1,19 @@
import { ajax } from 'discourse/lib/ajax';
import { default as discourseComputed } from 'discourse-common/utils/decorators';
import { ajax } from "discourse/lib/ajax";
import { default as discourseComputed } from "discourse-common/utils/decorators";
import EmberObject from "@ember/object";
import { A } from "@ember/array";
const CustomWizardApi = EmberObject.extend({
@discourseComputed('name')
@discourseComputed("name")
redirectUri(name) {
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`;
}
},
});
CustomWizardApi.reopenClass({
@ -38,7 +42,7 @@ CustomWizardApi.reopenClass({
tokenRefreshAt: authorization.token_refresh_at,
endpoints: A(endpoints),
isNew: params.isNew,
log: params.log
log: params.log,
});
return api;
@ -46,19 +50,19 @@ CustomWizardApi.reopenClass({
find(name) {
return ajax(`/admin/wizards/api/${name}`, {
type: 'GET'
}).then(result => {
type: "GET",
}).then((result) => {
return CustomWizardApi.create(result);
});
},
list() {
return ajax("/admin/wizards/api", {
type: 'GET'
}).then(result => {
type: "GET",
}).then((result) => {
return result;
});
}
},
});
export default CustomWizardApi;

Datei anzeigen

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

Datei anzeigen

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

Datei anzeigen

@ -1,5 +1,5 @@
import { ajax } from 'discourse/lib/ajax';
import { popupAjaxError } from 'discourse/lib/ajax-error';
import { ajax } from "discourse/lib/ajax";
import { popupAjaxError } from "discourse/lib/ajax-error";
import EmberObject from "@ember/object";
const CustomWizardManager = EmberObject.extend();
@ -9,35 +9,35 @@ const basePath = "admin/wizards/manager";
CustomWizardManager.reopenClass({
import($formData) {
return ajax(`/${basePath}/import`, {
type: 'POST',
type: "POST",
data: $formData,
processData: false,
contentType: false,
}).catch(popupAjaxError);
},
export(wizardIds) {
let url = `${Discourse.BaseUrl}/${basePath}/export?`;
wizardIds.forEach((wizardId, index) => {
let step = 'wizard_ids[]=' + wizardId;
let step = "wizard_ids[]=" + wizardId;
if (index !== wizardIds[wizardIds.length - 1]) {
step += '&';
step += "&";
}
url += step;
});
location.href = url;
},
destroy(wizardIds) {
return ajax(`/${basePath}/destroy`, {
type: "DELETE",
data: {
wizard_ids: wizardIds
}
wizard_ids: wizardIds,
},
}).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 { buildProperties, present, mapped } from '../lib/wizard-json';
import { listProperties, camelCase, snakeCase } from '../lib/wizard';
import wizardSchema from '../lib/wizard-schema';
import { buildProperties, present, mapped } from "../lib/wizard-json";
import { listProperties, camelCase, snakeCase } from "../lib/wizard";
import wizardSchema from "../lib/wizard-schema";
import { Promise } from "rsvp";
import { popupAjaxError } from 'discourse/lib/ajax-error';
import { popupAjaxError } from "discourse/lib/ajax-error";
const CustomWizard = EmberObject.extend({
save(opts) {
return new Promise((resolve, reject) => {
let wizard = this.buildJson(this, 'wizard');
return new Promise((resolve, reject) => {
let wizard = this.buildJson(this, "wizard");
if (wizard.error) {
reject(wizard);
}
let data = {
wizard
wizard,
};
if (opts.create) {
data.create = true;
}
ajax(`/admin/wizards/wizard/${wizard.id}`, {
type: 'PUT',
type: "PUT",
contentType: "application/json",
data: JSON.stringify(data)
data: JSON.stringify(data),
}).then((result) => {
if (result.error) {
reject(result);
@ -39,53 +39,55 @@ const CustomWizard = EmberObject.extend({
buildJson(object, type, result = {}) {
let objectType = object.type || null;
if (wizardSchema[type].types) {
if (!objectType) {
result.error = {
type: 'required',
params: { type, property: 'type' }
}
type: "required",
params: { type, property: "type" },
};
return result;
}
}
for (let property of listProperties(type, { objectType })) {
let value = object.get(property);
result = this.validateValue(property, value, object, type, result);
if (result.error) {
break;
}
if (mapped(property, type)) {
value = this.buildMappedJson(value);
}
if (value !== undefined && value !== null) {
result[property] = value;
}
};
}
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 objectArray = object.get(arraySchema.property);
if (arraySchema.required && !present(objectArray)) {
result.error = {
type: 'required',
params: { type, property: arraySchema.property }
}
type: "required",
params: { type, property: arraySchema.property },
};
break;
}
result[arraySchema.property] = [];
for (let item of objectArray) {
let itemProps = this.buildJson(item, arrayObjectType);
if (itemProps.error) {
result.error = itemProps.error;
break;
@ -93,115 +95,119 @@ const CustomWizard = EmberObject.extend({
result[arraySchema.property].push(itemProps);
}
}
};
}
}
return result;
},
validateValue(property, value, object, type, result) {
if (wizardSchema[type].required.indexOf(property) > -1 && !value) {
result.error = {
type: 'required',
params: { type, property }
}
type: "required",
params: { type, property },
};
}
let dependent = wizardSchema[type].dependent[property];
if (dependent && value && !object[dependent]) {
result.error = {
type: 'dependent',
params: { property, dependent }
}
type: "dependent",
params: { property, dependent },
};
}
if (property === 'api_body') {
if (property === "api_body") {
try {
value = JSON.parse(value);
} catch (e) {
result.error = {
type: 'invalid',
params: { type, property }
}
type: "invalid",
params: { type, property },
};
}
}
return result;
},
buildMappedJson(inputs) {
if (!inputs || !inputs.length) return false;
let result = [];
inputs.forEach(inpt => {
inputs.forEach((inpt) => {
let input = {
type: inpt.type,
};
if (inpt.connector) {
input.connector = inpt.connector;
}
if (present(inpt.output)) {
input.output = inpt.output;
input.output_type = snakeCase(inpt.output_type);
input.output_connector = inpt.output_connector;
}
if (present(inpt.pairs)) {
input.pairs = [];
inpt.pairs.forEach(pr => {
inpt.pairs.forEach((pr) => {
if (present(pr.key) && present(pr.value)) {
let pairParams = {
index: pr.index,
key: pr.key,
key_type: snakeCase(pr.key_type),
value: pr.value,
value_type: snakeCase(pr.value_type),
connector: pr.connector
}
connector: pr.connector,
};
input.pairs.push(pairParams);
}
});
}
if ((input.type === 'assignment' && present(input.output)) ||
present(input.pairs)) {
if (
(input.type === "assignment" && present(input.output)) ||
present(input.pairs)
) {
result.push(input);
}
});
if (!result.length) {
result = false;
}
return result;
},
remove() {
return ajax(`/admin/wizards/wizard/${this.id}`, {
type: 'DELETE'
}).then(() => this.destroy()).catch(popupAjaxError);
}
type: "DELETE",
})
.then(() => this.destroy())
.catch(popupAjaxError);
},
});
CustomWizard.reopenClass({
all() {
return ajax("/admin/wizards/wizard", {
type: 'GET'
}).then(result => {
return result.wizard_list;
}).catch(popupAjaxError);
type: "GET",
})
.then((result) => {
return result.wizard_list;
})
.catch(popupAjaxError);
},
submissions(wizardId) {
return ajax(`/admin/wizards/submissions/${wizardId}`, {
type: "GET"
type: "GET",
}).catch(popupAjaxError);
},
@ -209,7 +215,7 @@ CustomWizard.reopenClass({
const wizard = this._super.apply(this);
wizard.setProperties(buildProperties(wizardJson));
return wizard;
}
},
});
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";
export default DiscourseRoute.extend({
model(params) {
if (params.name === 'create') {
if (params.name === "create") {
return CustomWizardApi.create({ isNew: true });
} else {
return CustomWizardApi.find(params.name);
}
},
setupController(controller, model){
setupController(controller, model) {
controller.set("api", model);
}
},
});

Datei anzeigen

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

Datei anzeigen

@ -6,9 +6,9 @@ export default DiscourseRoute.extend({
model() {
return CustomWizardCustomField.listFields();
},
setupController(controller, 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";
export default DiscourseRoute.extend({
@ -7,6 +7,6 @@ export default DiscourseRoute.extend({
},
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";
export default DiscourseRoute.extend({
model() {
return CustomWizard.all();
},
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";
export default DiscourseRoute.extend({
@ -25,12 +25,12 @@ export default DiscourseRoute.extend({
});
submissions.push(submission);
});
controller.setProperties({
wizard: model.wizard,
submissions,
fields
fields,
});
}
}
},
});

Datei anzeigen

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

Datei anzeigen

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

Datei anzeigen

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

Datei anzeigen

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

Datei anzeigen

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

Datei anzeigen

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

Datei anzeigen

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

Datei anzeigen

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

Datei anzeigen

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

Datei anzeigen

@ -4,14 +4,14 @@ import { ajax } from "discourse/lib/ajax";
import { getToken } from "wizard/lib/ajax";
export default Component.extend({
classNames: ['validator'],
classNames: ["validator"],
classNameBindings: ["isValid", "isInvalid"],
validMessageKey: null,
invalidMessageKey: null,
isValid: null,
isInvalid: equal("isValid", false),
layoutName: "components/validator", // useful for sharing the template with extending components
init() {
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 { makeArray } from "discourse-common/lib/helpers";
export default CategorySelector.extend({
content: computed("categories.[]", "blacklist.[]", "whitelist.[]", function() {
return this._super().filter(category => {
const whitelist = makeArray(this.whitelist);
return !whitelist.length || whitelist.indexOf(category.id) > -1;
});
})
})
content: computed(
"categories.[]",
"blacklist.[]",
"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 { alias } from "@ember/object/computed";
import { uploadIcon } from "discourse/lib/uploads";
import WizardI18n from '../lib/wizard-i18n';
import WizardI18n from "../lib/wizard-i18n";
const uploadMarkdownResolvers = [];

Datei anzeigen

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

Datei anzeigen

@ -1,3 +1,3 @@
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 discourseComputed from 'discourse-common/utils/decorators';
import discourseComputed from "discourse-common/utils/decorators";
export default DateTimeInput.extend({
@discourseComputed('timeFirst', 'tabindex')
@discourseComputed("timeFirst", "tabindex")
timeTabindex(timeFirst, tabindex) {
return timeFirst ? tabindex : tabindex + 1;
},
@discourseComputed('timeFirst', 'tabindex')
@discourseComputed("timeFirst", "tabindex")
dateTabindex(timeFirst, tabindex) {
return timeFirst ? tabindex + 1 : tabindex;
}
});
},
});

Datei anzeigen

@ -1,32 +1,39 @@
import { observes } from 'discourse-common/utils/decorators';
import Category from 'discourse/models/category';
import { observes } from "discourse-common/utils/decorators";
import Category from "discourse/models/category";
export default Ember.Component.extend({
didInsertElement() {
const property = this.field.property || 'id';
const property = this.field.property || "id";
const value = this.field.value;
if (value) {
this.set('categories', [...value].reduce((result, v) => {
let val = property === 'id' ? Category.findById(v) : Category.findBySlug(v);
if (val) result.push(val);
return result;
}, []));
this.set(
"categories",
[...value].reduce((result, v) => {
let val =
property === "id" ? Category.findById(v) : Category.findBySlug(v);
if (val) result.push(val);
return result;
}, [])
);
}
},
@observes('categories')
@observes("categories")
setValue() {
const categories = (this.categories || []).filter(c => !!c);
const property = this.field.property || 'id';
if (categories.length) {
this.set('field.value', categories.reduce((result, c) => {
if (c && c[property]) {
result.push(c[property])
}
return result;
}, []));
const categories = (this.categories || []).filter((c) => !!c);
const property = this.field.property || "id";
if (categories.length) {
this.set(
"field.value",
categories.reduce((result, c) => {
if (c && c[property]) {
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";
export default Ember.Component.extend({
showPreview: false,
classNameBindings: [":wizard-field-composer", "showPreview:show-preview:hide-preview"],
classNameBindings: [
":wizard-field-composer",
"showPreview:show-preview:hide-preview",
],
didInsertElement() {
this.set('composer', EmberObject.create({
loading: false,
reply: this.get('field.value')
}))
this.set(
"composer",
EmberObject.create({
loading: false,
reply: this.get("field.value"),
})
);
},
@observes('composer.reply')
@observes("composer.reply")
setField() {
this.set('field.value', this.get('composer.reply'));
this.set("field.value", this.get("composer.reply"));
},
@computed('showPreview')
@computed("showPreview")
togglePreviewLabel(showPreview) {
return showPreview ? 'wizard_composer.hide_preview' : 'wizard_composer.show_preview';
return showPreview
? "wizard_composer.hide_preview"
: "wizard_composer.show_preview";
},
actions: {
togglePreview() {
this.toggleProperty('showPreview');
this.toggleProperty("showPreview");
},
groupsMentioned() {
},
afterRefresh() {
},
cannotSeeMention() {
},
importQuote() {
},
showUploadSelector() {
}
}
groupsMentioned() {},
afterRefresh() {},
cannotSeeMention() {},
importQuote() {},
showUploadSelector() {},
},
});

Datei anzeigen

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

Datei anzeigen

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

Datei anzeigen

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

Datei anzeigen

@ -20,10 +20,10 @@ export default Ember.Component.extend({
formData: {
synchronous: true,
type: `wizard_${id}`,
authenticity_token: getToken()
authenticity_token: getToken(),
},
dataType: "json",
dropZone: $upload
dropZone: $upload,
});
$upload.on("fileuploadsubmit", () => this.set("uploading", true));
@ -31,12 +31,16 @@ export default Ember.Component.extend({
$upload.on("fileuploaddone", (e, response) => {
this.setProperties({
"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({
"isImage": true
})
isImage: true,
});
}
});
@ -51,9 +55,9 @@ export default Ember.Component.extend({
title: "",
text: message,
type: "warning",
confirmButtonColor: "#6699ff"
confirmButtonColor: "#6699ff",
});
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 { makeArray } from "discourse-common/lib/helpers";
export default ComboBox.extend({
content: computed("groups.[]", "field.content.[]", function() {
export default ComboBox.extend({
content: computed("groups.[]", "field.content.[]", function () {
const whitelist = makeArray(this.field.content);
return this.groups.filter(group => {
return !whitelist.length || whitelist.indexOf(group.id) > -1;
}).map(g => {
return {
id: g.id,
name: g.full_name ? g.full_name : g.name
}
});
})
})
return this.groups
.filter((group) => {
return !whitelist.length || whitelist.indexOf(group.id) > -1;
})
.map((g) => {
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({
siteName: function() {
siteName: function () {
return Wizard.SiteSettings.title;
}.property(),
actions: {
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 { observes } from "discourse-common/utils/decorators";
export default Component.extend({
classNames: ['wizard-similar-topics'],
export default Component.extend({
classNames: ["wizard-similar-topics"],
showTopics: true,
didInsertElement() {
$(document).on("click", bind(this, this.documentClick));
},
@ -18,19 +18,19 @@ export default Component.extend({
if (this._state == "destroying") return;
let $target = $(e.target);
if (!$target.hasClass('show-topics')) {
this.set('showTopics', false);
if (!$target.hasClass("show-topics")) {
this.set("showTopics", false);
}
},
@observes('topics')
@observes("topics")
toggleShowWhenTopicsChange() {
this.set('showTopics', true);
this.set("showTopics", true);
},
actions: {
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";
export default TagChooser.extend({
@ -7,5 +7,5 @@ export default TagChooser.extend({
const whitelist = makeArray(context.whitelist);
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";
export default Ember.TextField.extend({
attributeBindings: ['autocorrect', 'autocapitalize', 'autofocus', 'maxLength', 'dir'],
attributeBindings: [
"autocorrect",
"autocapitalize",
"autofocus",
"maxLength",
"dir",
],
@computed
dir() {
if (Wizard.SiteSettings.support_mixed_text_direction) {
let val = this.value;
if (val) {
return isRTL(val) ? 'rtl' : 'ltr';
return isRTL(val) ? "rtl" : "ltr";
} else {
return siteDir();
}
@ -23,11 +29,11 @@ export default Ember.TextField.extend({
if (Wizard.SiteSettings.support_mixed_text_direction) {
let val = this.value;
if (isRTL(val)) {
this.set('dir', 'rtl');
this.set("dir", "rtl");
} else if (isLTR(val)) {
this.set('dir', 'ltr');
this.set("dir", "ltr");
} else {
this.set('dir', siteDir());
this.set("dir", siteDir());
}
}
},
@ -35,5 +41,5 @@ export default Ember.TextField.extend({
@computed("placeholderKey")
placeholder(placeholderKey) {
return placeholderKey ? WizardI18n(placeholderKey) : "";
}
},
});

Datei anzeigen

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

Datei anzeigen

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

Datei anzeigen

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

Datei anzeigen

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

Datei anzeigen

@ -1,5 +1,5 @@
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);
});
});

Datei anzeigen

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

Datei anzeigen

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

Datei anzeigen

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

Datei anzeigen

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

Datei anzeigen

@ -2,15 +2,20 @@ export default {
name: "custom-wizard-step",
initialize(app) {
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 StepComponent = requirejs("wizard/components/wizard-step").default;
const ajax = requirejs("wizard/lib/ajax").ajax;
const getUrl = requirejs("discourse-common/lib/get-url").default;
const discourseComputed = requirejs("discourse-common/utils/decorators").default;
const cook = requirejs("discourse/plugins/discourse-custom-wizard/wizard/lib/text-lite").cook;
const discourseComputed = requirejs("discourse-common/utils/decorators")
.default;
const cook = requirejs(
"discourse/plugins/discourse-custom-wizard/wizard/lib/text-lite"
).cook;
StepModel.reopen({
save() {
const wizardId = this.get("wizardId");
@ -68,13 +73,15 @@ export default {
Ember.run.later(() => this.set("message", null), 6000);
},
});
StepComponent.reopen({
classNameBindings: ["step.id"],
animateInvalidFields() {
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) {
$([document.documentElement, document.body]).animate(
@ -113,13 +120,13 @@ export default {
if (!src) return;
return getUrl(src);
}.property("step.banner"),
@discourseComputed('step.fields.[]')
@discourseComputed("step.fields.[]")
primaryButtonIndex(fields) {
return fields.length + 1;
},
@discourseComputed('step.fields.[]')
@discourseComputed("step.fields.[]")
secondaryButtonIndex(fields) {
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 Router = requirejs("wizard/router").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 Store = requirejs("discourse/models/store").default;
const registerRawHelpers = requirejs("discourse-common/lib/raw-handlebars-helpers").registerRawHelpers;
const createHelperContext = requirejs("discourse-common/lib/helpers").createHelperContext;
const RawHandlebars = requirejs("discourse-common/lib/raw-handlebars").default;
const Site = requirejs("discourse/plugins/discourse-custom-wizard/wizard/models/site").default;
const registerRawHelpers = requirejs(
"discourse-common/lib/raw-handlebars-helpers"
).registerRawHelpers;
const createHelperContext = requirejs("discourse-common/lib/helpers")
.createHelperContext;
const RawHandlebars = requirejs("discourse-common/lib/raw-handlebars")
.default;
const Site = requirejs(
"discourse/plugins/discourse-custom-wizard/wizard/models/site"
).default;
const RestAdapter = requirejs("discourse/adapters/rest").default;
const Session = requirejs("discourse/models/session").default;
const setDefaultOwner = requirejs("discourse-common/lib/get-owner").setDefaultOwner;
const setDefaultOwner = requirejs("discourse-common/lib/get-owner")
.setDefaultOwner;
const messageBus = requirejs("message-bus-client").default;
const container = app.__container__;
Discourse.Model = EmberObject.extend();
Discourse.__container__ = container;
@ -66,7 +75,7 @@ export default {
site.set("can_create_tag", false);
app.register("session:main", Session.current(), { instantiate: false });
targets.forEach((t) => app.inject(t, "session", "session:main"));
createHelperContext({
siteSettings: container.lookup("site-settings:main"),
currentUser: container.lookup("current-user:main"),
@ -74,13 +83,13 @@ export default {
session: container.lookup("session:main"),
capabilities: container.lookup("capabilities:main"),
});
const session = container.lookup("session:main");
const setupData = document.getElementById("data-discourse-setup").dataset;
session.set("highlightJsPath", setupData.highlightJsPath);
Router.reopen({
rootURL: getUrl("/w/")
rootURL: getUrl("/w/"),
});
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";
const _loaded = {};
const _loading = {};
function loadWithTag(path, cb) {
const head = document.getElementsByTagName('head')[0];
const head = document.getElementsByTagName("head")[0];
let finished = false;
let s = document.createElement('script');
let s = document.createElement("script");
s.src = path;
if (Ember.Test) {
Ember.Test.registerWaiter(() => finished);
}
head.appendChild(s);
s.onload = s.onreadystatechange = function(_, abort) {
s.onload = s.onreadystatechange = function (_, abort) {
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;
if (!abort) {
Ember.run(null, cb);
@ -31,38 +36,42 @@ export function loadCSS(url) {
}
export default function loadScript(url, opts) {
// 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 || {};
$('script').each((i, tag) => {
const src = tag.getAttribute('src');
$("script").each((i, tag) => {
const src = tag.getAttribute("src");
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);
// If we already loaded this url
if (_loaded[url]) { return resolve(); }
if (_loading[url]) { return _loading[url].then(resolve);}
if (_loaded[url]) {
return resolve();
}
if (_loading[url]) {
return _loading[url].then(resolve);
}
let done;
_loading[url] = new Ember.RSVP.Promise(function(_done){
_loading[url] = new Ember.RSVP.Promise(function (_done) {
done = _done;
});
_loading[url].then(function(){
_loading[url].then(function () {
delete _loading[url];
});
const cb = function(data) {
const cb = function (data) {
if (opts && opts.css) {
$("head").append("<style>" + data + "</style>");
}
@ -76,7 +85,7 @@ export default function loadScript(url, opts) {
// Scripts should always load from CDN
// 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] !== "/") {
cdnUrl = Discourse.CDN.replace(/\/$/,"") + url;
cdnUrl = Discourse.CDN.replace(/\/$/, "") + url;
}
// 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);
} 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 { default as PrettyText } from 'pretty-text/pretty-text';
import loadScript from "./load-script";
import { default as PrettyText } from "pretty-text/pretty-text";
export function cook(text, options) {
return new Handlebars.SafeString(new PrettyText(options).cook(text));
@ -10,8 +10,8 @@ export function cook(text, options) {
export function cookAsync(text, options) {
if (Discourse.MarkdownItURL) {
return loadScript(Discourse.MarkdownItURL)
.then(()=>cook(text, options))
.catch(e => Ember.Logger.error(e));
.then(() => cook(text, options))
.catch((e) => Ember.Logger.error(e));
} else {
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 getUrl from 'discourse-common/lib/get-url';
import getUrl from "discourse-common/lib/get-url";
var cache = {},
cacheTopicId,
cacheTime,
currentTerm,
oldSearch;
cacheTopicId,
cacheTime,
currentTerm,
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];
if (cached) {
resultsFn(cached);
@ -16,42 +25,49 @@ function performSearch(term, topicId, includeGroups, includeMentionableGroups, i
}
// need to be able to cancel this
oldSearch = $.ajax(getUrl('/u/search/users'), {
data: { term: term,
topic_id: topicId,
include_groups: includeGroups,
include_mentionable_groups: includeMentionableGroups,
include_messageable_groups: includeMessageableGroups,
group: group,
topic_allowed_users: allowedUsers }
oldSearch = $.ajax(getUrl("/u/search/users"), {
data: {
term: term,
topic_id: topicId,
include_groups: includeGroups,
include_mentionable_groups: includeMentionableGroups,
include_messageable_groups: includeMessageableGroups,
group: group,
topic_allowed_users: allowedUsers,
},
});
var returnVal = CANCELLED_STATUS;
oldSearch.then(function (r) {
cache[term] = r;
cacheTime = new Date();
// If there is a newer search term, return null
if (term === currentTerm) { returnVal = r; }
}).always(function(){
oldSearch = null;
resultsFn(returnVal);
});
oldSearch
.then(function (r) {
cache[term] = r;
cacheTime = new Date();
// If there is a newer search term, return null
if (term === currentTerm) {
returnVal = r;
}
})
.always(function () {
oldSearch = null;
resultsFn(returnVal);
});
}
function organizeResults(r, options) {
if (r === CANCELLED_STATUS) { return r; }
if (r === CANCELLED_STATUS) {
return r;
}
var exclude = options.exclude || [],
limit = options.limit || 5,
users = [],
emails = [],
groups = [],
results = [];
limit = options.limit || 5,
users = [],
emails = [],
groups = [],
results = [];
if (r.users) {
r.users.every(function(u) {
r.users.every(function (u) {
if (exclude.indexOf(u.username) === -1) {
users.push(u);
results.push(u);
@ -62,13 +78,17 @@ function organizeResults(r, options) {
if (options.term.match(/@/)) {
let e = { username: options.term };
emails = [ e ];
emails = [e];
results.push(e);
}
if (r.groups) {
r.groups.every(function(g) {
if (results.length > limit && options.term.toLowerCase() !== g.name.toLowerCase()) return false;
r.groups.every(function (g) {
if (
results.length > limit &&
options.term.toLowerCase() !== g.name.toLowerCase()
)
return false;
if (exclude.indexOf(g.name) === -1) {
groups.push(g);
results.push(g);
@ -83,16 +103,14 @@ function organizeResults(r, options) {
return results;
}
export default function userSearch(options) {
var term = options.term || "",
includeGroups = options.includeGroups,
includeMentionableGroups = options.includeMentionableGroups,
includeMessageableGroups = options.includeMessageableGroups,
allowedUsers = options.allowedUsers,
topicId = options.topicId,
group = options.group;
includeGroups = options.includeGroups,
includeMentionableGroups = options.includeMentionableGroups,
includeMessageableGroups = options.includeMessageableGroups,
allowedUsers = options.allowedUsers,
topicId = options.topicId,
group = options.group;
if (oldSearch) {
oldSearch.abort();
@ -101,26 +119,26 @@ export default function userSearch(options) {
currentTerm = term;
return new Ember.RSVP.Promise(function(resolve) {
return new Ember.RSVP.Promise(function (resolve) {
// TODO site setting for allowed regex in username
if (term.match(/[^\w_\-\.@\+]/)) {
resolve([]);
return;
}
if (((new Date() - cacheTime) > 30000) || (cacheTopicId !== topicId)) {
if (new Date() - cacheTime > 30000 || cacheTopicId !== topicId) {
cache = {};
}
cacheTopicId = topicId;
var clearPromise = setTimeout(function(){
var clearPromise = setTimeout(function () {
resolve(CANCELLED_STATUS);
}, 5000);
// TODO: Use discouseDebounce after it is available on stable.
debounce(
this,
function() {
function () {
performSearch(
term,
topicId,
@ -129,13 +147,13 @@ export default function userSearch(options) {
includeMessageableGroups,
allowedUsers,
group,
function(r) {
function (r) {
clearTimeout(clearPromise);
resolve(organizeResults(r, options));
}
)
);
},
300
)
);
});
}

Datei anzeigen

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

Datei anzeigen

@ -2,30 +2,32 @@ import I18n from "I18n";
const getThemeId = () => {
let themeId = parseInt($("meta[name=discourse_theme_ids]")[0].content, 10);
if (!isNaN(themeId)) {
return themeId.toString();
} else {
return null;
}
}
};
const translationExists = (key) => {
return I18n.findTranslation(key, { locale: I18n.locale }) ||
I18n.findTranslation(key, { locale: I18n.defaultLocale });
}
return (
I18n.findTranslation(key, { locale: I18n.locale }) ||
I18n.findTranslation(key, { locale: I18n.defaultLocale })
);
};
const WizardI18n = (key, params={}) => {
const WizardI18n = (key, params = {}) => {
const themeId = getThemeId();
if (!themeId) return I18n.t(key, params);
const themeKey = `theme_translations.${themeId}.${key}`;
if (translationExists(themeKey)) {
return I18n.t(themeKey, params);
} else {
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 getUrl from 'discourse-common/lib/get-url';
import WizardField from 'wizard/models/wizard-field';
import { ajax } from 'wizard/lib/ajax';
import Step from 'wizard/models/step';
import { default as computed } from "discourse-common/utils/decorators";
import getUrl from "discourse-common/lib/get-url";
import WizardField from "wizard/models/wizard-field";
import { ajax } from "wizard/lib/ajax";
import Step from "wizard/models/step";
import EmberObject from "@ember/object";
const CustomWizard = EmberObject.extend({
@computed('steps.length')
totalSteps: length => length,
@computed("steps.length")
totalSteps: (length) => length,
skip() {
if (this.required && (!this.completed && this.permitted)) return;
if (this.required && !this.completed && this.permitted) return;
CustomWizard.skip(this.id);
},
});
CustomWizard.reopenClass({
skip(wizardId) {
ajax({ url: `/w/${wizardId}/skip`, type: 'PUT' }).then((result) => {
ajax({ url: `/w/${wizardId}/skip`, type: "PUT" }).then((result) => {
CustomWizard.finished(result);
});
},
@ -28,52 +28,52 @@ CustomWizard.reopenClass({
url = result.redirect_on_complete;
}
window.location.href = getUrl(url);
}
},
});
export function findCustomWizard(wizardId, params = {}) {
let url = `/w/${wizardId}`;
let paramKeys = Object.keys(params).filter(k => {
if (k === 'wizard_id') return false;
let paramKeys = Object.keys(params).filter((k) => {
if (k === "wizard_id") return false;
return !!params[k];
});
if (paramKeys.length) {
url += '?';
paramKeys.forEach((k,i) => {
url += "?";
paramKeys.forEach((k, i) => {
if (i > 0) {
url += '&';
url += "&";
}
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;
if (!wizard) return null;
if (!wizard.completed) {
wizard.steps = wizard.steps.map(step => {
wizard.steps = wizard.steps.map((step) => {
const stepObj = Step.create(step);
stepObj.fields.sort((a, b) => {
return parseFloat(a.number) - parseFloat(b.number);
});
let tabindex = 1;
stepObj.fields.forEach((f, i) => {
f.tabindex = tabindex;
if (['date_time'].includes(f.type)) {
if (["date_time"].includes(f.type)) {
tabindex = tabindex + 2;
} else {
tabindex++;
}
});
stepObj.fields = stepObj.fields.map(f => WizardField.create(f));
stepObj.fields = stepObj.fields.map((f) => WizardField.create(f));
return stepObj;
});
}
@ -81,7 +81,7 @@ export function findCustomWizard(wizardId, params = {}) {
if (wizard.categories) {
let subcatMap = {};
let categoriesById = {};
let categories = wizard.categories.map(c => {
let categories = wizard.categories.map((c) => {
if (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
categories.forEach(c => {
categories.forEach((c) => {
let subcategoryIds = subcatMap[c.get("id")];
if (subcategoryIds) {
c.set("subcategories", subcategoryIds.map(id => categoriesById[id]));
c.set(
"subcategories",
subcategoryIds.map((id) => categoriesById[id])
);
}
if (c.get("parent_category_id")) {
c.set("parentCategory", categoriesById[c.get("parent_category_id")]);
}
});
Discourse.Site.currentProp('categoriesList', categories);
Discourse.Site.currentProp('sortedCategories', categories);
Discourse.Site.currentProp('listByActivity', categories);
Discourse.Site.currentProp('categoriesById', categoriesById);
Discourse.Site.currentProp('uncategorized_category_id', wizard.uncategorized_category_id);
Discourse.Site.currentProp("categoriesList", categories);
Discourse.Site.currentProp("sortedCategories", categories);
Discourse.Site.currentProp("listByActivity", categories);
Discourse.Site.currentProp("categoriesById", categoriesById);
Discourse.Site.currentProp(
"uncategorized_category_id",
wizard.uncategorized_category_id
);
}
return CustomWizard.create(wizard);
});
};
}
export default CustomWizard;

Datei anzeigen

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

Datei anzeigen

@ -1,22 +1,27 @@
export default Ember.Route.extend({
beforeModel() {
const appModel = this.modelFor('custom');
if (appModel && appModel.permitted && !appModel.completed && appModel.start) {
this.replaceWith('custom.step', appModel.start);
const appModel = this.modelFor("custom");
if (
appModel &&
appModel.permitted &&
!appModel.completed &&
appModel.start
) {
this.replaceWith("custom.step", appModel.start);
}
},
model() {
return this.modelFor('custom');
return this.modelFor("custom");
},
setupController(controller, model) {
if (model) {
const completed = model.get('completed');
const permitted = model.get('permitted');
const wizardId = model.get('id');
const user = model.get('user');
const name = model.get('name');
const completed = model.get("completed");
const permitted = model.get("permitted");
const wizardId = model.get("id");
const user = model.get("user");
const name = model.get("name");
controller.setProperties({
requiresLogin: !user,
@ -24,10 +29,10 @@ export default Ember.Route.extend({
name,
completed,
notPermitted: !permitted,
wizardId
wizardId,
});
} 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({
model(params) {
const appModel = this.modelFor('custom');
const appModel = this.modelFor("custom");
const allSteps = appModel.steps;
if (allSteps) {
const step = allSteps.findBy('id', params.step_id);
const step = allSteps.findBy("id", params.step_id);
return step ? step : allSteps[0];
};
}
return appModel;
},
afterModel(model) {
if (model.completed) return this.transitionTo('index');
return model.set("wizardId", this.modelFor('custom').id);
if (model.completed) return this.transitionTo("index");
return model.set("wizardId", this.modelFor("custom").id);
},
setupController(controller, model) {
let props = {
step: model,
wizard: this.modelFor('custom')
wizard: this.modelFor("custom"),
};
if (!model.permitted) {
props['stepMessage'] = {
state: 'not-permitted',
text: model.permitted_message || WizardI18n('wizard.step_not_permitted')
props["stepMessage"] = {
state: "not-permitted",
text:
model.permitted_message || WizardI18n("wizard.step_not_permitted"),
};
if (model.index > 0) {
props['showReset'] = true;
props["showReset"] = true;
}
}
controller.setProperties(props);
}
},
});

Datei anzeigen

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

Datei anzeigen

@ -1,39 +1,39 @@
/* eslint no-undef: 0 */
import { findCustomWizard } from '../models/custom';
import { ajax } from 'wizard/lib/ajax';
import { findCustomWizard } from "../models/custom";
import { ajax } from "wizard/lib/ajax";
export default Ember.Route.extend({
beforeModel(transition) {
this.set('queryParams', transition.intent.queryParams);
this.set("queryParams", transition.intent.queryParams);
},
model(params) {
return findCustomWizard(params.wizard_id, this.get('queryParams'));
return findCustomWizard(params.wizard_id, this.get("queryParams"));
},
afterModel() {
return ajax({
url: `/site/settings`,
type: 'GET',
type: "GET",
}).then((result) => {
$.extend(Wizard.SiteSettings, result);
});
},
setupController(controller, model) {
const background = model ? model.get('background') : 'AliceBlue';
Ember.run.scheduleOnce('afterRender', this, function(){
$('body.custom-wizard').css('background', background);
const background = model ? model.get("background") : "AliceBlue";
Ember.run.scheduleOnce("afterRender", this, function () {
$("body.custom-wizard").css("background", background);
if (model) {
$('#custom-wizard-main').addClass(model.get('id').dasherize());
$("#custom-wizard-main").addClass(model.get("id").dasherize());
}
});
controller.setProperties({
customWizard: true,
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 {
overflow-y: auto;
max-height: 150px;
width: 6.5em;
background: #fff;
border: 1px solid #ddd;
-webkit-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);
outline: none;
z-index: 10001;
margin: 0;
overflow-y: auto;
max-height: 150px;
width: 6.5em;
background: #fff;
border: 1px solid #ddd;
-webkit-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);
outline: none;
z-index: 10001;
margin: 0;
}
.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-60 {
width: 11em;
width: 11em;
}
.ui-timepicker-list {
margin: 0;
padding: 0;
list-style: none;
margin: 0;
padding: 0;
list-style: none;
}
.ui-timepicker-duration {
margin-left: 5px; color: #888;
margin-left: 5px;
color: #888;
}
.ui-timepicker-list:hover .ui-timepicker-duration {
color: #888;
color: #888;
}
.ui-timepicker-list li {
padding: 3px 0 3px 5px;
cursor: pointer;
white-space: nowrap;
color: #000;
list-style: none;
margin: 0;
padding: 3px 0 3px 5px;
cursor: pointer;
white-space: nowrap;
color: #000;
list-style: none;
margin: 0;
}
.ui-timepicker-list:hover .ui-timepicker-selected {
background: #fff; color: #000;
background: #fff;
color: #000;
}
li.ui-timepicker-selected,
.ui-timepicker-list li:hover,
.ui-timepicker-list .ui-timepicker-selected:hover {
background: #1980EC; color: #fff;
background: #1980ec;
color: #fff;
}
li.ui-timepicker-selected .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:hover,
.ui-timepicker-list li.ui-timepicker-selected.ui-timepicker-disabled {
color: #888;
cursor: default;
color: #888;
cursor: default;
}
.ui-timepicker-list li.ui-timepicker-disabled:hover,
.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-manager';
@import 'wizard-api';
@import 'common/components/buttons';
@import "wizard-mapper";
@import "wizard-manager";
@import "wizard-api";
@import "common/components/buttons";
.admin-wizard-controls {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 20px;
&+ .wizard-message + div {
& + .wizard-message + div {
margin-top: 20px;
}
}
@ -22,54 +22,52 @@
display: flex;
justify-content: space-between;
align-items: flex-start;
.message-block {
.d-icon {
margin-right: 4px;
}
.d-icon-check-circle {
color: var(--success);
}
.d-icon-times-circle {
color: var(--danger);
}
a + a {
border-left: 1px solid $primary-medium;
padding-left: 5px;
margin-left: 5px;
}
.message {
white-space: nowrap;
}
.list-colon {
margin-right: 5px;
}
ul {
list-style: none;
margin: 0;
span.action {
margin-left: 5px;
}
}
}
& + div {
margin-top: 30px;
}
}
.wizard-submissions {
overflow: scroll;
table td {
min-width: 150px;
}
@ -81,7 +79,7 @@
margin: 0 7px;
}
}
.wizard-logs {
.date {
width: 100px;
@ -125,11 +123,11 @@
.wizard-custom-action {
position: relative;
display: none;
&.visible {
display: flex;
}
.undo-changes {
position: absolute;
top: 0;
@ -139,11 +137,11 @@
.admin-wizard-container.settings .wizard-basic-details {
justify-content: initial;
.setting {
width: auto;
margin-right: 20px;
.setting-label {
width: initial;
min-width: initial;
@ -153,7 +151,7 @@
.wizard-header {
margin-bottom: 20px;
&.large {
font-size: 1.5em;
min-height: 31px;
@ -161,32 +159,32 @@
display: flex;
justify-content: space-between;
align-items: flex-start;
input {
margin-bottom: 0;
width: 400px;
}
label {
margin-bottom: 0;
}
.download-link {
font-size: 1rem;
line-height: 20px;
}
.wizard-url {
display: inline-flex;
margin-left: 20px;
max-width: 50%;
a {
padding: 6px 12px;
font-size: 1rem;
background-color: $primary-low;
}
button {
font-size: 1rem;
}
@ -210,22 +208,21 @@
.admin-wizard-buttons {
margin-top: 20px;
display: flex;
.btn {
margin-right: 1em;
}
}
.admin-wizard-container.settings {
[class~='setting'] {
[class~="setting"] {
display: inline-flex;
align-items: flex-start;
width: 48%;
margin-bottom: 30px;
padding-bottom: 0;
position: relative;
&:last-of-type {
margin-bottom: 0;
}
@ -241,7 +238,7 @@
float: initial;
width: initial;
padding: 0;
label {
font-size: 0.85em;
}
@ -253,97 +250,100 @@
button {
display: block;
}
input[type="text"], textarea {
input[type="text"],
textarea {
width: 100%;
box-sizing: border-box;
margin-bottom: 0;
}
input[type="number"] {
margin-bottom: 0;
}
input[disabled] {
background-color: $primary-low;
cursor: not-allowed;
}
input.medium {
width: 200px;
}
input.small {
width: 100px;
}
.uploaded-image-preview {
width: 100%;
max-height: 100px;
margin-bottom: 0;
}
.image-upload-controls {
label {
font-size: 1em;
margin: 0 5px 0 0;
}
}
> textarea {
min-height: 100px;
resize: vertical;
}
input[type="checkbox"] {
float: left;
margin: 5px 7px 0 0;
}
.input .select-kit, > .select-kit {
.input .select-kit,
> .select-kit {
max-width: 250px !important;
min-width: 250px !important;
}
}
&.full, &.full-inline {
&.full,
&.full-inline {
width: 100%;
.setting-value {
width: initial;
float: none;
&.editor {
.d-editor {
margin-bottom: 5px;
}
}
.uploaded-image-preview {
max-height: 200px;
}
}
}
&.full-inline {
.setting-value {
display: flex;
align-items: center;
input {
margin: 0 7px 0 0;
}
button {
margin: 0 0 0 20px;
}
}
}
&.field-mapper-setting {
.setting-value {
max-width: calc(100% - 80px);
.mapper-input {
max-width: 100%;
box-sizing: border-box;
@ -359,17 +359,17 @@
margin-top: 5px;
}
}
.advanced-settings {
width: 100%;
margin-top: 30px;
[class~='setting']:first-of-type {
[class~="setting"]:first-of-type {
border-top: none;
}
}
.wizard-custom-action > [class~='setting']:first-of-type {
.wizard-custom-action > [class~="setting"]:first-of-type {
margin-bottom: 0;
}
@ -406,20 +406,20 @@
.d-editor-input {
min-height: 150px;
}
.d-editor-container {
display: block;
}
.d-editor-textarea-wrapper {
display: grid;
margin-bottom: 10px;
textarea {
resize: vertical;
}
}
.d-editor-preview-wrapper {
display: none;
margin: 0 0 10px 0;
@ -427,7 +427,7 @@
background-color: $secondary;
border: 1px solid $primary-medium;
max-width: 100%;
&.force-preview {
display: block;
}
@ -437,20 +437,20 @@
margin: 0;
}
}
.wizard-editor-gutter {
position: relative;
display: flex;
.btn {
margin-right: 10px;
}
.wizard-editor-gutter-popover {
position: absolute;
padding: 10px;
background-color: $secondary;
box-shadow: shadow('card');
box-shadow: shadow("card");
z-index: 200;
top: 40px;
}
@ -476,7 +476,7 @@
margin-bottom: 10px;
margin-right: 10px;
}
.btn {
height: 32px;
}
@ -500,11 +500,11 @@
.required-data-message {
display: inline-block;
margin-top: 20px;
.label {
margin-bottom: 5px;
}
input {
margin-bottom: 0;
}
@ -517,7 +517,7 @@
.modal .modal-body.next-session-time-modal {
overflow: visible;
.picker-container {
position: absolute;
top: 30px;
@ -569,7 +569,9 @@
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;
border: 1px solid $primary-medium;
}
@ -579,47 +581,47 @@
.buttons {
display: flex;
align-items: center;
button.btn {
margin-left: 10px;
}
}
}
}
.btn.save:enabled {
@extend .btn-primary;
}
.btn.destroy {
@extend .btn-danger;
}
h3 {
margin-bottom: 0;
}
.select-kit {
width: 150px;
}
.select-kit.multi-select {
width: 300px;
.choices .choice,
.select-kit-filter .filter-input {
height: 25px;
min-height: 25px;
}
}
input[type="text"] {
margin: 0;
}
table {
td {
vertical-align: top;
label {
margin: 0;
line-height: 30px;
@ -627,25 +629,25 @@
margin-right: 10px;
}
}
td {
min-width: 170px;
width: 170px;
}
td.multi-select {
min-width: 300px;
}
td.input {
min-width: 210px;
width: 210px;
}
td.actions {
min-width: 100px;
text-align: right;
button.btn {
margin-left: 5px !important;
}
@ -661,7 +663,7 @@
background-color: var(--primary-low);
padding: 1em;
margin: 0 0 1em 0;
input {
margin-bottom: 0;
}
@ -671,7 +673,7 @@
.validation-container {
display: flex;
padding: 1em 0;
.validation-section {
width: 250px;
}

Datei anzeigen

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

Datei anzeigen

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

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