various
Dieser Commit ist enthalten in:
Ursprung
98f9215d65
Commit
024ab63006
13 geänderte Dateien mit 281 neuen und 132 gelöschten Zeilen
|
@ -1,4 +1,4 @@
|
|||
import { default as discourseComputed, observes } from 'discourse-common/utils/decorators';
|
||||
import { default as discourseComputed, observes, on } from 'discourse-common/utils/decorators';
|
||||
import { equal, empty, or } from "@ember/object/computed";
|
||||
import { actionTypes, generateName, selectKitContent } from '../lib/wizard';
|
||||
import Component from "@ember/component";
|
||||
|
@ -21,16 +21,14 @@ export default Component.extend({
|
|||
publicTopicFields: or('createTopic', 'openComposer'),
|
||||
showSkipRedirect: or('createTopic', 'sendMessage'),
|
||||
|
||||
@observes('action.type')
|
||||
setupDefaults() {
|
||||
if (this.action.type) {
|
||||
this.set('action.label', generateName(this.action.type));
|
||||
};
|
||||
},
|
||||
|
||||
@discourseComputed('wizard.steps')
|
||||
runAfterContent(steps) {
|
||||
let content = steps.map(s => ({ id: s.id, name: s.label }));
|
||||
let content = steps.map(function(step) {
|
||||
return {
|
||||
id: step.id,
|
||||
name: step.title || step.id
|
||||
};
|
||||
});
|
||||
|
||||
content.unshift({
|
||||
id: 'wizard_completion',
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import { default as discourseComputed, on, observes } from 'discourse-common/utils/decorators';
|
||||
import { generateName, defaultProperties } from '../lib/wizard';
|
||||
import { notEmpty } from "@ember/object/computed";
|
||||
import { scheduleOnce, bind } from "@ember/runloop";
|
||||
import EmberObject from "@ember/object";
|
||||
|
@ -35,23 +36,29 @@ export default Component.extend({
|
|||
@discourseComputed('type')
|
||||
header: (type) => `admin.wizard.${type}.header`,
|
||||
|
||||
@discourseComputed('current', 'items.@each.id', 'items.@each.label')
|
||||
@discourseComputed('current', 'items.@each.id', 'items.@each.type')
|
||||
links(current, items) {
|
||||
if (!items) return;
|
||||
|
||||
return items.map((item) => {
|
||||
if (item) {
|
||||
const id = item.id;
|
||||
const type = this.type;
|
||||
const label = item.label || item.title || id;
|
||||
let link = { id, label };
|
||||
let link = {
|
||||
id: item.id
|
||||
}
|
||||
|
||||
let label = item.label || item.title || item.id;
|
||||
if (this.generateLabels && item.type) {
|
||||
label = generateName(item.type);
|
||||
}
|
||||
|
||||
link.label = label;
|
||||
|
||||
let classes = 'btn';
|
||||
if (current && item.id === current.id) {
|
||||
classes += ' btn-primary';
|
||||
};
|
||||
|
||||
link['classes'] = classes;
|
||||
link.classes = classes;
|
||||
|
||||
return link;
|
||||
}
|
||||
|
@ -63,15 +70,25 @@ export default Component.extend({
|
|||
const items = this.items;
|
||||
const type = this.type;
|
||||
const newId = `${type}_${items.length + 1}`;
|
||||
let params = { id: newId, isNew: true };
|
||||
|
||||
let params = {
|
||||
id: newId,
|
||||
isNew: true
|
||||
};
|
||||
|
||||
if (type === 'step') {
|
||||
params['fields'] = A();
|
||||
params['actions'] = A();
|
||||
params.fields = A();
|
||||
};
|
||||
|
||||
if (defaultProperties[type]) {
|
||||
Object.keys(defaultProperties[type]).forEach(key => {
|
||||
params[key] = defaultProperties[type][key];
|
||||
});
|
||||
}
|
||||
|
||||
const newItem = EmberObject.create(params);
|
||||
items.pushObject(newItem);
|
||||
|
||||
this.set('current', newItem);
|
||||
},
|
||||
|
||||
|
|
|
@ -18,12 +18,7 @@ export default Controller.extend({
|
|||
|
||||
if (currentStep) {
|
||||
const fields = currentStep.fields;
|
||||
const actions = currentStep.actions;
|
||||
|
||||
this.setProperties({
|
||||
currentField: fields.length ? fields[0] : null,
|
||||
currentAction: actions.length ? actions[0] : null
|
||||
});
|
||||
this.set('currentField', fields && fields.length ? fields[0] : null)
|
||||
}
|
||||
|
||||
scheduleOnce('afterRender', () => ($("body").addClass('admin-wizard')));
|
||||
|
@ -98,6 +93,7 @@ export default Controller.extend({
|
|||
this.send("refreshWizard");
|
||||
}
|
||||
}).catch((result) => {
|
||||
console.log('catch result: ', result)
|
||||
this.set('saving', false);
|
||||
this.set('error', I18n.t(`admin.wizard.error.${result.error}`, result.errorParams || {}));
|
||||
later(() => this.set('error', null), 10000);
|
||||
|
|
|
@ -85,7 +85,7 @@ function wizardHasAdvanced(property, value) {
|
|||
}
|
||||
|
||||
function stepHasAdvanced(property, value) {
|
||||
return advancedProperties.step[property] && present(value);
|
||||
return advancedProperties.steps[property] && present(value);
|
||||
}
|
||||
|
||||
function objectHasAdvanced(params, type) {
|
||||
|
@ -96,23 +96,45 @@ function objectHasAdvanced(params, type) {
|
|||
});
|
||||
}
|
||||
|
||||
/// to be removed
|
||||
function actionPatch(json) {
|
||||
let actions = json.actions || [];
|
||||
|
||||
json.steps.forEach(step => {
|
||||
if (step.actions && step.actions.length) {
|
||||
step.actions.forEach(action => {
|
||||
action.run_after = 'wizard_completion';
|
||||
actions.push(action);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
json.actions = actions;
|
||||
|
||||
return json;
|
||||
}
|
||||
///
|
||||
|
||||
function buildProperties(json) {
|
||||
let props = {
|
||||
steps: A();
|
||||
action: A();
|
||||
steps: A(),
|
||||
actions: A()
|
||||
};
|
||||
|
||||
if (present(json)) {
|
||||
props.id = json.id;
|
||||
props.existingId = true;
|
||||
|
||||
properties.wizard.forEach((p) => {
|
||||
props[p] = buildProperty(json, p, 'wizard');
|
||||
// to fix
|
||||
properties.wizard
|
||||
.filter(p => ['steps', 'actions'].indexOf(p) === -1)
|
||||
.forEach((p) => {
|
||||
props[p] = buildProperty(json, p, 'wizard');
|
||||
|
||||
if (wizardHasAdvanced(p, json[p])) {
|
||||
props.showAdvanced = true;
|
||||
}
|
||||
});
|
||||
if (wizardHasAdvanced(p, json[p])) {
|
||||
props.showAdvanced = true;
|
||||
}
|
||||
});
|
||||
|
||||
if (present(json.steps)) {
|
||||
json.steps.forEach((stepJson) => {
|
||||
|
@ -120,7 +142,7 @@ function buildProperties(json) {
|
|||
isNew: false
|
||||
};
|
||||
|
||||
properties.step.forEach((p) => {
|
||||
properties.steps.forEach((p) => {
|
||||
stepParams[p] = buildProperty(stepJson, p, 'wizard');
|
||||
|
||||
if (stepHasAdvanced(p, stepJson[p])) {
|
||||
|
@ -132,9 +154,9 @@ function buildProperties(json) {
|
|||
|
||||
if (present(stepJson.fields)) {
|
||||
stepJson.fields.forEach((f) => {
|
||||
let params = buildObject(f, 'field');
|
||||
let params = buildObject(f, 'fields');
|
||||
|
||||
if (objectHasAdvanced(params, 'field')) {
|
||||
if (objectHasAdvanced(params, 'fields')) {
|
||||
params.showAdvanced = true;
|
||||
}
|
||||
|
||||
|
@ -142,17 +164,21 @@ function buildProperties(json) {
|
|||
});
|
||||
}
|
||||
|
||||
steps.pushObject(
|
||||
props.steps.pushObject(
|
||||
EmberObject.create(stepParams)
|
||||
);
|
||||
});
|
||||
};
|
||||
|
||||
// to be removed
|
||||
json = actionPatch(json);
|
||||
// to be removed
|
||||
|
||||
if (present(json.actions)) {
|
||||
json.actions.forEach((a) => {
|
||||
let params = buildObject(a, 'action');
|
||||
let params = buildObject(a, 'actions');
|
||||
|
||||
if (objectHasAdvanced(params, 'action')) {
|
||||
if (objectHasAdvanced(params, 'actions')) {
|
||||
params.showAdvanced = true;
|
||||
}
|
||||
|
||||
|
@ -177,7 +203,7 @@ function buildProperties(json) {
|
|||
}
|
||||
|
||||
export {
|
||||
buildStepJson,
|
||||
buildJson,
|
||||
buildProperties
|
||||
buildProperties,
|
||||
present,
|
||||
mapped
|
||||
}
|
|
@ -116,30 +116,93 @@ const actionProperties = [
|
|||
|
||||
const properties = {
|
||||
wizard: wizardProperties,
|
||||
step: stepProperties,
|
||||
field: fieldProperties,
|
||||
action: actionProperties
|
||||
steps: stepProperties,
|
||||
fields: fieldProperties,
|
||||
actions: actionProperties
|
||||
}
|
||||
|
||||
const objectArrays = [
|
||||
'steps',
|
||||
'fields',
|
||||
'actions'
|
||||
];
|
||||
const actionTypeProperties = {
|
||||
create_topic: [
|
||||
'id',
|
||||
'type',
|
||||
'run_after',
|
||||
'title',
|
||||
'post',
|
||||
'post_builder',
|
||||
'post_template',
|
||||
'category',
|
||||
'tags',
|
||||
'skip_redirect',
|
||||
'custom_fields'
|
||||
],
|
||||
send_message: [
|
||||
'id',
|
||||
'type',
|
||||
'run_after',
|
||||
'title',
|
||||
'post',
|
||||
'post_builder',
|
||||
'post_template',
|
||||
'skip_redirect',
|
||||
'custom_fields',
|
||||
'required',
|
||||
'recipient'
|
||||
],
|
||||
open_composer: [
|
||||
'id',
|
||||
'type',
|
||||
'run_after',
|
||||
'title',
|
||||
'post',
|
||||
'post_builder',
|
||||
'post_template',
|
||||
'category',
|
||||
'tags',
|
||||
'custom_fields'
|
||||
],
|
||||
update_profile: [
|
||||
'id',
|
||||
'type',
|
||||
'run_after',
|
||||
'profile_updates',
|
||||
'custom_fields'
|
||||
],
|
||||
add_to_group: [
|
||||
'id',
|
||||
'type',
|
||||
'run_after',
|
||||
'group'
|
||||
],
|
||||
route_to: [
|
||||
'id',
|
||||
'type',
|
||||
'run_after',
|
||||
'url',
|
||||
'code'
|
||||
],
|
||||
send_to_api: [
|
||||
'id',
|
||||
'type',
|
||||
'run_after',
|
||||
'api',
|
||||
'api_endpoint',
|
||||
'api_body'
|
||||
]
|
||||
}
|
||||
|
||||
const mappedProperties = {
|
||||
wizard: [
|
||||
'permitted'
|
||||
],
|
||||
step: [
|
||||
steps: [
|
||||
'required_data',
|
||||
'permitted_params'
|
||||
],
|
||||
field: [
|
||||
fields: [
|
||||
'prefill',
|
||||
'content'
|
||||
],
|
||||
action: [
|
||||
actions: [
|
||||
'title',
|
||||
'category',
|
||||
'tags',
|
||||
|
@ -151,6 +214,12 @@ const mappedProperties = {
|
|||
]
|
||||
}
|
||||
|
||||
const defaultProperties = {
|
||||
action: {
|
||||
run_after: 'wizard_completion'
|
||||
}
|
||||
}
|
||||
|
||||
const advancedFieldTypes = [
|
||||
'category',
|
||||
'tag',
|
||||
|
@ -176,11 +245,11 @@ const actionTypes = [
|
|||
});
|
||||
|
||||
const advancedProperties = {
|
||||
step: [
|
||||
steps: [
|
||||
'required_data',
|
||||
'permitted_params'
|
||||
],
|
||||
field: advancedFieldTypes.reduce(
|
||||
fields: advancedFieldTypes.reduce(
|
||||
function(map, type) {
|
||||
map[type] = advancedFieldProperties;
|
||||
if (type === 'category') {
|
||||
|
@ -189,7 +258,7 @@ const advancedProperties = {
|
|||
return map;
|
||||
}, {}
|
||||
),
|
||||
action: actionTypes.reduce(
|
||||
actions: actionTypes.reduce(
|
||||
function(map, type) {
|
||||
if (type === 'route_to') {
|
||||
map[type] = ['code'];
|
||||
|
@ -212,10 +281,11 @@ export {
|
|||
camelCase,
|
||||
snakeCase,
|
||||
properties,
|
||||
objectArrays,
|
||||
wizardProperties,
|
||||
mappedProperties,
|
||||
profileFields,
|
||||
advancedProperties,
|
||||
actionTypes
|
||||
actionTypes,
|
||||
actionTypeProperties,
|
||||
defaultProperties
|
||||
};
|
|
@ -1,7 +1,7 @@
|
|||
import { ajax } from 'discourse/lib/ajax';
|
||||
import EmberObject from "@ember/object";
|
||||
import { buildJson, buildProperties, present } from '../lib/wizard-json';
|
||||
import { properties, arrays, camelCase, snakeCase } from '../lib/wizard';
|
||||
import { buildProperties, present, mapped } from '../lib/wizard-json';
|
||||
import { properties, actionTypeProperties, camelCase, snakeCase } from '../lib/wizard';
|
||||
import { Promise } from "rsvp";
|
||||
|
||||
const jsonStrings = ['api_body'];
|
||||
|
@ -14,13 +14,13 @@ const CustomWizard = EmberObject.extend({
|
|||
let json = this.buildJson(this, 'wizard');
|
||||
|
||||
if (json.error) {
|
||||
reject({ eror: json.error });
|
||||
reject({ error: json.error });
|
||||
}
|
||||
|
||||
ajax("/admin/wizards/custom/save", {
|
||||
type: 'PUT',
|
||||
data: {
|
||||
wizard: JSON.stringify(wizardJson)
|
||||
wizard: JSON.stringify(json)
|
||||
}
|
||||
}).then((result) => {
|
||||
if (result.error) {
|
||||
|
@ -33,34 +33,43 @@ const CustomWizard = EmberObject.extend({
|
|||
},
|
||||
|
||||
buildJson(object, type, result = {}) {
|
||||
for (let property of properties[type]) {
|
||||
let allowedProperties;
|
||||
|
||||
if (type === 'actions') {
|
||||
if (!object.type) {
|
||||
result.error = {
|
||||
type: 'required',
|
||||
params: {
|
||||
type,
|
||||
property: 'type'
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
allowedProperties = actionTypeProperties[object.type];
|
||||
} else {
|
||||
allowedProperties = properties[type];
|
||||
}
|
||||
|
||||
for (let property of allowedProperties) {
|
||||
let value = object.get(property);
|
||||
|
||||
if (objectArrays[type]) {
|
||||
result[property] = [];
|
||||
|
||||
for (let obj of value) {
|
||||
let obj = this.buildJson(value, property, result);
|
||||
|
||||
if (obj.error) {
|
||||
result.error = r.error;
|
||||
break;
|
||||
} else {
|
||||
result[property].push(obj);
|
||||
}
|
||||
if (required[property] && !value) {
|
||||
result.error = {
|
||||
type: 'required',
|
||||
params: { type, property }
|
||||
}
|
||||
}
|
||||
|
||||
if (required[property] && !value) {
|
||||
result.error = 'required'
|
||||
result.errorParams = { type, property };
|
||||
}
|
||||
|
||||
if (dependent[property] && !properties[type][dependent[property]]) {
|
||||
result.error = 'dependent';
|
||||
result.errorParams = {
|
||||
dependentProperty: properties[type][dependent[property]],
|
||||
property
|
||||
let dependentOn = dependent[property];
|
||||
if (dependentOn && value && !object[dependentOn]) {
|
||||
result.error = {
|
||||
type: 'dependent',
|
||||
params: {
|
||||
property,
|
||||
dependentOn
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -68,24 +77,43 @@ const CustomWizard = EmberObject.extend({
|
|||
try {
|
||||
value = JSON.parse(value);
|
||||
} catch (e) {
|
||||
result.error = 'invalid';
|
||||
result.errorParams = { property };
|
||||
result.error = {
|
||||
type: 'invalid',
|
||||
params: { type, property }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (mapped(property, type)) {
|
||||
value = this.buildMappedJson(value);
|
||||
}
|
||||
|
||||
if (result.error) {
|
||||
break;
|
||||
} else if (value) {
|
||||
result[property] = value;
|
||||
}
|
||||
});
|
||||
|
||||
if (properties[property]) {
|
||||
result[property] = [];
|
||||
|
||||
for (let item of value) {
|
||||
let itemParams = this.buildJson(item, property);
|
||||
|
||||
if (itemParams.error) {
|
||||
result.error = r.error;
|
||||
break;
|
||||
} else {
|
||||
result[property].push(itemParams);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (mapped(property, type)) {
|
||||
value = this.buildMappedJson(value);
|
||||
}
|
||||
|
||||
if (value !== undefined && value !== null) {
|
||||
result[property] = value;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return result;
|
||||
}
|
||||
},
|
||||
|
||||
buildMappedJson(inputs) {
|
||||
if (!inputs || !inputs.length) return false;
|
||||
|
|
|
@ -91,12 +91,12 @@ export default DiscourseRoute.extend({
|
|||
|
||||
setupController(controller, model) {
|
||||
const newWizard = this.get('newWizard');
|
||||
const steps = model.get('steps') || [];
|
||||
|
||||
controller.setProperties({
|
||||
newWizard,
|
||||
model,
|
||||
currentStep: steps[0]
|
||||
currentStep: model.steps[0],
|
||||
currentAction: model.actions[0]
|
||||
});
|
||||
},
|
||||
|
||||
|
|
|
@ -150,7 +150,10 @@
|
|||
{{/if}}
|
||||
</div>
|
||||
|
||||
{{wizard-links type="step" current=currentStep items=model.steps}}
|
||||
{{wizard-links
|
||||
type="step"
|
||||
current=currentStep
|
||||
items=model.steps}}
|
||||
|
||||
{{#if currentStep}}
|
||||
{{wizard-custom-step
|
||||
|
@ -160,7 +163,11 @@
|
|||
wizardFields=wizardFields}}
|
||||
{{/if}}
|
||||
|
||||
{{wizard-links type="action" current=currentAction items=model.actions}}
|
||||
{{wizard-links
|
||||
type="action"
|
||||
current=currentAction
|
||||
items=model.actions
|
||||
generateLabels=true}}
|
||||
|
||||
{{#if currentAction}}
|
||||
{{wizard-custom-action
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
|
||||
<div class="setting">
|
||||
<div class="setting-label">
|
||||
<label>{{i18n "admin.wizard.run_after"}}</label>
|
||||
<label>{{i18n "admin.wizard.action.run_after.label"}}</label>
|
||||
</div>
|
||||
|
||||
<div class="setting-value">
|
||||
|
|
|
@ -97,7 +97,7 @@ en:
|
|||
error:
|
||||
required: "{{type}} requires {{property}}"
|
||||
invalid: "{{property}} is invalid"
|
||||
dependent: "{{dependentProperty}} is dependent on {{property}}"
|
||||
dependent: "{{property}} is dependent on {{dependentOn}}"
|
||||
|
||||
step:
|
||||
header: "Steps"
|
||||
|
@ -152,7 +152,7 @@ en:
|
|||
|
||||
run_after:
|
||||
label: "Run After"
|
||||
wizard_completion: "Wizard completes"
|
||||
wizard_completion: "Wizard Completion"
|
||||
|
||||
custom_fields:
|
||||
label: "Custom"
|
||||
|
|
|
@ -151,17 +151,21 @@ class CustomWizard::AdminController < ::ApplicationController
|
|||
error = check_depdendent(step, error)
|
||||
break if error.present?
|
||||
|
||||
step['fields'].each do |field|
|
||||
error = check_required(field, :field, error)
|
||||
error = check_depdendent(field, error)
|
||||
break if error.present?
|
||||
if step['fields'].present?
|
||||
step['fields'].each do |field|
|
||||
error = check_required(field, :field, error)
|
||||
error = check_depdendent(field, error)
|
||||
break if error.present?
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
wizard['actions'].each do |action|
|
||||
error = check_required(action, :action, error)
|
||||
error = check_depdendent(action, error)
|
||||
break if error.present?
|
||||
if wizard['actions'].present?
|
||||
wizard['actions'].each do |action|
|
||||
error = check_required(action, :action, error)
|
||||
error = check_depdendent(action, error)
|
||||
break if error.present?
|
||||
end
|
||||
end
|
||||
|
||||
if error
|
||||
|
@ -211,8 +215,8 @@ class CustomWizard::AdminController < ::ApplicationController
|
|||
return after_time_validation[:error] if after_time_validation[:error]
|
||||
|
||||
wizard['steps'].each do |step|
|
||||
if s['raw_description']
|
||||
step['description'] = PrettyText.cook(s['raw_description'])
|
||||
if step['raw_description']
|
||||
step['description'] = PrettyText.cook(step['raw_description'])
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -151,8 +151,8 @@ class CustomWizard::Builder
|
|||
if @actions.present?
|
||||
@actions.each do |action|
|
||||
|
||||
if (action.run_after === updater.step.id) ||
|
||||
(final_step && (!action.run_after || (action.run_after === 'wizard_completion')))
|
||||
if (action['run_after'] === updater.step.id) ||
|
||||
(final_step && (!action['run_after'] || (action['run_after'] === 'wizard_completion')))
|
||||
|
||||
CustomWizard::Action.new(
|
||||
action: action,
|
||||
|
|
|
@ -2,7 +2,6 @@ class CustomWizard::Template
|
|||
|
||||
attr_reader :id,
|
||||
:name,
|
||||
:steps,
|
||||
:background,
|
||||
:save_submissions,
|
||||
:multiple_submissions,
|
||||
|
@ -13,7 +12,9 @@ class CustomWizard::Template
|
|||
:after_time_scheduled,
|
||||
:required,
|
||||
:theme_id,
|
||||
:permitted
|
||||
:permitted,
|
||||
:steps,
|
||||
:actions
|
||||
|
||||
def initialize(data)
|
||||
data = data.is_a?(String) ? ::JSON.parse(data) : data
|
||||
|
@ -22,7 +23,6 @@ class CustomWizard::Template
|
|||
|
||||
@id = data['id']
|
||||
@name = data['name']
|
||||
@steps = data['steps']
|
||||
@background = data['background']
|
||||
@save_submissions = data['save_submissions'] || false
|
||||
@multiple_submissions = data['multiple_submissions'] || false
|
||||
|
@ -39,5 +39,8 @@ class CustomWizard::Template
|
|||
theme = Theme.find_by(name: data['theme'])
|
||||
@theme_id = theme.id if theme
|
||||
end
|
||||
|
||||
@steps = data['steps']
|
||||
@actions = data['actions']
|
||||
end
|
||||
end
|
||||
|
|
Laden …
In neuem Issue referenzieren