0
0
Fork 1
Spiegel von https://github.com/paviliondev/discourse-custom-wizard.git synchronisiert 2024-11-12 21:22:54 +01:00
Dieser Commit ist enthalten in:
Angus McLeod 2020-03-22 04:30:11 +11:00
Ursprung b8369146c7
Commit 2e6ab27ea0
50 geänderte Dateien mit 737 neuen und 284 gelöschten Zeilen

Datei anzeigen

@ -0,0 +1,25 @@
import discourseComputed from 'discourse-common/utils/decorators';
export default Ember.Component.extend({
tagName: 'a',
classNameBindings: ['type', 'active'],
@discourseComputed('type', 'activeType')
active(type, activeType) {
return type === activeType;
},
@discourseComputed('type')
label(type) {
let map = {
wizard: I18n.t('admin.wizard.label'),
user: I18n.t('users_lowercase.one'),
text: I18n.t('admin.wizard.text')
};
return map[type].toLowerCase();
},
click() {
this.toggle(this.type)
}
})

Datei anzeigen

@ -1,33 +1,16 @@
import { default as computed, observes } from 'ember-addons/ember-computed-decorators'; import {
default as computed,
const ACTION_TYPES = [ observes
{ id: 'create_topic', name: 'Create Topic' }, } from 'discourse-common/utils/decorators';
{ id: 'update_profile', name: 'Update Profile' }, import {
{ id: 'send_message', name: 'Send Message' }, actionTypes,
{ id: 'send_to_api', name: 'Send to API' }, generateName,
{ id: 'add_to_group', name: 'Add to Group' }, generateSelectKitContent
{ id: 'route_to', name: 'Route To' }, } from '../lib/custom-wizard';
{ id: 'open_composer', name: 'Open Composer' }
];
const PROFILE_FIELDS = [
'name',
'user_avatar',
'date_of_birth',
'title',
'locale',
'location',
'website',
'bio_raw',
'profile_background',
'card_background',
'theme_id'
];
export default Ember.Component.extend({ export default Ember.Component.extend({
classNames: 'wizard-custom-action', classNames: 'wizard-custom-action',
types: ACTION_TYPES, types: actionTypes.map(t => ({ id: t, name: generateName(t) })),
profileFields: PROFILE_FIELDS,
createTopic: Ember.computed.equal('action.type', 'create_topic'), createTopic: Ember.computed.equal('action.type', 'create_topic'),
updateProfile: Ember.computed.equal('action.type', 'update_profile'), updateProfile: Ember.computed.equal('action.type', 'update_profile'),
sendMessage: Ember.computed.equal('action.type', 'send_message'), sendMessage: Ember.computed.equal('action.type', 'send_message'),
@ -36,6 +19,7 @@ export default Ember.Component.extend({
addToGroup: Ember.computed.equal('action.type', 'add_to_group'), addToGroup: Ember.computed.equal('action.type', 'add_to_group'),
routeTo: Ember.computed.equal('action.type', 'route_to'), routeTo: Ember.computed.equal('action.type', 'route_to'),
disableId: Ember.computed.not('action.isNew'), disableId: Ember.computed.not('action.isNew'),
groupPropertyTypes: generateSelectKitContent(['id', 'name']),
@computed('action.type') @computed('action.type')
basicTopicFields(actionType) { basicTopicFields(actionType) {
@ -52,17 +36,17 @@ export default Ember.Component.extend({
return ['create_topic', 'send_message'].indexOf(actionType) > -1; return ['create_topic', 'send_message'].indexOf(actionType) > -1;
}, },
@computed('availableFields') @computed('wizardFields')
builderWizardFields(fields) { builderWizardFields(fields) {
return fields.map((f) => ` w{${f.id}}`); return fields.map((f) => ` w{${f.id}}`);
}, },
@computed('availableFields') @computed('wizardFields')
categoryFields(fields) { categoryFields(fields) {
return fields.filter(f => f.type == 'category'); return fields.filter(f => f.type == 'category');
}, },
@computed('availableFields') @computed('wizardFields')
tagFields(fields) { tagFields(fields) {
return fields.filter(f => f.type == 'tag'); return fields.filter(f => f.type == 'tag');
}, },

Datei anzeigen

@ -1,4 +1,4 @@
import { default as computed, observes, on } from 'ember-addons/ember-computed-decorators'; import { default as computed, observes, on } from 'discourse-common/utils/decorators';
import { generateSelectKitContent } from '../lib/custom-wizard'; import { generateSelectKitContent } from '../lib/custom-wizard';
export default Ember.Component.extend({ export default Ember.Component.extend({

Datei anzeigen

@ -0,0 +1,46 @@
import { alias, equal } from "@ember/object/computed";
import { computed } from "@ember/object";
import {
default as discourseComputed,
observes
} from "discourse-common/utils/decorators";
export default Ember.Component.extend({
@observes('activeType')
clearValue() {
this.set('value', null);
},
@discourseComputed('customPlaceholder')
textPlaceholder(customPlaceholder) {
return customPlaceholder || 'admin.wizard.text';
},
@discourseComputed('activeType', 'userEnabled')
showUser(activeType, userEnabled) {
return activeType === 'user' && userEnabled;
},
@discourseComputed('activeType', 'wizardEnabled')
showWizard(activeType, wizardEnabled) {
return activeType === 'wizard' && wizardEnabled;
},
showText: equal('activeType', 'text'),
@discourseComputed('options.allowWizardField', 'inputType')
wizardEnabled(allowWizardField, inputType) {
return allowWizardField === true || allowWizardField === inputType;
},
@discourseComputed('options.allowUserField', 'inputType')
userEnabled(allowUserField, inputType) {
return allowUserField === true || allowUserField === inputType;
},
actions: {
toggleType(type) {
this.set('activeType', type);
}
}
})

Datei anzeigen

@ -0,0 +1,9 @@
import { connectors } from '../lib/custom-wizard';
import { gt } from "@ember/object/computed";
export default Ember.Component.extend({
classNames: 'pair',
connectorNone: 'admin.wizard.connector.none',
connectors: connectors.map(c => ({ id: c, name: I18n.t(`admin.wizard.connector.${c}`) })),
showRemove: gt('pair.index', 0)
})

Datei anzeigen

@ -1,34 +1,19 @@
import { default as computed, on } from 'ember-addons/ember-computed-decorators'; import { newPair } from '../lib/custom-wizard';
import { getOwner } from 'discourse-common/lib/get-owner';
export default Ember.Component.extend({ export default Ember.Component.extend({
classNames: 'custom-input', classNames: 'custom-input',
noneKey: 'admin.wizard.select_field', outputConnectorKey: 'admin.wizard.connector.prefill',
noneValue: 'admin.wizard.none', outputPrefixKey: 'admin.wizard.if',
connectorNone: 'admin.wizard.none',
inputKey: 'admin.wizard.key', actions: {
customDisabled: Ember.computed.alias('input.user_field'), addPair() {
this.get('input.pairs').pushObject(
@computed('input.value_custom', 'input.user_field') newPair(this.options, this.input.pairs.length)
valueDisabled(custom, user) { );
return Boolean(custom || user); },
},
removePair(pair) {
@on('init') this.get('input.pairs').removeObject(pair);
setupUserFields() {
const allowUserField = this.get('allowUserField');
if (allowUserField) {
const store = getOwner(this).lookup('store:main');
store.findAll('user-field').then((result) => {
if (result && result.content && result.content.length) {
this.set('userFields', result.content.map((f) => {
return {
id: `user_field_${f.id}`,
name: f.name
};
}));
}
});
} }
} }
}); });

Datei anzeigen

@ -1,13 +1,14 @@
import { getOwner } from 'discourse-common/lib/get-owner';
import { on } from 'discourse-common/utils/decorators';
import { newInput } from '../lib/custom-wizard';
export default Ember.Component.extend({ export default Ember.Component.extend({
classNames: 'custom-inputs', classNames: 'custom-inputs',
valuePlaceholder: 'admin.wizard.value',
actions: { actions: {
add() { add() {
if (!this.get('inputs')) { if (!this.get('inputs')) this.set('inputs', Ember.A());
this.set('inputs', Ember.A()); this.get('inputs').pushObject(newInput(this.options));
}
this.get('inputs').pushObject(Ember.Object.create());
}, },
remove(input) { remove(input) {

Datei anzeigen

@ -1,4 +1,4 @@
import { observes, default as computed } from 'ember-addons/ember-computed-decorators'; import { observes, default as computed } from 'discourse-common/utils/decorators';
export default Ember.Component.extend({ export default Ember.Component.extend({
classNames: 'wizard-custom-step', classNames: 'wizard-custom-step',
@ -16,9 +16,9 @@ export default Ember.Component.extend({
}); });
}, },
@computed('availableFields', 'wizard.steps') @computed('wizardFields', 'wizard.steps')
requiredContent(availableFields, steps) { requiredContent(wizardFields, steps) {
let content = availableFields; let content = wizardFields;
let actions = []; let actions = [];
steps.forEach(s => { steps.forEach(s => {
@ -37,19 +37,8 @@ export default Ember.Component.extend({
return content; 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') @computed('step.id', 'wizard.save_submissions')
availableFields(currentStepId, saveSubmissions) { wizardFields(currentStepId, saveSubmissions) {
const allSteps = this.get('wizard.steps'); const allSteps = this.get('wizard.steps');
let steps = allSteps; let steps = allSteps;
let fields = []; let fields = [];

Datei anzeigen

@ -1,5 +1,5 @@
import { ajax } from 'discourse/lib/ajax'; import { ajax } from 'discourse/lib/ajax';
import { default as computed } from 'ember-addons/ember-computed-decorators'; import { default as computed } from 'discourse-common/utils/decorators';
export default Ember.Component.extend({ export default Ember.Component.extend({
classNames: ['container', 'import'], classNames: ['container', 'import'],

Datei anzeigen

@ -1,4 +1,4 @@
import { default as computed, on, observes } from 'ember-addons/ember-computed-decorators'; import { default as computed, on, observes } from 'discourse-common/utils/decorators';
export default Ember.Component.extend({ export default Ember.Component.extend({
classNames: 'wizard-links', classNames: 'wizard-links',

Datei anzeigen

@ -1,3 +1,3 @@
{{#if currentUser.admin}} {{#if currentUser.admin}}
{{nav-item route='adminWizards' label='admin.wizard.label'}} {{nav-item route='adminWizards' label='admin.wizard.nav'}}
{{/if}} {{/if}}

Datei anzeigen

@ -1,4 +1,4 @@
import { default as computed } from 'ember-addons/ember-computed-decorators'; import { default as computed } from 'discourse-common/utils/decorators';
import showModal from 'discourse/lib/show-modal'; import showModal from 'discourse/lib/show-modal';
export default Ember.Controller.extend({ export default Ember.Controller.extend({

Datei anzeigen

@ -1,7 +1,7 @@
import { ajax } from 'discourse/lib/ajax'; import { ajax } from 'discourse/lib/ajax';
import { popupAjaxError } from 'discourse/lib/ajax-error'; import { popupAjaxError } from 'discourse/lib/ajax-error';
import CustomWizardApi from '../models/custom-wizard-api'; import CustomWizardApi from '../models/custom-wizard-api';
import { default as computed } from 'ember-addons/ember-computed-decorators'; import { default as computed } from 'discourse-common/utils/decorators';
import { generateSelectKitContent } from '../lib/custom-wizard'; import { generateSelectKitContent } from '../lib/custom-wizard';
export default Ember.Controller.extend({ export default Ember.Controller.extend({

Datei anzeigen

@ -1,4 +1,4 @@
import { default as computed } from 'ember-addons/ember-computed-decorators'; import { default as computed } from 'discourse-common/utils/decorators';
export default Ember.Controller.extend({ export default Ember.Controller.extend({
title: 'admin.wizard.after_time_modal.title', title: 'admin.wizard.after_time_modal.title',

Datei anzeigen

@ -2,4 +2,74 @@ function generateSelectKitContent(content) {
return content.map(i => ({id: i, name: i})) return content.map(i => ({id: i, name: i}))
} }
export { generateSelectKitContent }; function generateName(id) {
return id.replace(/[_\-]+/g, ' ')
.toLowerCase()
.replace(/(^\w|\b\w)/g, (m) => m.toUpperCase())
}
const profileFields = [
'name',
'user_avatar',
'date_of_birth',
'title',
'locale',
'location',
'website',
'bio_raw',
'profile_background',
'card_background',
'theme_id'
];
const connectors = [
'equal'
]
const actionTypes = [
'create_topic',
'update_profile',
'create_topic',
'update_profile',
'send_message',
'send_to_api',
'add_to_group',
'route_to',
'open_composer'
];
function newInput(options = {}) {
let params = {
pairs: Ember.A([newPair(options, 0)])
}
if (options.hasOutput) {
params['output'] = '';
params['output_type'] = 'text';
}
return Ember.Object.create(params);
}
function newPair(options = {}, index) {
let params = {
index,
key: '',
key_type: 'text',
value: '',
value_type: 'text',
connector: 'equal'
}
return Ember.Object.create(params);
}
export {
generateSelectKitContent,
profileFields,
actionTypes,
generateName,
connectors,
newInput,
newPair
};

Datei anzeigen

@ -1,7 +1,8 @@
import { ajax } from 'discourse/lib/ajax'; import { ajax } from 'discourse/lib/ajax';
import { default as computed } from 'ember-addons/ember-computed-decorators'; import { default as computed } from 'discourse-common/utils/decorators';
import EmberObject from "@ember/object";
const CustomWizardApi = Discourse.Model.extend({ const CustomWizardApi = EmberObject.extend({
@computed('name') @computed('name')
redirectUri(name) { redirectUri(name) {
let nameParam = name.toString().dasherize(); let nameParam = name.toString().dasherize();

Datei anzeigen

@ -1,4 +1,5 @@
import { ajax } from 'discourse/lib/ajax'; import { ajax } from 'discourse/lib/ajax';
import EmberObject from "@ember/object";
const wizardProperties = [ const wizardProperties = [
'name', 'name',
@ -15,7 +16,7 @@ const wizardProperties = [
'theme_id' 'theme_id'
]; ];
const CustomWizard = Discourse.Model.extend({ const CustomWizard = EmberObject.extend({
save() { save() {
return new Ember.RSVP.Promise((resolve, reject) => { return new Ember.RSVP.Promise((resolve, reject) => {

Datei anzeigen

@ -1,6 +1,7 @@
import CustomWizard from '../models/custom-wizard'; import CustomWizard from '../models/custom-wizard';
import DiscourseRoute from "discourse/routes/discourse";
export default Discourse.Route.extend({ export default DiscourseRoute.extend({
model(params) { model(params) {
return CustomWizard.submissions(params.wizard_id); return CustomWizard.submissions(params.wizard_id);
}, },

Datei anzeigen

@ -1,8 +1,13 @@
import CustomWizard from '../models/custom-wizard'; import CustomWizard from '../models/custom-wizard';
import { ajax } from 'discourse/lib/ajax'; import { ajax } from 'discourse/lib/ajax';
import { generateSelectKitContent } from '../lib/custom-wizard'; import {
generateSelectKitContent,
profileFields,
generateName
} from '../lib/custom-wizard';
import DiscourseRoute from "discourse/routes/discourse";
export default Discourse.Route.extend({ export default DiscourseRoute.extend({
beforeModel() { beforeModel() {
const param = this.paramsFor('adminWizard').wizard_id; const param = this.paramsFor('adminWizard').wizard_id;
const wizards = this.modelFor('admin-wizards-custom'); const wizards = this.modelFor('admin-wizards-custom');
@ -35,7 +40,8 @@ export default Discourse.Route.extend({
return Ember.RSVP.all([ return Ember.RSVP.all([
this._getFieldTypes(model), this._getFieldTypes(model),
this._getThemes(model), this._getThemes(model),
this._getApis(model) this._getApis(model),
this._getUserFields(model)
]); ]);
}, },
@ -59,6 +65,20 @@ export default Discourse.Route.extend({
return ajax('/admin/wizards/apis') return ajax('/admin/wizards/apis')
.then((result) => model.set('apis', result)); .then((result) => model.set('apis', result));
}, },
_getUserFields(model) {
return this.store.findAll('user-field').then((result) => {
if (result && result.content) {
let userContent = result.content.map((f) => {
return { id: `user_field_${f.id}`, name: f.name};
});
let profileContent = profileFields.map((f) => {
return { id: f, name: generateName(f) };
});
model.set('userFields', userContent.concat(profileContent));
}
});
},
setupController(controller, model) { setupController(controller, model) {
const newWizard = this.get('newWizard'); const newWizard = this.get('newWizard');

Datei anzeigen

@ -1,6 +1,7 @@
import CustomWizardApi from '../models/custom-wizard-api'; import CustomWizardApi from '../models/custom-wizard-api';
import DiscourseRoute from "discourse/routes/discourse";
export default Discourse.Route.extend({ export default DiscourseRoute.extend({
queryParams: { queryParams: {
refresh_list: { refresh_list: {
refreshModel: true refreshModel: true

Datei anzeigen

@ -1,6 +1,7 @@
import CustomWizardApi from '../models/custom-wizard-api'; import CustomWizardApi from '../models/custom-wizard-api';
import DiscourseRoute from "discourse/routes/discourse";
export default Discourse.Route.extend({ export default DiscourseRoute.extend({
model() { model() {
return CustomWizardApi.list(); return CustomWizardApi.list();
}, },

Datei anzeigen

@ -1,4 +1,6 @@
export default Discourse.Route.extend({ import DiscourseRoute from "discourse/routes/discourse";
export default DiscourseRoute.extend({
redirect() { redirect() {
this.transitionTo('adminWizard', 'first'); this.transitionTo('adminWizard', 'first');
} }

Datei anzeigen

@ -1,6 +1,7 @@
import CustomWizard from '../models/custom-wizard'; import CustomWizard from '../models/custom-wizard';
import DiscourseRoute from "discourse/routes/discourse";
export default Discourse.Route.extend({ export default DiscourseRoute.extend({
model() { model() {
return CustomWizard.all(); return CustomWizard.all();
}, },

Datei anzeigen

@ -1,4 +1,6 @@
export default Discourse.Route.extend({ import DiscourseRoute from "discourse/routes/discourse";
export default DiscourseRoute.extend({
redirect() { redirect() {
this.transitionTo('adminWizardsCustom'); this.transitionTo('adminWizardsCustom');
} }

Datei anzeigen

@ -1,6 +1,7 @@
import CustomWizard from '../models/custom-wizard'; import CustomWizard from '../models/custom-wizard';
import DiscourseRoute from "discourse/routes/discourse";
export default Discourse.Route.extend({ export default DiscourseRoute.extend({
model() { model() {
return CustomWizard.all(); return CustomWizard.all();
}, },

Datei anzeigen

@ -1,6 +1,7 @@
import CustomWizard from '../models/custom-wizard'; import CustomWizard from '../models/custom-wizard';
import DiscourseRoute from "discourse/routes/discourse";
export default Discourse.Route.extend({ export default DiscourseRoute.extend({
model() { model() {
return CustomWizard.all(); return CustomWizard.all();
} }

Datei anzeigen

@ -0,0 +1 @@
{{label}}

Datei anzeigen

@ -27,7 +27,7 @@
<div class="setting-value"> <div class="setting-value">
{{combo-box {{combo-box
value=action.title value=action.title
content=availableFields content=wizardFields
nameProperty="label" nameProperty="label"
isDisabled=action.custom_title_enabled isDisabled=action.custom_title_enabled
none='admin.wizard.select_field'}} none='admin.wizard.select_field'}}
@ -48,7 +48,7 @@
<div class="setting-value"> <div class="setting-value">
{{combo-box {{combo-box
value=action.post value=action.post
content=availableFields content=wizardFields
nameProperty='label' nameProperty='label'
isDisabled=action.post_builder isDisabled=action.post_builder
none='admin.wizard.select_field'}} none='admin.wizard.select_field'}}
@ -65,9 +65,10 @@
<h3>{{i18n 'admin.wizard.action.post_builder.label'}}</h3> <h3>{{i18n 'admin.wizard.action.post_builder.label'}}</h3>
</div> </div>
<div class="setting-value editor"> <div class="setting-value editor">
{{d-editor value=action.post_template {{d-editor
placeholder='admin.wizard.action.interpolate_fields' value=action.post_template
classNames='post-builder-editor'}} placeholder='admin.wizard.action.interpolate_fields'
classNames='post-builder-editor'}}
<div> <div>
<label>{{i18n 'admin.wizard.action.post_builder.user_fields'}}{{builderUserFields}}</label> <label>{{i18n 'admin.wizard.action.post_builder.user_fields'}}{{builderUserFields}}</label>
<label>{{i18n 'admin.wizard.action.post_builder.wizard_fields'}}{{builderWizardFields}}</label> <label>{{i18n 'admin.wizard.action.post_builder.wizard_fields'}}{{builderWizardFields}}</label>
@ -119,12 +120,14 @@
<div class="setting-label"> <div class="setting-label">
<h3>{{i18n "admin.wizard.action.create_topic.tags"}}</h3> <h3>{{i18n "admin.wizard.action.create_topic.tags"}}</h3>
</div> </div>
<div class="setting-value"> <div class="setting-value">
{{tag-chooser {{tag-chooser
tags=action.tags tags=action.tags
filterable=true filterable=true
allowCreate=true allowCreate=true
isDisabled=action.custom_tag_enabled}} isDisabled=action.custom_tag_enabled}}
<div class="setting-gutter"> <div class="setting-gutter">
{{input type='checkbox' checked=action.custom_tag_enabled}} {{input type='checkbox' checked=action.custom_tag_enabled}}
<span>{{i18n 'admin.wizard.action.custom_tag.label'}}</span> <span>{{i18n 'admin.wizard.action.custom_tag.label'}}</span>
@ -157,11 +160,13 @@
{{#if createTopic}} {{#if createTopic}}
<div class="setting full"> <div class="setting full">
<label>{{i18n 'admin.wizard.action.add_fields' type='Topic'}}</label> <label>{{i18n 'admin.wizard.action.add_fields' type='Topic'}}</label>
{{wizard-custom-inputs inputs=action.add_fields {{wizard-custom-inputs
valueContent=availableFields inputs=action.add_fields
inputKey='admin.wizard.action.topic_attr' userFields=userFields
noneValue='admin.wizard.select_field' wizardFields=wizardFields
allowCustomField=true}} options=(hash
allowWizardField=true
)}}
</div> </div>
{{/if}} {{/if}}
@ -170,43 +175,49 @@
<div class="setting-label"> <div class="setting-label">
<h3>{{i18n 'admin.wizard.required'}}</h3> <h3>{{i18n 'admin.wizard.required'}}</h3>
</div> </div>
<div class="setting-value"> <div class="setting-value">
{{combo-box {{combo-box
value=action.required value=action.required
content=availableFields content=wizardFields
nameProperty='label' nameProperty='label'
none='admin.wizard.select_field'}} none='admin.wizard.select_field'}}
</div> </div>
</div> </div>
<div class="setting"> <div class="setting">
<div class="setting-label"> <div class="setting-label">
<h3>{{i18n "admin.wizard.action.send_message.recipient"}}</h3> <h3>{{i18n "admin.wizard.action.send_message.recipient"}}</h3>
</div> </div>
<div class="setting-value"> <div class="setting-value">
{{user-selector single="true" {{user-selector
includeMentionableGroups="true" single="true"
usernames=action.username includeMentionableGroups="true"
allowedUsers="true"}} usernames=action.username
allowedUsers="true"}}
</div> </div>
</div> </div>
<div class="setting full"> <div class="setting full">
<label>{{i18n "admin.wizard.action.add_fields" type='Message'}}</label> <label>{{i18n "admin.wizard.action.add_fields" type='Message'}}</label>
{{wizard-custom-inputs inputs=action.add_fields {{wizard-custom-inputs
keyContent=availableFields inputs=action.add_fields
valuePlaceholder='admin.wizard.action.topic_attr'}} userFields=userFields
wizardFields=wizardFields}}
</div> </div>
{{/if}} {{/if}}
{{#if updateProfile}} {{#if updateProfile}}
<div class="setting full"> <div class="setting full">
<label>{{i18n "admin.wizard.action.add_fields" type='Profile'}}</label> <label>{{i18n "admin.wizard.action.add_fields" type='Profile'}}</label>
{{wizard-custom-inputs inputs=action.profile_updates {{wizard-custom-inputs
valueContent=profileFields inputs=action.profile_updates
keyContent=availableFields userFields=userFields
noneValue='admin.wizard.action.update_profile.profile_field' wizardFields=wizardFields
allowCustomField=true options=(hash
allowUserField=true}} allowWizardField=true
allowUserField=true
)}}
</div> </div>
{{/if}} {{/if}}
@ -244,8 +255,9 @@
<div class="setting-value"> <div class="setting-value">
<label>{{i18n 'admin.wizard.action.post_builder.user_fields'}}{{builderUserFields}}</label> <label>{{i18n 'admin.wizard.action.post_builder.user_fields'}}{{builderUserFields}}</label>
<label>{{i18n 'admin.wizard.action.post_builder.wizard_fields'}}{{builderWizardFields}}</label> <label>{{i18n 'admin.wizard.action.post_builder.wizard_fields'}}{{builderWizardFields}}</label>
{{textarea value=action.api_body {{textarea
placeholder=(i18n 'admin.wizard.action.interpolate_fields')}} value=action.api_body
placeholder=(i18n 'admin.wizard.action.interpolate_fields')}}
</div> </div>
</div> </div>
{{/if}} {{/if}}
@ -257,20 +269,36 @@
</div> </div>
<div class="setting-value"> <div class="setting-value">
{{combo-box {{combo-box
value=action.group_id value=action.value
content=availableFields content=wizardFields
isDisabled=action.custom_group_enabled isDisabled=action.custom
nameProperty="label" nameProperty="label"
none='admin.wizard.select_field'}} none='admin.wizard.select_field'}}
<div class="setting-gutter"> <div class="setting-gutter">
{{input type='checkbox' checked=action.custom_group_enabled}} {{input type='checkbox' checked=action.custom_group_enabled}}
<span>{{i18n 'admin.wizard.action.add_to_group.custom_group'}}</span> <span>{{i18n 'admin.wizard.action.add_to_group.custom_group'}}</span>
{{#if action.custom_group_enabled}} {{#if action.custom_group_enabled}}
{{input value=action.group_id}} {{input value=action.custom}}
{{/if}} {{/if}}
</div> </div>
</div> </div>
</div> </div>
<div class="setting">
<div class="setting-label">
<h3>{{i18n "admin.wizard.action.add_to_group.property"}}</h3>
</div>
<div class="setting-value">
{{combo-box
value=action.property
content=groupPropertyTypes
options=(hash
none='admin.wizard.select_property'
)}}
</div>
</div>
{{/if}} {{/if}}
{{#if routeTo}} {{#if routeTo}}

Datei anzeigen

@ -98,7 +98,10 @@
<div class="wizard-header small"> <div class="wizard-header small">
{{i18n 'admin.wizard.field.choices_custom'}} {{i18n 'admin.wizard.field.choices_custom'}}
</div> </div>
{{wizard-custom-inputs inputs=field.choices}} {{wizard-custom-inputs
inputs=field.choices
userFields=userFields
wizardFields=wizardFields}}
{{/if}} {{/if}}
<div class="wizard-header small"> <div class="wizard-header small">
@ -138,7 +141,28 @@
<div class="setting-value"> <div class="setting-value">
{{combo-box {{combo-box
content=categoryPropertyTypes content=categoryPropertyTypes
value=field.property}} value=field.property
options=(hash
none='admin.wizard.select_property'
)}}
</div> </div>
</div> </div>
{{/if}} {{/if}}
<div class="setting full">
<div class="setting-label">
<h3>{{i18n 'admin.wizard.field.prefill'}}</h3>
</div>
<div class="setting-value">
{{wizard-custom-inputs
inputs=field.prefill
userFields=userFields
wizardFields=wizardFields
options=(hash
hasOutput=true
enableConnectors=true
allowWizardField=true
allowUserField=true
)}}
</div>
</div>

Datei anzeigen

@ -0,0 +1,47 @@
<div class="type-selector">
{{input-type-toggle
activeType=activeType
type='text'
toggle=(action 'toggleType')}}
{{#if wizardEnabled}}
{{input-type-toggle
activeType=activeType
type='wizard'
toggle=(action 'toggleType')}}
{{/if}}
{{#if userEnabled}}
{{input-type-toggle
activeType=activeType
type='user'
toggle=(action 'toggleType')}}
{{/if}}
</div>
<div class="input">
{{#if showText}}
{{input
type="text"
value=value
placeholder=(i18n textPlaceholder)}}
{{/if}}
{{#if showWizard}}
{{combo-box
value=value
content=wizardFields
options=(hash
none='admin.wizard.wizard_field'
)}}
{{/if}}
{{#if showUser}}
{{combo-box
value=value
content=userFields
options=(hash
none='admin.wizard.user_field'
)}}
{{/if}}
</div>

Datei anzeigen

@ -0,0 +1,42 @@
<div class="key input-block">
{{wizard-custom-input-chooser
inputType='key'
userFields=userFields
wizardFields=wizardFields
value=pair.key
activeType=pair.key_type
customPlaceholder=keyPlaceholder
options=options}}
</div>
<div class="connector">
{{#if options.enableConnectors}}
{{combo-box
value=pair.connector
content=connectors
options=(hash
none=connectorNone
)}}
{{/if}}
{{#if connectorKey}}
<span class="key-connector">
{{i18n connectorKey}}
</span>
{{/if}}
</div>
<div class="value input-block">
{{wizard-custom-input-chooser
inputType='value'
userFields=userFields
wizardFields=wizardFields
value=pair.value
activeType=pair.value_type
customPlaceholder=valuePlaceholder
options=options}}
</div>
{{#if showRemove}}
<a {{action removePair pair}} class="remove-pair">{{d-icon 'minus'}}</a>
{{/if}}

Datei anzeigen

@ -1,55 +1,50 @@
<div class="key"> {{#if options.hasOutput}}
{{#if keyContent}} {{#if outputPrefixKey}}
{{combo-box value=input.key content=keyContent nameProperty="label" none=noneKey}} <div class="prefix">
{{else}} <span>{{i18n outputPrefixKey}}</span>
{{input type="text" value=input.key placeholder=(i18n inputKey)}}
{{/if}}
</div>
<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">
{{#if valueContent}}
{{combo-box value=input.value
content=valueContent
nameProperty="label"
none=noneValue
isDisabled=valueDisabled}}
{{else}}
{{input type="text" value=input.value placeholder=(i18n valuePlaceholder)}}
{{/if}}
{{#if allowCustomField}}
<div class="text-divider">
<span>{{i18n 'admin.wizard.or'}}</span>
</div> </div>
{{input type="text"
value=input.value_custom
placeholder=(i18n 'admin.wizard.custom_value_placeholder')
disabled=customDisabled}}
{{/if}} {{/if}}
{{/if}}
{{#if allowUserField}} <div class="pairs">
<div class="text-divider"> {{#each input.pairs as |pair|}}
<span>{{i18n 'admin.wizard.or'}}</span> {{wizard-custom-input-pair
</div> pair=pair
keyPlaceholder=keyPlaceholder
{{combo-box value=input.user_field valuePlaceholder=valuePlaceholder
content=userFields userFields=userFields
none='admin.wizard.user_field_placeholder'}} wizardFields=wizardFields
options=options
removePair=(action 'removePair')}}
{{/each}}
{{#if options.hasOutput}}
<a {{action 'addPair'}} class="add-pair">{{d-icon 'plus'}}</a>
{{/if}} {{/if}}
</div> </div>
{{d-button action=remove actionParam=input icon='times' class='remove'}} {{#if options.hasOutput}}
<div class="connector">
{{#if outputConnectorKey}}
<span class="output-connector">
{{i18n outputConnectorKey}}
</span>
{{/if}}
</div>
<div class="output input-block">
{{wizard-custom-input-chooser
inputType='output'
userFields=userFields
wizardFields=wizardFields
value=input.output
activeType=input.output_type
customPlaceholder=outputPlaceholder
options=options}}
</div>
{{/if}}
{{d-button
action=remove
actionParam=input
icon='times'
class='remove-input'}}

Datei anzeigen

@ -1,15 +1,16 @@
{{#each inputs as |input|}} {{#each inputs as |input|}}
{{wizard-custom-input input=input {{wizard-custom-input
valueContent=valueContent input=input
keyContent=keyContent userFields=userFields
connectorContent=connectorContent wizardFields=wizardFields
connectorKey=connectorKey keyPlaceholder=keyPlaceholder
noneValue=noneValue valuePlaceholder=valuePlaceholder
valuePlaceholder=valuePlaceholder connectorContent=connectorContent
allowCustomField=allowCustomField connectorKey=connectorKey
allowUserField=allowUserField options=options
remove=(action 'remove')}} remove=(action 'remove')}}
{{/each}} {{/each}}
<div class="add-custom-input"> <div class="add-custom-input">
{{d-button action='add' label='admin.wizard.add' icon='plus'}} {{d-button action='add' label='admin.wizard.add' icon='plus'}}
</div> </div>

Datei anzeigen

@ -39,7 +39,9 @@
<h3>{{i18n 'admin.wizard.step.description'}}</h3> <h3>{{i18n 'admin.wizard.step.description'}}</h3>
</div> </div>
<div class="setting-value"> <div class="setting-value">
{{d-editor value=step.raw_description placeholder="admin.wizard.custom_text_placeholder"}} {{d-editor
value=step.raw_description
placeholder="admin.wizard.custom_text_placeholder"}}
</div> </div>
</div> </div>
@ -48,10 +50,16 @@
<h3>{{i18n 'admin.wizard.step.required_data.label'}}</h3> <h3>{{i18n 'admin.wizard.step.required_data.label'}}</h3>
</div> </div>
<div class="setting-value"> <div class="setting-value">
{{wizard-custom-inputs inputs=step.required_data {{wizard-custom-inputs
inputKey='admin.wizard.step.required_data.key' inputs=step.required_data
valueContent=requiredContent userFields=userFields
connectorContent=requiredConnectorContent}} wizardFields=wizardFields
keyPlaceholder="admin.wizard.submission_key"
options=(hash
enableConnectors=true
allowWizardField='value'
allowUserField='value'
)}}
{{#if step.required_data}} {{#if step.required_data}}
<div class="required-data-message"> <div class="required-data-message">
<div class="label"> <div class="label">
@ -68,24 +76,36 @@
<h3>{{i18n 'admin.wizard.step.permitted_params.label'}}</h3> <h3>{{i18n 'admin.wizard.step.permitted_params.label'}}</h3>
</div> </div>
<div class="setting-value"> <div class="setting-value">
{{wizard-custom-inputs inputs=step.permitted_params {{wizard-custom-inputs
inputKey='admin.wizard.step.permitted_params.key' inputs=step.permitted_params
valuePlaceholder='admin.wizard.step.permitted_params.value' userFields=userFields
connectorKey='admin.wizard.step.permitted_params.connector'}} wizardFields=wizardFields
keyPlaceholder='admin.wizard.param_key'
valuePlaceholder='admin.wizard.submission_key'
connectorKey='admin.wizard.step.permitted_params.connector'}}
</div> </div>
</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"
userFields=wizard.userFields
wizardFields=wizardFields}}
{{/if}} {{/if}}
{{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-custom-action
wizard=wizard action=currentAction
removeAction="removeAction" wizard=wizard
availableFields=availableFields}} removeAction="removeAction"
wizardFields=wizardFields
userFields=wizard.userFields}}
{{/if}} {{/if}}
<label>{{i18n 'admin.wizard.action.available_fields'}}</label> <label>{{i18n 'admin.wizard.action.available_fields'}}</label>

Datei anzeigen

@ -1,4 +1,4 @@
import { default as computed, observes } from 'ember-addons/ember-computed-decorators'; import { default as computed, observes } from 'discourse-common/utils/decorators';
import { renderAvatar } from 'discourse/helpers/user-avatar'; import { renderAvatar } from 'discourse/helpers/user-avatar';
import userSearch from '../lib/user-search'; import userSearch from '../lib/user-search';

Datei anzeigen

@ -1,5 +1,5 @@
import ComposerEditor from 'discourse/components/composer-editor'; import ComposerEditor from 'discourse/components/composer-editor';
import { default as computed, on } from 'ember-addons/ember-computed-decorators'; import { default as computed, on } from 'discourse-common/utils/decorators';
import { findRawTemplate } from "discourse/lib/raw-templates"; import { findRawTemplate } from "discourse/lib/raw-templates";
import { throttle } from "@ember/runloop"; import { throttle } from "@ember/runloop";
import { scheduleOnce } from "@ember/runloop"; import { scheduleOnce } from "@ember/runloop";

Datei anzeigen

@ -1,4 +1,4 @@
import { observes } from 'ember-addons/ember-computed-decorators'; import { observes } from 'discourse-common/utils/decorators';
import Category from 'discourse/models/category'; import Category from 'discourse/models/category';
export default Ember.Component.extend({ export default Ember.Component.extend({

Datei anzeigen

@ -1,4 +1,4 @@
import { default as computed, observes } from 'ember-addons/ember-computed-decorators'; import { default as computed, observes } from 'discourse-common/utils/decorators';
export default Ember.Component.extend({ export default Ember.Component.extend({
showPreview: false, showPreview: false,

Datei anzeigen

@ -0,0 +1,5 @@
export default Ember.Component.extend({
didInsertElement() {
console.log(this.field)
}
})

Datei anzeigen

@ -1,6 +1,6 @@
/* eslint no-undef: 0 */ /* eslint no-undef: 0 */
import computed from "ember-addons/ember-computed-decorators"; import computed from "discourse-common/utils/decorators";
import { siteDir, isRTL, isLTR } from "discourse/lib/text-direction"; import { siteDir, isRTL, isLTR } from "discourse/lib/text-direction";
export default Ember.TextField.extend({ export default Ember.TextField.extend({

Datei anzeigen

@ -1,4 +1,4 @@
import { default as computed } from 'ember-addons/ember-computed-decorators'; import { default as computed } from 'discourse-common/utils/decorators';
export default { export default {
name: 'custom-routes', name: 'custom-routes',
@ -227,7 +227,8 @@ export default {
'image', 'image',
'user-selector', 'user-selector',
'text-only', 'text-only',
'composer' 'composer',
'group'
]; ];
FieldModel.reopen({ FieldModel.reopen({

Datei anzeigen

@ -1,4 +1,4 @@
import { default as computed } from 'ember-addons/ember-computed-decorators'; import { default as computed } from 'discourse-common/utils/decorators';
import getUrl from 'discourse-common/lib/get-url'; import getUrl from 'discourse-common/lib/get-url';
import WizardField from 'wizard/models/wizard-field'; import WizardField from 'wizard/models/wizard-field';
import { ajax } from 'wizard/lib/ajax'; import { ajax } from 'wizard/lib/ajax';

Datei anzeigen

@ -0,0 +1,7 @@
{{combo-box
content=wizard.groups
value=field.value
onChange=(action (mut field.value))
options=(hash
none='group.select'
)}}

Datei anzeigen

@ -872,3 +872,7 @@ input.input-location, div.input-location {
} }
} }
} }
.select-kit.combo-box.group-dropdown {
min-width: 220px;
}

Datei anzeigen

@ -52,7 +52,6 @@
} }
button { button {
margin-top: 5px;
display: block; display: block;
} }
@ -88,11 +87,6 @@
margin-bottom: 5px; margin-bottom: 5px;
} }
} }
.custom-input .remove {
margin-left: 10px;
margin-top: 0;
}
} }
} }
@ -194,11 +188,45 @@
.custom-input { .custom-input {
display: flex; display: flex;
align-items: center; align-items: flex-start;
margin-bottom: 10px; margin-bottom: 10px;
position: relative;
.type-selector a {
color: $primary;
margin-right: 10px;
&.active {
color: $tertiary;
text-decoration: underline;
}
}
.pairs {
display: flex;
flex-direction: column;
align-items: center;
position: relative;
.add-pair {
margin-top: 4px;
}
.remove-pair {
position: absolute;
top: 25px;
right: -30px;
}
}
.pair {
display: flex;
align-items: flex-end;
position: relative;
margin-bottom: 5px;
}
.d-icon { .d-icon {
margin: 0 auto;
text-align: center; text-align: center;
} }
@ -210,18 +238,38 @@
background-color: $primary-low; background-color: $primary-low;
border-color: #ddd; border-color: #ddd;
} }
.select-kit { .input-block, .select-kit, input {
width: 232px !important; width: 150px;
min-width: 150px;
} }
.remove { button.remove-input {
margin: 0 auto; margin: 21px 0 0 10px;
align-self: flex-start;
} }
.connector { .connector {
margin: 0 10px; margin: 0 10px;
.select-kit {
min-width: 50px;
}
.key-connector {
padding-bottom: 5px;
display: inline-block;
}
.output-connector {
margin-top: 25px;
display: inline-block;
}
}
.prefix {
position: absolute;
left: -20px;
top: 24px;
} }
} }

Datei anzeigen

@ -6,7 +6,8 @@ en:
admin_js: admin_js:
admin: admin:
wizard: wizard:
label: "Wizards" label: "Wizard"
nav: "Wizards"
new: "New" new: "New"
custom_label: "Custom" custom_label: "Custom"
submissions_label: "Submissions" submissions_label: "Submissions"
@ -46,17 +47,30 @@ en:
url: "Url" url: "Url"
key: "Key" key: "Key"
or: "Or" or: "Or"
if: "if"
value: "Value" value: "Value"
output: "Output"
property: "Property"
text: "text"
profile: "profile"
id: "Id" id: "Id"
id_placeholder: "Underscored. Cannot be changed." id_placeholder: "Underscored. Cannot be changed."
key_placeholder: "Translation key" key_placeholder: "Translation key"
custom_text_placeholder: "Overrides translation" custom_text_placeholder: "Overrides translation"
custom_field_placeholder: "Custom Field"
custom_value_placeholder: "Custom Value"
user_field_placeholder: "User Field"
type: "Type" type: "Type"
none: "Make a selection" none: "Make a selection"
user_field: "User Field"
wizard_field: "Wizard Field"
select_field: "Select Field" select_field: "Select Field"
select_property: "Select Property"
profile_field: "Profile Field"
submission_key: 'submission key'
param_key: 'param'
connector:
none: "op"
prefill: "prefill"
equal: "="
error: error:
name_required: "Wizards must have a name." name_required: "Wizards must have a name."
steps_required: "Wizards must have at least one step." steps_required: "Wizards must have at least one step."
@ -68,6 +82,7 @@ en:
field: field:
need_choices: "All dropdowns need choices." need_choices: "All dropdowns need choices."
choices_label_empty: "Custom choice labels cannot be empty." choices_label_empty: "Custom choice labels cannot be empty."
step: step:
header: "Steps" header: "Steps"
title: "Title" title: "Title"
@ -76,15 +91,11 @@ en:
description: "Description" description: "Description"
required_data: required_data:
label: "Required Data" label: "Required Data"
key: 'Submission key'
connector:
equals: "Equals"
not_permitted_message: "Message shown when required data not present" not_permitted_message: "Message shown when required data not present"
permitted_params: permitted_params:
label: "Permitted Params" label: "Permitted Params"
key: 'Param' connector: "save as"
value: 'Submission key'
connector: "Save as"
field: field:
type: "Choose a type" type: "Choose a type"
header: "Fields" header: "Fields"
@ -110,6 +121,8 @@ en:
category: "Category" category: "Category"
limit: "Limit" limit: "Limit"
property: "Property" property: "Property"
prefill: "Prefill"
action: action:
header: "Actions<sup>*</sup>" header: "Actions<sup>*</sup>"
include: "Include Fields" include: "Include Fields"
@ -132,7 +145,6 @@ en:
tags: "Tags" tags: "Tags"
update_profile: update_profile:
label: "Update Profile" label: "Update Profile"
profile_field: "Profile Field"
post_builder: post_builder:
checkbox: "Post Builder" checkbox: "Post Builder"
label: "Builder" label: "Builder"
@ -142,8 +154,9 @@ en:
add_to_group: add_to_group:
label: "Add to Group" label: "Add to Group"
group: "Group" group: "Group"
group_selection: "Group Selection" group_selection: "Field"
custom_group: "Custom Group" custom_group: "Custom"
property: "Property"
route_to: route_to:
label: "Route To" label: "Route To"
url: "Url" url: "Url"
@ -151,7 +164,6 @@ en:
custom_title: "Custom Title" custom_title: "Custom Title"
custom_category: custom_category:
label: "Custom Category" label: "Custom Category"
wizard_field: "Wizard Field"
user_field: "User Field" user_field: "User Field"
custom_tag: custom_tag:
label: "Custom Tag" label: "Custom Tag"
@ -230,6 +242,9 @@ en:
file_size_error: "The file must be JSON and 512kb or less" file_size_error: "The file must be JSON and 512kb or less"
wizard_js: wizard_js:
group:
select: "Select a group"
location: location:
name: name:
title: "Name (optional)" title: "Name (optional)"

Datei anzeigen

@ -44,6 +44,9 @@ class CustomWizard::Builder
USER_FIELDS = ['name', 'username', 'email', 'date_of_birth', 'title', 'locale'] USER_FIELDS = ['name', 'username', 'email', 'date_of_birth', 'title', 'locale']
PROFILE_FIELDS = ['location', 'website', 'bio_raw', 'profile_background', 'card_background'] PROFILE_FIELDS = ['location', 'website', 'bio_raw', 'profile_background', 'card_background']
OPERATORS = {
'equal': '=='
}
def self.fill_placeholders(string, user, data) def self.fill_placeholders(string, user, data)
result = string.gsub(/u\{(.*?)\}/) do |match| result = string.gsub(/u\{(.*?)\}/) do |match|
@ -99,8 +102,9 @@ class CustomWizard::Builder
permitted_data = {} permitted_data = {}
permitted_params.each do |p| permitted_params.each do |p|
params_key = p['key'].to_sym pair = p['pairs'].first
submission_key = p['value'].to_sym params_key = pair['key'].to_sym
submission_key = pair['value'].to_sym
permitted_data[submission_key] = params[params_key] if params[params_key] permitted_data[submission_key] = params[params_key] if params[params_key]
end end
@ -110,21 +114,32 @@ class CustomWizard::Builder
end end
end end
if required_data = step_template['required_data'] if (required_data = step_template['required_data']).present?
if !@submissions.last && required_data.present? has_required_data = true
step.permitted = false pairs =
next
end required_data.each do |required|
required['pairs'].each do |pair|
required_data.each do |rd| if pair['key'].blank? || pair['value'].blank?
if rd['connector'] === 'equals' has_required_data = false
step.permitted = @submissions.last[rd['key']] == @submissions.last[rd['value']] end
end end
end end
if !step.permitted if has_required_data
step.permitted_message = step_template['required_data_message'] if step_template['required_data_message'] if !@submissions.last
next step.permitted = false
else
required_data.each do |required|
pairs = required['pairs'].map { |p| p['value'] = @submissions.last[p['value']] }
step.permitted = false unless validate_pairs(pairs)
end
end
if !step.permitted
step.permitted_message = step_template['required_data_message'] if step_template['required_data_message']
next
end
end end
end end
@ -217,18 +232,7 @@ class CustomWizard::Builder
params[:value] = submission[field_template['id']] if submission[field_template['id']] params[:value] = submission[field_template['id']] if submission[field_template['id']]
end end
## If a field updates a profile field, load the current value params[:value] = prefill_field(field_template, step_template) || params[:value]
if step_template['actions'] && step_template['actions'].any?
profile_actions = step_template['actions'].select { |a| a['type'] === 'update_profile' }
if profile_actions.any?
profile_actions.each do |action|
if update = action['profile_updates'].select { |u| u['key'] === field_template['id'] }.first
params[:value] = prefill_profile_field(update) || params[:value]
end
end
end
end
if field_template['type'] === 'checkbox' if field_template['type'] === 'checkbox'
params[:value] = standardise_boolean(params[:value]) params[:value] = standardise_boolean(params[:value])
@ -253,6 +257,8 @@ class CustomWizard::Builder
if field_template['type'] === 'group' if field_template['type'] === 'group'
@wizard.needs_groups = true @wizard.needs_groups = true
end end
puts "ADDING FIELD: #{params.inspect}"
field = step.add_field(params) field = step.add_field(params)
@ -260,24 +266,81 @@ class CustomWizard::Builder
build_dropdown_list(field, field_template) build_dropdown_list(field, field_template)
end end
end end
def prefill_field(field_template, step_template)
if (prefill = field_template['prefill']).present?
output = nil
prefill.each do |item|
puts "PREFIL: #{item.inspect}"
if validate_pairs(item['pairs'])
puts "OUTPUT: #{get_field(item['output'], item['output_type'])}"
output = get_field(item['output'], item['output_type'])
end
end
output
else
actions = step_template['actions']
if actions && actions.any?
profile_actions = actions.select { |a| a['type'] === 'update_profile' } || []
def prefill_profile_field(update) profile_actions.each do |action|
attribute = update['value'] update = action['profile_updates'].select { |u| u['key'] === field_template['id'] }.first
custom_field = update['value_custom'] get_user_field(update['value']) if update
user_field = update['user_field'] end
end
end
end
def validate_pairs(pairs)
failed = false
pairs.each do |pair|
puts "PAIR: #{pair.inspect}"
key = get_field(pair['key'], pair['key_type'])
value = get_field(pair['value'], pair['value_type'])
puts "KEY VALUE: #{key.inspect}; #{value.inspect}"
failed = true unless key.public_send(get_operator(pair['connector']), value)
end
!failed
end
def get_operator(connector)
OPERATORS[connector] || '=='
end
def get_field(value, type)
method = "get_#{type}_field"
if self.respond_to?(method)
self.send(method, value)
else
value
end
end
def get_wizard_field(value)
@submissions.last &&
!@submissions.last.key?("submitted_at") &&
@submissions.last[value]
end
if user_field || custom_field def get_user_field(value)
UserCustomField.where(user_id: @wizard.user.id, name: user_field || custom_field).pluck(:value).first puts "GETTING USER FIELD: #{value.inspect}"
elsif UserProfile.column_names.include? attribute if value.include?('user_field_')
UserProfile.find_by(user_id: @wizard.user.id).send(attribute) UserCustomField.where(user_id: @wizard.user.id, name: value).pluck(:value).first
elsif User.column_names.include? attribute elsif UserProfile.column_names.include? value
User.find(@wizard.user.id).send(attribute) UserProfile.find_by(user_id: @wizard.user.id).send(value)
elsif User.column_names.include? value
User.find(@wizard.user.id).send(value)
end end
end end
def build_dropdown_list(field, template) def build_dropdown_list(field, template)
field.dropdown_none = template['dropdown_none'] if template['dropdown_none'] field.dropdown_none = template['dropdown_none'] if template['dropdown_none']
self.send("build_dropdown_#{template['choices_type']}", field, template) method = "build_dropdown_#{template['choices_type']}"
self.send(method, field, template) if self.respond_to?(method)
end end
def build_dropdown_custom(field, template) def build_dropdown_custom(field, template)
@ -552,8 +615,8 @@ class CustomWizard::Builder
end end
def add_to_group(user, action, data) def add_to_group(user, action, data)
if group_id = data[action['group_id']] if value = data[action['value']]
if group = Group.find(group_id) if group = Group.where("#{action['property']} = '#{value}'").first
group.add(user) group.add(user)
end end
end end

Datei anzeigen

@ -1,6 +1,6 @@
class CustomWizard::Field class CustomWizard::Field
def self.types def self.types
@types ||= ['checkbox', 'composer', 'dropdown', 'tag', 'category', 'image', 'text', 'textarea', 'text-only', 'upload', 'user-selector'] @types ||= ['checkbox', 'composer', 'dropdown', 'tag', 'category', 'group', 'image', 'text', 'textarea', 'text-only', 'upload', 'user-selector']
end end
def self.require_assets def self.require_assets

Datei anzeigen

@ -21,7 +21,8 @@ class CustomWizard::Wizard
:required, :required,
:prompt_completion, :prompt_completion,
:restart_on_revisit, :restart_on_revisit,
:needs_categories :needs_categories,
:needs_groups
def initialize(user=nil, attrs = {}) def initialize(user=nil, attrs = {})
@steps = [] @steps = []
@ -29,6 +30,7 @@ class CustomWizard::Wizard
@first_step = nil @first_step = nil
@required = false @required = false
@needs_categories = false @needs_categories = false
@needs_groups = false
attrs.each do |key, value| attrs.each do |key, value|
setter = "#{key}=" setter = "#{key}="
@ -140,6 +142,10 @@ class CustomWizard::Wizard
def categories def categories
@categories ||= ::Site.new(Guardian.new(@user)).categories @categories ||= ::Site.new(Guardian.new(@user)).categories
end end
def groups
@groups ||= ::Site.new(Guardian.new(@user)).groups
end
def self.after_signup def self.after_signup
rows = PluginStoreRow.where(plugin_name: 'custom_wizard') rows = PluginStoreRow.where(plugin_name: 'custom_wizard')

Datei anzeigen

@ -14,6 +14,7 @@ class CustomWizardSerializer < ::WizardSerializer
has_one :user, serializer: ::BasicUserSerializer, embed: :objects has_one :user, serializer: ::BasicUserSerializer, embed: :objects
has_many :steps, serializer: ::CustomWizardStepSerializer, embed: :objects has_many :steps, serializer: ::CustomWizardStepSerializer, embed: :objects
has_many :categories, serializer: ::BasicCategorySerializer, embed: :objects has_many :categories, serializer: ::BasicCategorySerializer, embed: :objects
has_many :groups, serializer: ::BasicGroupSerializer, embed: :objects
def completed def completed
object.completed? object.completed?
@ -41,6 +42,10 @@ class CustomWizardSerializer < ::WizardSerializer
object.needs_categories object.needs_categories
end end
def include_groups?
object.needs_groups
end
def uncategorized_category_id def uncategorized_category_id
SiteSetting.uncategorized_category_id SiteSetting.uncategorized_category_id
end end