Spiegel von
https://github.com/paviliondev/discourse-custom-wizard.git
synchronisiert 2024-11-22 17:30:29 +01:00
Merge branch 'master' into api_authentication
Dieser Commit ist enthalten in:
Commit
dfc87bccb0
31 geänderte Dateien mit 412 neuen und 100 gelöschten Zeilen
|
@ -5,6 +5,8 @@ const ACTION_TYPES = [
|
||||||
{ id: 'update_profile', name: 'Update Profile' },
|
{ id: 'update_profile', name: 'Update Profile' },
|
||||||
{ id: 'send_message', name: 'Send Message' },
|
{ id: 'send_message', name: 'Send Message' },
|
||||||
{ id: 'send_to_api', name: 'Send to API' }
|
{ id: 'send_to_api', name: 'Send to API' }
|
||||||
|
{ id: 'add_to_group', name: 'Add to Group' },
|
||||||
|
{ id: 'route_to', name: 'Route To' }
|
||||||
];
|
];
|
||||||
|
|
||||||
const PROFILE_FIELDS = [
|
const PROFILE_FIELDS = [
|
||||||
|
@ -29,33 +31,10 @@ export default Ember.Component.extend({
|
||||||
sendMessage: Ember.computed.equal('action.type', 'send_message'),
|
sendMessage: Ember.computed.equal('action.type', 'send_message'),
|
||||||
sendToApi: Ember.computed.equal('action.type', 'send_to_api'),
|
sendToApi: Ember.computed.equal('action.type', 'send_to_api'),
|
||||||
apiEmpty: Ember.computed.empty('action.api'),
|
apiEmpty: Ember.computed.empty('action.api'),
|
||||||
|
addToGroup: Ember.computed.equal('action.type', 'add_to_group'),
|
||||||
|
routeTo: Ember.computed.equal('action.type', 'route_to'),
|
||||||
disableId: Ember.computed.not('action.isNew'),
|
disableId: Ember.computed.not('action.isNew'),
|
||||||
|
|
||||||
@computed('currentStepId', 'wizard.save_submissions')
|
|
||||||
availableFields(currentStepId, saveSubmissions) {
|
|
||||||
const allSteps = this.get('wizard.steps');
|
|
||||||
let steps = allSteps;
|
|
||||||
let fields = [];
|
|
||||||
|
|
||||||
if (!saveSubmissions) {
|
|
||||||
steps = [allSteps.findBy('id', currentStepId)];
|
|
||||||
}
|
|
||||||
|
|
||||||
steps.forEach((s) => {
|
|
||||||
if (s.fields && s.fields.length > 0) {
|
|
||||||
let stepFields = s.fields.map((f) => {
|
|
||||||
return Ember.Object.create({
|
|
||||||
id: f.id,
|
|
||||||
label: `${f.id} (${s.id})`
|
|
||||||
});
|
|
||||||
});
|
|
||||||
fields.push(...stepFields);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return fields;
|
|
||||||
},
|
|
||||||
|
|
||||||
@computed('availableFields')
|
@computed('availableFields')
|
||||||
builderWizardFields(fields) {
|
builderWizardFields(fields) {
|
||||||
return fields.map((f) => ` w{${f.id}}`);
|
return fields.map((f) => ` w{${f.id}}`);
|
||||||
|
|
|
@ -15,7 +15,13 @@ export default Ember.Component.extend({
|
||||||
@computed()
|
@computed()
|
||||||
presetChoices() {
|
presetChoices() {
|
||||||
return [
|
return [
|
||||||
{ id: 'categories', name: I18n.t('admin.wizard.field.choices_preset.categories') }
|
{
|
||||||
|
id: 'categories',
|
||||||
|
name: I18n.t('admin.wizard.field.choices_preset.categories')
|
||||||
|
},{
|
||||||
|
id: 'groups',
|
||||||
|
name: I18n.t('admin.wizard.field.choices_preset.groups')
|
||||||
|
}
|
||||||
];
|
];
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
|
@ -5,6 +5,7 @@ export default Ember.Component.extend({
|
||||||
classNames: 'custom-input',
|
classNames: 'custom-input',
|
||||||
noneKey: 'admin.wizard.select_field',
|
noneKey: 'admin.wizard.select_field',
|
||||||
noneValue: 'admin.wizard.none',
|
noneValue: 'admin.wizard.none',
|
||||||
|
connectorNone: 'admin.wizard.none',
|
||||||
inputKey: 'admin.wizard.key',
|
inputKey: 'admin.wizard.key',
|
||||||
customDisabled: Ember.computed.alias('input.user_field'),
|
customDisabled: Ember.computed.alias('input.user_field'),
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
export default Ember.Component.extend({
|
export default Ember.Component.extend({
|
||||||
|
classNames: 'custom-inputs',
|
||||||
valuePlaceholder: 'admin.wizard.value',
|
valuePlaceholder: 'admin.wizard.value',
|
||||||
|
|
||||||
actions: {
|
actions: {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { observes } from 'ember-addons/ember-computed-decorators';
|
import { observes, default as computed } from 'ember-addons/ember-computed-decorators';
|
||||||
|
|
||||||
export default Ember.Component.extend({
|
export default Ember.Component.extend({
|
||||||
classNames: 'wizard-custom-step',
|
classNames: 'wizard-custom-step',
|
||||||
|
@ -14,5 +14,62 @@ export default Ember.Component.extend({
|
||||||
currentField: fields.length ? fields[0] : null,
|
currentField: fields.length ? fields[0] : null,
|
||||||
currentAction: actions.length ? actions[0] : null
|
currentAction: actions.length ? actions[0] : null
|
||||||
});
|
});
|
||||||
}
|
},
|
||||||
|
|
||||||
|
@computed('availableFields', 'wizard.steps')
|
||||||
|
requiredContent(availableFields, steps) {
|
||||||
|
let content = availableFields;
|
||||||
|
let actions = [];
|
||||||
|
|
||||||
|
steps.forEach(s => {
|
||||||
|
actions.push(...s.actions);
|
||||||
|
});
|
||||||
|
|
||||||
|
actions.forEach(a => {
|
||||||
|
if (a.type === 'route_to' && a.code) {
|
||||||
|
content.push(Ember.Object.create({
|
||||||
|
id: a.code,
|
||||||
|
label: "code (Route To)"
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return content;
|
||||||
|
},
|
||||||
|
|
||||||
|
@computed
|
||||||
|
requiredConnectorContent() {
|
||||||
|
const label = (id) => I18n.t(`admin.wizard.step.required_data.connector.${id}`);
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
id: 'equals',
|
||||||
|
label: label('equals')
|
||||||
|
}
|
||||||
|
];
|
||||||
|
},
|
||||||
|
|
||||||
|
@computed('step.id', 'wizard.save_submissions')
|
||||||
|
availableFields(currentStepId, saveSubmissions) {
|
||||||
|
const allSteps = this.get('wizard.steps');
|
||||||
|
let steps = allSteps;
|
||||||
|
let fields = [];
|
||||||
|
|
||||||
|
if (!saveSubmissions) {
|
||||||
|
steps = [allSteps.findBy('id', currentStepId)];
|
||||||
|
}
|
||||||
|
|
||||||
|
steps.forEach((s) => {
|
||||||
|
if (s.fields && s.fields.length > 0) {
|
||||||
|
let stepFields = s.fields.map((f) => {
|
||||||
|
return Ember.Object.create({
|
||||||
|
id: f.id,
|
||||||
|
label: `${f.id} (${s.id})`
|
||||||
|
});
|
||||||
|
});
|
||||||
|
fields.push(...stepFields);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return fields;
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
|
@ -77,6 +77,8 @@ const CustomWizard = Discourse.Model.extend({
|
||||||
if (s.key) step['key'] = s.key;
|
if (s.key) step['key'] = s.key;
|
||||||
if (s.banner) step['banner'] = s.banner;
|
if (s.banner) step['banner'] = s.banner;
|
||||||
if (s.raw_description) step['raw_description'] = s.raw_description;
|
if (s.raw_description) step['raw_description'] = s.raw_description;
|
||||||
|
if (s.required_data) step['required_data'] = s.required_data;
|
||||||
|
if (s.permitted_params) step['permitted_params'] = s.permitted_params;
|
||||||
|
|
||||||
const fields = s.get('fields');
|
const fields = s.get('fields');
|
||||||
if (fields.length) {
|
if (fields.length) {
|
||||||
|
@ -242,6 +244,8 @@ CustomWizard.reopenClass({
|
||||||
title: s.title,
|
title: s.title,
|
||||||
raw_description: s.raw_description,
|
raw_description: s.raw_description,
|
||||||
banner: s.banner,
|
banner: s.banner,
|
||||||
|
required_data: s.required_data,
|
||||||
|
permitted_params: s.permitted_params,
|
||||||
fields,
|
fields,
|
||||||
actions,
|
actions,
|
||||||
isNew: false
|
isNew: false
|
||||||
|
|
|
@ -242,3 +242,44 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
|
{{#if addToGroup}}
|
||||||
|
<div class="setting">
|
||||||
|
<div class="setting-label">
|
||||||
|
<h3>{{i18n "admin.wizard.action.add_to_group.group_selection"}}</h3>
|
||||||
|
</div>
|
||||||
|
<div class="setting-value">
|
||||||
|
{{combo-box value=action.group_id
|
||||||
|
content=availableFields
|
||||||
|
nameProperty="label"
|
||||||
|
none='admin.wizard.select_field'
|
||||||
|
isDisabled=action.custom_group_enabled}}
|
||||||
|
<div class="setting-gutter">
|
||||||
|
{{input type='checkbox' checked=action.custom_group_enabled}}
|
||||||
|
<span>{{i18n 'admin.wizard.action.add_to_group.custom_group'}}</span>
|
||||||
|
{{#if action.custom_group_enabled}}
|
||||||
|
{{input value=action.group_id}}
|
||||||
|
{{/if}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
|
{{#if routeTo}}
|
||||||
|
<div class="setting">
|
||||||
|
<div class="setting-label">
|
||||||
|
<h3>{{i18n "admin.wizard.action.route_to.url"}}</h3>
|
||||||
|
</div>
|
||||||
|
<div class="setting-value">
|
||||||
|
{{input value=action.url}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="setting">
|
||||||
|
<div class="setting-label">
|
||||||
|
<h3>{{i18n "admin.wizard.action.route_to.code"}}</h3>
|
||||||
|
</div>
|
||||||
|
<div class="setting-value">
|
||||||
|
{{input value=action.code}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{{/if}}
|
||||||
|
|
|
@ -6,7 +6,18 @@
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{d-icon 'arrow-right'}}
|
<div class="connector">
|
||||||
|
{{#if connectorContent}}
|
||||||
|
{{combo-box value=input.connector
|
||||||
|
content=connectorContent
|
||||||
|
nameProperty="label"
|
||||||
|
none=connectorNone}}
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
|
{{#if connectorKey}}
|
||||||
|
{{i18n connectorKey}}
|
||||||
|
{{/if}}
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="value">
|
<div class="value">
|
||||||
{{#if valueContent}}
|
{{#if valueContent}}
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
{{wizard-custom-input input=input
|
{{wizard-custom-input input=input
|
||||||
valueContent=valueContent
|
valueContent=valueContent
|
||||||
keyContent=keyContent
|
keyContent=keyContent
|
||||||
|
connectorContent=connectorContent
|
||||||
|
connectorKey=connectorKey
|
||||||
noneValue=noneValue
|
noneValue=noneValue
|
||||||
valuePlaceholder=valuePlaceholder
|
valuePlaceholder=valuePlaceholder
|
||||||
allowCustomField=allowCustomField
|
allowCustomField=allowCustomField
|
||||||
|
|
|
@ -43,6 +43,30 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="setting full">
|
||||||
|
<div class="setting-label">
|
||||||
|
<h3>{{i18n 'admin.wizard.step.required_data.label'}}</h3>
|
||||||
|
</div>
|
||||||
|
<div class="setting-value">
|
||||||
|
{{wizard-custom-inputs inputs=step.required_data
|
||||||
|
inputKey='admin.wizard.step.required_data.key'
|
||||||
|
valueContent=requiredContent
|
||||||
|
connectorContent=requiredConnectorContent}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="setting full">
|
||||||
|
<div class="setting-label">
|
||||||
|
<h3>{{i18n 'admin.wizard.step.permitted_params.label'}}</h3>
|
||||||
|
</div>
|
||||||
|
<div class="setting-value">
|
||||||
|
{{wizard-custom-inputs inputs=step.permitted_params
|
||||||
|
inputKey='admin.wizard.step.permitted_params.key'
|
||||||
|
valuePlaceholder='admin.wizard.step.permitted_params.value'
|
||||||
|
connectorKey='admin.wizard.step.permitted_params.connector'}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
{{wizard-links type="field" current=currentField items=step.fields}}
|
{{wizard-links type="field" current=currentField items=step.fields}}
|
||||||
{{#if currentField}}
|
{{#if currentField}}
|
||||||
{{wizard-custom-field field=currentField types=wizard.fieldTypes removeField="removeField"}}
|
{{wizard-custom-field field=currentField types=wizard.fieldTypes removeField="removeField"}}
|
||||||
|
@ -50,7 +74,10 @@
|
||||||
|
|
||||||
{{wizard-links type="action" current=currentAction items=step.actions}}
|
{{wizard-links type="action" current=currentAction items=step.actions}}
|
||||||
{{#if currentAction}}
|
{{#if currentAction}}
|
||||||
{{wizard-custom-action action=currentAction wizard=wizard removeAction="removeAction" currentStepId=step.id}}
|
{{wizard-custom-action action=currentAction
|
||||||
|
wizard=wizard
|
||||||
|
removeAction="removeAction"
|
||||||
|
availableFields=availableFields}}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
<label>{{i18n 'admin.wizard.action.available_fields'}}</label>
|
<label>{{i18n 'admin.wizard.action.available_fields'}}</label>
|
||||||
|
|
|
@ -81,8 +81,7 @@ export default Ember.TextField.extend({
|
||||||
includeGroups,
|
includeGroups,
|
||||||
allowedUsers,
|
allowedUsers,
|
||||||
includeMentionableGroups,
|
includeMentionableGroups,
|
||||||
includeMessageableGroups,
|
includeMessageableGroups
|
||||||
group: self.get("group")
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return results;
|
return results;
|
||||||
|
|
|
@ -10,4 +10,4 @@ export default Ember.Component.extend({
|
||||||
CustomWizard.skip(this.get('wizardId'));
|
CustomWizard.skip(this.get('wizardId'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
|
|
|
@ -5,7 +5,9 @@ export default StepController.extend({
|
||||||
actions: {
|
actions: {
|
||||||
goNext(response) {
|
goNext(response) {
|
||||||
const next = this.get('step.next');
|
const next = this.get('step.next');
|
||||||
if (response.refresh_required) {
|
if (response.route_to) {
|
||||||
|
window.location.href = response.route_to;
|
||||||
|
} else if (response.refresh_required) {
|
||||||
const id = this.get('wizard.id');
|
const id = this.get('wizard.id');
|
||||||
window.location.href = getUrl(`/w/${id}/steps/${next}`);
|
window.location.href = getUrl(`/w/${id}/steps/${next}`);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
export default Ember.Controller.extend({
|
export default Ember.Controller.extend({
|
||||||
queryParams: ['reset']
|
queryParams: ['reset']
|
||||||
})
|
});
|
||||||
|
|
|
@ -71,6 +71,10 @@ export default {
|
||||||
return index === 0 && !required;
|
return index === 0 && !required;
|
||||||
}.property('step.index', 'wizard.required'),
|
}.property('step.index', 'wizard.required'),
|
||||||
|
|
||||||
|
cookedTitle: function() {
|
||||||
|
return cook(this.get('step.title'));
|
||||||
|
}.property('step.title'),
|
||||||
|
|
||||||
cookedDescription: function() {
|
cookedDescription: function() {
|
||||||
return cook(this.get('step.description'));
|
return cook(this.get('step.description'));
|
||||||
}.property('step.description'),
|
}.property('step.description'),
|
||||||
|
|
|
@ -24,20 +24,33 @@ CustomWizard.reopenClass({
|
||||||
|
|
||||||
finished(result) {
|
finished(result) {
|
||||||
let url = "/";
|
let url = "/";
|
||||||
if (result.redirect_to) {
|
if (result.redirect_on_complete) {
|
||||||
url = result.redirect_to;
|
url = result.redirect_on_complete;
|
||||||
}
|
}
|
||||||
window.location.href = getUrl(url);
|
window.location.href = getUrl(url);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
export function findCustomWizard(wizardId, opts = {}) {
|
export function findCustomWizard(wizardId, params = {}) {
|
||||||
let url = `/w/${wizardId}`;
|
let url = `/w/${wizardId}`;
|
||||||
if (opts.reset) url += '?reset=true';
|
|
||||||
|
let paramKeys = Object.keys(params).filter(k => {
|
||||||
|
if (k === 'wizard_id') return false;
|
||||||
|
return !!params[k];
|
||||||
|
});
|
||||||
|
|
||||||
|
if (paramKeys.length) {
|
||||||
|
url += '?';
|
||||||
|
paramKeys.forEach((k,i) => {
|
||||||
|
if (i > 0) {
|
||||||
|
url += '&';
|
||||||
|
}
|
||||||
|
url += `${k}=${params[k]}`;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
return ajax({ url, cache: false, dataType: 'json' }).then(result => {
|
return ajax({ url, cache: false, dataType: 'json' }).then(result => {
|
||||||
const wizard = result.wizard;
|
const wizard = result.wizard;
|
||||||
|
|
||||||
if (!wizard) return null;
|
if (!wizard) return null;
|
||||||
|
|
||||||
if (!wizard.completed) {
|
if (!wizard.completed) {
|
||||||
|
|
|
@ -16,8 +16,13 @@ export default Ember.Route.extend({
|
||||||
const permitted = model.get('permitted');
|
const permitted = model.get('permitted');
|
||||||
const minTrust = model.get('min_trust');
|
const minTrust = model.get('min_trust');
|
||||||
const wizardId = model.get('id');
|
const wizardId = model.get('id');
|
||||||
|
const user = model.get('user');
|
||||||
|
const name = model.get('name');
|
||||||
|
|
||||||
controller.setProperties({
|
controller.setProperties({
|
||||||
|
requiresLogin: !user,
|
||||||
|
user,
|
||||||
|
name,
|
||||||
completed,
|
completed,
|
||||||
notPermitted: !permitted,
|
notPermitted: !permitted,
|
||||||
minTrust,
|
minTrust,
|
||||||
|
|
|
@ -15,9 +15,19 @@ export default Ember.Route.extend({
|
||||||
return model.set("wizardId", this.modelFor('custom').id);
|
return model.set("wizardId", this.modelFor('custom').id);
|
||||||
},
|
},
|
||||||
|
|
||||||
setupController(controller, step) {
|
setupController(controller, model) {
|
||||||
controller.setProperties({
|
let props = {
|
||||||
step, wizard: this.modelFor('custom')
|
step: model,
|
||||||
});
|
wizard: this.modelFor('custom')
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!model.permitted) {
|
||||||
|
props['stepMessage'] = {
|
||||||
|
state: 'not-permitted',
|
||||||
|
text: "You're not allowed to view this step."
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
controller.setProperties(props);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -4,10 +4,12 @@ import { findCustomWizard } from '../models/custom';
|
||||||
import { ajax } from 'wizard/lib/ajax';
|
import { ajax } from 'wizard/lib/ajax';
|
||||||
|
|
||||||
export default Ember.Route.extend({
|
export default Ember.Route.extend({
|
||||||
|
beforeModel(transition) {
|
||||||
|
this.set('queryParams', transition.intent.queryParams);
|
||||||
|
},
|
||||||
|
|
||||||
model(params) {
|
model(params) {
|
||||||
let opts = {};
|
return findCustomWizard(params.wizard_id, this.get('queryParams'));
|
||||||
if (params.reset == 'true') opts['reset'] = true;
|
|
||||||
return findCustomWizard(params.wizard_id, opts);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
afterModel() {
|
afterModel() {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<div class='wizard-step-contents'>
|
<div class='wizard-step-contents'>
|
||||||
{{#if step.title}}
|
{{#if step.title}}
|
||||||
<h1 class='wizard-step-title'>{{step.title}}</h1>
|
<h1 class='wizard-step-title'>{{cookedTitle}}</h1>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
{{#if step.description}}
|
{{#if step.description}}
|
||||||
|
|
|
@ -1,10 +1,15 @@
|
||||||
{{#if completed}}
|
{{#if noWizard}}
|
||||||
{{wizard-no-access text=(i18n 'wizard.completed') wizardId=wizardId}}
|
{{wizard-no-access text=(i18n 'wizard.none') wizardId=wizardId}}
|
||||||
{{else}}
|
{{else}}
|
||||||
{{#if notPermitted}}
|
{{#if requiresLogin}}
|
||||||
{{wizard-no-access text=(i18n 'wizard.not_permitted' level=minTrust) wizardId=wizardId}}
|
{{wizard-no-access text=(i18n 'wizard.requires_login' name=name) wizardId=wizardId}}
|
||||||
{{/if}}
|
{{else}}
|
||||||
{{#if noWizard}}
|
{{#if notPermitted}}
|
||||||
{{wizard-no-access text=(i18n 'wizard.none') wizardId=wizardId}}
|
{{wizard-no-access text=(i18n 'wizard.not_permitted' name=name level=minTrust) wizardId=wizardId}}
|
||||||
|
{{else}}
|
||||||
|
{{#if completed}}
|
||||||
|
{{wizard-no-access text=(i18n 'wizard.completed' name=name) wizardId=wizardId}}
|
||||||
|
{{/if}}
|
||||||
|
{{/if}}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
<div class="step-message {{stepMessage.state}}">
|
<div class="step-message {{stepMessage.state}}">
|
||||||
{{stepMessage.text}}
|
{{stepMessage.text}}
|
||||||
</div>
|
</div>
|
||||||
{{wizard-step step=step
|
{{#if step.permitted}}
|
||||||
wizard=wizard
|
{{wizard-step step=step
|
||||||
goNext="goNext"
|
wizard=wizard
|
||||||
goBack=(action "goBack")
|
goNext="goNext"
|
||||||
finished="finished"
|
goBack=(action "goBack")
|
||||||
showMessage="showMessage"}}
|
finished="finished"
|
||||||
|
showMessage="showMessage"}}
|
||||||
|
{{/if}}
|
||||||
|
|
|
@ -157,7 +157,12 @@
|
||||||
////
|
////
|
||||||
|
|
||||||
.d-editor {
|
.d-editor {
|
||||||
max-height: 250px;
|
min-height: 200px;
|
||||||
|
|
||||||
|
.d-editor-input {
|
||||||
|
resize: vertical;
|
||||||
|
flex: initial;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.d-editor-modal.hidden {
|
.d-editor-modal.hidden {
|
||||||
|
|
|
@ -293,6 +293,13 @@
|
||||||
background-color: #e45735;
|
background-color: #e45735;
|
||||||
color: #ffffff;
|
color: #ffffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.not-permitted {
|
||||||
|
height: 60px;
|
||||||
|
line-height: 60px;
|
||||||
|
background-color: #e45735;
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.p-list-box {
|
.p-list-box {
|
||||||
|
|
|
@ -83,8 +83,13 @@
|
||||||
|
|
||||||
.setting-value {
|
.setting-value {
|
||||||
width: initial;
|
width: initial;
|
||||||
overflow: hidden;
|
|
||||||
float: none;
|
float: none;
|
||||||
|
display: flex;
|
||||||
|
|
||||||
|
.custom-input .remove {
|
||||||
|
margin-left: 10px;
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -186,13 +191,18 @@
|
||||||
|
|
||||||
.custom-input {
|
.custom-input {
|
||||||
display: flex;
|
display: flex;
|
||||||
margin: 5px 0;
|
align-items: center;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
|
||||||
.d-icon {
|
.d-icon {
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
input {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
input[disabled] {
|
input[disabled] {
|
||||||
background-color: $primary-low;
|
background-color: $primary-low;
|
||||||
border-color: #ddd;
|
border-color: #ddd;
|
||||||
|
@ -206,6 +216,10 @@
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
align-self: flex-start;
|
align-self: flex-start;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.connector {
|
||||||
|
margin: 0 10px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.setting .add-custom-input {
|
.setting .add-custom-input {
|
||||||
|
@ -213,12 +227,12 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.admin-contents .wizard-submissions {
|
.admin-contents .wizard-submissions {
|
||||||
padding: 0 20px;
|
width: 100%;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
overflow: scroll;
|
|
||||||
|
|
||||||
table {
|
table {
|
||||||
margin-top: 0;
|
margin-top: 0;
|
||||||
|
display: inline-block;
|
||||||
|
overflow-x: scroll;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -450,3 +464,7 @@
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
margin-bottom: 20px;
|
margin-bottom: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.wizard-step-contents{
|
||||||
|
height: unset !important;
|
||||||
|
}
|
||||||
|
|
|
@ -72,6 +72,16 @@ en:
|
||||||
banner: "Banner"
|
banner: "Banner"
|
||||||
banner_placeholder: "Image url"
|
banner_placeholder: "Image url"
|
||||||
description: "Description"
|
description: "Description"
|
||||||
|
required_data:
|
||||||
|
label: "Required Data"
|
||||||
|
key: 'Submission key'
|
||||||
|
connector:
|
||||||
|
equals: "Equals"
|
||||||
|
permitted_params:
|
||||||
|
label: "Permitted Params"
|
||||||
|
key: 'Param'
|
||||||
|
value: 'Submission key'
|
||||||
|
connector: "Save as"
|
||||||
field:
|
field:
|
||||||
type: "Choose a type"
|
type: "Choose a type"
|
||||||
header: "Fields"
|
header: "Fields"
|
||||||
|
@ -88,6 +98,7 @@ en:
|
||||||
choices_preset:
|
choices_preset:
|
||||||
label: "Preset"
|
label: "Preset"
|
||||||
categories: "Categories"
|
categories: "Categories"
|
||||||
|
groups: "Groups"
|
||||||
filter: "Preset Filter"
|
filter: "Preset Filter"
|
||||||
choice:
|
choice:
|
||||||
value: "Value"
|
value: "Value"
|
||||||
|
@ -123,6 +134,16 @@ en:
|
||||||
label: "Builder"
|
label: "Builder"
|
||||||
user_fields: "User Fields: "
|
user_fields: "User Fields: "
|
||||||
wizard_fields: "Wizard Fields: "
|
wizard_fields: "Wizard Fields: "
|
||||||
|
placeholder: "Insert wizard fields using the field_id in w{}. Insert user fields using field key in u{}."
|
||||||
|
add_to_group:
|
||||||
|
label: "Add to Group"
|
||||||
|
group: "Group"
|
||||||
|
group_selection: "Group Selection"
|
||||||
|
custom_group: "Custom Group"
|
||||||
|
route_to:
|
||||||
|
label: "Route To"
|
||||||
|
url: "Url"
|
||||||
|
code: "Code"
|
||||||
custom_title: "Custom Title"
|
custom_title: "Custom Title"
|
||||||
custom_category:
|
custom_category:
|
||||||
label: "Custom Category"
|
label: "Custom Category"
|
||||||
|
@ -237,10 +258,11 @@ en:
|
||||||
filter_placeholder: "Search..."
|
filter_placeholder: "Search..."
|
||||||
|
|
||||||
wizard:
|
wizard:
|
||||||
completed: "You have completed this wizard."
|
completed: "You have completed the {{name}} wizard."
|
||||||
not_permitted: "You need to be trust level {{level}} or higher to access this wizard."
|
not_permitted: "You need to be trust level {{level}} or higher to access the {{name}} wizard."
|
||||||
none: "There is no wizard here."
|
none: "There is no wizard here."
|
||||||
return_to_site: "Return to {{siteName}}"
|
return_to_site: "Return to {{siteName}}"
|
||||||
|
requires_login: "You need to be logged in to access the {{name}} wizard."
|
||||||
|
|
||||||
wizard_composer:
|
wizard_composer:
|
||||||
show_preview: "Preview Post"
|
show_preview: "Preview Post"
|
||||||
|
|
|
@ -2,7 +2,6 @@ class CustomWizard::WizardController < ::ApplicationController
|
||||||
prepend_view_path(Rails.root.join('plugins', 'discourse-custom-wizard', 'views'))
|
prepend_view_path(Rails.root.join('plugins', 'discourse-custom-wizard', 'views'))
|
||||||
layout 'wizard'
|
layout 'wizard'
|
||||||
|
|
||||||
requires_login
|
|
||||||
helper_method :wizard_page_title
|
helper_method :wizard_page_title
|
||||||
helper_method :theme_ids
|
helper_method :theme_ids
|
||||||
|
|
||||||
|
@ -22,12 +21,11 @@ class CustomWizard::WizardController < ::ApplicationController
|
||||||
respond_to do |format|
|
respond_to do |format|
|
||||||
format.json do
|
format.json do
|
||||||
builder = CustomWizard::Builder.new(current_user, params[:wizard_id].underscore)
|
builder = CustomWizard::Builder.new(current_user, params[:wizard_id].underscore)
|
||||||
|
|
||||||
builder_opts = {}
|
builder_opts = {}
|
||||||
builder_opts[:reset] = params[:reset] if params[:reset]
|
builder_opts[:reset] = params[:reset] if params[:reset]
|
||||||
|
|
||||||
if builder.wizard.present?
|
if builder.wizard.present?
|
||||||
wizard = builder.build(builder_opts)
|
wizard = builder.build(builder_opts, params)
|
||||||
render_serialized(wizard, WizardSerializer)
|
render_serialized(wizard, WizardSerializer)
|
||||||
else
|
else
|
||||||
render json: { error: I18n.t('wizard.none') }
|
render json: { error: I18n.t('wizard.none') }
|
||||||
|
@ -52,19 +50,22 @@ class CustomWizard::WizardController < ::ApplicationController
|
||||||
end
|
end
|
||||||
|
|
||||||
result = success_json
|
result = success_json
|
||||||
submission = Array.wrap(PluginStore.get("#{wizard_id}_submissions", user.id)).last
|
|
||||||
|
|
||||||
if submission && submission['redirect_to']
|
if user
|
||||||
result.merge!(redirect_to: submission['redirect_to'])
|
submission = Array.wrap(PluginStore.get("#{wizard_id}_submissions", user.id)).last
|
||||||
end
|
|
||||||
|
|
||||||
if submission && !wizard.save_submissions
|
if submission && submission['redirect_to']
|
||||||
PluginStore.remove("#{wizard_id}_submissions", user.id)
|
result.merge!(redirect_to: submission['redirect_to'])
|
||||||
end
|
end
|
||||||
|
|
||||||
if user.custom_fields['redirect_to_wizard'] === wizard_id
|
if submission && !wizard.save_submissions
|
||||||
user.custom_fields.delete('redirect_to_wizard')
|
PluginStore.remove("#{wizard_id}_submissions", user.id)
|
||||||
user.save_custom_fields(true)
|
end
|
||||||
|
|
||||||
|
if user.custom_fields['redirect_to_wizard'] === wizard_id
|
||||||
|
user.custom_fields.delete('redirect_to_wizard')
|
||||||
|
user.save_custom_fields(true)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
render json: result
|
render json: result
|
||||||
|
|
|
@ -2,14 +2,16 @@ class CustomWizard::Builder
|
||||||
|
|
||||||
attr_accessor :wizard, :updater, :submissions
|
attr_accessor :wizard, :updater, :submissions
|
||||||
|
|
||||||
def initialize(user, wizard_id)
|
def initialize(user=nil, wizard_id)
|
||||||
data = PluginStore.get('custom_wizard', wizard_id)
|
data = PluginStore.get('custom_wizard', wizard_id)
|
||||||
|
|
||||||
return if data.blank?
|
return if data.blank?
|
||||||
|
|
||||||
@steps = data['steps']
|
@steps = data['steps']
|
||||||
@wizard = CustomWizard::Wizard.new(user, data)
|
@wizard = CustomWizard::Wizard.new(user, data)
|
||||||
@submissions = Array.wrap(PluginStore.get("#{wizard_id}_submissions", user.id))
|
|
||||||
|
if user
|
||||||
|
@submissions = Array.wrap(PluginStore.get("#{wizard_id}_submissions", user.id))
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.sorted_handlers
|
def self.sorted_handlers
|
||||||
|
@ -49,10 +51,10 @@ class CustomWizard::Builder
|
||||||
result
|
result
|
||||||
end
|
end
|
||||||
|
|
||||||
result.gsub(/w\{(.*?)\}/) { |match| data[$1.to_sym] }
|
result = result.gsub(/w\{(.*?)\}/) { |match| data[$1.to_sym] }
|
||||||
end
|
end
|
||||||
|
|
||||||
def build(build_opts = {})
|
def build(build_opts = {}, params = {})
|
||||||
unless (@wizard.completed? && !@wizard.multiple_submissions && !@wizard.user.admin) || !@steps || !@wizard.permitted?
|
unless (@wizard.completed? && !@wizard.multiple_submissions && !@wizard.user.admin) || !@steps || !@wizard.permitted?
|
||||||
|
|
||||||
reset_submissions if build_opts[:reset]
|
reset_submissions if build_opts[:reset]
|
||||||
|
@ -63,6 +65,36 @@ class CustomWizard::Builder
|
||||||
step.description = step_template['description'] if step_template['description']
|
step.description = step_template['description'] if step_template['description']
|
||||||
step.banner = step_template['banner'] if step_template['banner']
|
step.banner = step_template['banner'] if step_template['banner']
|
||||||
step.key = step_template['key'] if step_template['key']
|
step.key = step_template['key'] if step_template['key']
|
||||||
|
step.permitted = true
|
||||||
|
|
||||||
|
if permitted_params = step_template['permitted_params']
|
||||||
|
permitted_data = {}
|
||||||
|
|
||||||
|
permitted_params.each do |param|
|
||||||
|
key = param['key'].to_sym
|
||||||
|
permitted_data[key] = params[key] if params[key]
|
||||||
|
end
|
||||||
|
|
||||||
|
if permitted_data.present?
|
||||||
|
current_data = @submissions.last || {}
|
||||||
|
save_submissions(current_data.merge(permitted_data), false)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if required_data = step_template['required_data']
|
||||||
|
if !@submissions.last && required_data.length
|
||||||
|
step.permitted = false
|
||||||
|
next
|
||||||
|
end
|
||||||
|
|
||||||
|
required_data.each do |rd|
|
||||||
|
if rd['connector'] === 'equals'
|
||||||
|
step.permitted = @submissions.last[rd['key']] == @submissions.last[rd['value']]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
next if !step.permitted
|
||||||
|
end
|
||||||
|
|
||||||
if step_template['fields'] && step_template['fields'].length
|
if step_template['fields'] && step_template['fields'].length
|
||||||
step_template['fields'].each do |field_template|
|
step_template['fields'].each do |field_template|
|
||||||
|
@ -118,8 +150,13 @@ class CustomWizard::Builder
|
||||||
end
|
end
|
||||||
|
|
||||||
if updater.errors.empty?
|
if updater.errors.empty?
|
||||||
redirect_to = data['redirect_to']
|
if route_to = data['route_to']
|
||||||
updater.result = { redirect_to: redirect_to } if redirect_to
|
updater.result[:route_to] = route_to
|
||||||
|
end
|
||||||
|
|
||||||
|
if redirect_on_complete = data['redirect_on_complete']
|
||||||
|
updater.result[:redirect_on_complete] = redirect_on_complete
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -200,9 +237,14 @@ class CustomWizard::Builder
|
||||||
end
|
end
|
||||||
elsif field_template['choices_preset'] && field_template['choices_preset'].length > 0
|
elsif field_template['choices_preset'] && field_template['choices_preset'].length > 0
|
||||||
objects = []
|
objects = []
|
||||||
|
site = Site.new(Guardian.new(@wizard.user))
|
||||||
|
|
||||||
if field_template['choices_preset'] === 'categories'
|
if field_template['choices_preset'] === 'categories'
|
||||||
objects = Site.new(Guardian.new(@wizard.user)).categories
|
objects = site.categories
|
||||||
|
end
|
||||||
|
|
||||||
|
if field_template['choices_preset'] === 'groups'
|
||||||
|
objects = site.groups
|
||||||
end
|
end
|
||||||
|
|
||||||
if field_template['choices_filters'] && field_template['choices_filters'].length > 0
|
if field_template['choices_filters'] && field_template['choices_filters'].length > 0
|
||||||
|
@ -227,7 +269,11 @@ class CustomWizard::Builder
|
||||||
|
|
||||||
def validate_field(field, updater, step_template)
|
def validate_field(field, updater, step_template)
|
||||||
value = updater.fields[field['id']]
|
value = updater.fields[field['id']]
|
||||||
min_length = field['min_length']
|
min_length = false
|
||||||
|
|
||||||
|
if is_text_type(field)
|
||||||
|
min_length = field['min_length']
|
||||||
|
end
|
||||||
|
|
||||||
if min_length && value.is_a?(String) && value.strip.length < min_length.to_i
|
if min_length && value.is_a?(String) && value.strip.length < min_length.to_i
|
||||||
label = field['label'] || I18n.t("#{field['key']}.label")
|
label = field['label'] || I18n.t("#{field['key']}.label")
|
||||||
|
@ -246,6 +292,10 @@ class CustomWizard::Builder
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def is_text_type(field)
|
||||||
|
['text', 'textarea'].include? field['type']
|
||||||
|
end
|
||||||
|
|
||||||
def standardise_boolean(value)
|
def standardise_boolean(value)
|
||||||
!!HasCustomFields::Helpers::CUSTOM_FIELD_TRUE.include?(value)
|
!!HasCustomFields::Helpers::CUSTOM_FIELD_TRUE.include?(value)
|
||||||
end
|
end
|
||||||
|
@ -309,6 +359,7 @@ class CustomWizard::Builder
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
|
value = [value] if key === 'tags'
|
||||||
params[key.to_sym] = value
|
params[key.to_sym] = value
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -329,7 +380,7 @@ class CustomWizard::Builder
|
||||||
end
|
end
|
||||||
|
|
||||||
unless action['skip_redirect']
|
unless action['skip_redirect']
|
||||||
data['redirect_to'] = post.topic.url
|
data['redirect_on_complete'] = post.topic.url
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -358,7 +409,7 @@ class CustomWizard::Builder
|
||||||
updater.errors.add(:send_message, creator.errors.full_messages.join(" "))
|
updater.errors.add(:send_message, creator.errors.full_messages.join(" "))
|
||||||
else
|
else
|
||||||
unless action['skip_redirect']
|
unless action['skip_redirect']
|
||||||
data['redirect_to'] = post.topic.url
|
data['redirect_on_complete'] = post.topic.url
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -394,7 +445,6 @@ class CustomWizard::Builder
|
||||||
end
|
end
|
||||||
|
|
||||||
def send_to_api(user, action, data)
|
def send_to_api(user, action, data)
|
||||||
|
|
||||||
api_body = nil
|
api_body = nil
|
||||||
|
|
||||||
if action['api_body'] != ""
|
if action['api_body'] != ""
|
||||||
|
@ -415,6 +465,23 @@ class CustomWizard::Builder
|
||||||
## add validation callback
|
## add validation callback
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def add_to_group(user, action, data)
|
||||||
|
if group_id = data[action['group_id']]
|
||||||
|
if group = Group.find(group_id)
|
||||||
|
group.add(user)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def route_to(user, action, data)
|
||||||
|
url = CustomWizard::Builder.fill_placeholders(action['url'], user, data)
|
||||||
|
if action['code']
|
||||||
|
data[action['code']] = SecureRandom.hex(8)
|
||||||
|
url += "&#{action['code']}=#{data[action['code']]}"
|
||||||
|
end
|
||||||
|
data['route_to'] = URI.encode(url)
|
||||||
|
end
|
||||||
|
|
||||||
def save_submissions(data, final_step)
|
def save_submissions(data, final_step)
|
||||||
if final_step
|
if final_step
|
||||||
|
|
|
@ -9,6 +9,7 @@ class CustomWizard::StepUpdater
|
||||||
@step = step
|
@step = step
|
||||||
@refresh_required = false
|
@refresh_required = false
|
||||||
@fields = fields
|
@fields = fields
|
||||||
|
@result = {}
|
||||||
end
|
end
|
||||||
|
|
||||||
def update
|
def update
|
||||||
|
|
|
@ -18,7 +18,7 @@ class CustomWizard::Wizard
|
||||||
:required,
|
:required,
|
||||||
:prompt_completion
|
:prompt_completion
|
||||||
|
|
||||||
def initialize(user, attrs = {})
|
def initialize(user=nil, attrs = {})
|
||||||
@steps = []
|
@steps = []
|
||||||
@user = user
|
@user = user
|
||||||
@first_step = nil
|
@first_step = nil
|
||||||
|
@ -54,6 +54,8 @@ class CustomWizard::Wizard
|
||||||
end
|
end
|
||||||
|
|
||||||
def start
|
def start
|
||||||
|
return nil if !@user
|
||||||
|
|
||||||
if unfinished? && last_completed_step = ::UserHistory.where(
|
if unfinished? && last_completed_step = ::UserHistory.where(
|
||||||
acting_user_id: @user.id,
|
acting_user_id: @user.id,
|
||||||
action: ::UserHistory.actions[:custom_wizard_step],
|
action: ::UserHistory.actions[:custom_wizard_step],
|
||||||
|
@ -76,6 +78,8 @@ class CustomWizard::Wizard
|
||||||
end
|
end
|
||||||
|
|
||||||
def unfinished?
|
def unfinished?
|
||||||
|
return nil if !@user
|
||||||
|
|
||||||
most_recent = ::UserHistory.where(
|
most_recent = ::UserHistory.where(
|
||||||
acting_user_id: @user.id,
|
acting_user_id: @user.id,
|
||||||
action: ::UserHistory.actions[:custom_wizard_step],
|
action: ::UserHistory.actions[:custom_wizard_step],
|
||||||
|
@ -94,6 +98,8 @@ class CustomWizard::Wizard
|
||||||
end
|
end
|
||||||
|
|
||||||
def completed?
|
def completed?
|
||||||
|
return nil if !@user
|
||||||
|
|
||||||
steps = CustomWizard::Wizard.step_ids(@id)
|
steps = CustomWizard::Wizard.step_ids(@id)
|
||||||
|
|
||||||
history = ::UserHistory.where(
|
history = ::UserHistory.where(
|
||||||
|
@ -112,7 +118,7 @@ class CustomWizard::Wizard
|
||||||
end
|
end
|
||||||
|
|
||||||
def permitted?
|
def permitted?
|
||||||
user.staff? || user.trust_level.to_i >= min_trust.to_i
|
user && (user.staff? || user.trust_level.to_i >= min_trust.to_i)
|
||||||
end
|
end
|
||||||
|
|
||||||
def reset
|
def reset
|
||||||
|
|
|
@ -60,11 +60,11 @@ end
|
||||||
end
|
end
|
||||||
|
|
||||||
class ::Wizard::Step
|
class ::Wizard::Step
|
||||||
attr_accessor :title, :description, :key
|
attr_accessor :title, :description, :key, :permitted
|
||||||
end
|
end
|
||||||
|
|
||||||
::WizardSerializer.class_eval do
|
::WizardSerializer.class_eval do
|
||||||
attributes :id, :background, :completed, :required, :min_trust, :permitted
|
attributes :id, :name, :background, :completed, :required, :min_trust, :permitted, :user
|
||||||
|
|
||||||
def id
|
def id
|
||||||
object.id
|
object.id
|
||||||
|
@ -74,6 +74,10 @@ end
|
||||||
object.respond_to?(:id)
|
object.respond_to?(:id)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def name
|
||||||
|
object.name
|
||||||
|
end
|
||||||
|
|
||||||
def background
|
def background
|
||||||
object.background
|
object.background
|
||||||
end
|
end
|
||||||
|
@ -123,18 +127,28 @@ end
|
||||||
def include_required?
|
def include_required?
|
||||||
object.respond_to?(:required)
|
object.respond_to?(:required)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def user
|
||||||
|
object.user
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
::WizardStepSerializer.class_eval do
|
::WizardStepSerializer.class_eval do
|
||||||
|
attributes :permitted
|
||||||
|
|
||||||
def title
|
def title
|
||||||
return object.title if object.title
|
return PrettyText.cook(object.title) if object.title
|
||||||
I18n.t("#{object.key || i18n_key}.title", default: '')
|
PrettyText.cook(I18n.t("#{object.key || i18n_key}.title", default: ''))
|
||||||
end
|
end
|
||||||
|
|
||||||
def description
|
def description
|
||||||
return object.description if object.description
|
return object.description if object.description
|
||||||
PrettyText.cook(I18n.t("#{object.key || i18n_key}.description", default: '', base_url: Discourse.base_url))
|
PrettyText.cook(I18n.t("#{object.key || i18n_key}.description", default: '', base_url: Discourse.base_url))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def permitted
|
||||||
|
object.permitted
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
::WizardFieldSerializer.class_eval do
|
::WizardFieldSerializer.class_eval do
|
||||||
|
|
Laden …
In neuem Issue referenzieren