0
0
Fork 1
Spiegel von https://github.com/paviliondev/discourse-custom-wizard.git synchronisiert 2024-11-22 17:30:29 +01:00
Dieser Commit ist enthalten in:
Angus McLeod 2020-04-01 21:58:30 +11:00
Ursprung 515f0b3393
Commit 2046648862
18 geänderte Dateien mit 580 neuen und 446 gelöschten Zeilen

Datei anzeigen

@ -1,7 +1,5 @@
import { import { default as discourseComputed, observes } from 'discourse-common/utils/decorators';
default as computed, import { equal, not, empty } from "@ember/object/computed";
observes
} from 'discourse-common/utils/decorators';
import { import {
actionTypes, actionTypes,
generateName, generateName,
@ -12,37 +10,37 @@ import {
export default Ember.Component.extend({ export default Ember.Component.extend({
classNames: 'wizard-custom-action', classNames: 'wizard-custom-action',
types: actionTypes.map(t => ({ id: t, name: generateName(t) })), types: actionTypes.map(t => ({ id: t, name: generateName(t) })),
createTopic: Ember.computed.equal('action.type', 'create_topic'), createTopic: equal('action.type', 'create_topic'),
updateProfile: Ember.computed.equal('action.type', 'update_profile'), updateProfile: equal('action.type', 'update_profile'),
sendMessage: Ember.computed.equal('action.type', 'send_message'), sendMessage: equal('action.type', 'send_message'),
sendToApi: Ember.computed.equal('action.type', 'send_to_api'), sendToApi: equal('action.type', 'send_to_api'),
apiEmpty: Ember.computed.empty('action.api'), apiEmpty: empty('action.api'),
addToGroup: Ember.computed.equal('action.type', 'add_to_group'), addToGroup: equal('action.type', 'add_to_group'),
routeTo: Ember.computed.equal('action.type', 'route_to'), routeTo: equal('action.type', 'route_to'),
disableId: Ember.computed.not('action.isNew'), disableId: not('action.isNew'),
groupPropertyTypes: generateSelectKitContent(['id', 'name']), groupPropertyTypes: generateSelectKitContent(['id', 'name']),
@computed('action.type') @discourseComputed('action.type')
basicTopicFields(actionType) { basicTopicFields(actionType) {
return ['create_topic', 'send_message', 'open_composer'].indexOf(actionType) > -1; return ['create_topic', 'send_message', 'open_composer'].indexOf(actionType) > -1;
}, },
@computed('action.type') @discourseComputed('action.type')
publicTopicFields(actionType) { publicTopicFields(actionType) {
return ['create_topic', 'open_composer'].indexOf(actionType) > -1; return ['create_topic', 'open_composer'].indexOf(actionType) > -1;
}, },
@computed('action.type') @discourseComputed('action.type')
newTopicFields(actionType) { newTopicFields(actionType) {
return ['create_topic', 'send_message'].indexOf(actionType) > -1; return ['create_topic', 'send_message'].indexOf(actionType) > -1;
}, },
@computed('wizardFields') @discourseComputed('wizardFields')
categoryFields(fields) { categoryFields(fields) {
return fields.filter(f => f.type == 'category'); return fields.filter(f => f.type == 'category');
}, },
@computed('wizardFields') @discourseComputed('wizardFields')
tagFields(fields) { tagFields(fields) {
return fields.filter(f => f.type == 'tag'); return fields.filter(f => f.type == 'tag');
}, },
@ -59,7 +57,7 @@ export default Ember.Component.extend({
this.set('action.custom_category_wizard_field', false); this.set('action.custom_category_wizard_field', false);
}, },
@computed('wizard.apis') @discourseComputed('wizard.apis')
availableApis(apis) { availableApis(apis) {
return apis.map(a => { return apis.map(a => {
return { return {
@ -69,7 +67,7 @@ export default Ember.Component.extend({
}); });
}, },
@computed('wizard.apis', 'action.api') @discourseComputed('wizard.apis', 'action.api')
availableEndpoints(apis, api) { availableEndpoints(apis, api) {
if (!api) return []; if (!api) return [];
return apis.find(a => a.name === api).endpoints; return apis.find(a => a.name === api).endpoints;

Datei anzeigen

@ -1,4 +1,4 @@
import { default as computed, observes, on } from 'discourse-common/utils/decorators'; import { default as discourseComputed, observes, on } from 'discourse-common/utils/decorators';
import { equal, not, or } from "@ember/object/computed"; import { equal, not, or } from "@ember/object/computed";
import { generateSelectKitContent } from '../lib/custom-wizard'; import { generateSelectKitContent } from '../lib/custom-wizard';
@ -17,10 +17,10 @@ export default Ember.Component.extend({
prefillEnabled: or('isCategory', 'isTag', 'isGroup'), prefillEnabled: or('isCategory', 'isTag', 'isGroup'),
contentEnabled: or('isCategory', 'isTag', 'isGroup'), contentEnabled: or('isCategory', 'isTag', 'isGroup'),
@computed('field.type') @discourseComputed('field.type')
isInput: (type) => type === 'text' || type === 'textarea' || type === 'url', isInput: (type) => type === 'text' || type === 'textarea' || type === 'url',
@computed('field.type') @discourseComputed('field.type')
isCategoryOrTag: (type) => type === 'tag' || type === 'category', isCategoryOrTag: (type) => type === 'tag' || type === 'category',
@on('didInsertElement') @on('didInsertElement')
@ -31,7 +31,7 @@ export default Ember.Component.extend({
} }
}, },
@computed('field.type') @discourseComputed('field.type')
prefillOptions(fieldType) { prefillOptions(fieldType) {
if (!this.prefillEnabled) return {}; if (!this.prefillEnabled) return {};
@ -48,7 +48,7 @@ export default Ember.Component.extend({
return options; return options;
}, },
@computed('field.type') @discourseComputed('field.type')
contentOptions(fieldType) { contentOptions(fieldType) {
if (!this.contentEnabled) return {}; if (!this.contentEnabled) return {};

Datei anzeigen

@ -1,27 +1,25 @@
import { import { observes, on, default as discourseComputed } from 'discourse-common/utils/decorators';
observes, import { not } from "@ember/object/computed";
on,
default as computed
} from 'discourse-common/utils/decorators';
export default Ember.Component.extend({ export default Ember.Component.extend({
classNames: 'wizard-custom-step', classNames: 'wizard-custom-step',
currentField: null, currentField: null,
currentAction: null, currentAction: null,
disableId: Ember.computed.not('step.isNew'), disableId: not('step.isNew'),
@on('didInsertElement') @on('didInsertElement')
@observes('step') @observes('step')
resetCurrentObjects() { resetCurrentObjects() {
const fields = this.get('step.fields'); const fields = this.step.fields;
const actions = this.get('step.actions'); const actions = this.step.actions;
this.setProperties({ this.setProperties({
currentField: fields.length ? fields[0] : null, currentField: fields.length ? fields[0] : null,
currentAction: actions.length ? actions[0] : null currentAction: actions.length ? actions[0] : null
}); });
}, },
@computed('wizardFields', 'wizard.steps') @discourseComputed('wizardFields', 'wizard.steps')
requiredContent(wizardFields, steps) { requiredContent(wizardFields, steps) {
let content = wizardFields; let content = wizardFields;
let actions = []; let actions = [];

Datei anzeigen

@ -1,10 +1,6 @@
import { computed, set } from "@ember/object"; import { computed, set } from "@ember/object";
import { alias, equal } from "@ember/object/computed"; import { alias, equal } from "@ember/object/computed";
import { import { newPair, connectorContent, inputTypesContent } from '../lib/mapper';
newPair,
connectorContent,
inputTypesContent
} from '../lib/custom-wizard';
export default Ember.Component.extend({ export default Ember.Component.extend({
classNameBindings: [':mapper-input', 'type'], classNameBindings: [':mapper-input', 'type'],

Datei anzeigen

@ -1,4 +1,4 @@
import { connectorContent } from '../lib/custom-wizard'; import { connectorContent } from '../lib/mapper';
import { gt, or, alias } from "@ember/object/computed"; import { gt, or, alias } from "@ember/object/computed";
import { computed, observes } from "@ember/object"; import { computed, observes } from "@ember/object";

Datei anzeigen

@ -1,11 +1,8 @@
import { alias } from "@ember/object/computed"; import { alias } from "@ember/object/computed";
import { computed } from "@ember/object"; import { computed } from "@ember/object";
import { import { default as discourseComputed, observes } from "discourse-common/utils/decorators";
default as discourseComputed,
observes,
} from "discourse-common/utils/decorators";
import { defaultSelectionType } from '../lib/custom-wizard';
import { getOwner } from 'discourse-common/lib/get-owner'; import { getOwner } from 'discourse-common/lib/get-owner';
import { defaultSelectionType } from '../lib/mapper';
export default Ember.Component.extend({ export default Ember.Component.extend({
classNames: 'mapper-selector', classNames: 'mapper-selector',

Datei anzeigen

@ -1,6 +1,6 @@
import { getOwner } from 'discourse-common/lib/get-owner'; import { getOwner } from 'discourse-common/lib/get-owner';
import { on } from 'discourse-common/utils/decorators'; import { on } from 'discourse-common/utils/decorators';
import { newInput } from '../lib/custom-wizard'; import { newInput } from '../lib/mapper';
import { default as discourseComputed } from 'discourse-common/utils/decorators'; import { default as discourseComputed } from 'discourse-common/utils/decorators';
export default Ember.Component.extend({ export default Ember.Component.extend({

Datei anzeigen

@ -27,6 +27,77 @@ const profileFields = [
'trust_level' 'trust_level'
]; ];
const wizardProperties = [
'id',
'name',
'background',
'save_submissions',
'multiple_submissions',
'after_signup',
'after_time',
'after_time_scheduled',
'required',
'prompt_completion',
'restart_on_revisit',
'theme_id',
'permitted'
];
const stepProperties = [
'id',
'title',
'key',
'banner',
'raw_description',
'required_data',
'required_data_message',
'permitted_params'
]
const fieldProperties = [
'id',
'label',
'key',
'image',
'description',
'type',
'required',
'min_length',
'file_types',
'property',
'limit',
'prefill',
'content',
]
const actionProperties = [
'id',
'type',
'title',
'post',
'post_template',
'category',
'tags',
'skip_redirect',
'custom_fields',
'required',
'recipient',
'profile_updates',
'group',
'url',
'code',
'api',
'api_endpoint',
'api_body'
]
const properties = {
wizard: wizardProperties,
step: stepProperties,
field: fieldProperties,
action: actionProperties
}
const actionTypes = [ const actionTypes = [
'create_topic', 'create_topic',
'update_profile', 'update_profile',
@ -39,158 +110,12 @@ const actionTypes = [
'open_composer' 'open_composer'
]; ];
// Inputs
const selectableInputTypes = [
'conditional',
'assignment'
]
function defaultInputType(options = {}) {
if (!options.hasOutput) return 'pair';
if (!options.inputTypes) return selectableInputTypes[0];
return options.inputTypes.split(',')[0];
}
function mapInputTypes(types) {
return types.map(function(type) {
return {
id: type,
name: I18n.t(`admin.wizard.input.${type}.name`)
};
});
}
function inputTypesContent(options = {}) {
return options.inputTypes ?
mapInputTypes(options.inputTypes.split(',')) :
mapInputTypes(selectableInputTypes);
}
// Connectors
const connectors = {
output: [
'then',
'set',
],
pair: [
'equal',
'greater',
'less',
'greater_or_equal',
'less_or_equal'
]
}
function connectorItem(connector) {
return {
id: connector,
name: I18n.t(`admin.wizard.connector.${connector}`)
};
}
function defaultConnector(connectorType, inputType, opts = {}) {
if (opts[`${connectorType}Connector`]) return opts[`${connectorType}Connector`];
if (inputType === 'assignment') return 'set';
return connectorType === 'output' ? 'then' : 'equal';
}
function connectorContent(connectorType, inputType, opts) {
let connector = opts[`${connectorType}Connector`] || defaultConnector(connectorType, inputType, opts);
if (connector) return [connectorItem(connector)];
return connectors[connectorType].map(function(connector) {
return connectorItem(connector);
});
}
// Selectors
const selectionTypes = [
'text',
'wizard',
'user',
'group',
'category',
'tag'
]
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)) {
type = t;
break;
}
}
return type;
}
// items
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)
}
return Ember.Object.create(params);
}
function newInput(options = {}) {
const inputType = defaultInputType(options);
let params = {
type: inputType,
pairs: Ember.A(
[
newPair(
inputType,
Object.assign({},
options,
{ index: 0, pairCount: 1 }
)
)
]
)
}
if (options.hasOutput) {
params['output_type'] = defaultSelectionType('output', options);
params['connector'] = defaultConnector('output', inputType, options);
}
return Ember.Object.create(params);
}
//
export { export {
generateSelectKitContent, generateSelectKitContent,
profileFields,
actionTypes,
generateName, generateName,
defaultInputType, generateId,
defaultSelectionType, properties,
connectorContent, wizardProperties,
inputTypesContent, profileFields,
newInput, actionTypes
newPair,
generateId
}; };

Datei anzeigen

@ -0,0 +1,241 @@
import { properties } from '../lib/custom-wizard';
import { mappedProperties } from '../lib/mapper';
import { EmberObject } from '@ember/object';
function present(val) {
return val && val.length;
}
function mapped(property, type) {
return mappedProperties[type] &&
mappedProperties[type].indexOf(property) > -1;
}
function buildJson(object, type) {
let result = {};
properties[type].forEach((p) => {
let value = object.get(p);
if (value) {
result[p] = mapped(p, type) ? buildMappedJson(value) : value;
}
});
return result;
},
function buildMappedJson(inputs) {
if (!inputs || !inputs.length) return false;
let result = [];
inputs.forEach(inpt => {
let input = {
type: inpt.type,
};
if (present(inpt.output)) {
input.output = inpt.output;
input.output_type = inpt.output_type;
input.connector = inpt.connector;
}
if (present(inpt.pairs)) {
input.pairs = [];
inpt.pairs.forEach(pr => {
if (present(pr.key) && present(pr.value)) {
let pairParams = {
index: pr.index,
key: pr.key,
key_type: pr.key_type,
value: pr.value,
value_type: pr.value_type,
connector: pr.connector
}
input.pairs.push(pairParams);
}
});
}
if ((input.type === 'assignment' && present(input.output)) ||
(input.type === 'conditional' && present(input.pairs)) ||
(input.type === 'pair' && present(input.pairs))) {
result.push(input);
}
});
if (!result.length) {
result = false;
}
return result;
}
buildStepJson(object) {
let steps = [];
let error = null;
object.some((s) => {
let step = buildJson(s, 'step');
let fields = s.fields;
if (fields.length) {
step.fields = [];
fields.some((f) => {
if (!f.type) {
error = 'type_required';
return;
}
step.fields.push(
buildJson(f, 'field')
);
});
if (error) return;
}
let actions = s.actions;
if (actions.length) {
step.actions = [];
actions.some((a) => {
if (a.api_body) {
try {
JSON.parse(a.api_body);
} catch (e) {
error = 'invalid_api_body';
return;
}
}
step.actions.push(
buildJson(a, 'action')
);
});
if (error) return;
}
steps.push(step);
});
if (error) {
return { error };
} else {
return { steps };
};
}
function buildObject(json, type) {
let params = {
isNew: false
}
Object.keys(json).forEach(prop => {
if (mapped(prop, type)) {
let inputs = [];
json[prop].forEach(inputJson => {
let input = {}
Object.keys(inputJson).forEach(inputKey => {
if (inputKey === 'pairs') {
let pairs = [];
let pairCount = inputJson.pairs.length;
inputJson.pairs.forEach(pairJson => {
let pair = pairJson;
pair.pairCount = pairCount;
pairs.push(EmberObject.create(pair));
});
} else {
input[inputKey] = inputJson[inputKey];
}
});
inputs.push(EmberObject.create(input));
});
params[prop] = Ember.A(inputs);
} else {
params[prop] = json[prop];
}
});
EmberObject.create();
}
function buildWizardProperties(json) {
let steps = Ember.A();
let props = {
steps
};
if (present(json)) {
props.id = json.id;
props.existingId = true;
properties.wizard.forEach((p) => {
props[p] = json[p];
});
if (present(json.steps)) {
json.steps.forEach((s) => {
let fields = Ember.A();
if (present(s.fields)) {
s.fields.forEach((f) => {
fields.pushObject(buildObject(f, 'field'));
});
}
let actions = Ember.A();
if (s.actions && s.actions.length) {
s.actions.forEach((a) => {
const actionParams = { isNew: false };
const action = EmberObject.create($.extend(a, actionParams));
actions.pushObject(action);
});
}
steps.pushObject(EmberObject.create({
id: s.id,
key: s.key,
title: s.title,
raw_description: s.raw_description,
banner: s.banner,
required_data: s.required_data,
required_data_message: s.required_data_message,
permitted_params: s.permitted_params,
fields,
actions,
isNew: false
}));
});
};
} else {
props['id'] = '';
props['name'] = '';
props['background'] = '';
props['save_submissions'] = true;
props['multiple_submissions'] = false;
props['after_signup'] = false;
props['after_time'] = false;
props['required'] = false;
props['prompt_completion'] = false;
props['restart_on_revisit'] = false;
props['permitted'] = null;
props['steps'] = Ember.A();
}
return props;
}

Datei anzeigen

@ -0,0 +1,174 @@
const mappedProperties = {
wizard: [
'permitted'
],
step: [
'required_data',
'permitted_params'
],
field: [
'choices',
'prefill',
'content'
],
action: [
'title',
'category',
'tags',
'custom_fields',
'required',
'recipient',
'profile_updates',
'group'
]
}
// Inputs
const selectableInputTypes = [
'conditional',
'assignment'
]
function defaultInputType(options = {}) {
if (!options.hasOutput) return 'pair';
if (!options.inputTypes) return selectableInputTypes[0];
return options.inputTypes.split(',')[0];
}
function mapInputTypes(types) {
return types.map(function(type) {
return {
id: type,
name: I18n.t(`admin.wizard.input.${type}.name`)
};
});
}
function inputTypesContent(options = {}) {
return options.inputTypes ?
mapInputTypes(options.inputTypes.split(',')) :
mapInputTypes(selectableInputTypes);
}
// Connectors
const connectors = {
output: [
'then',
'set',
],
pair: [
'equal',
'greater',
'less',
'greater_or_equal',
'less_or_equal'
]
}
function connectorItem(connector) {
return {
id: connector,
name: I18n.t(`admin.wizard.connector.${connector}`)
};
}
function defaultConnector(connectorType, inputType, opts = {}) {
if (opts[`${connectorType}Connector`]) return opts[`${connectorType}Connector`];
if (inputType === 'assignment') return 'set';
return connectorType === 'output' ? 'then' : 'equal';
}
function connectorContent(connectorType, inputType, opts) {
let connector = opts[`${connectorType}Connector`] || defaultConnector(connectorType, inputType, opts);
if (connector) return [connectorItem(connector)];
return connectors[connectorType].map(function(connector) {
return connectorItem(connector);
});
}
// Selectors
const selectionTypes = [
'text',
'wizard',
'user',
'group',
'category',
'tag'
]
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)) {
type = t;
break;
}
}
return type;
}
// items
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)
}
return Ember.Object.create(params);
}
function newInput(options = {}) {
const inputType = defaultInputType(options);
let params = {
type: inputType,
pairs: Ember.A(
[
newPair(
inputType,
Object.assign({},
options,
{ index: 0, pairCount: 1 }
)
)
]
)
}
if (options.hasOutput) {
params['output_type'] = defaultSelectionType('output', options);
params['connector'] = defaultConnector('output', inputType, options);
}
return Ember.Object.create(params);
}
export {
mappedProperties,
defaultInputType,
defaultSelectionType,
connectorContent,
inputTypesContent,
newInput,
newPair,
}

Datei anzeigen

@ -1,57 +1,38 @@
import { ajax } from 'discourse/lib/ajax'; import { ajax } from 'discourse/lib/ajax';
import EmberObject from "@ember/object"; import EmberObject from "@ember/object";
import { buildStepJson, buildJson, buildWizardProperties } from '../lib/json';
const wizardProperties = [
'name',
'background',
'save_submissions',
'multiple_submissions',
'after_signup',
'after_time',
'after_time_scheduled',
'required',
'prompt_completion',
'restart_on_revisit',
'theme_id',
'permitted'
];
const CustomWizard = EmberObject.extend({ const CustomWizard = EmberObject.extend({
save() { save() {
return new Ember.RSVP.Promise((resolve, reject) => { return new Ember.RSVP.Promise((resolve, reject) => {
const id = this.get('id'); let wizardJson = buildJson(this, 'wizard');
if (!id || !id.underscore()) return reject({ error: 'id_required' });
let wizard = { id: id.underscore() }; if (wizardJson.after_time && !wizardJson.after_time_scheduled) {
reject({
wizardProperties.forEach((p) => { error: 'after_time_need_time'
const value = this.get(p);
if (value) wizard[p] = value;
}); });
if (wizard['after_time'] && !wizard['after_time_scheduled']) {
return reject({ error: 'after_time_need_time' });
}; };
const steps = this.get('steps'); if (this.steps.length > 0) {
if (steps.length > 0) { let stepsResult = buildStepJson(this.steps);
const stepsResult = this.buildSteps(steps);
if (stepsResult.error) {
reject({ error: stepsResult.error });
} else {
wizard['steps'] = stepsResult.steps;
}
}
if (steps.length < 1 || !wizard['steps'] || wizard['steps'].length < 1) { if (stepsResult.error ||
return reject({ error: 'steps_required' }); !stepsResult.steps ||
stepsResult.steps.length < 1) {
reject({
error: stepsResult.error || 'steps_required'
});
} else {
wizardJson.steps = stepsResult.steps;
}
} }
ajax("/admin/wizards/custom/save", { ajax("/admin/wizards/custom/save", {
type: 'PUT', type: 'PUT',
data: { data: {
wizard: JSON.stringify(wizard) wizard: JSON.stringify(wizardJson)
} }
}).then((result) => { }).then((result) => {
if (result.error) { if (result.error) {
@ -63,107 +44,6 @@ const CustomWizard = EmberObject.extend({
}); });
}, },
buildSteps(stepsObj) {
let steps = [];
let error = null;
stepsObj.some((s) => {
if (!s.id || !s.id.underscore()) {
error = 'id_required';
return;
};
let step = { id: s.id.underscore() };
if (s.title) step['title'] = s.title;
if (s.key) step['key'] = s.key;
if (s.banner) step['banner'] = s.banner;
if (s.raw_description) step['raw_description'] = s.raw_description;
if (s.required_data) step['required_data'] = s.required_data;
if (s.required_data_message) step['required_data_message'] = s.required_data_message;
if (s.permitted_params) step['permitted_params'] = s.permitted_params;
const fields = s.get('fields');
if (fields.length) {
step['fields'] = [];
fields.some((f) => {
let id = f.id;
if (!id || !id.underscore()) {
error = 'id_required';
return;
}
if (!f.type) {
error = 'type_required';
return;
}
f.set('id', id.underscore());
if (f.label === '') delete f.label;
if (f.description === '') delete f.description;
if (f.type === 'dropdown') {
const choices = f.choices;
if ((!choices || choices.length < 1) && !f.choices_key) {
error = 'field.need_choices';
return;
}
if (f.dropdown_none === '') delete f.dropdown_none;
}
delete f.isNew;
step['fields'].push(f);
});
if (error) return;
}
const actions = s.actions;
if (actions.length) {
step['actions'] = [];
actions.some((a) => {
let id = a.get('id');
if (!id || !id.underscore()) {
error = 'id_required';
return;
}
//check if api_body is valid JSON
let api_body = a.get('api_body');
if (api_body) {
try {
JSON.parse(api_body);
} catch (e) {
error = 'invalid_api_body';
return;
}
}
a.set('id', id.underscore());
delete a.isNew;
step['actions'].push(a);
});
if (error) return;
}
steps.push(step);
});
if (error) {
return { error };
} else {
return { steps };
};
},
remove() { remove() {
return ajax("/admin/wizards/custom/remove", { return ajax("/admin/wizards/custom/remove", {
type: 'DELETE', type: 'DELETE',
@ -191,87 +71,11 @@ CustomWizard.reopenClass({
}); });
}, },
create(w) { create(wizardJson = {}) {
const wizard = this._super.apply(this); const wizard = this._super.apply(this);
let steps = Ember.A();
let props = { steps };
if (w) {
props['id'] = w.id;
props['existingId'] = true;
wizardProperties.forEach((p) => { wizard.setProperties(buildWizardProperties(wizardJson));
props[p] = w[p];
});
if (w.steps && w.steps.length) {
w.steps.forEach((s) => {
// clean empty strings
Object.keys(s).forEach((key) => (s[key] === '') && delete s[key]);
let fields = Ember.A();
if (s.fields && s.fields.length) {
s.fields.forEach((f) => {
Object.keys(f).forEach((key) => (f[key] === '') && delete f[key]);
const fieldParams = { isNew: false };
let field = Ember.Object.create($.extend(f, fieldParams));
if (f.choices) {
let choices = Ember.A();
f.choices.forEach((c) => {
choices.pushObject(Ember.Object.create(c));
});
field.set('choices', choices);
}
fields.pushObject(field);
});
}
let actions = Ember.A();
if (s.actions && s.actions.length) {
s.actions.forEach((a) => {
const actionParams = { isNew: false };
const action = Ember.Object.create($.extend(a, actionParams));
actions.pushObject(action);
});
}
steps.pushObject(Ember.Object.create({
id: s.id,
key: s.key,
title: s.title,
raw_description: s.raw_description,
banner: s.banner,
required_data: s.required_data,
required_data_message: s.required_data_message,
permitted_params: s.permitted_params,
fields,
actions,
isNew: false
}));
});
};
} else {
props['id'] = '';
props['name'] = '';
props['background'] = '';
props['save_submissions'] = true;
props['multiple_submissions'] = false;
props['after_signup'] = false;
props['after_time'] = false;
props['required'] = false;
props['prompt_completion'] = false;
props['restart_on_revisit'] = false;
props['permitted'] = null;
props['steps'] = Ember.A();
};
wizard.setProperties(props);
return wizard; return wizard;
} }

Datei anzeigen

@ -80,9 +80,11 @@
inputs=action.category inputs=action.category
options=(hash options=(hash
hasOutput=true hasOutput=true
categorySelection='output' textSelection='key,value'
wizardSelection=true wizardSelection=true
userSelection='key,value' userSelection='key,value'
categorySelection='output'
outputDefaultSelection='category'
)}} )}}
</div> </div>
</div> </div>

Datei anzeigen

@ -1,41 +1,41 @@
<div class="type-selector"> <div class="type-selector">
{{#if textEnabled}} {{#if textEnabled}}
{{input-type-toggle {{wizard-mapper-selector-type
activeType=activeType activeType=activeType
type='text' type='text'
toggle=(action 'toggleType')}} toggle=(action 'toggleType')}}
{{/if}} {{/if}}
{{#if wizardEnabled}} {{#if wizardEnabled}}
{{input-type-toggle {{wizard-mapper-selector-type
activeType=activeType activeType=activeType
type='wizard' type='wizard'
toggle=(action 'toggleType')}} toggle=(action 'toggleType')}}
{{/if}} {{/if}}
{{#if userEnabled}} {{#if userEnabled}}
{{input-type-toggle {{wizard-mapper-selector-type
activeType=activeType activeType=activeType
type='user' type='user'
toggle=(action 'toggleType')}} toggle=(action 'toggleType')}}
{{/if}} {{/if}}
{{#if categoryEnabled}} {{#if categoryEnabled}}
{{input-type-toggle {{wizard-mapper-selector-type
activeType=activeType activeType=activeType
type='category' type='category'
toggle=(action 'toggleType')}} toggle=(action 'toggleType')}}
{{/if}} {{/if}}
{{#if tagEnabled}} {{#if tagEnabled}}
{{input-type-toggle {{wizard-mapper-selector-type
activeType=activeType activeType=activeType
type='tag' type='tag'
toggle=(action 'toggleType')}} toggle=(action 'toggleType')}}
{{/if}} {{/if}}
{{#if groupEnabled}} {{#if groupEnabled}}
{{input-type-toggle {{wizard-mapper-selector-type
activeType=activeType activeType=activeType
type='group' type='group'
toggle=(action 'toggleType')}} toggle=(action 'toggleType')}}

Datei anzeigen

@ -24,7 +24,6 @@ export default Ember.Route.extend({
name, name,
completed, completed,
notPermitted: !permitted, notPermitted: !permitted,
minTrust,
wizardId wizardId
}); });
} else { } else {

Datei anzeigen

@ -150,40 +150,38 @@ class CustomWizard::Wizard
@groups ||= ::Site.new(Guardian.new(@user)).groups @groups ||= ::Site.new(Guardian.new(@user)).groups
end end
def self.templates(filter = nil) def self.filter_records(filter)
rows = [*PluginStoreRow.where(plugin_name: 'custom_wizard')] PluginStoreRow.where("
rows = rows.select { |r| r.value[filter] } if filter plugin_name = 'custom_wizard' AND
rows (value::json ->> '#{filter}')::boolean IS TRUE
")
end end
def self.after_signup(user) def self.after_signup(user)
if (temps = templates('after_signup')).any? if (records = filter_records('after_signup')).any?
wizard = nil result = false
temps records
.sort_by { |t| template.value['permitted'].present? } .sort_by { |record| record.value['permitted'].present? }
.each do |template| .each do |record|
wizard = CustomWizard::Wizard.new(user, template) wizard = CustomWizard::Wizard.new(user, JSON.parse(record.value))
if wizard.permitted? if wizard.permitted?
wizard = wizard result = wizard
break break
end end
end end
wizard result
else else
false false
end end
end end
def self.prompt_completion(user) def self.prompt_completion(user)
if (temps = templates('prompt_completion')).any? if (records = filter_records('prompt_completion')).any?
temps.reduce([]) do |result, w| records.reduce([]) do |result, record|
data = ::JSON.parse(w.value) wizard = CustomWizard::Wizard.new(user, ::JSON.parse(record.value))
id = data['id']
name = data['name']
wizard = CustomWizard::Wizard.new(user, id: id, name: name)
result.push(id: id, name: name) if !wizard.completed? result.push(id: id, name: name) if !wizard.completed?
result result
end end
@ -193,8 +191,8 @@ class CustomWizard::Wizard
end end
def self.restart_on_revisit def self.restart_on_revisit
if (temps = templates('restart_on_revisit')).any? if (records = filter_records('restart_on_revisit')).any?
temps.first.key records.first.key
else else
false false
end end

Datei anzeigen

@ -90,6 +90,8 @@ after_initialize do
user.first_seen_at.blank? && user.first_seen_at.blank? &&
wizard = CustomWizard::Wizard.after_signup(user) wizard = CustomWizard::Wizard.after_signup(user)
byebug
if !wizard.completed? if !wizard.completed?
custom_redirect = true custom_redirect = true
CustomWizard::Wizard.set_wizard_redirect(user, wizard.id) CustomWizard::Wizard.set_wizard_redirect(user, wizard.id)