diff --git a/assets/javascripts/discourse/components/wizard-mapper-connector.js.es6 b/assets/javascripts/discourse/components/wizard-mapper-connector.js.es6
index aaf555b4..ee6c38b2 100644
--- a/assets/javascripts/discourse/components/wizard-mapper-connector.js.es6
+++ b/assets/javascripts/discourse/components/wizard-mapper-connector.js.es6
@@ -1,7 +1,6 @@
import Component from "@ember/component";
import { gt } from '@ember/object/computed';
import { computed } from "@ember/object";
-import { removeMapperClasses } from '../lib/wizard-mapper';
export default Component.extend({
classNameBindings: [':mapper-connector', ':mapper-block', 'hasMultiple::single'],
@@ -10,11 +9,5 @@ export default Component.extend({
let key = this.connector;
let path = this.inputTypes ? `input.${key}.name` : `connector.${key}`;
return I18n.t(`admin.wizard.${path}`);
- }),
-
- actions: {
- onOpen() {
- removeMapperClasses(this);
- }
- }
+ })
});
\ No newline at end of file
diff --git a/assets/javascripts/discourse/components/wizard-mapper-selector.js.es6 b/assets/javascripts/discourse/components/wizard-mapper-selector.js.es6
index 22ad9ef2..b77f80f3 100644
--- a/assets/javascripts/discourse/components/wizard-mapper-selector.js.es6
+++ b/assets/javascripts/discourse/components/wizard-mapper-selector.js.es6
@@ -2,7 +2,7 @@ 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, removeMapperClasses } from '../lib/wizard-mapper';
+import { defaultSelectionType, selectionTypes } from '../lib/wizard-mapper';
import { snakeCase } from '../lib/wizard';
import Component from "@ember/component";
import { bind } from "@ember/runloop";
@@ -30,6 +30,7 @@ export default Component.extend({
userEnabled: computed('options.userSelection', 'inputType', function() { return this.optionEnabled('userSelection') }),
listEnabled: computed('options.listSelection', 'inputType', function() { return this.optionEnabled('listSelection') }),
hasTypes: gt('selectorTypes.length', 1),
+ showTypes: false,
didInsertElement() {
$(document).on("click", bind(this, this.documentClick));
@@ -41,15 +42,10 @@ export default Component.extend({
documentClick(e) {
if (this._state == "destroying") return;
-
let $target = $(e.target);
-
- if (!$target.parents('.wizard-mapper .input').length) {
- this.send('disableActive');
- }
-
- if (!$target.parents('.type-selector').length) {
- this.send('hideTypes');
+
+ if (!$target.parents('.type-selector').length && this.showTypes) {
+ this.set('showTypes', false);
}
},
@@ -80,9 +76,9 @@ export default Component.extend({
@discourseComputed('activeType')
comboBoxContent(activeType) {
- const controller = getOwner(this).lookup('controller:admin-wizard');
+ const controller = getOwner(this).lookup('controller:admin-wizards-wizard-show');
let content = controller[`${activeType}s`];
-
+
// you can't select the current field in the field context
if (activeType === 'wizardField' && this.options.context === 'field') {
content = content.filter(field => field.id !== controller.currentField.id);
@@ -148,34 +144,14 @@ export default Component.extend({
return this.activeType === type && this[`${type}Enabled`];
},
- removeClasses() {
- removeMapperClasses(this);
- },
-
actions: {
toggleType(type) {
this.set('activeType', type);
- this.send('hideTypes');
+ this.set('showTypes', false);
},
- // jquery is used here to ensure other selectors and types disable properly
-
- showTypes() {
- this.removeClasses();
- $(this.element).find('.selector-types').addClass('show');
- },
-
- hideTypes() {
- $(this.element).find('.selector-types').removeClass('show');
- },
-
- enableActive() {
- this.removeClasses();
- $(this.element).addClass('active');
- },
-
- disableActive() {
- $(this.element).removeClass('active');
+ toggleTypes() {
+ this.toggleProperty('showTypes');
}
}
})
\ No newline at end of file
diff --git a/assets/javascripts/discourse/controllers/admin-wizards-api.js.es6 b/assets/javascripts/discourse/controllers/admin-wizards-api-show.js.es6
similarity index 100%
rename from assets/javascripts/discourse/controllers/admin-wizards-api.js.es6
rename to assets/javascripts/discourse/controllers/admin-wizards-api-show.js.es6
diff --git a/assets/javascripts/discourse/controllers/admin-wizards-apis.js.es6 b/assets/javascripts/discourse/controllers/admin-wizards-apis.js.es6
deleted file mode 100644
index 7b087af3..00000000
--- a/assets/javascripts/discourse/controllers/admin-wizards-apis.js.es6
+++ /dev/null
@@ -1,5 +0,0 @@
-import Controller from "@ember/controller";
-
-export default Controller.extend({
- queryParams: ['refresh']
-});
diff --git a/assets/javascripts/discourse/controllers/admin-wizard-submissions.js.es6 b/assets/javascripts/discourse/controllers/admin-wizards-submissions-show.js.es6
similarity index 100%
rename from assets/javascripts/discourse/controllers/admin-wizard-submissions.js.es6
rename to assets/javascripts/discourse/controllers/admin-wizards-submissions-show.js.es6
diff --git a/assets/javascripts/discourse/controllers/admin-wizard.js.es6 b/assets/javascripts/discourse/controllers/admin-wizards-wizard-show.js.es6
similarity index 70%
rename from assets/javascripts/discourse/controllers/admin-wizard.js.es6
rename to assets/javascripts/discourse/controllers/admin-wizards-wizard-show.js.es6
index 42c3d534..e2aaec10 100644
--- a/assets/javascripts/discourse/controllers/admin-wizard.js.es6
+++ b/assets/javascripts/discourse/controllers/admin-wizards-wizard-show.js.es6
@@ -8,10 +8,10 @@ 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';
export default Controller.extend({
- hasName: notEmpty('model.name'),
- userFields: alias('model.userFields'),
+ hasName: notEmpty('wizard.name'),
@observes('currentStep')
resetCurrentObjects() {
@@ -25,28 +25,29 @@ export default Controller.extend({
scheduleOnce('afterRender', () => ($("body").addClass('admin-wizard')));
},
- @observes('model.name')
+ @observes('wizard.name')
setId() {
- if (!this.model.existingId) {
- this.set('model.id', generateId(this.model.name));
+ const wizard = this.wizard;
+ if (wizard && !wizard.existingId) {
+ this.set('wizard.id', generateId(wizard.name));
}
},
- @discourseComputed('model.id')
+ @discourseComputed('wizard.id')
wizardUrl(wizardId) {
return window.location.origin + '/w/' + dasherize(wizardId);
},
- @discourseComputed('model.after_time_scheduled')
+ @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', 'model.save_submissions', 'model.steps.@each.fields[]')
+ @discourseComputed('currentStep.id', 'wizard.save_submissions', 'wizard.steps.@each.fields[]')
wizardFields(currentStepId, saveSubmissions) {
- const allSteps = this.get('model.steps');
+ const allSteps = this.get('wizard.steps');
let steps = allSteps;
let fields = [];
@@ -71,31 +72,24 @@ export default Controller.extend({
return fields;
},
- actions: {
+ actions: {
save() {
this.setProperties({
saving: true,
error: null
});
- const wizard = this.model;
+ const wizard = this.wizard;
+ const creating = this.creating;
+ let opts = {};
- wizard.save().then((result) => {
-
- this.model.setProperties(
- buildProperties(result.wizard)
- );
+ if (creating) {
+ opts.create = true;
+ }
- this.set('saving', false);
-
- if (this.get('newWizard')) {
- this.send("refreshAllWizards");
- } else {
- this.send("refreshWizard");
- }
- }).catch((result) => {
- this.set('saving', false);
-
+ wizard.save(opts).then((result) => {
+ this.send('afterSave', result.wizard_id);
+ }).catch((result) => {
let errorType = 'failed';
let errorParams = {};
@@ -107,21 +101,18 @@ export default Controller.extend({
this.set('error', I18n.t(`admin.wizard.error.${errorType}`, errorParams));
later(() => this.set('error', null), 10000);
- });
+ }).finally(() => this.set('saving', false));
},
remove() {
- const wizard = this.get('model');
- wizard.remove().then(() => {
- this.send("refreshAllWizards");
- });
+ this.wizard.remove().then(() => this.send('afterDestroy'));
},
setNextSessionScheduled() {
let controller = showModal('next-session-scheduled', {
model: {
- dateTime: this.get('model.after_time_scheduled'),
- update: (dateTime) => this.set('model.after_time_scheduled', dateTime)
+ dateTime: this.wizard.after_time_scheduled,
+ update: (dateTime) => this.set('wizard.after_time_scheduled', dateTime)
}
});
@@ -129,7 +120,7 @@ export default Controller.extend({
},
toggleAdvanced() {
- this.toggleProperty('model.showAdvanced');
+ this.toggleProperty('wizard.showAdvanced');
},
copyUrl() {
diff --git a/assets/javascripts/discourse/controllers/admin-wizards-wizard.js.es6 b/assets/javascripts/discourse/controllers/admin-wizards-wizard.js.es6
new file mode 100644
index 00000000..b09e2ecd
--- /dev/null
+++ b/assets/javascripts/discourse/controllers/admin-wizards-wizard.js.es6
@@ -0,0 +1,25 @@
+import Controller from "@ember/controller";
+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')
+ wizardListVal(creating, wizardId) {
+ return creating ? null : wizardId;
+ },
+
+ @discourseComputed('creating', 'wizardId')
+ message(creating, wizardId) {
+ let type = 'select';
+
+ if (creating) {
+ type = 'create';
+ } else if (wizardId) {
+ type = 'edit';
+ }
+
+ return I18n.t(`admin.wizard.message.${type}`);
+ }
+});
\ No newline at end of file
diff --git a/assets/javascripts/discourse/custom-wizard-admin-route-map.js.es6 b/assets/javascripts/discourse/custom-wizard-admin-route-map.js.es6
index 205e2454..66cdacea 100644
--- a/assets/javascripts/discourse/custom-wizard-admin-route-map.js.es6
+++ b/assets/javascripts/discourse/custom-wizard-admin-route-map.js.es6
@@ -2,14 +2,17 @@ export default {
resource: 'admin',
map() {
this.route('adminWizards', { path: '/wizards', resetNamespace: true }, function() {
- this.route('adminWizardsCustom', { path: '/custom', resetNamespace: true }, function() {
- this.route('adminWizard', { path: '/:wizard_id', resetNamespace: true });
+
+ this.route('adminWizardsWizard', { path: '/wizard/', resetNamespace: true }, function() {
+ this.route('adminWizardsWizardShow', { path: '/:wizardId/', resetNamespace: true });
});
+
this.route('adminWizardsSubmissions', { path: '/submissions', resetNamespace: true }, function() {
- this.route('adminWizardSubmissions', { path: '/:wizard_id', resetNamespace: true });
- });
- this.route('adminWizardsApis', { path: '/apis', resetNamespace: true }, function() {
- this.route('adminWizardsApi', { path: '/:name', resetNamespace: true });
+ this.route('adminWizardsSubmissionsShow', { path: '/:wizardId/', resetNamespace: true });
+ })
+
+ this.route('adminWizardsApi', { path: '/api', resetNamespace: true }, function() {
+ this.route('adminWizardsApiShow', { path: '/:name', resetNamespace: true });
});
this.route('adminWizardsTransfer', { path: '/transfer', resetNamespace: true });
diff --git a/assets/javascripts/discourse/lib/wizard-mapper.js.es6 b/assets/javascripts/discourse/lib/wizard-mapper.js.es6
index 533d852d..3d3ad034 100644
--- a/assets/javascripts/discourse/lib/wizard-mapper.js.es6
+++ b/assets/javascripts/discourse/lib/wizard-mapper.js.es6
@@ -22,12 +22,6 @@ function inputTypesContent(options = {}) {
mapInputTypes(selectableInputTypes);
}
-function removeMapperClasses(ctx) {
- const $mapper = $(ctx.element).parents('.wizard-mapper');
- $mapper.find('.selector-types').removeClass('show');
- $mapper.find('.mapper-selector').removeClass('active');
-}
-
// Connectors
const connectors = {
@@ -160,7 +154,6 @@ export {
defaultInputType,
defaultSelectionType,
defaultConnector,
- removeMapperClasses,
connectorContent,
inputTypesContent,
selectionTypes,
diff --git a/assets/javascripts/discourse/models/custom-wizard.js.es6 b/assets/javascripts/discourse/models/custom-wizard.js.es6
index 2e1decb4..e65ad169 100644
--- a/assets/javascripts/discourse/models/custom-wizard.js.es6
+++ b/assets/javascripts/discourse/models/custom-wizard.js.es6
@@ -5,19 +5,26 @@ import { schema, listProperties, camelCase, snakeCase } from '../lib/wizard';
import { Promise } from "rsvp";
const CustomWizard = EmberObject.extend({
- save() {
+ save(opts) {
return new Promise((resolve, reject) => {
- let json = this.buildJson(this, 'wizard');
+ let wizard = this.buildJson(this, 'wizard');
- if (json.error) {
- reject({ error: json.error });
+ if (wizard.error) {
+ reject(wizard);
}
- ajax("/admin/wizards/custom/save", {
+ let data = {
+ wizard
+ };
+
+ if (opts.create) {
+ data.create = true;
+ }
+
+ ajax(`/admin/wizards/wizard/${wizard.id}`, {
type: 'PUT',
- data: {
- wizard: JSON.stringify(json)
- }
+ contentType: "application/json",
+ data: JSON.stringify(data)
}).then((result) => {
if (result.error) {
reject(result);
@@ -40,7 +47,7 @@ const CustomWizard = EmberObject.extend({
return result;
}
}
-
+
for (let property of listProperties(type, objectType)) {
let value = object.get(property);
@@ -175,23 +182,18 @@ const CustomWizard = EmberObject.extend({
},
remove() {
- return ajax("/admin/wizards/custom/remove", {
- type: 'DELETE',
- data: {
- id: this.get('id')
- }
+ return ajax(`/admin/wizards/wizard/${this.id}`, {
+ type: 'DELETE'
}).then(() => this.destroy());
}
});
CustomWizard.reopenClass({
all() {
- return ajax("/admin/wizards/custom/all", {
+ return ajax("/admin/wizards/wizard", {
type: 'GET'
}).then(result => {
- return result.wizards.map(wizard => {
- return CustomWizard.create(wizard);
- });
+ return result.wizard_list;
});
},
diff --git a/assets/javascripts/discourse/routes/admin-wizard.js.es6 b/assets/javascripts/discourse/routes/admin-wizard.js.es6
deleted file mode 100644
index 826fbf7b..00000000
--- a/assets/javascripts/discourse/routes/admin-wizard.js.es6
+++ /dev/null
@@ -1,108 +0,0 @@
-import CustomWizard from '../models/custom-wizard';
-import { ajax } from 'discourse/lib/ajax';
-import { selectKitContent, userProperties, generateName } from '../lib/wizard';
-import DiscourseRoute from "discourse/routes/discourse";
-import { all } from "rsvp";
-
-export default DiscourseRoute.extend({
- beforeModel() {
- const param = this.paramsFor('adminWizard').wizard_id;
- const wizards = this.modelFor('admin-wizards-custom');
-
- if (wizards.length && (param === 'first' || param === 'last')) {
- const wizard = wizards.get(`${param}Object`);
- if (wizard) {
- this.transitionTo('adminWizard', wizard.id.dasherize());
- }
- }
- },
-
- model(params) {
- const wizardId = params.wizard_id;
- this.set('newWizard', wizardId === 'new');
-
- if (this.newWizard) {
- return CustomWizard.create();
- } else {
- const wizard = this.modelFor('admin-wizards-custom')
- .findBy('id', wizardId.underscore());
-
- if (!wizard) {
- return this.transitionTo('adminWizard', 'new');
- } else {
- return wizard;
- }
- }
- },
-
- afterModel(model) {
- return all([
- this._getFieldTypes(model),
- this._getThemes(model),
- this._getApis(model),
- this._getUserFields(model)
- ]);
- },
-
- _getFieldTypes(model) {
- return ajax('/admin/wizards/field-types')
- .then((result) => {
- model.set(
- 'fieldTypes',
- selectKitContent([...result.types])
- )
- });
- },
-
- _getThemes(model) {
- return ajax('/admin/themes')
- .then((result) => {
- model.set('themes', result.themes.map(t => {
- return {
- id: t.id,
- name: t.name
- }
- }));
- });
- },
-
- _getApis(model) {
- return ajax('/admin/wizards/apis')
- .then((result) => model.set('apis', result));
- },
-
- _getUserFields(model) {
- return this.store.findAll('user-field').then((result) => {
- if (result && result.content) {
- model.set('userFields',
- result.content.map((f) => ({
- id: `user_field_${f.id}`,
- name: f.name
- })).concat(
- userProperties.map((f) => ({
- id: f,
- name: generateName(f)
- }))
- )
- );
- }
- });
- },
-
- setupController(controller, model) {
- const newWizard = this.get('newWizard');
-
- controller.setProperties({
- newWizard,
- model,
- currentStep: model.steps[0],
- currentAction: model.actions[0]
- });
- },
-
- actions: {
- refreshWizard() {
- this.refresh();
- }
- }
-});
diff --git a/assets/javascripts/discourse/routes/admin-wizards-api-show.js.es6 b/assets/javascripts/discourse/routes/admin-wizards-api-show.js.es6
new file mode 100644
index 00000000..6d710c41
--- /dev/null
+++ b/assets/javascripts/discourse/routes/admin-wizards-api-show.js.es6
@@ -0,0 +1,22 @@
+import CustomWizardApi from '../models/custom-wizard-api';
+import DiscourseRoute from "discourse/routes/discourse";
+
+export default DiscourseRoute.extend({
+ queryParams: {
+ refresh_list: {
+ refreshModel: true
+ }
+ },
+
+ model(params) {
+ if (params.name === 'new') {
+ return CustomWizardApi.create({ isNew: true });
+ } else {
+ return CustomWizardApi.find(params.name);
+ }
+ },
+
+ setupController(controller, model){
+ controller.set("api", model);
+ }
+});
diff --git a/assets/javascripts/discourse/routes/admin-wizards-api.js.es6 b/assets/javascripts/discourse/routes/admin-wizards-api.js.es6
index 6d710c41..62ecd8fe 100644
--- a/assets/javascripts/discourse/routes/admin-wizards-api.js.es6
+++ b/assets/javascripts/discourse/routes/admin-wizards-api.js.es6
@@ -1,22 +1,7 @@
-import CustomWizardApi from '../models/custom-wizard-api';
import DiscourseRoute from "discourse/routes/discourse";
export default DiscourseRoute.extend({
- queryParams: {
- refresh_list: {
- refreshModel: true
- }
- },
-
- model(params) {
- if (params.name === 'new') {
- return CustomWizardApi.create({ isNew: true });
- } else {
- return CustomWizardApi.find(params.name);
- }
- },
-
- setupController(controller, model){
- controller.set("api", model);
+ beforeModel() {
+ this.transitionTo('adminWizardsApiShow');
}
-});
+});
\ No newline at end of file
diff --git a/assets/javascripts/discourse/routes/admin-wizards-apis.js.es6 b/assets/javascripts/discourse/routes/admin-wizards-apis.js.es6
deleted file mode 100644
index 37c594c9..00000000
--- a/assets/javascripts/discourse/routes/admin-wizards-apis.js.es6
+++ /dev/null
@@ -1,32 +0,0 @@
-import CustomWizardApi from '../models/custom-wizard-api';
-import DiscourseRoute from "discourse/routes/discourse";
-
-export default DiscourseRoute.extend({
- model() {
- return CustomWizardApi.list();
- },
-
- afterModel(model) {
- const apiParams = this.paramsFor('admin-wizards-api');
-
- if (model.length) {
- if (!apiParams.name) {
- this.transitionTo('adminWizardsApi', model[0].name.dasherize());
- } else {
- return;
- }
- } else {
- this.transitionTo('adminWizardsApi', 'new');
- }
- },
-
- setupController(controller, model){
- controller.set("model", model);
- },
-
- actions: {
- refreshModel() {
- this.refresh();
- }
- }
-});
diff --git a/assets/javascripts/discourse/routes/admin-wizards-custom.js.es6 b/assets/javascripts/discourse/routes/admin-wizards-custom.js.es6
deleted file mode 100644
index 716b92bb..00000000
--- a/assets/javascripts/discourse/routes/admin-wizards-custom.js.es6
+++ /dev/null
@@ -1,27 +0,0 @@
-import CustomWizard from '../models/custom-wizard';
-import DiscourseRoute from "discourse/routes/discourse";
-
-export default DiscourseRoute.extend({
- model() {
- return CustomWizard.all();
- },
-
- afterModel(model) {
- const transitionToWizard = this.get('transitionToWizard');
- if (transitionToWizard && model.length) {
- this.set('transitionToWizard', null);
- this.transitionTo('adminWizard', transitionToWizard);
- };
- },
-
- setupController(controller, model){
- controller.set("model", model.toArray());
- },
-
- actions: {
- refreshAllWizards() {
- this.set('transitionToWizard', 'last');
- this.refresh();
- }
- }
-});
diff --git a/assets/javascripts/discourse/routes/admin-wizards-index.js.es6 b/assets/javascripts/discourse/routes/admin-wizards-index.js.es6
deleted file mode 100644
index bcfd1251..00000000
--- a/assets/javascripts/discourse/routes/admin-wizards-index.js.es6
+++ /dev/null
@@ -1,7 +0,0 @@
-import DiscourseRoute from "discourse/routes/discourse";
-
-export default DiscourseRoute.extend({
- redirect() {
- this.transitionTo('adminWizardsCustom');
- }
-});
diff --git a/assets/javascripts/discourse/routes/admin-wizards-submissions-index.js.es6 b/assets/javascripts/discourse/routes/admin-wizards-submissions-index.js.es6
deleted file mode 100644
index 6bfca635..00000000
--- a/assets/javascripts/discourse/routes/admin-wizards-submissions-index.js.es6
+++ /dev/null
@@ -1,7 +0,0 @@
-import DiscourseRoute from "discourse/routes/discourse";
-
-export default DiscourseRoute.extend({
- redirect() {
- this.transitionTo('adminWizardSubmissions', 'first');
- }
-});
diff --git a/assets/javascripts/discourse/routes/admin-wizard-submissions.js.es6 b/assets/javascripts/discourse/routes/admin-wizards-submissions-show.js.es6
similarity index 57%
rename from assets/javascripts/discourse/routes/admin-wizard-submissions.js.es6
rename to assets/javascripts/discourse/routes/admin-wizards-submissions-show.js.es6
index b1f6b226..d4818024 100644
--- a/assets/javascripts/discourse/routes/admin-wizard-submissions.js.es6
+++ b/assets/javascripts/discourse/routes/admin-wizards-submissions-show.js.es6
@@ -2,25 +2,8 @@ import CustomWizard from '../models/custom-wizard';
import DiscourseRoute from "discourse/routes/discourse";
export default DiscourseRoute.extend({
- beforeModel() {
- const param = this.paramsFor('adminWizardSubmissions').wizard_id;
- const wizards = this.modelFor('admin-wizards-submissions');
-
- if (wizards.length && (param === 'first')) {
- const wizard = wizards.get(`${param}Object`);
- if (wizard) {
- this.transitionTo('adminWizardSubmissions', wizard.id.dasherize());
- }
- }
- },
-
model(params) {
- const wizardId = params.wizard_id;
- if (wizardId && wizardId !== 'new') {
- return CustomWizard.submissions(params.wizard_id);
- } else {
- return {};
- }
+ return CustomWizard.submissions(params.wizardId);
},
setupController(controller, model) {
@@ -43,8 +26,6 @@ export default DiscourseRoute.extend({
submissions.push(submission);
});
- console.log(model.id)
-
controller.setProperties({
wizard: model.wizard,
submissions,
diff --git a/assets/javascripts/discourse/routes/admin-wizards-submissions.js.es6 b/assets/javascripts/discourse/routes/admin-wizards-submissions.js.es6
index 9dc509fa..6dff576d 100644
--- a/assets/javascripts/discourse/routes/admin-wizards-submissions.js.es6
+++ b/assets/javascripts/discourse/routes/admin-wizards-submissions.js.es6
@@ -1,12 +1,24 @@
-import CustomWizard from '../models/custom-wizard';
import DiscourseRoute from "discourse/routes/discourse";
+import { ajax } from 'discourse/lib/ajax';
export default DiscourseRoute.extend({
model() {
- return CustomWizard.all();
+ return ajax(`/admin/wizards/wizard`);
},
-
- setupController(controller, model){
- controller.set("model", model);
+
+ setupController(controller, model) {
+ const showParams = this.paramsFor('adminWizardsSubmissionsShow');
+
+ controller.setProperties({
+ wizardId: showParams.wizardId,
+ wizardList: model.wizard_list
+ })
+ },
+
+ actions: {
+ changeWizard(wizardId) {
+ this.controllerFor('adminWizardsSubmissions').set('wizardId', wizardId);
+ this.transitionTo('adminWizardsSubmissionsShow', wizardId);
+ }
}
-});
+});
\ No newline at end of file
diff --git a/assets/javascripts/discourse/routes/admin-wizards-wizard-show.js.es6 b/assets/javascripts/discourse/routes/admin-wizards-wizard-show.js.es6
new file mode 100644
index 00000000..22b4c0f3
--- /dev/null
+++ b/assets/javascripts/discourse/routes/admin-wizards-wizard-show.js.es6
@@ -0,0 +1,37 @@
+import CustomWizard from '../models/custom-wizard';
+import { ajax } from 'discourse/lib/ajax';
+import DiscourseRoute from "discourse/routes/discourse";
+import { selectKitContent } from '../lib/wizard';
+
+export default DiscourseRoute.extend({
+ model(params) {
+ if (params.wizardId === 'create') {
+ return { create: true };
+ } else {
+ return ajax(`/admin/wizards/wizard/${params.wizardId}`);
+ }
+ },
+
+ afterModel(model) {
+ if (model.none) {
+ return this.transitionTo('adminWizardsWizard');
+ }
+ },
+
+ setupController(controller, model) {
+ const parentModel = this.modelFor('adminWizardsWizard');
+ const wizard = CustomWizard.create((!model || model.create) ? {} : model);
+
+ controller.setProperties({
+ wizardList: parentModel.wizard_list,
+ fieldTypes: selectKitContent(parentModel.field_types),
+ userFields: parentModel.userFields,
+ apis: parentModel.apis,
+ themes: parentModel.themes,
+ wizard,
+ currentStep: wizard.steps[0],
+ currentAction: wizard.actions[0],
+ creating: model.create
+ });
+ }
+});
diff --git a/assets/javascripts/discourse/routes/admin-wizards-wizard.js.es6 b/assets/javascripts/discourse/routes/admin-wizards-wizard.js.es6
new file mode 100644
index 00000000..5b2c88e3
--- /dev/null
+++ b/assets/javascripts/discourse/routes/admin-wizards-wizard.js.es6
@@ -0,0 +1,92 @@
+import DiscourseRoute from "discourse/routes/discourse";
+import { userProperties, generateName } from '../lib/wizard';
+import { set } from "@ember/object";
+import { all } from "rsvp";
+import { ajax } from 'discourse/lib/ajax';
+
+export default DiscourseRoute.extend({
+ model() {
+ return ajax(`/admin/wizards/wizard`);
+ },
+
+ afterModel(model) {
+ return all([
+ this._getThemes(model),
+ this._getApis(model),
+ this._getUserFields(model)
+ ]);
+ },
+
+ _getThemes(model) {
+ return ajax('/admin/themes')
+ .then((result) => {
+ set(model, 'themes', result.themes.map(t => {
+ return {
+ id: t.id,
+ name: t.name
+ }
+ }));
+ });
+ },
+
+ _getApis(model) {
+ return ajax('/admin/wizards/apis')
+ .then((result) => set(model, 'apis', result));
+ },
+
+ _getUserFields(model) {
+ return this.store.findAll('user-field').then((result) => {
+ if (result && result.content) {
+ set(model, 'userFields',
+ result.content.map((f) => ({
+ id: `user_field_${f.id}`,
+ name: f.name
+ })).concat(
+ userProperties.map((f) => ({
+ id: f,
+ name: generateName(f)
+ }))
+ )
+ );
+ }
+ });
+ },
+
+ setupController(controller, model) {
+ let props = {
+ wizardList: model.wizard_list
+ }
+
+ const params = this.paramsFor('adminWizardsWizardShow');
+ if (params && params.wizardId) {
+ props.wizardId = params.wizardId;
+ }
+
+ controller.setProperties(props);
+ },
+
+ actions: {
+ changeWizard(wizardId) {
+ this.controllerFor('adminWizardsWizard').set('wizardId', wizardId);
+
+ if (wizardId) {
+ this.transitionTo('adminWizardsWizardShow', wizardId);
+ } else {
+ this.transitionTo('adminWizardsWizard');
+ }
+ },
+
+ afterDestroy() {
+ this.transitionTo('adminWizardsWizard').then(() => this.refresh());
+ },
+
+ afterSave(wizardId) {
+ this.refresh().then(() => this.send('changeWizard', wizardId));
+ },
+
+ createWizard() {
+ this.controllerFor('adminWizardsWizard').set('wizardId', 'create');
+ this.transitionTo('adminWizardsWizardShow', 'create');
+ }
+ }
+});
\ No newline at end of file
diff --git a/assets/javascripts/discourse/routes/admin-wizards.js.es6 b/assets/javascripts/discourse/routes/admin-wizards.js.es6
new file mode 100644
index 00000000..7647207a
--- /dev/null
+++ b/assets/javascripts/discourse/routes/admin-wizards.js.es6
@@ -0,0 +1,9 @@
+import DiscourseRoute from "discourse/routes/discourse";
+
+export default DiscourseRoute.extend({
+ beforeModel(transition) {
+ if (transition.targetName === "adminWizards.index") {
+ this.transitionTo('adminWizardsWizard');
+ }
+ },
+});
\ No newline at end of file
diff --git a/assets/javascripts/discourse/templates/admin-wizard-submissions.hbs b/assets/javascripts/discourse/templates/admin-wizard-submissions.hbs
deleted file mode 100644
index 1265db8a..00000000
--- a/assets/javascripts/discourse/templates/admin-wizard-submissions.hbs
+++ /dev/null
@@ -1,27 +0,0 @@
-
-
-
-
-
- {{#each fields as |f|}}
- {{f}} |
- {{/each}}
-
- {{#each submissions as |s|}}
-
- {{#each-in s as |k v|}}
- {{v}} |
- {{/each-in}}
-
- {{/each}}
-
-
diff --git a/assets/javascripts/discourse/templates/admin-wizards-api.hbs b/assets/javascripts/discourse/templates/admin-wizards-api-show.hbs
similarity index 100%
rename from assets/javascripts/discourse/templates/admin-wizards-api.hbs
rename to assets/javascripts/discourse/templates/admin-wizards-api-show.hbs
diff --git a/assets/javascripts/discourse/templates/admin-wizards-apis.hbs b/assets/javascripts/discourse/templates/admin-wizards-apis.hbs
deleted file mode 100644
index c5f67660..00000000
--- a/assets/javascripts/discourse/templates/admin-wizards-apis.hbs
+++ /dev/null
@@ -1,26 +0,0 @@
-
-
-
- {{#each model as |api|}}
- -
- {{#link-to "adminWizardsApi" (dasherize api.name)}}
- {{#if api.title}}
- {{api.title}}
- {{else}}
- {{api.name}}
- {{/if}}
- {{/link-to}}
-
- {{/each}}
-
-
- {{#link-to 'adminWizardsApi' 'new' class="btn"}}
- {{d-icon "plus"}} {{i18n 'admin.wizard.api.new'}}
- {{/link-to}}
-
-
-
-
- {{outlet}}
-
-
diff --git a/assets/javascripts/discourse/templates/admin-wizards-custom-index.hbs b/assets/javascripts/discourse/templates/admin-wizards-custom-index.hbs
deleted file mode 100644
index e9c27e0b..00000000
--- a/assets/javascripts/discourse/templates/admin-wizards-custom-index.hbs
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/assets/javascripts/discourse/templates/admin-wizards-custom.hbs b/assets/javascripts/discourse/templates/admin-wizards-custom.hbs
deleted file mode 100644
index 06056ee2..00000000
--- a/assets/javascripts/discourse/templates/admin-wizards-custom.hbs
+++ /dev/null
@@ -1,20 +0,0 @@
-
-
-
- {{#each model as |w|}}
- -
- {{#link-to "adminWizard" (dasherize w.id)}}{{w.name}}{{/link-to}}
-
- {{/each}}
-
-
- {{#link-to 'adminWizard' 'new' class="btn"}}
- {{d-icon "plus"}} {{i18n 'admin.wizard.new'}}
- {{/link-to}}
-
-
-
-
- {{outlet}}
-
-
diff --git a/assets/javascripts/discourse/templates/admin-wizards-submissions-show.hbs b/assets/javascripts/discourse/templates/admin-wizards-submissions-show.hbs
new file mode 100644
index 00000000..3b4cb401
--- /dev/null
+++ b/assets/javascripts/discourse/templates/admin-wizards-submissions-show.hbs
@@ -0,0 +1,29 @@
+{{#if submissions}}
+
+
+
+
+
+ {{#each fields as |f|}}
+ {{f}} |
+ {{/each}}
+
+ {{#each submissions as |s|}}
+
+ {{#each-in s as |k v|}}
+ {{v}} |
+ {{/each-in}}
+
+ {{/each}}
+
+
+{{/if}}
diff --git a/assets/javascripts/discourse/templates/admin-wizards-submissions.hbs b/assets/javascripts/discourse/templates/admin-wizards-submissions.hbs
index 1637b6bf..ca0b835e 100644
--- a/assets/javascripts/discourse/templates/admin-wizards-submissions.hbs
+++ b/assets/javascripts/discourse/templates/admin-wizards-submissions.hbs
@@ -1,15 +1,13 @@
-
-
-
- {{#each model as |w|}}
- -
- {{#link-to "adminWizardSubmissions" w.id}}{{w.name}}{{/link-to}}
-
- {{/each}}
-
-
-
-
- {{outlet}}
-
+
+ {{combo-box
+ value=wizardId
+ content=wizardList
+ onChange=(route-action 'changeWizard')
+ options=(hash
+ none='admin.wizard.select'
+ )}}
+
+
+
+ {{outlet}}
diff --git a/assets/javascripts/discourse/templates/admin-wizard.hbs b/assets/javascripts/discourse/templates/admin-wizards-wizard-show.hbs
similarity index 83%
rename from assets/javascripts/discourse/templates/admin-wizard.hbs
rename to assets/javascripts/discourse/templates/admin-wizards-wizard-show.hbs
index c89eac36..e0d511c1 100644
--- a/assets/javascripts/discourse/templates/admin-wizard.hbs
+++ b/assets/javascripts/discourse/templates/admin-wizards-wizard-show.hbs
@@ -1,22 +1,22 @@
-
+{{#if wizard}}
-
+
@@ -25,7 +25,7 @@
{{input
name="background"
- value=model.background
+ value=wizard.background
placeholderKey="admin.wizard.background_placeholder"
class="small"}}
@@ -37,28 +37,28 @@
{{combo-box
- content=model.themes
+ content=themes
valueProperty='id'
- value=model.theme_id
- onChange=(action (mut model.theme_id))
+ value=wizard.theme_id
+ onChange=(action (mut wizard.theme_id))
options=(hash
none='admin.wizard.no_theme'
)}}
-
+
-
+
- {{input type='checkbox' checked=model.required}}
+ {{input type='checkbox' checked=wizard.required}}
{{i18n 'admin.wizard.required_label'}}
@@ -68,7 +68,7 @@
- {{input type='checkbox' checked=model.after_signup}}
+ {{input type='checkbox' checked=wizard.after_signup}}
{{i18n 'admin.wizard.after_signup_label'}}
@@ -78,7 +78,7 @@
- {{input type='checkbox' checked=model.multiple_submissions}}
+ {{input type='checkbox' checked=wizard.multiple_submissions}}
{{i18n 'admin.wizard.multiple_submissions_label'}}
@@ -88,7 +88,7 @@
- {{input type='checkbox' checked=model.prompt_completion}}
+ {{input type='checkbox' checked=wizard.prompt_completion}}
{{i18n 'admin.wizard.prompt_completion_label'}}
@@ -98,7 +98,7 @@
- {{input type='checkbox' checked=model.after_time}}
+ {{input type='checkbox' checked=wizard.after_time}}
{{i18n 'admin.wizard.after_time_label'}}
{{d-button
action='setNextSessionScheduled'
@@ -114,7 +114,7 @@
{{wizard-mapper
- inputs=model.permitted
+ inputs=wizard.permitted
options=(hash
context='wizard'
inputTypes='assignment,validation'
@@ -126,9 +126,9 @@
- {{wizard-advanced-toggle showAdvanced=model.showAdvanced}}
+ {{wizard-advanced-toggle showAdvanced=wizard.showAdvanced}}
- {{#if model.showAdvanced}}
+ {{#if wizard.showAdvanced}}
@@ -136,7 +136,7 @@
- {{input type='checkbox' checked=model.save_submissions}}
+ {{input type='checkbox' checked=wizard.save_submissions}}
{{i18n 'admin.wizard.save_submissions_label'}}
@@ -146,7 +146,7 @@
- {{input type='checkbox' checked=model.restart_on_revisit}}
+ {{input type='checkbox' checked=wizard.restart_on_revisit}}
{{i18n 'admin.wizard.restart_on_revisit_label'}}
@@ -158,26 +158,27 @@
{{wizard-links
itemType="step"
current=currentStep
- items=model.steps}}
-
+ items=wizard.steps}}
+
{{#if currentStep}}
{{wizard-custom-step
step=currentStep
- wizard=model
+ wizard=wizard
currentField=currentField
- wizardFields=wizardFields}}
+ wizardFields=wizardFields
+ fieldTypes=fieldTypes}}
{{/if}}
-
+
{{wizard-links
itemType="action"
current=currentAction
- items=model.actions
+ items=wizard.actions
generateLabels=true}}
{{#if currentAction}}
{{wizard-custom-action
action=currentAction
- wizard=model
+ wizard=wizard
removeAction="removeAction"
wizardFields=wizardFields}}
{{/if}}
@@ -187,7 +188,7 @@
{{i18n 'admin.wizard.save'}}
- {{#unless newWizard}}
+ {{#unless creating}}
@@ -199,4 +200,4 @@
{{d-icon "times"}}{{error}}
{{/if}}
-
+{{/if}}
diff --git a/assets/javascripts/discourse/templates/admin-wizards-wizard.hbs b/assets/javascripts/discourse/templates/admin-wizards-wizard.hbs
new file mode 100644
index 00000000..08c33fbf
--- /dev/null
+++ b/assets/javascripts/discourse/templates/admin-wizards-wizard.hbs
@@ -0,0 +1,32 @@
+
+ {{combo-box
+ value=wizardListVal
+ content=wizardList
+ onChange=(route-action 'changeWizard')
+ options=(hash
+ none='admin.wizard.select'
+ )}}
+
+ {{d-button
+ action="createWizard"
+ label="admin.wizard.create"
+ icon="plus"}}
+
+
+
+
+ {{d-icon 'info-circle'}}
+ {{message}}
+
+
+
+
+
+
+ {{outlet}}
+
\ No newline at end of file
diff --git a/assets/javascripts/discourse/templates/admin-wizards.hbs b/assets/javascripts/discourse/templates/admin-wizards.hbs
index 578e4380..102ffcde 100644
--- a/assets/javascripts/discourse/templates/admin-wizards.hbs
+++ b/assets/javascripts/discourse/templates/admin-wizards.hbs
@@ -1,5 +1,5 @@
{{#admin-nav}}
- {{nav-item route='adminWizardsCustom' label='admin.wizard.nav_label'}}
+ {{nav-item route='adminWizardsWizard' label='admin.wizard.nav_label'}}
{{nav-item route='adminWizardsSubmissions' label='admin.wizard.submissions.nav_label'}}
{{#if siteSettings.wizard_api_features}}
{{nav-item route='adminWizardsApis' label='admin.wizard.api.nav_label'}}
@@ -7,6 +7,6 @@
{{nav-item route='adminWizardsTransfer' label='admin.wizard.transfer.nav_label'}}
{{/admin-nav}}
-
+
{{outlet}}
diff --git a/assets/javascripts/discourse/templates/components/wizard-custom-field.hbs b/assets/javascripts/discourse/templates/components/wizard-custom-field.hbs
index b2ba27e9..016100b5 100644
--- a/assets/javascripts/discourse/templates/components/wizard-custom-field.hbs
+++ b/assets/javascripts/discourse/templates/components/wizard-custom-field.hbs
@@ -64,7 +64,11 @@
- {{input type="number" name="min_length" value=field.min_length}}
+ {{input
+ type="number"
+ name="min_length"
+ value=field.min_length
+ class="small"}}
{{/if}}
@@ -88,7 +92,7 @@
- {{input type="number" value=field.limit}}
+ {{input type="number" value=field.limit class="small"}}
{{/if}}
@@ -148,8 +152,12 @@
-
- {{input name="key" value=field.key placeholderKey="admin.wizard.translation_placeholder"}}
+
+ {{input
+ name="key"
+ value=field.key
+ class="small"
+ placeholderKey="admin.wizard.translation_placeholder"}}
diff --git a/assets/javascripts/discourse/templates/components/wizard-custom-step.hbs b/assets/javascripts/discourse/templates/components/wizard-custom-step.hbs
index 6752f6af..c2f0b073 100644
--- a/assets/javascripts/discourse/templates/components/wizard-custom-step.hbs
+++ b/assets/javascripts/discourse/templates/components/wizard-custom-step.hbs
@@ -104,7 +104,7 @@
{{#if currentField}}
{{wizard-custom-field
field=currentField
- fieldTypes=wizard.fieldTypes
+ fieldTypes=fieldTypes
removeField="removeField"
wizardFields=wizardFields}}
{{/if}}
\ No newline at end of file
diff --git a/assets/javascripts/discourse/templates/components/wizard-export.hbs b/assets/javascripts/discourse/templates/components/wizard-export.hbs
index 6f4e0c33..9bbfabcf 100644
--- a/assets/javascripts/discourse/templates/components/wizard-export.hbs
+++ b/assets/javascripts/discourse/templates/components/wizard-export.hbs
@@ -8,7 +8,7 @@
id=(dasherize w.id)
change=(action 'checkChanged')}}
- {{#link-to "adminWizard" (dasherize w.id)}}
+ {{#link-to "adminWizardsWizardShow" (dasherize w.id)}}
{{w.name}}
{{/link-to}}
diff --git a/assets/javascripts/discourse/templates/components/wizard-mapper-connector.hbs b/assets/javascripts/discourse/templates/components/wizard-mapper-connector.hbs
index ea1a365d..9ac7ddfe 100644
--- a/assets/javascripts/discourse/templates/components/wizard-mapper-connector.hbs
+++ b/assets/javascripts/discourse/templates/components/wizard-mapper-connector.hbs
@@ -2,8 +2,7 @@
{{combo-box
value=connector
content=connectors
- onChange=(action (mut connector))
- onOpen=(action "onOpen")}}
+ onChange=(action (mut connector))}}
{{else}}
{{connectorLabel}}
diff --git a/assets/javascripts/discourse/templates/components/wizard-mapper-selector.hbs b/assets/javascripts/discourse/templates/components/wizard-mapper-selector.hbs
index dd4e06df..b0c0d8fd 100644
--- a/assets/javascripts/discourse/templates/components/wizard-mapper-selector.hbs
+++ b/assets/javascripts/discourse/templates/components/wizard-mapper-selector.hbs
@@ -1,17 +1,19 @@
{{#if hasTypes}}
-
+
{{activeTypeLabel}}
-
- {{#each selectorTypes as |item|}}
- {{wizard-mapper-selector-type
- activeType=activeType
- item=item
- toggle=(action 'toggleType')}}
- {{/each}}
-
+ {{#if showTypes}}
+
+ {{#each selectorTypes as |item|}}
+ {{wizard-mapper-selector-type
+ activeType=activeType
+ item=item
+ toggle=(action 'toggleType')}}
+ {{/each}}
+
+ {{/if}}
{{else}}
{{activeTypeLabel}}
{{/if}}
@@ -22,7 +24,6 @@
{{input
type="text"
value=value
- click=(action 'enableActive')
placeholder=(i18n placeholderKey)}}
{{/if}}
@@ -31,8 +32,6 @@
value=value
content=comboBoxContent
onChange=(action (mut value))
- onOpen=(action "enableActive")
- onClick=(action 'enableActive')
options=(hash
none=placeholderKey
)}}
@@ -43,8 +42,6 @@
content=multiSelectContent
value=value
onChange=(action (mut value))
- onOpen=(action "enableActive")
- onClose=(action "disableActive")
options=multiSelectOptions}}
{{/if}}
@@ -58,8 +55,6 @@
{{tag-chooser
tags=value
filterable=true
- onOpen=(action "enableActive")
- onClose=(action "disableActive")
options=(hash
none=placeholderKey
)}}
@@ -70,7 +65,6 @@
includeMessageableGroups='true'
placeholderKey=placeholderKey
usernames=value
- autocomplete="discourse"
- click=(action "enableActive")}}
+ autocomplete="discourse"}}
{{/if}}
\ No newline at end of file
diff --git a/assets/javascripts/wizard-custom.js b/assets/javascripts/wizard-custom.js
index 0bb16dba..d67fa1b9 100644
--- a/assets/javascripts/wizard-custom.js
+++ b/assets/javascripts/wizard-custom.js
@@ -92,6 +92,7 @@
//= require discourse/templates/components/d-button
//= require discourse/templates/components/d-editor
//= require discourse/templates/components/emoji-picker
+//= require discourse/templates/components/popup-input-tip
//= require discourse/templates/category-tag-autocomplete
//= require discourse/templates/emoji-selector-autocomplete
//= require discourse/templates/user-selector-autocomplete
@@ -107,7 +108,6 @@
//= require preload-store
//= require lodash.js
//= require mousetrap.js
-//= require jquery.putcursoratend.js
//= require template_include.js
//= require caret_position.js
//= require popper.js
diff --git a/assets/javascripts/wizard/models/custom.js.es6 b/assets/javascripts/wizard/models/custom.js.es6
index 9477e813..1a78b4c4 100644
--- a/assets/javascripts/wizard/models/custom.js.es6
+++ b/assets/javascripts/wizard/models/custom.js.es6
@@ -50,7 +50,7 @@ export function findCustomWizard(wizardId, params = {}) {
}
return ajax({ url, cache: false, dataType: 'json' }).then(result => {
- const wizard = result.custom_wizard;
+ const wizard = result;
if (!wizard) return null;
if (!wizard.completed) {
diff --git a/assets/stylesheets/common/wizard-admin.scss b/assets/stylesheets/common/wizard-admin.scss
index 9794fba7..e4b25e12 100644
--- a/assets/stylesheets/common/wizard-admin.scss
+++ b/assets/stylesheets/common/wizard-admin.scss
@@ -2,35 +2,30 @@
@import 'wizard-transfer';
@import 'wizard-api';
+.admin-wizard-controls {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ margin-bottom: 20px;
+}
+
+.admin-wizard-message {
+ background-color: $primary-low;
+ padding: 10px;
+ display: flex;
+ justify-content: space-between;
+}
+
.admin-wizard-container {
- .row {
- display: flex;
-
- > .content {
- flex: 1;
- margin-top: 10px;
- margin-left: 30px;
-
- table {
- margin-top: 0;
- min-width: 100%;
- width: auto;
- }
- }
+ margin-top: 20px;
+
+ .row > .content table {
+ margin-top: 0;
+ min-width: 100%;
+ width: auto;
}
}
-.wizard-submissions {
- overflow: scroll;
-}
-
-.wizard-list {
- width: 250px;
- min-width: 250px;
- margin-top: 10px;
- float: none;
-}
-
.wizard-settings-parent {
margin-bottom: 30px;
padding: 20px;
@@ -65,25 +60,7 @@
padding: 20px;
}
-// style workdarounds for wizard_step_advanced site setting - to be refactored
-
-.wizard-custom-step .wizard-advanced-toggle + .wizard-links.field,
-.wizard-custom-step .advanced-settings + .wizard-links.field,
-.wizard-links.action {
- margin-top: 40px;
-}
-
-.wizard-links.field {
- margin-top: 20px;
-}
-
-// end workdarounds //
-
-.wizard-settings > .advanced-settings > div.setting {
- margin-bottom: 0;
-}
-
-.admin-wizard.settings .wizard-basic-details {
+.admin-wizard-container.settings .wizard-basic-details {
justify-content: initial;
.setting {
@@ -97,23 +74,20 @@
}
}
-.new-wizard {
- margin-top: 15px;
-}
-
.wizard-header {
margin-bottom: 20px;
&.large {
font-size: 1.5em;
min-height: 31px;
- margin-bottom: 30px;
+ margin-bottom: 20px;
display: flex;
justify-content: space-between;
+ align-items: flex-start;
input {
margin-bottom: 0;
- width: 350px;
+ width: 400px;
}
label {
@@ -124,6 +98,22 @@
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;
+ }
+ }
}
&.medium {
@@ -138,28 +128,13 @@
&.underline {
text-decoration: underline;
}
-
- .wizard-url {
- display: inline-flex;
- margin-left: 20px;
-
- a {
- padding: 6px 12px;
- font-size: 1rem;
- background-color: $primary-low;
- }
-
- button {
- font-size: 1rem;
- }
- }
}
.admin-wizard-buttons {
margin-top: 20px;
}
-.admin-wizard.settings {
+.admin-wizard-container.settings {
[class~='setting'] {
display: inline-flex;
@@ -208,15 +183,14 @@
cursor: not-allowed;
}
- input[type="number"] {
- width: 70px;
- margin-bottom: 0;
- }
-
input.medium {
width: 200px;
}
+ input.small {
+ width: 100px;
+ }
+
.uploaded-image-preview {
width: 100%;
max-height: 100px;
@@ -239,6 +213,11 @@
float: left;
margin: 5px 7px 0 0;
}
+
+ .input .select-kit, > .select-kit {
+ max-width: 250px !important;
+ min-width: 250px !important;
+ }
}
&.full, &.full-inline {
@@ -255,7 +234,7 @@
}
.uploaded-image-preview {
- max-height: 170px;
+ max-height: 200px;
}
}
}
@@ -293,7 +272,7 @@
}
}
- .wizard-custom-action > [class~='setting']:last-of-type {
+ .wizard-custom-action > [class~='setting']:first-of-type {
margin-bottom: 0;
}
@@ -328,7 +307,7 @@
width: 100%;
.d-editor-input {
- min-height: 130px;
+ min-height: 150px;
}
.d-editor-container {
diff --git a/assets/stylesheets/common/wizard-mapper.scss b/assets/stylesheets/common/wizard-mapper.scss
index 2903aeb6..97f8b2aa 100644
--- a/assets/stylesheets/common/wizard-mapper.scss
+++ b/assets/stylesheets/common/wizard-mapper.scss
@@ -100,41 +100,16 @@
}
}
-.mapper-input.assignment,
-.mapper-input.validation,
-.mapper-input.association {
- .mapper-selector {
- max-width: 250px;
- min-width: 250px;
-
- > input, .select-kit, .ac-wrap, .autocomplete.ac-user {
- width: 250px !important;
- }
- }
-}
-
-.mapper-input.conditional {
- .mapper-selector {
- max-width: 170px;
- min-width: 170px;
-
- &:not(.text).active .input {
- width: 250px;
- box-shadow: 0 2px 3px 0 rgba(0, 0, 0, 0.2);
- position: absolute;
- z-index: 300;
-
- .select-kit, .ac-wrap, .autocomplete.ac-user, .select-kit-wrapper {
- width: 250px !important;
- }
- }
- }
-}
-
.mapper-selector {
width: 100%;
+ max-width: 250px;
+ min-width: 250px;
position: relative;
+ > input, .select-kit, .ac-wrap, .autocomplete.ac-user {
+ width: 250px !important;
+ }
+
.input {
width: 100%;
transition: all 0.1s;
@@ -170,16 +145,12 @@
.selector-types {
box-shadow: shadow('dropdown');
position: absolute;
- display: none;
+ display: flex;
background: $secondary;
z-index: 200;
padding: 5px 7px;
flex-direction: column;
border: 1px solid $primary-low;
-
- &.show {
- display: flex;
- }
}
.value-list .remove-value-btn {
diff --git a/config/locales/client.en.yml b/config/locales/client.en.yml
index 4214e5a7..b3e729b8 100644
--- a/config/locales/client.en.yml
+++ b/config/locales/client.en.yml
@@ -8,11 +8,12 @@ en:
wizard:
label: "Wizard"
nav_label: "Wizards"
- new: "New"
+ select: "Select a wizard"
+ create: "Create Wizard"
name: "Name"
name_placeholder: "wizard name"
background: "Background"
- background_placeholder: "#hex"
+ background_placeholder: "color"
save_submissions: "Save"
save_submissions_label: "Save wizard submissions."
multiple_submissions: "Multiple"
@@ -53,6 +54,12 @@ en:
permitted: "Permitted"
advanced: "Advanced"
+ message:
+ select: "Select a wizard, or create a new one"
+ edit: "You're editing a wizard"
+ create: "You're creating a new wizard"
+ help: "Stuck? Check out the documentation"
+
editor:
show: "Show"
hide: "Hide"
@@ -97,6 +104,7 @@ en:
required: "{{type}} requires {{property}}"
invalid: "{{property}} is invalid"
dependent: "{{property}} is dependent on {{dependent}}"
+ conflict: "{{type}} with {{property}} '{{value}}' already exists"
step:
header: "Steps"
diff --git a/config/routes.rb b/config/routes.rb
index b586e55b..539d8b92 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -12,25 +12,26 @@ Discourse::Application.routes.append do
scope module: 'custom_wizard', constraints: AdminConstraint.new do
get 'admin/wizards' => 'admin#index'
- get 'admin/wizards/field-types' => 'admin#field_types'
- get 'admin/wizards/custom' => 'admin#index'
- get 'admin/wizards/custom/new' => 'admin#index'
- get 'admin/wizards/custom/all' => 'admin#custom_wizards'
- get 'admin/wizards/custom/:wizard_id' => 'admin#find_wizard'
- get 'admin/wizards/custom/:wizard_id' => 'admin#find_wizard'
- put 'admin/wizards/custom/save' => 'admin#save'
- delete 'admin/wizards/custom/remove' => 'admin#remove'
- get 'admin/wizards/submissions' => 'admin#index'
- get 'admin/wizards/submissions/:wizard_id' => 'admin#submissions'
- get 'admin/wizards/submissions/:wizard_id/download' => 'admin#download_submissions'
- get 'admin/wizards/apis' => 'api#list'
- get 'admin/wizards/apis/new' => 'api#index'
- get 'admin/wizards/apis/:name' => 'api#find'
- put 'admin/wizards/apis/:name' => 'api#save'
- delete 'admin/wizards/apis/:name' => 'api#remove'
- delete 'admin/wizards/apis/logs/:name' => 'api#clearlogs'
- get 'admin/wizards/apis/:name/redirect' => 'api#redirect'
- get 'admin/wizards/apis/:name/authorize' => 'api#authorize'
+
+ get 'admin/wizards/wizard' => 'admin_wizard#index'
+ get 'admin/wizards/wizard/create' => 'admin#index'
+ get 'admin/wizards/wizard/:wizard_id' => 'admin_wizard#show'
+ put 'admin/wizards/wizard/:wizard_id' => 'admin_wizard#save'
+ delete 'admin/wizards/wizard/:wizard_id' => 'admin_wizard#remove'
+
+ get 'admin/wizards/submissions' => 'admin_submissions#index'
+ get 'admin/wizards/submissions/:wizard_id' => 'admin_submissions#show'
+ get 'admin/wizards/submissions/:wizard_id/download' => 'admin_submissions#download'
+
+ get 'admin/wizards/apis' => 'admin_api#list'
+ get 'admin/wizards/apis/new' => 'admin_api#index'
+ get 'admin/wizards/apis/:name' => 'admin_api#find'
+ put 'admin/wizards/apis/:name' => 'admin_api#save'
+ delete 'admin/wizards/apis/:name' => 'admin_api#remove'
+ delete 'admin/wizards/apis/logs/:name' => 'admin_api#clearlogs'
+ get 'admin/wizards/apis/:name/redirect' => 'admin_api#redirect'
+ get 'admin/wizards/apis/:name/authorize' => 'admin_api#authorize'
+
get 'admin/wizards/transfer' => 'transfer#index'
get 'admin/wizards/transfer/export' => 'transfer#export'
post 'admin/wizards/transfer/import' => 'transfer#import'
diff --git a/controllers/custom_wizard/admin.rb b/controllers/custom_wizard/admin.rb
deleted file mode 100644
index 01df5167..00000000
--- a/controllers/custom_wizard/admin.rb
+++ /dev/null
@@ -1,271 +0,0 @@
-class CustomWizard::AdminController < ::Admin::AdminController
- skip_before_action :check_xhr, only: [:download_submissions]
- before_action :ensure_admin
-
- def index
- render nothing: true
- end
-
- def field_types
- render json: { types: CustomWizard::Field.types }
- end
-
- def save
- result = build_wizard
-
- if result[:error]
- render json: { error: result[:error] }
- else
- wizard = result[:wizard]
- existing_wizard = result[:existing_wizard]
- after_time = result[:after_time]
-
- ActiveRecord::Base.transaction do
- PluginStore.set('custom_wizard', wizard["id"], wizard)
-
- if after_time[:enabled]
- Jobs.cancel_scheduled_job(:set_after_time_wizard, wizard_id: wizard['id'])
- Jobs.enqueue_at(after_time[:scheduled], :set_after_time_wizard, wizard_id: wizard['id'])
- end
-
- if existing_wizard && existing_wizard['after_time'] && !after_time[:enabled]
- Jobs.cancel_scheduled_job(:set_after_time_wizard, wizard_id: wizard['id'])
- Jobs.enqueue(:clear_after_time_wizard, wizard_id: wizard['id'])
- end
- end
-
- render json: success_json.merge(wizard: wizard)
- end
- end
-
- def remove
- params.require(:id)
-
- wizard = PluginStore.get('custom_wizard', params[:id])
-
- if wizard['after_time']
- Jobs.cancel_scheduled_job(:set_after_time_wizard)
- Jobs.enqueue(:clear_after_time_wizard, wizard_id: wizard['id'])
- end
-
- PluginStore.remove('custom_wizard', params[:id])
-
- render json: success_json
- end
-
- def find_wizard
- params.require(:wizard_id)
- wizard = PluginStore.get('custom_wizard', params[:wizard_id].underscore)
- render json: success_json.merge(wizard: wizard)
- end
-
- def custom_wizards
- rows = PluginStoreRow.where(plugin_name: 'custom_wizard').order(:id)
- wizards = [*rows].map { |r| CustomWizard::Template.new(r.value) }
- render json: success_json.merge(wizards: wizards)
- end
-
- def submissions
- params.require(:wizard_id)
-
- wizard_id = params[:wizard_id].underscore
- wizard = PluginStore.get('custom_wizard', wizard_id)
-
- if wizard.present?
- render json: success_json.merge(
- submissions: build_submissions(wizard_id),
- wizard: wizard.slice(:id, :name)
- )
- else
- head :ok
- end
- end
-
- def download_submissions
- params.require(:wizard_id)
- wizard_id = params[:wizard_id].underscore
-
- wizard = PluginStore.get('custom_wizard', wizard_id)
- submissions = build_submissions(wizard_id).to_json
-
- send_data submissions,
- filename: "#{Discourse.current_hostname}-wizard-submissions-#{wizard['name']}.json",
- content_type: "application/json"
- end
-
- private
-
- def wizard_params
- params.require(:wizard)
- params[:wizard]
- end
-
- def required_properties
- {
- wizard: ['id', 'name', 'steps'],
- step: ['id'],
- field: ['id', 'type'],
- action: ['id', 'type']
- }
- end
-
- def dependent_properties
- {
- wizard: {
- after_time: 'after_time_scheduled'
- },
- step: {},
- field: {},
- action: {}
- }
- end
-
- def check_required(object, type, error)
- required_properties[type].each do |property|
- if object[property].blank?
- error = {
- type: 'required',
- params: { type: type, property: property }
- }
- end
- end
-
- error
- end
-
- def check_depdendent(object, type, error)
- dependent_properties[type].each do |property, dependent|
- if object[property] && object[dependent].blank?
- error = {
- type: 'dependent',
- params: { property: property, dependent: dependent }
- }
- end
- end
-
- error
- end
-
- def validate_wizard(wizard)
- error = nil
-
- error = check_required(wizard, :wizard, error)
- error = check_depdendent(wizard, :wizard, error)
-
- if !error
- wizard['steps'].each do |step|
- error = check_required(step, :step, error)
- error = check_depdendent(step, :step, error)
- break if error.present?
-
- if step['fields'].present?
- step['fields'].each do |field|
- error = check_required(field, :field, error)
- error = check_depdendent(field, :field, error)
- break if error.present?
- end
- end
- end
-
- if wizard['actions'].present?
- wizard['actions'].each do |action|
- error = check_required(action, :action, error)
- error = check_depdendent(action, :action, error)
- break if error.present?
- end
- end
- end
-
- if error
- { error: error }
- else
- { success: true }
- end
- end
-
- def validate_after_time(wizard, existing_wizard)
- new = false
- error = nil
- enabled = false
- scheduled = nil
-
- if wizard["after_time"]
- enabled = true
-
- if !wizard["after_time_scheduled"] && !existing_wizard["after_time_scheduled"]
- error = 'after_time_need_time'
- else
- scheduled = Time.parse(wizard["after_time_scheduled"]).utc
- new = false
-
- if existing_wizard['after_time_scheduled']
- new = scheduled != Time.parse(existing_wizard['after_time_scheduled']).utc
- end
-
- begin
- error = 'after_time_invalid' if new && scheduled < Time.now.utc
- rescue ArgumentError
- error = 'after_time_invalid'
- end
- end
- end
-
- if error
- { error: { type: error } }
- else
- {
- new: new,
- scheduled: scheduled,
- enabled: enabled
- }
- end
- end
-
- def build_wizard
- wizard = ::JSON.parse(wizard_params)
- existing_wizard = PluginStore.get('custom_wizard', wizard['id']) || {}
-
- validation = validate_wizard(wizard)
- return validation if validation[:error]
-
- after_time = validate_after_time(wizard, existing_wizard)
- return after_time if after_time[:error]
-
- wizard['steps'].each do |step|
- if step['raw_description']
- step['description'] = PrettyText.cook(step['raw_description'])
- end
- end
-
- result = {
- wizard: wizard,
- existing_wizard: existing_wizard
- }
-
- if after_time[:enabled]
- result[:after_time] = after_time
- end
-
- result
- end
-
- def build_submissions(wizard_id)
- rows = PluginStoreRow.where(plugin_name: "#{wizard_id}_submissions").order('id DESC')
-
- submissions = [*rows].map do |row|
- value = ::JSON.parse(row.value)
-
- if user = User.find_by(id: row.key)
- username = user.username
- else
- username = I18n.t('admin.wizard.submissions.no_user', id: row.key)
- end
-
- value.map do |submission|
- {
- username: username
- }.merge!(submission.except("redirect_to"))
- end
- end.flatten
- end
-end
diff --git a/controllers/custom_wizard/admin/admin.rb b/controllers/custom_wizard/admin/admin.rb
new file mode 100644
index 00000000..2dd87e86
--- /dev/null
+++ b/controllers/custom_wizard/admin/admin.rb
@@ -0,0 +1,13 @@
+class CustomWizard::AdminController < ::Admin::AdminController
+ before_action :ensure_admin
+
+ def index
+ end
+
+ private
+
+ def find_wizard
+ params.require(:wizard_id)
+ @wizard = CustomWizard::Wizard.create(params[:wizard_id].underscore)
+ end
+end
\ No newline at end of file
diff --git a/controllers/custom_wizard/api.rb b/controllers/custom_wizard/admin/api.rb
similarity index 96%
rename from controllers/custom_wizard/api.rb
rename to controllers/custom_wizard/admin/api.rb
index a4ed8e6d..1e811061 100644
--- a/controllers/custom_wizard/api.rb
+++ b/controllers/custom_wizard/admin/api.rb
@@ -1,6 +1,4 @@
-class CustomWizard::ApiController < ::ApplicationController
- before_action :ensure_logged_in
- before_action :ensure_admin
+class CustomWizard::AdminApiController < CustomWizard::AdminController
skip_before_action :check_xhr, only: [:redirect]
def index
diff --git a/controllers/custom_wizard/admin/submissions.rb b/controllers/custom_wizard/admin/submissions.rb
new file mode 100644
index 00000000..28dbe553
--- /dev/null
+++ b/controllers/custom_wizard/admin/submissions.rb
@@ -0,0 +1,51 @@
+class CustomWizard::AdminSubmissionsController < CustomWizard::AdminController
+ skip_before_action :check_xhr, only: [:download_submissions]
+ before_action :find_wizard
+
+ def index
+ render json: ActiveModel::ArraySerializer.new(
+ CustomWizard::Wizard.list,
+ each_serializer: CustomWizard::BasicWizardSerializer
+ )
+ end
+
+ def show
+ result = {}
+
+ if wizard = @wizard
+ submissions = build_submissions(wizard.id)
+ result[:wizard] = CustomWizard::BasicWizardSerializer.new(wizard, root: false)
+ result[:submissions] = submissions.as_json
+ end
+
+ render_json_dump(result)
+ end
+
+ def download
+ send_data build_submissions(@wizard.id).to_json,
+ filename: "#{Discourse.current_hostname}-wizard-submissions-#{wizard['name']}.json",
+ content_type: "application/json"
+ end
+
+ private
+
+ def build_submissions(wizard_id)
+ rows = PluginStoreRow.where(plugin_name: "#{wizard_id}_submissions").order('id DESC')
+
+ submissions = [*rows].map do |row|
+ value = ::JSON.parse(row.value)
+
+ if user = User.find_by(id: row.key)
+ username = user.username
+ else
+ username = I18n.t('admin.wizard.submissions.no_user', id: row.key)
+ end
+
+ value.map do |submission|
+ {
+ username: username
+ }.merge!(submission.except("redirect_to"))
+ end
+ end.flatten
+ end
+end
\ No newline at end of file
diff --git a/controllers/custom_wizard/admin/wizard.rb b/controllers/custom_wizard/admin/wizard.rb
new file mode 100644
index 00000000..e090314c
--- /dev/null
+++ b/controllers/custom_wizard/admin/wizard.rb
@@ -0,0 +1,133 @@
+class CustomWizard::AdminWizardController < CustomWizard::AdminController
+ before_action :find_wizard, only: [:show, :remove]
+
+ def index
+ render_json_dump(
+ wizard_list: ActiveModel::ArraySerializer.new(
+ CustomWizard::Wizard.list,
+ each_serializer: CustomWizard::BasicWizardSerializer
+ ),
+ field_types: CustomWizard::Field.types
+ )
+ end
+
+ def show
+ params.require(:wizard_id)
+
+ if data = CustomWizard::Wizard.find(params[:wizard_id].underscore)
+ render json: data.as_json
+ else
+ render json: { none: true }
+ end
+ end
+
+ def remove
+ CustomWizard::Wizard.remove(@wizard.id)
+ render json: success_json
+ end
+
+ def save
+ opts = {}
+ opts[:create] = params[:create] if params[:create]
+
+ validator = CustomWizard::Validator.new(save_wizard_params.to_h, opts)
+ validation = validator.perform
+
+ if validation[:error]
+ render json: { error: validation[:error] }
+ else
+ params = validation[:wizard]
+
+ if wizard_id = CustomWizard::Wizard.save(params)
+ render json: success_json.merge(wizard_id: wizard_id)
+ else
+ render json: failed_json
+ end
+ end
+ end
+
+ private
+
+ def mapped_params
+ [
+ :type,
+ :connector,
+ :output,
+ :output_type,
+ :output_connector,
+ pairs: [
+ :index,
+ :key,
+ :key_type,
+ :value,
+ :value_type,
+ :connector,
+ value: [],
+ key: [],
+ ],
+ output: [],
+ ]
+ end
+
+ def save_wizard_params
+ params.require(:wizard).permit(
+ :id,
+ :name,
+ :background,
+ :save_submissions,
+ :multiple_submissions,
+ :after_signup,
+ :after_time,
+ :after_time_scheduled,
+ :required,
+ :prompt_completion,
+ :restart_on_revisit,
+ :theme_id,
+ permitted: mapped_params,
+ steps: [
+ :id,
+ :title,
+ :key,
+ :banner,
+ :raw_description,
+ :required_data_message,
+ required_data: mapped_params,
+ permitted_params: mapped_params,
+ fields: [
+ :id,
+ :label,
+ :image,
+ :description,
+ :required,
+ :key,
+ :type,
+ :min_length,
+ :file_types,
+ :limit,
+ :property,
+ prefill: mapped_params,
+ content: mapped_params
+ ]
+ ],
+ actions: [
+ :id,
+ :run_after,
+ :type,
+ :code,
+ :skip_redirect,
+ :url,
+ title: mapped_params,
+ post: mapped_params,
+ post_builder: mapped_params,
+ post_template: mapped_params,
+ category: mapped_params,
+ tags: mapped_params,
+ custom_fields: mapped_params,
+ required: mapped_params,
+ recipient: mapped_params,
+ profile_updates: mapped_params,
+ group: mapped_params
+ ]
+ )
+ end
+end
diff --git a/controllers/custom_wizard/steps.rb b/controllers/custom_wizard/steps.rb
index a627b960..8707f3ed 100644
--- a/controllers/custom_wizard/steps.rb
+++ b/controllers/custom_wizard/steps.rb
@@ -12,7 +12,7 @@ class CustomWizard::StepsController < ::ApplicationController
permitted.permit!
end
- wizard = CustomWizard::Builder.new(current_user, permitted[:wizard_id].underscore).build
+ wizard = CustomWizard::Builder.new(permitted[:wizard_id].underscore, current_user).build
updater = wizard.create_updater(permitted[:step_id], permitted[:fields])
updater.update
diff --git a/controllers/custom_wizard/transfer.rb b/controllers/custom_wizard/transfer.rb
index 4da52bb9..f1bf0bba 100644
--- a/controllers/custom_wizard/transfer.rb
+++ b/controllers/custom_wizard/transfer.rb
@@ -53,7 +53,7 @@ class CustomWizard::TransferController < ::ApplicationController
failed_ids = []
jsonObject.each do |o|
- if !CustomWizard::Template.new(o)
+ if !CustomWizard::Wizard.new(o)
failed_ids.push o['id']
next
end
diff --git a/controllers/custom_wizard/wizard.rb b/controllers/custom_wizard/wizard.rb
index ebe6cd55..914d3cea 100644
--- a/controllers/custom_wizard/wizard.rb
+++ b/controllers/custom_wizard/wizard.rb
@@ -6,7 +6,7 @@ class CustomWizard::WizardController < ::ApplicationController
helper_method :theme_ids
def wizard
- CustomWizard::Template.new(PluginStore.get('custom_wizard', params[:wizard_id].underscore))
+ CustomWizard::Wizard.create(params[:wizard_id].underscore, current_user)
end
def wizard_page_title
@@ -20,12 +20,14 @@ class CustomWizard::WizardController < ::ApplicationController
def index
respond_to do |format|
format.json do
- builder = CustomWizard::Builder.new(current_user, params[:wizard_id].underscore)
- builder_opts = {}
- builder_opts[:reset] = params[:reset] || builder.wizard.restart_on_revisit
-
+ builder = CustomWizard::Builder.new(params[:wizard_id].underscore, current_user)
+
if builder.wizard.present?
- render_serialized(builder.build(builder_opts, params), ::CustomWizardSerializer)
+ builder_opts = {}
+ builder_opts[:reset] = params[:reset] || builder.wizard.restart_on_revisit
+ built_wizard = builder.build(builder_opts, params)
+
+ render_serialized(built_wizard, ::CustomWizard::WizardSerializer, root: false)
else
render json: { error: I18n.t('wizard.none') }
end
@@ -34,34 +36,28 @@ class CustomWizard::WizardController < ::ApplicationController
end
end
- ## clean up if user skips wizard
def skip
params.require(:wizard_id)
- wizard_id = params[:wizard_id]
-
- user = current_user
- wizard_template = PluginStore.get('custom_wizard', wizard_id.underscore)
- wizard = CustomWizard::Wizard.new(user, wizard_template)
-
if wizard.required && !wizard.completed? && wizard.permitted?
return render json: { error: I18n.t('wizard.no_skip') }
end
result = success_json
-
+ user = current_user
+
if user
- submission = Array.wrap(PluginStore.get("#{wizard_id}_submissions", user.id)).last
+ submission = wizard.submissions.last
if submission && submission['redirect_to']
result.merge!(redirect_to: submission['redirect_to'])
end
if submission && !wizard.save_submissions
- PluginStore.remove("#{wizard_id}_submissions", user.id)
+ PluginStore.remove("#{wizard.id}_submissions", user.id)
end
- if user.custom_fields['redirect_to_wizard'] === wizard_id
+ if user.custom_fields['redirect_to_wizard'] === wizard.id
user.custom_fields.delete('redirect_to_wizard')
user.save_custom_fields(true)
end
diff --git a/jobs/set_after_time_wizard.rb b/jobs/set_after_time_wizard.rb
index 76d408d4..e94d2d92 100644
--- a/jobs/set_after_time_wizard.rb
+++ b/jobs/set_after_time_wizard.rb
@@ -5,7 +5,7 @@ module Jobs
user_ids = []
User.human_users.each do |user|
- if CustomWizard::Wizard.set_wizard_redirect(user, args[:wizard_id])
+ if CustomWizard::Wizard.set_wizard_redirect(args[:wizard_id], user)
user_ids.push(user.id)
end
end
diff --git a/lib/custom_wizard/builder.rb b/lib/custom_wizard/builder.rb
index fa5d8c96..aca414cf 100644
--- a/lib/custom_wizard/builder.rb
+++ b/lib/custom_wizard/builder.rb
@@ -1,14 +1,14 @@
class CustomWizard::Builder
attr_accessor :wizard, :updater, :submissions
- def initialize(user=nil, wizard_id)
- template = PluginStore.get('custom_wizard', wizard_id)
- return if template.blank?
-
- @steps = template['steps']
- @actions = template['actions']
- @wizard = CustomWizard::Wizard.new(user, template)
- @submissions = Array.wrap(PluginStore.get("#{wizard_id}_submissions", user.id)) if user
+ def initialize(wizard_id, user=nil)
+ params = CustomWizard::Wizard.find(wizard_id)
+ return nil if params.blank?
+
+ @wizard = CustomWizard::Wizard.new(params, user)
+ @steps = params['steps'] || []
+ @actions = params['actions'] || []
+ @submissions = @wizard.submissions if user && @wizard
end
def self.sorted_handlers
@@ -38,13 +38,8 @@ class CustomWizard::Builder
end
def build(build_opts = {}, params = {})
-
- return @wizard if !SiteSetting.custom_wizard_enabled ||
- (!@wizard.multiple_submissions &&
- @wizard.completed? &&
- !@wizard.user.admin) ||
- !@steps ||
- !@wizard.permitted?
+ return nil if !SiteSetting.custom_wizard_enabled || !@wizard
+ return @wizard if !@wizard.can_access?
reset_submissions if build_opts[:reset]
@@ -150,10 +145,10 @@ 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')))
-
+
CustomWizard::Action.new(
action: action,
user: user,
@@ -189,7 +184,7 @@ class CustomWizard::Builder
end
end
end
-
+
@wizard
end
@@ -213,7 +208,7 @@ class CustomWizard::Builder
params[:value] = prefill_field(field_template, step_template) || params[:value]
- if field_template['type'] === 'group'
+ if field_template['type'] === 'group' && params[:value].present?
params[:value] = params[:value].first
end
@@ -262,7 +257,7 @@ class CustomWizard::Builder
params[:content] = content[:result]
end
-
+
field = step.add_field(params)
end
diff --git a/lib/custom_wizard/mapper.rb b/lib/custom_wizard/mapper.rb
index 43573102..8f2be414 100644
--- a/lib/custom_wizard/mapper.rb
+++ b/lib/custom_wizard/mapper.rb
@@ -160,6 +160,10 @@ class CustomWizard::Mapper
end
end
+ def map_text(value)
+ interpolate(value)
+ end
+
def map_wizard_field(value)
data && !data.key?("submitted_at") && data[value]
end
diff --git a/lib/custom_wizard/template.rb b/lib/custom_wizard/template.rb
deleted file mode 100644
index 51536dfa..00000000
--- a/lib/custom_wizard/template.rb
+++ /dev/null
@@ -1,46 +0,0 @@
-class CustomWizard::Template
-
- attr_reader :id,
- :name,
- :background,
- :save_submissions,
- :multiple_submissions,
- :prompt_completion,
- :restart_on_revisit,
- :after_signup,
- :after_time,
- :after_time_scheduled,
- :required,
- :theme_id,
- :permitted,
- :steps,
- :actions
-
- def initialize(data)
- data = data.is_a?(String) ? ::JSON.parse(data) : data
-
- return nil if data.blank?
-
- @id = data['id']
- @name = data['name']
- @background = data['background']
- @save_submissions = data['save_submissions'] || false
- @multiple_submissions = data['multiple_submissions'] || false
- @prompt_completion = data['prompt_completion'] || false
- @restart_on_revisit = data['restart_on_revisit'] || false
- @after_signup = data['after_signup']
- @after_time = data['after_time']
- @after_time_scheduled = data['after_time_scheduled']
- @required = data['required'] || false
- @theme_id = data['theme_id']
- @permitted = data['permitted'] || nil
-
- if data['theme']
- theme = Theme.find_by(name: data['theme'])
- @theme_id = theme.id if theme
- end
-
- @steps = data['steps']
- @actions = data['actions']
- end
-end
diff --git a/lib/custom_wizard/validator.rb b/lib/custom_wizard/validator.rb
new file mode 100644
index 00000000..df9f26ca
--- /dev/null
+++ b/lib/custom_wizard/validator.rb
@@ -0,0 +1,143 @@
+class CustomWizard::Validator
+
+ def initialize(params, opts={})
+ @params = params
+ @opts = opts
+ @error = nil
+ end
+
+ def perform
+ params = @params
+
+ check_id(params, :wizard)
+ check_required(params, :wizard)
+ check_depdendent(params, :wizard)
+
+ after_time = nil
+
+ if !@error && @params[:after_time]
+ after_time = validate_after_time
+ end
+
+ if !@error
+ params[:steps].each do |step|
+ check_required(step, :step)
+ check_depdendent(step, :step)
+ break if @error.present?
+
+ if params[:fields].present?
+ params[:fields].each do |field|
+ check_required(field, :field)
+ check_depdendent(field, :field)
+ break if @error.present?
+ end
+ end
+ end
+
+ if params[:actions].present?
+ params[:actions].each do |action|
+ check_required(action, :action)
+ check_depdendent(action, :action)
+ break if @error.present?
+ end
+ end
+ end
+
+ if @error
+ { error: @error }
+ else
+ result = { wizard: params }
+ result[:after_time] = after_time if after_time
+ result
+ end
+ end
+
+ def self.required
+ {
+ wizard: ['id', 'name', 'steps'],
+ step: ['id'],
+ field: ['id', 'type'],
+ action: ['id', 'type']
+ }
+ end
+
+ def self.dependent
+ {
+ wizard: {
+ after_time: 'after_time_scheduled'
+ },
+ step: {},
+ field: {},
+ action: {}
+ }
+ end
+
+ private
+
+ def check_required(object, type)
+ CustomWizard::Validator.required[type].each do |property|
+ if object[property].blank?
+ @error = {
+ type: 'required',
+ params: { type: type, property: property }
+ }
+ end
+ end
+ end
+
+ def check_depdendent(object, type)
+ CustomWizard::Validator.dependent[type].each do |property, dependent|
+ if object[property] && object[dependent].blank?
+ @error = {
+ type: 'dependent',
+ params: { property: property, dependent: dependent }
+ }
+ end
+ end
+ end
+
+ def check_id(object, type)
+ if type === :wizard && @opts[:create] && CustomWizard::Wizard.exists?(object[:id])
+ @error = {
+ type: 'conflict',
+ params: { type: type, property: 'id', value: object[:id] }
+ }
+ end
+ end
+
+ def validate_after_time
+ if !@opts[:create]
+ wizard = CustomWizard::Wizard.create(params)
+ end
+
+ new = false
+ error = nil
+ scheduled = nil
+
+ if !@params[:after_time_scheduled] && !wizard[:after_time_scheduled]
+ error = 'after_time_need_time'
+ else
+ scheduled = Time.parse(@params[:after_time_scheduled]).utc
+ new = false
+
+ if wizard[:after_time_scheduled]
+ new = scheduled != Time.parse(wizard[:after_time_scheduled]).utc
+ end
+
+ begin
+ error = 'after_time_invalid' if new && scheduled < Time.now.utc
+ rescue ArgumentError
+ error = 'after_time_invalid'
+ end
+ end
+
+ if error
+ @error = { type: error }
+ else
+ {
+ new: new,
+ scheduled: scheduled
+ }
+ end
+ end
+end
\ No newline at end of file
diff --git a/lib/custom_wizard/wizard.rb b/lib/custom_wizard/wizard.rb
index 35657494..049786da 100644
--- a/lib/custom_wizard/wizard.rb
+++ b/lib/custom_wizard/wizard.rb
@@ -8,10 +8,10 @@ UserHistory.actions[:custom_wizard_step] = 1000
class CustomWizard::Wizard
include ActiveModel::SerializerSupport
- attr_reader :steps, :user
attr_accessor :id,
:name,
:background,
+ :theme_id,
:save_submissions,
:multiple_submissions,
:after_time,
@@ -22,20 +22,38 @@ class CustomWizard::Wizard
:restart_on_revisit,
:permitted,
:needs_categories,
- :needs_groups
+ :needs_groups,
+ :steps,
+ :actions,
+ :user
- def initialize(user=nil, attrs = {})
- @steps = []
+ def initialize(attrs = {}, user=nil)
@user = user
- @first_step = nil
- @required = false
+
+ @id = attrs['id']
+ @name = attrs['name']
+ @background = attrs['background']
+ @save_submissions = attrs['save_submissions'] || false
+ @multiple_submissions = attrs['multiple_submissions'] || false
+ @prompt_completion = attrs['prompt_completion'] || false
+ @restart_on_revisit = attrs['restart_on_revisit'] || false
+ @after_signup = attrs['after_signup']
+ @after_time = attrs['after_time']
+ @after_time_scheduled = attrs['after_time_scheduled']
+ @required = attrs['required'] || false
+ @permitted = attrs['permitted'] || nil
@needs_categories = false
@needs_groups = false
-
- attrs.each do |key, value|
- setter = "#{key}="
- send(setter, value) if respond_to?(setter.to_sym, false)
+ @theme_id = attrs['theme_id']
+
+ if attrs['theme']
+ theme = Theme.find_by(name: attrs['theme'])
+ @theme_id = theme.id if theme
end
+
+ @first_step = nil
+ @steps = []
+ @actions = []
end
def create_step(step_name)
@@ -44,13 +62,13 @@ class CustomWizard::Wizard
def append_step(step)
step = create_step(step) if step.is_a?(String)
-
+
yield step if block_given?
last_step = @steps.last
@steps << step
-
+
# If it's the first step
if @steps.size == 1
@first_step = step
@@ -108,7 +126,7 @@ class CustomWizard::Wizard
def completed?
return nil if !@user
-
+
steps = CustomWizard::Wizard.step_ids(@id)
history = ::UserHistory.where(
@@ -151,6 +169,13 @@ class CustomWizard::Wizard
end
end
end
+
+ def can_access?
+ return true if user.admin
+ return false if multiple_submissions && completed?
+ return false if !permitted?
+ return true
+ end
def reset
::UserHistory.create(
@@ -169,6 +194,10 @@ class CustomWizard::Wizard
@groups ||= ::Site.new(Guardian.new(@user)).groups
end
+ def submissions
+ Array.wrap(PluginStore.get("#{id}_submissions", @user.id))
+ end
+
def self.filter_records(filter)
PluginStoreRow.where("
plugin_name = 'custom_wizard' AND
@@ -183,7 +212,7 @@ class CustomWizard::Wizard
records
.sort_by { |record| record.value['permitted'].present? ? 0 : 1 }
.each do |record|
- wizard = CustomWizard::Wizard.new(user, JSON.parse(record.value))
+ wizard = CustomWizard::Wizard.new(JSON.parse(record.value), user)
if wizard.permitted?
result = wizard
@@ -200,7 +229,7 @@ class CustomWizard::Wizard
def self.prompt_completion(user)
if (records = filter_records('prompt_completion')).any?
records.reduce([]) do |result, record|
- wizard = CustomWizard::Wizard.new(user, ::JSON.parse(record.value))
+ wizard = CustomWizard::Wizard.new(::JSON.parse(record.value), user)
result.push(id: wizard.id, name: wizard.name) if !wizard.completed?
result
end
@@ -247,21 +276,69 @@ class CustomWizard::Wizard
def self.find(wizard_id)
PluginStore.get('custom_wizard', wizard_id)
end
+
+ def self.list(user=nil)
+ PluginStoreRow.where(plugin_name: 'custom_wizard').order(:id)
+ .map { |record| self.new(JSON.parse(record.value), user) }
+ end
+
+ def self.save(wizard)
+ existing_wizard = self.create(wizard[:id])
+
+ wizard[:steps].each do |step|
+ if step[:raw_description]
+ step[:description] = PrettyText.cook(step[:raw_description])
+ end
+ end
+
+ wizard = wizard.slice!(:create)
+
+ ActiveRecord::Base.transaction do
+ PluginStore.set('custom_wizard', wizard[:id], wizard)
+
+ if wizard[:after_time]
+ Jobs.cancel_scheduled_job(:set_after_time_wizard, wizard_id: wizard[:id])
+ Jobs.enqueue_at(wizard[:after_time_scheduled], :set_after_time_wizard, wizard_id: wizard[:id])
+ end
+
+ if existing_wizard && existing_wizard.after_time && !wizard[:after_time]
+ Jobs.cancel_scheduled_job(:set_after_time_wizard, wizard_id: wizard[:id])
+ Jobs.enqueue(:clear_after_time_wizard, wizard_id: wizard[:id])
+ end
+ end
+
+ wizard[:id]
+ end
+
+ def self.remove(wizard_id)
+ wizard = self.create(wizard_id)
+
+ ActiveRecord::Base.transaction do
+ if wizard.after_time
+ Jobs.cancel_scheduled_job(:set_after_time_wizard)
+ Jobs.enqueue(:clear_after_time_wizard, wizard_id: wizard.id)
+ end
+
+ PluginStore.remove('custom_wizard', wizard.id)
+ end
+ end
def self.exists?(wizard_id)
PluginStoreRow.exists?(plugin_name: 'custom_wizard', key: wizard_id)
end
- def self.create(user, wizard_id)
- CustomWizard::Wizard.new(user, self.find(wizard_id).to_h)
+ def self.create(wizard_id, user = nil)
+ if wizard = self.find(wizard_id)
+ CustomWizard::Wizard.new(wizard.to_h, user)
+ end
end
def self.set_submission_redirect(user, wizard_id, url)
PluginStore.set("#{wizard_id.underscore}_submissions", user.id, [{ redirect_to: url }])
end
- def self.set_wizard_redirect(user, wizard_id)
- wizard = CustomWizard::Wizard.create(user, wizard_id)
+ def self.set_wizard_redirect(wizard_id, user)
+ wizard = CustomWizard::Wizard.create(wizard_id, user)
if wizard.permitted?
user.custom_fields['redirect_to_wizard'] = wizard_id
diff --git a/plugin.rb b/plugin.rb
index c48ed998..0fc88744 100644
--- a/plugin.rb
+++ b/plugin.rb
@@ -44,11 +44,13 @@ after_initialize do
%w[
../lib/custom_wizard/engine.rb
../config/routes.rb
+ ../controllers/custom_wizard/admin/admin.rb
+ ../controllers/custom_wizard/admin/wizard.rb
+ ../controllers/custom_wizard/admin/submissions.rb
+ ../controllers/custom_wizard/admin/api.rb
../controllers/custom_wizard/wizard.rb
../controllers/custom_wizard/steps.rb
- ../controllers/custom_wizard/admin.rb
../controllers/custom_wizard/transfer.rb
- ../controllers/custom_wizard/api.rb
../controllers/application_controller.rb
../controllers/extra_locales_controller.rb
../controllers/invites_controller.rb
@@ -60,7 +62,7 @@ after_initialize do
../lib/custom_wizard/field.rb
../lib/custom_wizard/mapper.rb
../lib/custom_wizard/step_updater.rb
- ../lib/custom_wizard/template.rb
+ ../lib/custom_wizard/validator.rb
../lib/custom_wizard/wizard.rb
../lib/custom_wizard/api/api.rb
../lib/custom_wizard/api/authorization.rb
@@ -74,6 +76,7 @@ after_initialize do
../serializers/custom_wizard/api/log_serializer.rb
../serializers/custom_wizard/api_serializer.rb
../serializers/custom_wizard/basic_api_serializer.rb
+ ../serializers/custom_wizard/basic_wizard_serializer.rb
../serializers/custom_wizard/wizard_field_serializer.rb
../serializers/custom_wizard/wizard_step_serializer.rb
../serializers/custom_wizard/wizard_serializer.rb
@@ -94,7 +97,7 @@ after_initialize do
if !wizard.completed?
custom_redirect = true
- CustomWizard::Wizard.set_wizard_redirect(user, wizard.id)
+ CustomWizard::Wizard.set_wizard_redirect(wizard.id, user)
end
end
@@ -115,7 +118,7 @@ after_initialize do
on(:user_approved) do |user|
if wizard_id = CustomWizard::Wizard.after_signup
- CustomWizard::Wizard.set_wizard_redirect(user, wizard_id)
+ CustomWizard::Wizard.set_wizard_redirect(wizard_id, user)
end
end
diff --git a/serializers/custom_wizard/basic_wizard_serializer.rb b/serializers/custom_wizard/basic_wizard_serializer.rb
new file mode 100644
index 00000000..76c94614
--- /dev/null
+++ b/serializers/custom_wizard/basic_wizard_serializer.rb
@@ -0,0 +1,3 @@
+class CustomWizard::BasicWizardSerializer < ::ApplicationSerializer
+ attributes :id, :name
+end
\ No newline at end of file
diff --git a/serializers/custom_wizard/wizard_field_serializer.rb b/serializers/custom_wizard/wizard_field_serializer.rb
index 62022c05..c03628db 100644
--- a/serializers/custom_wizard/wizard_field_serializer.rb
+++ b/serializers/custom_wizard/wizard_field_serializer.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-class CustomWizardFieldSerializer < ::WizardFieldSerializer
+class CustomWizard::FieldSerializer < ::WizardFieldSerializer
attributes :image,
:file_types,
diff --git a/serializers/custom_wizard/wizard_serializer.rb b/serializers/custom_wizard/wizard_serializer.rb
index afb7a2c7..93596e24 100644
--- a/serializers/custom_wizard/wizard_serializer.rb
+++ b/serializers/custom_wizard/wizard_serializer.rb
@@ -1,17 +1,17 @@
# frozen_string_literal: true
-class CustomWizardSerializer < ::WizardSerializer
+class CustomWizard::WizardSerializer < CustomWizard::BasicWizardSerializer
- attributes :id,
- :name,
+ attributes :start,
:background,
+ :theme_id,
:completed,
:required,
:permitted,
:uncategorized_category_id
- has_one :user, serializer: ::BasicUserSerializer, embed: :objects
- has_many :steps, serializer: ::CustomWizardStepSerializer, embed: :objects
+ has_many :steps, serializer: ::CustomWizard::StepSerializer, embed: :objects
+ has_one :user, serializer: ::BasicUserSerializer, embed: :objects
has_many :categories, serializer: ::BasicCategorySerializer, embed: :objects
has_many :groups, serializer: ::BasicGroupSerializer, embed: :objects
@@ -28,6 +28,10 @@ class CustomWizardSerializer < ::WizardSerializer
def permitted
object.permitted?
end
+
+ def start
+ object.start.id
+ end
def include_start?
object.start && include_steps?
diff --git a/serializers/custom_wizard/wizard_step_serializer.rb b/serializers/custom_wizard/wizard_step_serializer.rb
index 05f48efe..2cd74393 100644
--- a/serializers/custom_wizard/wizard_step_serializer.rb
+++ b/serializers/custom_wizard/wizard_step_serializer.rb
@@ -1,9 +1,9 @@
# frozen_string_literal: true
-class ::CustomWizardStepSerializer < ::WizardStepSerializer
+class CustomWizard::StepSerializer < ::WizardStepSerializer
attributes :permitted, :permitted_message
- has_many :fields, serializer: ::CustomWizardFieldSerializer, embed: :objects
+ has_many :fields, serializer: ::CustomWizard::FieldSerializer, embed: :objects
def title
return PrettyText.cook(object.title) if object.title
diff --git a/spec/components/custom_wizard/builder_spec.rb b/spec/components/custom_wizard/builder_spec.rb
index cbba78ae..ba8da001 100644
--- a/spec/components/custom_wizard/builder_spec.rb
+++ b/spec/components/custom_wizard/builder_spec.rb
@@ -17,7 +17,7 @@ describe CustomWizard::Builder do
def build_wizard(t = template, u = user, build_opts = {}, params = {})
CustomWizard::Wizard.add_wizard(t)
- CustomWizard::Builder.new(u, 'welcome').build(build_opts, params)
+ CustomWizard::Builder.new('welcome', u).build(build_opts, params)
end
def add_submission_data(data = {})
diff --git a/spec/serializers/custom_wizard/wizard_serializer_spec.rb b/spec/serializers/custom_wizard/wizard_serializer_spec.rb
index eabe26e4..a470bccd 100644
--- a/spec/serializers/custom_wizard/wizard_serializer_spec.rb
+++ b/spec/serializers/custom_wizard/wizard_serializer_spec.rb
@@ -16,7 +16,7 @@ describe CustomWizardSerializer do
def build_wizard(t = template, u = user, build_opts = {}, params = {})
CustomWizard::Wizard.add_wizard(t)
- CustomWizard::Builder.new(u, 'welcome').build(build_opts, params)
+ CustomWizard::Builder.new('welcome', u).build(build_opts, params)
end
it 'should return the wizard attributes' do
diff --git a/views/layouts/wizard.html.erb b/views/layouts/wizard.html.erb
index 4fa985f1..47d54309 100644
--- a/views/layouts/wizard.html.erb
+++ b/views/layouts/wizard.html.erb
@@ -8,7 +8,7 @@
<%= stylesheet_link_tag "wizard_custom_mobile" %>
<%= stylesheet_link_tag "wizard_locations"%>
<%= stylesheet_link_tag "wizard_events"%>
- <%- if theme_ids %>
+ <%- if theme_ids.present? %>
<%= discourse_stylesheet_link_tag (mobile_view? ? :mobile_theme : :desktop_theme) %>
<%- end %>