From fe7283ab3c1c90aa545f675381d97f4052ccea59 Mon Sep 17 00:00:00 2001 From: Angus McLeod Date: Tue, 24 Mar 2020 20:35:46 +1100 Subject: [PATCH] Add content conditionals --- .../components/wizard-custom-field.js.es6 | 44 +++++++---- .../wizard-custom-input-chooser.js.es6 | 52 ------------ .../wizard-custom-input-pair.js.es6 | 2 +- .../wizard-custom-input-selector.js.es6 | 71 +++++++++++++++++ .../components/wizard-custom-input.js.es6 | 44 ++++++++++- ...puts.js.es6 => wizard-field-mapper.js.es6} | 2 +- .../discourse/lib/custom-wizard.js.es6 | 54 +++++++++++-- .../components/wizard-custom-action.hbs | 22 +++--- .../components/wizard-custom-field.hbs | 22 +++++- .../components/wizard-custom-input-pair.hbs | 10 ++- ...r.hbs => wizard-custom-input-selector.hbs} | 25 +++--- .../components/wizard-custom-input.hbs | 39 ++++----- .../components/wizard-custom-step.hbs | 8 +- ...tom-inputs.hbs => wizard-field-mapper.hbs} | 0 .../wizard-category-selector.js.es6 | 12 +++ .../components/wizard-group-selector.js.es6 | 12 +++ .../components/wizard-tag-selector.js.es6 | 11 +++ .../components/wizard-field-category.hbs | 3 +- .../components/wizard-field-group.hbs | 5 +- assets/stylesheets/wizard_custom_admin.scss | 52 ++++++++---- config/locales/client.en.yml | 11 ++- lib/custom_wizard/builder.rb | 79 ++++++++++++++----- lib/wizard/field.rb | 4 +- .../custom_wizard/wizard_field_serializer.rb | 7 +- 24 files changed, 414 insertions(+), 177 deletions(-) delete mode 100644 assets/javascripts/discourse/components/wizard-custom-input-chooser.js.es6 create mode 100644 assets/javascripts/discourse/components/wizard-custom-input-selector.js.es6 rename assets/javascripts/discourse/components/{wizard-custom-inputs.js.es6 => wizard-field-mapper.js.es6} (93%) rename assets/javascripts/discourse/templates/components/{wizard-custom-input-chooser.hbs => wizard-custom-input-selector.hbs} (80%) rename assets/javascripts/discourse/templates/components/{wizard-custom-inputs.hbs => wizard-field-mapper.hbs} (100%) create mode 100644 assets/javascripts/wizard/components/wizard-category-selector.js.es6 create mode 100644 assets/javascripts/wizard/components/wizard-group-selector.js.es6 create mode 100644 assets/javascripts/wizard/components/wizard-tag-selector.js.es6 diff --git a/assets/javascripts/discourse/components/wizard-custom-field.js.es6 b/assets/javascripts/discourse/components/wizard-custom-field.js.es6 index 2777f4ef..654fea42 100644 --- a/assets/javascripts/discourse/components/wizard-custom-field.js.es6 +++ b/assets/javascripts/discourse/components/wizard-custom-field.js.es6 @@ -1,5 +1,5 @@ import { default as computed, observes, on } from 'discourse-common/utils/decorators'; -import { equal, not } from "@ember/object/computed"; +import { equal, not, or } from "@ember/object/computed"; import { generateSelectKitContent } from '../lib/custom-wizard'; export default Ember.Component.extend({ @@ -34,25 +34,35 @@ export default Ember.Component.extend({ let options = { hasOutput: true, enableConnectors: true, - allowWizard: true, - allowUser: true + wizardFieldSelection: true, + userFieldSelection: true } - if (isCategory) { - options.allowUser = 'key,value'; - options.allowCategory = 'output'; - } - - if (isGroup) { - options.allowUser = 'key,value'; - options.allowGroup = 'output'; - } - - if (isTag) { - options.allowUser = 'key,value'; - options.allowTag = 'output'; + if (isCategory || isGroup || isTag) { + options.userFieldSelection = 'key,value'; + options[`${this.field.type}Selection`] = 'output'; } return options; - } + }, + + canFilter: or('isCategory', 'isTag', 'isGroup'), + + @computed('field.type') + filterOptions(fieldType) { + if (!this.canFilter) return {}; + + let options = { + hasOutput: true, + enableConnectors: true, + wizardFieldSelection: 'key,value', + userFieldSelection: 'key,value', + textDisabled: 'output' + } + + options[`${this.field.type}Selection`] = 'output'; + options[`${this.field.type}AllowMultiple`] = true; + + return options; + }, }); diff --git a/assets/javascripts/discourse/components/wizard-custom-input-chooser.js.es6 b/assets/javascripts/discourse/components/wizard-custom-input-chooser.js.es6 deleted file mode 100644 index 9dd44751..00000000 --- a/assets/javascripts/discourse/components/wizard-custom-input-chooser.js.es6 +++ /dev/null @@ -1,52 +0,0 @@ -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'; - }, - - showText: equal('activeType', 'text'), - - showInput(type) { - return this.activeType === type && this[`${type}Enabled`]; - }, - - showWizard: computed('activeType', function() { return this.showInput('wizard') }), - showUser: computed('activeType', function() { return this.showInput('user') }), - showCategory: computed('activeType', function() { return this.showInput('category') }), - showTag: computed('activeType', function() { return this.showInput('tag') }), - showGroup: computed('activeType', function() { return this.showInput('group') }), - - optionEnabled(type) { - const options = this.options; - if (!options) return false; - - const option = options[type]; - if (option === true) return true; - if (typeof option !== 'string') return false; - return option.split(',').indexOf(this.inputType) > -1; - }, - - wizardEnabled: computed('options.allowWizard', function() { return this.optionEnabled('allowWizard') }), - userEnabled: computed('options.allowUser', function() { return this.optionEnabled('allowUser') }), - categoryEnabled: computed('options.allowCategory', function() { return this.optionEnabled('allowCategory') }), - tagEnabled: computed('options.allowTag', function() { return this.optionEnabled('allowTag') }), - groupEnabled: computed('options.allowGroup', function() { return this.optionEnabled('allowGroup') }), - - actions: { - toggleType(type) { - this.set('activeType', type); - } - } -}) \ No newline at end of file diff --git a/assets/javascripts/discourse/components/wizard-custom-input-pair.js.es6 b/assets/javascripts/discourse/components/wizard-custom-input-pair.js.es6 index e2045b64..26a90c47 100644 --- a/assets/javascripts/discourse/components/wizard-custom-input-pair.js.es6 +++ b/assets/javascripts/discourse/components/wizard-custom-input-pair.js.es6 @@ -3,7 +3,7 @@ import { gt, or, alias } from "@ember/object/computed"; import { computed, observes} from "@ember/object"; export default Ember.Component.extend({ - classNames: 'pair', + classNameBindings: [':input-pair', 'hasConnector::no-connector'], connectors: connectors, hasConnector: or('options.enableConnectors', 'connectorKey'), firstPair: gt('pair.index', 0), diff --git a/assets/javascripts/discourse/components/wizard-custom-input-selector.js.es6 b/assets/javascripts/discourse/components/wizard-custom-input-selector.js.es6 new file mode 100644 index 00000000..7c1067aa --- /dev/null +++ b/assets/javascripts/discourse/components/wizard-custom-input-selector.js.es6 @@ -0,0 +1,71 @@ +import { alias, equal } from "@ember/object/computed"; +import { computed } from "@ember/object"; +import { + default as discourseComputed, + observes +} from "discourse-common/utils/decorators"; +import { defaultSelectionType } from '../lib/custom-wizard'; + +export default Ember.Component.extend({ + classNames: 'input-selector', + groups: alias('site.groups'), + categories: computed(function() { + return this.site.categories.map(c => ({ id: c.id, name: c.name })); + }), + + @observes('options.@each') + resetActiveType() { + this.set('activeType', defaultSelectionType(this.selectorType, this.options)); + }, + + @observes('activeType') + clearValue() { + this.set('value', null); + }, + + @discourseComputed('customPlaceholder') + textPlaceholder(customPlaceholder) { + return customPlaceholder || 'admin.wizard.text'; + }, + + showText: equal('activeType', 'text'), + + showInput(type) { + return this.activeType === type && this[`${type}Enabled`] && !this[`${type}Disabled`]; + }, + + showWizard: computed('activeType', function() { return this.showInput('wizard') }), + showUser: computed('activeType', function() { return this.showInput('user') }), + showCategory: computed('activeType', function() { return this.showInput('category') }), + showTag: computed('activeType', function() { return this.showInput('tag') }), + showGroup: computed('activeType', function() { return this.showInput('group') }), + + optionEnabled(type) { + const options = this.options; + if (!options) return false; + + const option = options[type]; + + if (option === true) return true; + if (typeof option !== 'string') return false; + + const types = [this.selectorType, this.inputType]; + + console.log('running', types, option) + + return option.split(',').filter(o => types.indexOf(o) !== -1).length + }, + + textDisabled: computed('options.textDisabled', 'inputType', function() { return this.optionEnabled('textDisabled') }), + wizardEnabled: computed('options.wizardFieldSelection', 'inputType', function() { return this.optionEnabled('wizardFieldSelection') }), + userEnabled: computed('options.userFieldSelection', 'inputType', function() { return this.optionEnabled('userFieldSelection') }), + categoryEnabled: computed('options.categorySelection', 'inputType', function() { return this.optionEnabled('categorySelection') }), + tagEnabled: computed('options.tagSelection', 'inputType', function() { return this.optionEnabled('tagSelection') }), + groupEnabled: computed('options.groupSelection', 'inputType', function() { return this.optionEnabled('groupSelection') }), + + actions: { + toggleType(type) { + this.set('activeType', type); + } + } +}) \ No newline at end of file diff --git a/assets/javascripts/discourse/components/wizard-custom-input.js.es6 b/assets/javascripts/discourse/components/wizard-custom-input.js.es6 index 0c69a9c3..0858fb7c 100644 --- a/assets/javascripts/discourse/components/wizard-custom-input.js.es6 +++ b/assets/javascripts/discourse/components/wizard-custom-input.js.es6 @@ -1,12 +1,48 @@ -import { newPair } from '../lib/custom-wizard'; +import { + newPair, + generateSelectKitContent, + defaultInputType +} from '../lib/custom-wizard'; +import { + default as discourseComputed, + on +} from 'discourse-common/utils/decorators'; import { computed } from "@ember/object"; +import { alias } from "@ember/object/computed"; export default Ember.Component.extend({ - classNames: 'custom-input', - outputConnector: computed(function() { - return I18n.t(this.outputConnectorKey || 'admin.wizard.output.connector').toLowerCase(); + classNameBindings: [':custom-input', 'type'], + inputType: alias('input.type'), + outputConnector: computed('inputTypes', function() { + const key = this.outputConnectorKey || `admin.wizard.input.${this.type}.output`; + return I18n.t(key).toLowerCase(); }), + @on('init') + setDefaults() { + if (!this.type) this.set('type', defaultInputType(this.options)); + }, + + @discourseComputed + inputTypes() { + return ['conditional', 'assignment'].map((type) => { + return { + id: type, + name: I18n.t(`admin.wizard.input.${type}.prefix`) + } + }); + }, + + @discourseComputed('options.hasOutput', 'input.type') + hasPairs(hasOutput, inputType) { + return !hasOutput || inputType === 'conditional'; + }, + + @discourseComputed('input.type') + hasOutputConnector(inputType) { + return inputType === 'conditional'; + }, + actions: { addPair() { const pairs = this.get('input.pairs'); diff --git a/assets/javascripts/discourse/components/wizard-custom-inputs.js.es6 b/assets/javascripts/discourse/components/wizard-field-mapper.js.es6 similarity index 93% rename from assets/javascripts/discourse/components/wizard-custom-inputs.js.es6 rename to assets/javascripts/discourse/components/wizard-field-mapper.js.es6 index 7468744a..a0b352f0 100644 --- a/assets/javascripts/discourse/components/wizard-custom-inputs.js.es6 +++ b/assets/javascripts/discourse/components/wizard-field-mapper.js.es6 @@ -3,7 +3,7 @@ import { on } from 'discourse-common/utils/decorators'; import { newInput } from '../lib/custom-wizard'; export default Ember.Component.extend({ - classNames: 'custom-inputs', + classNames: 'field-mapper', actions: { add() { diff --git a/assets/javascripts/discourse/lib/custom-wizard.js.es6 b/assets/javascripts/discourse/lib/custom-wizard.js.es6 index cc7ba277..90c7036c 100644 --- a/assets/javascripts/discourse/lib/custom-wizard.js.es6 +++ b/assets/javascripts/discourse/lib/custom-wizard.js.es6 @@ -53,28 +53,68 @@ const actionTypes = [ 'open_composer' ]; +const selectionTypes = [ + 'text', + 'wizardField', + 'userField', + 'group', + 'category', + 'tag' +] + +const inputTypes = [ + 'pair', + 'conditional', + 'assignment' +] + +function defaultInputType(options = {}) { + return options.hasOutput ? 'conditional' : 'pair'; +} + +function defaultSelectionType(inputType, options = {}) { + const textDisabled = options.textDisabled; + let type = 'text'; + + if (textDisabled === true || + ((typeof textDisabled == 'string') && textDisabled.indexOf(inputType) > -1)) { + + for (let t of selectionTypes) { + let inputTypes = options[`${t}Selection`]; + + if (inputTypes === true || + ((typeof inputTypes == 'string') && inputTypes.indexOf(inputType) > -1)) { + + type = t; + break; + } + } + } + + return type; +} + function newInput(options = {}) { - let params = { + let params = { + type: defaultInputType(options), pairs: Ember.A([newPair({ index: 0, pairCount: 1 })]) } if (options.hasOutput) { - params['output'] = ''; - params['output_type'] = 'text'; + params['output_type'] = defaultSelectionType('output', options); } return Ember.Object.create(params); } function newPair(options = {}) { - console.log('newPair: ', options) let params = { index: options.index, pairCount: options.pairCount, key: '', - key_type: 'text', + key_type: defaultSelectionType('text', options), value: '', - value_type: 'text', + value_type: defaultSelectionType('text', options), connector: 'eq' } @@ -86,6 +126,8 @@ export { profileFields, actionTypes, generateName, + defaultInputType, + defaultSelectionType, connectors, newInput, newPair diff --git a/assets/javascripts/discourse/templates/components/wizard-custom-action.hbs b/assets/javascripts/discourse/templates/components/wizard-custom-action.hbs index 2e639b46..7f6085de 100644 --- a/assets/javascripts/discourse/templates/components/wizard-custom-action.hbs +++ b/assets/javascripts/discourse/templates/components/wizard-custom-action.hbs @@ -170,12 +170,12 @@ {{#if createTopic}}
- {{wizard-custom-inputs + {{wizard-field-mapper inputs=action.add_fields userFields=userFields wizardFields=wizardFields options=(hash - allowWizard=true + wizardFieldSelection=true )}}
{{/if}} @@ -212,7 +212,7 @@
- {{wizard-custom-inputs + {{wizard-field-mapper inputs=action.add_fields userFields=userFields wizardFields=wizardFields}} @@ -222,13 +222,13 @@ {{#if updateProfile}}
- {{wizard-custom-inputs + {{wizard-field-mapper inputs=action.profile_updates userFields=userFields wizardFields=wizardFields options=(hash - allowWizard=true - allowUser=true + wizardFieldSelection=true + userFieldSelection=true )}}
{{/if}} @@ -284,17 +284,17 @@

{{i18n "admin.wizard.action.add_to_group.group"}}

- {{wizard-custom-inputs - inputs=action.selection + {{wizard-field-mapper + inputs=action.inputs userFields=userFields wizardFields=wizardFields outputConnectorKey='admin.wizard.action.add_to_group.output_connector' options=(hash hasOutput=true enableConnectors=true - allowWizard='key,value' - allowUser='key,value' - allowGroup='value,output' + wizardFieldSelection='key,value,assignment' + userFieldSelection='key,value,assignment' + groupSelection='value,output' )}}
diff --git a/assets/javascripts/discourse/templates/components/wizard-custom-field.hbs b/assets/javascripts/discourse/templates/components/wizard-custom-field.hbs index 697fed25..32f58dd8 100644 --- a/assets/javascripts/discourse/templates/components/wizard-custom-field.hbs +++ b/assets/javascripts/discourse/templates/components/wizard-custom-field.hbs @@ -102,7 +102,7 @@
{{i18n 'admin.wizard.field.choices_custom'}}
- {{wizard-custom-inputs + {{wizard-field-mapper inputs=field.choices userFields=userFields wizardFields=wizardFields}} @@ -153,16 +153,30 @@ {{/if}} -
+

{{i18n 'admin.wizard.field.prefill'}}

- {{wizard-custom-inputs + {{wizard-field-mapper inputs=field.prefill userFields=userFields wizardFields=wizardFields - outputConnectorKey='admin.wizard.field.prefill' options=prefillOptions}}
+ +{{#if canFilter}} +
+
+

{{i18n 'admin.wizard.field.filter'}}

+
+
+ {{wizard-field-mapper + inputs=field.filters + userFields=userFields + wizardFields=wizardFields + options=filterOptions}} +
+
+{{/if}} diff --git a/assets/javascripts/discourse/templates/components/wizard-custom-input-pair.hbs b/assets/javascripts/discourse/templates/components/wizard-custom-input-pair.hbs index dcc7fc46..41dbd3e9 100644 --- a/assets/javascripts/discourse/templates/components/wizard-custom-input-pair.hbs +++ b/assets/javascripts/discourse/templates/components/wizard-custom-input-pair.hbs @@ -1,6 +1,7 @@
- {{wizard-custom-input-chooser - inputType='key' + {{wizard-custom-input-selector + selectorType='key' + inputType=inputType userFields=userFields wizardFields=wizardFields value=pair.key @@ -26,8 +27,9 @@ {{/if}}
- {{wizard-custom-input-chooser - inputType='value' + {{wizard-custom-input-selector + selectorType='value' + inputType=inputType userFields=userFields wizardFields=wizardFields value=pair.value diff --git a/assets/javascripts/discourse/templates/components/wizard-custom-input-chooser.hbs b/assets/javascripts/discourse/templates/components/wizard-custom-input-selector.hbs similarity index 80% rename from assets/javascripts/discourse/templates/components/wizard-custom-input-chooser.hbs rename to assets/javascripts/discourse/templates/components/wizard-custom-input-selector.hbs index 4bf9d212..30f40653 100644 --- a/assets/javascripts/discourse/templates/components/wizard-custom-input-chooser.hbs +++ b/assets/javascripts/discourse/templates/components/wizard-custom-input-selector.hbs @@ -1,8 +1,10 @@
- {{input-type-toggle - activeType=activeType - type='text' - toggle=(action 'toggleType')}} + {{#unless textDisabled}} + {{input-type-toggle + activeType=activeType + type='text' + toggle=(action 'toggleType')}} + {{/unless}} {{#if wizardEnabled}} {{input-type-toggle @@ -69,19 +71,24 @@ {{/if}} {{#if showCategory}} - {{category-chooser value=value}} + {{multi-select + content=categories + value=value + onChange=(action (mut value)) + options=(hash + none='admin.wizard.select_category' + )}} {{/if}} {{#if showTag}} {{tag-chooser tags=value - filterable=true - allowCreate=true}} + filterable=true}} {{/if}} {{#if showGroup}} - {{combo-box - content=site.groups + {{multi-select + content=groups value=value onChange=(action (mut value)) options=(hash diff --git a/assets/javascripts/discourse/templates/components/wizard-custom-input.hbs b/assets/javascripts/discourse/templates/components/wizard-custom-input.hbs index 998c0bd8..c49a7dd6 100644 --- a/assets/javascripts/discourse/templates/components/wizard-custom-input.hbs +++ b/assets/javascripts/discourse/templates/components/wizard-custom-input.hbs @@ -1,18 +1,18 @@ {{#if options.hasOutput}} -
+
{{combo-box value=input.type - contents=inputTypes - onChange=(mut (input.prefix))}} + content=inputTypes}}
{{/if}} {{#if hasPairs}} -
+
{{#each input.pairs as |pair|}} {{wizard-custom-input-pair pair=pair last=pair.last + inputType=inputType keyPlaceholder=keyPlaceholder valuePlaceholder=valuePlaceholder userFields=userFields @@ -21,21 +21,26 @@ removePair=(action 'removePair')}} {{/each}} {{#if options.hasOutput}} - {{d-icon 'plus'}} + + {{d-icon 'plus'}} + {{/if}}
-{{/if }} +{{/if}} {{#if options.hasOutput}} -
- - {{outputConnector}} - -
+ {{#if hasOutputConnector}} +
+ + {{outputConnector}} + +
+ {{/if}}
- {{wizard-custom-input-chooser - inputType='output' + {{wizard-custom-input-selector + selectorType='output' + inputType=inputType userFields=userFields wizardFields=wizardFields value=input.output @@ -45,8 +50,6 @@
{{/if}} -{{d-button - action=remove - actionParam=input - icon='times' - class='remove-input'}} + + {{d-icon 'times'}} + diff --git a/assets/javascripts/discourse/templates/components/wizard-custom-step.hbs b/assets/javascripts/discourse/templates/components/wizard-custom-step.hbs index 29376aec..50af2ee8 100644 --- a/assets/javascripts/discourse/templates/components/wizard-custom-step.hbs +++ b/assets/javascripts/discourse/templates/components/wizard-custom-step.hbs @@ -50,15 +50,15 @@

{{i18n 'admin.wizard.step.required_data.label'}}

- {{wizard-custom-inputs + {{wizard-field-mapper inputs=step.required_data userFields=userFields wizardFields=wizardFields keyPlaceholder="admin.wizard.submission_key" options=(hash enableConnectors=true - allowWizard='value' - allowUser='value' + wizardFieldSelection='value' + userFieldSelection='value' )}} {{#if step.required_data}}
@@ -76,7 +76,7 @@

{{i18n 'admin.wizard.step.permitted_params.label'}}

- {{wizard-custom-inputs + {{wizard-field-mapper inputs=step.permitted_params userFields=userFields wizardFields=wizardFields diff --git a/assets/javascripts/discourse/templates/components/wizard-custom-inputs.hbs b/assets/javascripts/discourse/templates/components/wizard-field-mapper.hbs similarity index 100% rename from assets/javascripts/discourse/templates/components/wizard-custom-inputs.hbs rename to assets/javascripts/discourse/templates/components/wizard-field-mapper.hbs diff --git a/assets/javascripts/wizard/components/wizard-category-selector.js.es6 b/assets/javascripts/wizard/components/wizard-category-selector.js.es6 new file mode 100644 index 00000000..98c032cc --- /dev/null +++ b/assets/javascripts/wizard/components/wizard-category-selector.js.es6 @@ -0,0 +1,12 @@ +import CategorySelector from 'discourse/components/category-selector'; +import { computed } from "@ember/object"; +import { makeArray } from "discourse-common/lib/helpers"; + +export default CategorySelector.extend({ + content: computed("categories.[]", "blacklist.[]", "whitelist.[]", function() { + return this._super().filter(category => { + const whitelist = makeArray(this.whitelist); + return !whitelist.length || whitelist.indexOf(category.id) > -1; + }); + }) +}) \ No newline at end of file diff --git a/assets/javascripts/wizard/components/wizard-group-selector.js.es6 b/assets/javascripts/wizard/components/wizard-group-selector.js.es6 new file mode 100644 index 00000000..af21db23 --- /dev/null +++ b/assets/javascripts/wizard/components/wizard-group-selector.js.es6 @@ -0,0 +1,12 @@ +import ComboBox from 'select-kit/components/combo-box'; +import { computed } from "@ember/object"; +import { makeArray } from "discourse-common/lib/helpers"; + +export default ComboBox.extend({ + content: computed("groups.[]", "whitelist.[]", function() { + const whitelist = makeArray(this.whitelist); + return this.groups.filter(group => { + return !whitelist.length || whitelist.indexOf(group.id) > -1; + }); + }) +}) \ No newline at end of file diff --git a/assets/javascripts/wizard/components/wizard-tag-selector.js.es6 b/assets/javascripts/wizard/components/wizard-tag-selector.js.es6 new file mode 100644 index 00000000..24acf2e2 --- /dev/null +++ b/assets/javascripts/wizard/components/wizard-tag-selector.js.es6 @@ -0,0 +1,11 @@ +import TagChooser from 'select-kit/components/tag-chooser'; +import { makeArray } from "discourse-common/lib/helpers"; + +export default TagChooser.extend({ + _transformJson(context, json) { + return this._super(context, json).filter((tag) => { + const whitelist = makeArray(context.whitelist); + return !whitelist.length || whitelist.indexOf(tag.id) > 1; + }); + } +}) \ No newline at end of file diff --git a/assets/javascripts/wizard/templates/components/wizard-field-category.hbs b/assets/javascripts/wizard/templates/components/wizard-field-category.hbs index 904dd414..5ea598a3 100644 --- a/assets/javascripts/wizard/templates/components/wizard-field-category.hbs +++ b/assets/javascripts/wizard/templates/components/wizard-field-category.hbs @@ -1,5 +1,6 @@ -{{category-selector +{{wizard-category-selector categories=categories + whitelist=field.filter maximum=field.limit onChange=(action (mut categories))}} diff --git a/assets/javascripts/wizard/templates/components/wizard-field-group.hbs b/assets/javascripts/wizard/templates/components/wizard-field-group.hbs index 124f56fb..dc7be340 100644 --- a/assets/javascripts/wizard/templates/components/wizard-field-group.hbs +++ b/assets/javascripts/wizard/templates/components/wizard-field-group.hbs @@ -1,5 +1,6 @@ -{{combo-box - content=wizard.groups +{{wizard-group-selector + groups=wizard.groups + whitelist=field.filter value=field.value onChange=(action (mut field.value)) options=(hash diff --git a/assets/stylesheets/wizard_custom_admin.scss b/assets/stylesheets/wizard_custom_admin.scss index 030da895..56727b1c 100644 --- a/assets/stylesheets/wizard_custom_admin.scss +++ b/assets/stylesheets/wizard_custom_admin.scss @@ -31,7 +31,6 @@ .admin-wizard.settings { margin-left: 30px; - margin-right: 30px; .setting { display: inline-block; @@ -70,6 +69,28 @@ &.full { width: 100%; + + &.custom-inputs { + padding-bottom: 30px; + + .setting-label { + margin-top: 20px; + } + + .add-custom-input:first-child { + margin-top: 16px; + } + + .multi-select { + .multi-select-header, input { + min-height: 25px; + } + + .choices .choice { + height: 24px; + } + } + } .setting-label { width: 10%; @@ -206,7 +227,7 @@ } } - .pairs { + .input-pairs { display: flex; flex-direction: column; align-items: center; @@ -230,11 +251,15 @@ } } - .pair { + .input-pair { display: flex; align-items: flex-end; position: relative; margin-bottom: 10px; + + &.no-connector div.input-block:not(:last-of-type) { + margin-right: 10px; + } } .d-icon { @@ -255,12 +280,17 @@ min-width: 160px; } - button.remove-input { - margin: 21px 0 0 10px; + a.remove-input { + margin: 25px 0 0 10px; } .connector { margin: 0 10px; + margin-top: 21px; + + &.prefix { + margin-left: 0; + } .select-kit { min-width: 50px; @@ -272,17 +302,9 @@ } .output-connector { - margin-top: 25px; - display: inline-block; white-space: nowrap; } } - - .prefix { - position: absolute; - left: -20px; - top: 24px; - } } .required-data .setting-value { @@ -297,10 +319,6 @@ } } -.setting .add-custom-input { - margin-top: 5px; -} - .admin-contents .wizard-submissions { width: 100%; display: inline-block; diff --git a/config/locales/client.en.yml b/config/locales/client.en.yml index 41657672..61103996 100644 --- a/config/locales/client.en.yml +++ b/config/locales/client.en.yml @@ -65,10 +65,12 @@ en: submission_key: 'submission key' param_key: 'param' - output: - label: "Output" - prefix: 'if' - connector: 'then' + input: + conditional: + prefix: 'if' + output: 'then' + assignment: + prefix: 'set' error: name_required: "Wizards must have a name." @@ -121,6 +123,7 @@ en: limit: "Limit" property: "Property" prefill: "Prefill" + filter: "Content" action: header: "Actions*" diff --git a/lib/custom_wizard/builder.rb b/lib/custom_wizard/builder.rb index ba53e041..4f972e83 100644 --- a/lib/custom_wizard/builder.rb +++ b/lib/custom_wizard/builder.rb @@ -262,8 +262,10 @@ class CustomWizard::Builder @wizard.needs_groups = true end - puts "ADDING FIELD: #{params.inspect}" - + if (prefill = field_template['filters']).present? + params[:filter] = get_output(field_template['filters']) + end + field = step.add_field(params) if field_template['type'] === 'dropdown' @@ -273,25 +275,47 @@ class CustomWizard::Builder def prefill_field(field_template, step_template) if (prefill = field_template['prefill']).present? - output = nil - - prefill.each do |item| - if validate_pairs(item['pairs']) - output = get_field(item['output'], item['output_type']) + get_output(prefill) + end + end + + def get_output(inputs, opts = {}) + output = opts[:multiple] ? [] : nil + + inputs.each do |input| + if input['type'] === 'conditional' && validate_pairs(input['pairs']) + if opts[:multiple] + output.push(get_field(input['output'], input['output_type'], opts)) + else + output = get_field(input['output'], input['output_type'], opts) + break + end + end + + if input['type'] === 'assignment' + value = get_field(input['output'], input['output_type'], opts) + + if opts[:multiple] + output.push(value) + else + output = value + break end end - - output end + + output end def validate_pairs(pairs) failed = false + pairs.each do |pair| key = get_field(pair['key'], pair['key_type']) value = get_field(pair['value'], pair['value_type']) failed = true unless key.public_send(get_operator(pair['connector']), value) end + !failed end @@ -299,23 +323,22 @@ class CustomWizard::Builder OPERATORS[connector] || '==' end - def get_field(value, type) + def get_field(value, type, opts = {}) method = "get_#{type}_field" - + if self.respond_to?(method) - self.send(method, value) + self.send(method, value, opts) else value end end - def get_wizard_field(value) - @submissions.last && - !@submissions.last.key?("submitted_at") && - @submissions.last[value] + def get_wizard_field(value, opts = {}) + data = opts[:data] || @submissions.last + data && !data.key?("submitted_at") && data[value] end - def get_user_field(value) + def get_user_field(value, opts = {}) puts "GETTING USER FIELD: #{value.inspect}" if value.include?('user_field_') UserCustomField.where(user_id: @wizard.user.id, name: value).pluck(:value).first @@ -592,9 +615,25 @@ class CustomWizard::Builder end def add_to_group(user, action, data) - if value = data[action['value']] - if group = Group.where("#{action['property']} = '#{value}'").first - group.add(user) + groups = get_output(action['inputs'], multiple: true, data: data) + + groups = groups.reduce([]) do |result, g| + g = g.first if g.is_a?(Array) + + begin + result.push(Integer(g)) + rescue ArgumentError + group = Group.find_by(name: g) + result.push(group.id) if group + end + + result + end + + if groups.present? + groups.each do |group_id| + group = Group.find(group_id) if group_id + group.add(user) if group end end end diff --git a/lib/wizard/field.rb b/lib/wizard/field.rb index 038fdbbc..7de580bc 100644 --- a/lib/wizard/field.rb +++ b/lib/wizard/field.rb @@ -6,7 +6,8 @@ module CustomWizardFieldExtension :min_length, :file_types, :limit, - :property + :property, + :filter attr_accessor :dropdown_none @@ -25,6 +26,7 @@ module CustomWizardFieldExtension @file_types = attrs[:file_types] @limit = attrs[:limit] @property = attrs[:property] + @filter = attrs[:filter] end def label diff --git a/serializers/custom_wizard/wizard_field_serializer.rb b/serializers/custom_wizard/wizard_field_serializer.rb index dbaa2054..820a1740 100644 --- a/serializers/custom_wizard/wizard_field_serializer.rb +++ b/serializers/custom_wizard/wizard_field_serializer.rb @@ -6,7 +6,8 @@ class CustomWizardFieldSerializer < ::WizardFieldSerializer :image, :file_types, :limit, - :property + :property, + :filter has_many :choices, serializer: WizardFieldChoiceSerializer, embed: :objects @@ -47,4 +48,8 @@ class CustomWizardFieldSerializer < ::WizardFieldSerializer def property object.property end + + def filter + object.filter + end end \ No newline at end of file