Spiegel von
https://github.com/paviliondev/discourse-custom-wizard.git
synchronisiert 2024-11-09 20:02:54 +01:00
various
Dieser Commit ist enthalten in:
Ursprung
dae08e53d4
Commit
ab18769820
65 geänderte Dateien mit 995 neuen und 1011 gelöschten Zeilen
|
@ -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);
|
||||
}
|
||||
}
|
||||
})
|
||||
});
|
|
@ -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');
|
||||
}
|
||||
}
|
||||
})
|
|
@ -1,5 +0,0 @@
|
|||
import Controller from "@ember/controller";
|
||||
|
||||
export default Controller.extend({
|
||||
queryParams: ['refresh']
|
||||
});
|
|
@ -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() {
|
25
assets/javascripts/discourse/controllers/admin-wizards-wizard.js.es6
Normale Datei
25
assets/javascripts/discourse/controllers/admin-wizards-wizard.js.es6
Normale Datei
|
@ -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}`);
|
||||
}
|
||||
});
|
|
@ -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 });
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
});
|
||||
},
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
});
|
22
assets/javascripts/discourse/routes/admin-wizards-api-show.js.es6
Normale Datei
22
assets/javascripts/discourse/routes/admin-wizards-api-show.js.es6
Normale Datei
|
@ -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);
|
||||
}
|
||||
});
|
|
@ -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');
|
||||
}
|
||||
});
|
||||
});
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
});
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
});
|
|
@ -1,7 +0,0 @@
|
|||
import DiscourseRoute from "discourse/routes/discourse";
|
||||
|
||||
export default DiscourseRoute.extend({
|
||||
redirect() {
|
||||
this.transitionTo('adminWizardsCustom');
|
||||
}
|
||||
});
|
|
@ -1,7 +0,0 @@
|
|||
import DiscourseRoute from "discourse/routes/discourse";
|
||||
|
||||
export default DiscourseRoute.extend({
|
||||
redirect() {
|
||||
this.transitionTo('adminWizardSubmissions', 'first');
|
||||
}
|
||||
});
|
|
@ -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,
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
37
assets/javascripts/discourse/routes/admin-wizards-wizard-show.js.es6
Normale Datei
37
assets/javascripts/discourse/routes/admin-wizards-wizard-show.js.es6
Normale Datei
|
@ -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
|
||||
});
|
||||
}
|
||||
});
|
92
assets/javascripts/discourse/routes/admin-wizards-wizard.js.es6
Normale Datei
92
assets/javascripts/discourse/routes/admin-wizards-wizard.js.es6
Normale Datei
|
@ -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');
|
||||
}
|
||||
}
|
||||
});
|
9
assets/javascripts/discourse/routes/admin-wizards.js.es6
Normale Datei
9
assets/javascripts/discourse/routes/admin-wizards.js.es6
Normale Datei
|
@ -0,0 +1,9 @@
|
|||
import DiscourseRoute from "discourse/routes/discourse";
|
||||
|
||||
export default DiscourseRoute.extend({
|
||||
beforeModel(transition) {
|
||||
if (transition.targetName === "adminWizards.index") {
|
||||
this.transitionTo('adminWizardsWizard');
|
||||
}
|
||||
},
|
||||
});
|
|
@ -1,27 +0,0 @@
|
|||
<div class="wizard-header large">
|
||||
<label>{{i18n 'admin.wizard.submissions.title' name=wizard.name}}</label>
|
||||
|
||||
<a class="btn btn-default download-link" href="{{downloadUrl}}" target="_blank">
|
||||
{{d-icon 'download'}}
|
||||
<span class="d-button-label">
|
||||
{{i18n "admin.wizard.submissions.download"}}
|
||||
</span>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="wizard-submissions">
|
||||
<table>
|
||||
<tr>
|
||||
{{#each fields as |f|}}
|
||||
<th>{{f}}</th>
|
||||
{{/each}}
|
||||
</tr>
|
||||
{{#each submissions as |s|}}
|
||||
<tr>
|
||||
{{#each-in s as |k v|}}
|
||||
<td>{{v}}</td>
|
||||
{{/each-in}}
|
||||
</tr>
|
||||
{{/each}}
|
||||
</table>
|
||||
</div>
|
|
@ -1,26 +0,0 @@
|
|||
<div class='row'>
|
||||
<div class='content-list wizard-list'>
|
||||
<ul>
|
||||
{{#each model as |api|}}
|
||||
<li>
|
||||
{{#link-to "adminWizardsApi" (dasherize api.name)}}
|
||||
{{#if api.title}}
|
||||
{{api.title}}
|
||||
{{else}}
|
||||
{{api.name}}
|
||||
{{/if}}
|
||||
{{/link-to}}
|
||||
</li>
|
||||
{{/each}}
|
||||
</ul>
|
||||
<div class="new-api">
|
||||
{{#link-to 'adminWizardsApi' 'new' class="btn"}}
|
||||
{{d-icon "plus"}} {{i18n 'admin.wizard.api.new'}}
|
||||
{{/link-to}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="content">
|
||||
{{outlet}}
|
||||
</div>
|
||||
</div>
|
|
@ -1 +0,0 @@
|
|||
<div class="groups-type-index"></div>
|
|
@ -1,20 +0,0 @@
|
|||
<div class='row'>
|
||||
<div class='content-list wizard-list'>
|
||||
<ul>
|
||||
{{#each model as |w|}}
|
||||
<li>
|
||||
{{#link-to "adminWizard" (dasherize w.id)}}{{w.name}}{{/link-to}}
|
||||
</li>
|
||||
{{/each}}
|
||||
</ul>
|
||||
<div class="new-wizard">
|
||||
{{#link-to 'adminWizard' 'new' class="btn"}}
|
||||
{{d-icon "plus"}} {{i18n 'admin.wizard.new'}}
|
||||
{{/link-to}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="content">
|
||||
{{outlet}}
|
||||
</div>
|
||||
</div>
|
|
@ -0,0 +1,29 @@
|
|||
{{#if submissions}}
|
||||
<div class="wizard-header large">
|
||||
<label>{{i18n 'admin.wizard.submissions.title' name=wizard.name}}</label>
|
||||
|
||||
<a class="btn btn-default download-link" href="{{downloadUrl}}" target="_blank">
|
||||
{{d-icon 'download'}}
|
||||
<span class="d-button-label">
|
||||
{{i18n "admin.wizard.submissions.download"}}
|
||||
</span>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="wizard-submissions">
|
||||
<table>
|
||||
<tr>
|
||||
{{#each fields as |f|}}
|
||||
<th>{{f}}</th>
|
||||
{{/each}}
|
||||
</tr>
|
||||
{{#each submissions as |s|}}
|
||||
<tr>
|
||||
{{#each-in s as |k v|}}
|
||||
<td>{{v}}</td>
|
||||
{{/each-in}}
|
||||
</tr>
|
||||
{{/each}}
|
||||
</table>
|
||||
</div>
|
||||
{{/if}}
|
|
@ -1,15 +1,13 @@
|
|||
<div class='row'>
|
||||
<div class='content-list wizard-list'>
|
||||
<ul>
|
||||
{{#each model as |w|}}
|
||||
<li>
|
||||
{{#link-to "adminWizardSubmissions" w.id}}{{w.name}}{{/link-to}}
|
||||
</li>
|
||||
{{/each}}
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="content submissions">
|
||||
{{outlet}}
|
||||
</div>
|
||||
<div class="admin-wizard-select">
|
||||
{{combo-box
|
||||
value=wizardId
|
||||
content=wizardList
|
||||
onChange=(route-action 'changeWizard')
|
||||
options=(hash
|
||||
none='admin.wizard.select'
|
||||
)}}
|
||||
</div>
|
||||
|
||||
<div class="admin-wizard-container">
|
||||
{{outlet}}
|
||||
</div>
|
||||
|
|
|
@ -1,22 +1,22 @@
|
|||
<div class="admin-wizard settings">
|
||||
{{#if wizard}}
|
||||
<div class="wizard-header large">
|
||||
{{input
|
||||
name="name"
|
||||
value=model.name
|
||||
value=wizard.name
|
||||
placeholderKey="admin.wizard.name_placeholder"}}
|
||||
|
||||
<div class="wizard-url">
|
||||
{{#if model.name}}
|
||||
<a href="{{wizardUrl}}" target="_blank">{{wizardUrl}}</a>
|
||||
{{#if wizard.name}}
|
||||
{{#if copiedUrl}}
|
||||
{{d-button class="btn-hover pull-right" icon="copy" label="ip_lookup.copied"}}
|
||||
{{else}}
|
||||
{{d-button action=(action "copyUrl") class="pull-right no-text" icon="copy"}}
|
||||
{{/if}}
|
||||
<a href="{{wizardUrl}}" target="_blank">{{wizardUrl}}</a>
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="wizard-basic-details">
|
||||
<div class="setting">
|
||||
<div class="setting-label">
|
||||
|
@ -25,7 +25,7 @@
|
|||
<div class="setting-value">
|
||||
{{input
|
||||
name="background"
|
||||
value=model.background
|
||||
value=wizard.background
|
||||
placeholderKey="admin.wizard.background_placeholder"
|
||||
class="small"}}
|
||||
</div>
|
||||
|
@ -37,28 +37,28 @@
|
|||
</div>
|
||||
<div class="setting-value">
|
||||
{{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'
|
||||
)}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="wizard-header medium">
|
||||
{{i18n 'admin.wizard.label'}}
|
||||
</div>
|
||||
|
||||
|
||||
<div class="wizard-settings">
|
||||
<div class="setting">
|
||||
<div class="setting-label">
|
||||
<label>{{i18n 'admin.wizard.required'}}</label>
|
||||
</div>
|
||||
<div class="setting-value">
|
||||
{{input type='checkbox' checked=model.required}}
|
||||
{{input type='checkbox' checked=wizard.required}}
|
||||
<span>{{i18n 'admin.wizard.required_label'}}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -68,7 +68,7 @@
|
|||
<label>{{i18n 'admin.wizard.after_signup'}}</label>
|
||||
</div>
|
||||
<div class="setting-value">
|
||||
{{input type='checkbox' checked=model.after_signup}}
|
||||
{{input type='checkbox' checked=wizard.after_signup}}
|
||||
<span>{{i18n 'admin.wizard.after_signup_label'}}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -78,7 +78,7 @@
|
|||
<label>{{i18n 'admin.wizard.multiple_submissions'}}</label>
|
||||
</div>
|
||||
<div class="setting-value">
|
||||
{{input type='checkbox' checked=model.multiple_submissions}}
|
||||
{{input type='checkbox' checked=wizard.multiple_submissions}}
|
||||
<span>{{i18n 'admin.wizard.multiple_submissions_label'}}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -88,7 +88,7 @@
|
|||
<label>{{i18n 'admin.wizard.prompt_completion'}}</label>
|
||||
</div>
|
||||
<div class="setting-value">
|
||||
{{input type='checkbox' checked=model.prompt_completion}}
|
||||
{{input type='checkbox' checked=wizard.prompt_completion}}
|
||||
<span>{{i18n 'admin.wizard.prompt_completion_label'}}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -98,7 +98,7 @@
|
|||
<label>{{i18n 'admin.wizard.after_time'}}</label>
|
||||
</div>
|
||||
<div class="setting-value">
|
||||
{{input type='checkbox' checked=model.after_time}}
|
||||
{{input type='checkbox' checked=wizard.after_time}}
|
||||
<span>{{i18n 'admin.wizard.after_time_label'}}</span>
|
||||
{{d-button
|
||||
action='setNextSessionScheduled'
|
||||
|
@ -114,7 +114,7 @@
|
|||
</div>
|
||||
<div class="setting-value">
|
||||
{{wizard-mapper
|
||||
inputs=model.permitted
|
||||
inputs=wizard.permitted
|
||||
options=(hash
|
||||
context='wizard'
|
||||
inputTypes='assignment,validation'
|
||||
|
@ -126,9 +126,9 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
{{wizard-advanced-toggle showAdvanced=model.showAdvanced}}
|
||||
{{wizard-advanced-toggle showAdvanced=wizard.showAdvanced}}
|
||||
|
||||
{{#if model.showAdvanced}}
|
||||
{{#if wizard.showAdvanced}}
|
||||
<div class="advanced-settings">
|
||||
|
||||
<div class="setting">
|
||||
|
@ -136,7 +136,7 @@
|
|||
<label>{{i18n 'admin.wizard.save_submissions'}}</label>
|
||||
</div>
|
||||
<div class="setting-value">
|
||||
{{input type='checkbox' checked=model.save_submissions}}
|
||||
{{input type='checkbox' checked=wizard.save_submissions}}
|
||||
<span>{{i18n 'admin.wizard.save_submissions_label'}}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -146,7 +146,7 @@
|
|||
<label>{{i18n 'admin.wizard.restart_on_revisit'}}</label>
|
||||
</div>
|
||||
<div class="setting-value">
|
||||
{{input type='checkbox' checked=model.restart_on_revisit}}
|
||||
{{input type='checkbox' checked=wizard.restart_on_revisit}}
|
||||
<span>{{i18n 'admin.wizard.restart_on_revisit_label'}}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -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'}}
|
||||
</button>
|
||||
|
||||
{{#unless newWizard}}
|
||||
{{#unless creating}}
|
||||
<button {{action "remove"}} class='btn btn-danger remove'>
|
||||
{{d-icon "far-trash-alt"}}{{i18n 'admin.wizard.remove'}}
|
||||
</button>
|
||||
|
@ -199,4 +200,4 @@
|
|||
<span class="error">{{d-icon "times"}}{{error}}</span>
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
{{/if}}
|
32
assets/javascripts/discourse/templates/admin-wizards-wizard.hbs
Normale Datei
32
assets/javascripts/discourse/templates/admin-wizards-wizard.hbs
Normale Datei
|
@ -0,0 +1,32 @@
|
|||
<div class="admin-wizard-controls">
|
||||
{{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"}}
|
||||
</div>
|
||||
|
||||
<div class="admin-wizard-message">
|
||||
<div class="wizard-message">
|
||||
{{d-icon 'info-circle'}}
|
||||
<span>{{message}}</span>
|
||||
</div>
|
||||
|
||||
<div class="wizard-message">
|
||||
{{d-icon 'question-circle'}}
|
||||
<a href="https://thepavilion.io/c/knowledge/custom-wizard" target="_blank">
|
||||
{{i18n 'admin.wizard.message.help'}}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="admin-wizard-container settings">
|
||||
{{outlet}}
|
||||
</div>
|
|
@ -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}}
|
||||
|
||||
<div class="admin-container admin-wizard-container">
|
||||
<div class="admin-container">
|
||||
{{outlet}}
|
||||
</div>
|
||||
|
|
|
@ -64,7 +64,11 @@
|
|||
</div>
|
||||
|
||||
<div class="setting-value">
|
||||
{{input type="number" name="min_length" value=field.min_length}}
|
||||
{{input
|
||||
type="number"
|
||||
name="min_length"
|
||||
value=field.min_length
|
||||
class="small"}}
|
||||
</div>
|
||||
</div>
|
||||
{{/if}}
|
||||
|
@ -88,7 +92,7 @@
|
|||
</div>
|
||||
|
||||
<div class="setting-value">
|
||||
{{input type="number" value=field.limit}}
|
||||
{{input type="number" value=field.limit class="small"}}
|
||||
</div>
|
||||
</div>
|
||||
{{/if}}
|
||||
|
@ -148,8 +152,12 @@
|
|||
<div class="setting-label">
|
||||
<label>{{i18n 'admin.wizard.translation'}}</label>
|
||||
</div>
|
||||
<div class="setting-value">
|
||||
{{input name="key" value=field.key placeholderKey="admin.wizard.translation_placeholder"}}
|
||||
<div class="setting-value medium">
|
||||
{{input
|
||||
name="key"
|
||||
value=field.key
|
||||
class="small"
|
||||
placeholderKey="admin.wizard.translation_placeholder"}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -104,7 +104,7 @@
|
|||
{{#if currentField}}
|
||||
{{wizard-custom-field
|
||||
field=currentField
|
||||
fieldTypes=wizard.fieldTypes
|
||||
fieldTypes=fieldTypes
|
||||
removeField="removeField"
|
||||
wizardFields=wizardFields}}
|
||||
{{/if}}
|
|
@ -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}}
|
||||
</li>
|
||||
|
|
|
@ -2,8 +2,7 @@
|
|||
{{combo-box
|
||||
value=connector
|
||||
content=connectors
|
||||
onChange=(action (mut connector))
|
||||
onOpen=(action "onOpen")}}
|
||||
onChange=(action (mut connector))}}
|
||||
{{else}}
|
||||
<span class="connector-single">
|
||||
{{connectorLabel}}
|
||||
|
|
|
@ -1,17 +1,19 @@
|
|||
<div class="type-selector">
|
||||
{{#if hasTypes}}
|
||||
<a {{action "showTypes"}} class="active">
|
||||
<a {{action "toggleTypes"}} class="active">
|
||||
{{activeTypeLabel}}
|
||||
</a>
|
||||
|
||||
<div class="selector-types">
|
||||
{{#each selectorTypes as |item|}}
|
||||
{{wizard-mapper-selector-type
|
||||
activeType=activeType
|
||||
item=item
|
||||
toggle=(action 'toggleType')}}
|
||||
{{/each}}
|
||||
</div>
|
||||
{{#if showTypes}}
|
||||
<div class="selector-types">
|
||||
{{#each selectorTypes as |item|}}
|
||||
{{wizard-mapper-selector-type
|
||||
activeType=activeType
|
||||
item=item
|
||||
toggle=(action 'toggleType')}}
|
||||
{{/each}}
|
||||
</div>
|
||||
{{/if}}
|
||||
{{else}}
|
||||
<span>{{activeTypeLabel}}</span>
|
||||
{{/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}}
|
||||
</div>
|
|
@ -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
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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'
|
||||
|
|
|
@ -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
|
13
controllers/custom_wizard/admin/admin.rb
Normale Datei
13
controllers/custom_wizard/admin/admin.rb
Normale Datei
|
@ -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
|
|
@ -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
|
51
controllers/custom_wizard/admin/submissions.rb
Normale Datei
51
controllers/custom_wizard/admin/submissions.rb
Normale Datei
|
@ -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
|
133
controllers/custom_wizard/admin/wizard.rb
Normale Datei
133
controllers/custom_wizard/admin/wizard.rb
Normale Datei
|
@ -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
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
143
lib/custom_wizard/validator.rb
Normale Datei
143
lib/custom_wizard/validator.rb
Normale Datei
|
@ -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
|
|
@ -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
|
||||
|
|
13
plugin.rb
13
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
|
||||
|
||||
|
|
3
serializers/custom_wizard/basic_wizard_serializer.rb
Normale Datei
3
serializers/custom_wizard/basic_wizard_serializer.rb
Normale Datei
|
@ -0,0 +1,3 @@
|
|||
class CustomWizard::BasicWizardSerializer < ::ApplicationSerializer
|
||||
attributes :id, :name
|
||||
end
|
|
@ -1,6 +1,6 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class CustomWizardFieldSerializer < ::WizardFieldSerializer
|
||||
class CustomWizard::FieldSerializer < ::WizardFieldSerializer
|
||||
|
||||
attributes :image,
|
||||
:file_types,
|
||||
|
|
|
@ -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?
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 = {})
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 %>
|
||||
|
||||
|
|
Laden …
In neuem Issue referenzieren