diff --git a/assets/javascripts/discourse/components/wizard-custom-action.js.es6 b/assets/javascripts/discourse/components/wizard-custom-action.js.es6 index 37b76f83..8f5a6103 100644 --- a/assets/javascripts/discourse/components/wizard-custom-action.js.es6 +++ b/assets/javascripts/discourse/components/wizard-custom-action.js.es6 @@ -21,17 +21,6 @@ export default Component.extend({ publicTopicFields: or('createTopic', 'openComposer'), showSkipRedirect: or('createTopic', 'sendMessage'), - @observes('action.type') - setupDefaults() { - const defaultProperties = schema.action.types[this.action.type]; - - Object.keys(defaultProperties).forEach(property => { - if (defaultProperties[property]) { - this.set(`action.${property}`, defaultProperties[property]); - } - }); - }, - @discourseComputed('wizard.steps') runAfterContent(steps) { let content = steps.map(function(step) { diff --git a/assets/javascripts/discourse/components/wizard-custom-field.js.es6 b/assets/javascripts/discourse/components/wizard-custom-field.js.es6 index b0903ae0..3c54748a 100644 --- a/assets/javascripts/discourse/components/wizard-custom-field.js.es6 +++ b/assets/javascripts/discourse/components/wizard-custom-field.js.es6 @@ -19,17 +19,6 @@ export default Component.extend({ showMinLength: or('isText', 'isTextarea', 'isUrl', 'isComposer'), categoryPropertyTypes: selectKitContent(['id', 'slug']), - @observes('field.type') - setupDefaults() { - const defaultProperties = schema.field.types[this.field.type]; - - Object.keys(defaultProperties).forEach(property => { - if (defaultProperties[property]) { - this.set(`field.${property}`, defaultProperties[property]); - } - }); - }, - @observes('field.type') clearMapped() { schema.field.mapped.forEach(property => { diff --git a/assets/javascripts/discourse/components/wizard-links.js.es6 b/assets/javascripts/discourse/components/wizard-links.js.es6 index fedbc273..5f7be87b 100644 --- a/assets/javascripts/discourse/components/wizard-links.js.es6 +++ b/assets/javascripts/discourse/components/wizard-links.js.es6 @@ -18,11 +18,11 @@ export default Component.extend({ }, applySortable() { - $(this.element).find("ul").sortable({tolerance: 'pointer'}).on('sortupdate', (e, ui) => { - const itemId = ui.item.data('id'); - const index = ui.item.index(); - bind(this, this.updateItemOrder(itemId, index)); - }); + $(this.element).find("ul") + .sortable({ tolerance: 'pointer' }) + .on('sortupdate', (e, ui) => { + this.updateItemOrder(ui.item.data('id'), ui.item.index()); + }); }, updateItemOrder(itemId, newIndex) { @@ -51,7 +51,7 @@ export default Component.extend({ label = generateName(item.type); } - link.label = label; + link.label = `${label} (${item.id})`; let classes = 'btn'; if (current && item.id === current.id) { @@ -77,22 +77,30 @@ export default Component.extend({ actions: { add() { const items = this.items; - const itemType = this.itemType; + const itemType = this.itemType; + let next = 1; + if (items.length) { + next = Math.max.apply(Math, items.map((i) => (i.id.split('_')[1]))) + 1; + } + let params = { - id: `${itemType}_${items.length + 1}`, + id: `${itemType}_${next}`, isNew: true }; - if (schema[itemType].objectArrays) { - Object.keys(schema[itemType].objectArrays).forEach(objectType => { + let objectArrays = schema[itemType].objectArrays; + if (objectArrays) { + Object.keys(objectArrays).forEach(objectType => { params[objectArrays[objectType].property] = A(); }); }; params = this.setDefaults(schema[itemType].basic, params); - if (schema[itemType].types) { - params = this.setDefaults(schema[itemType].types[params.type], params); + + let types = schema[itemType].types; + if (types && params.type) { + params = this.setDefaults(types[params.type], params); } const newItem = EmberObject.create(params); @@ -107,8 +115,26 @@ export default Component.extend({ remove(itemId) { const items = this.items; - items.removeObject(items.findBy('id', itemId)); - this.set('current', items[items.length - 1]); + let item; + let index; + + items.forEach((it, ind) => { + if (it.id === itemId) { + item = it; + index = ind; + } + }); + + let nextIndex; + if (this.current.id === itemId) { + nextIndex = index < (items.length-2) ? (index+1) : (index-1); + } + + items.removeObject(item); + + if (nextIndex) { + this.set('current', items[nextIndex]); + } } } }); diff --git a/assets/javascripts/discourse/components/wizard-mapper-connector.js.es6 b/assets/javascripts/discourse/components/wizard-mapper-connector.js.es6 index ee6c38b2..aaf555b4 100644 --- a/assets/javascripts/discourse/components/wizard-mapper-connector.js.es6 +++ b/assets/javascripts/discourse/components/wizard-mapper-connector.js.es6 @@ -1,6 +1,7 @@ import Component from "@ember/component"; import { gt } from '@ember/object/computed'; import { computed } from "@ember/object"; +import { removeMapperClasses } from '../lib/wizard-mapper'; export default Component.extend({ classNameBindings: [':mapper-connector', ':mapper-block', 'hasMultiple::single'], @@ -9,5 +10,11 @@ export default Component.extend({ let key = this.connector; let path = this.inputTypes ? `input.${key}.name` : `connector.${key}`; return I18n.t(`admin.wizard.${path}`); - }) + }), + + actions: { + onOpen() { + removeMapperClasses(this); + } + } }); \ No newline at end of file diff --git a/assets/javascripts/discourse/components/wizard-mapper-selector.js.es6 b/assets/javascripts/discourse/components/wizard-mapper-selector.js.es6 index bd8408b2..22ad9ef2 100644 --- a/assets/javascripts/discourse/components/wizard-mapper-selector.js.es6 +++ b/assets/javascripts/discourse/components/wizard-mapper-selector.js.es6 @@ -2,13 +2,13 @@ import { alias, or, gt } from "@ember/object/computed"; import { computed } from "@ember/object"; import { default as discourseComputed, observes, on } from "discourse-common/utils/decorators"; import { getOwner } from 'discourse-common/lib/get-owner'; -import { defaultSelectionType, selectionTypes } from '../lib/wizard-mapper'; +import { defaultSelectionType, selectionTypes, removeMapperClasses } from '../lib/wizard-mapper'; import { snakeCase } from '../lib/wizard'; import Component from "@ember/component"; import { bind } from "@ember/runloop"; export default Component.extend({ - classNames: 'mapper-selector', + classNameBindings: [':mapper-selector', 'activeType'], groups: alias('site.groups'), categories: alias('site.categories'), showText: computed('activeType', function() { return this.showInput('text') }), @@ -30,7 +30,6 @@ export default Component.extend({ userEnabled: computed('options.userSelection', 'inputType', function() { return this.optionEnabled('userSelection') }), listEnabled: computed('options.listSelection', 'inputType', function() { return this.optionEnabled('listSelection') }), hasTypes: gt('selectorTypes.length', 1), - showTypes: false, didInsertElement() { $(document).on("click", bind(this, this.documentClick)); @@ -41,14 +40,16 @@ export default Component.extend({ }, documentClick(e) { - let $element = $(this.element); + if (this._state == "destroying") return; + let $target = $(e.target); - - if (!$target.hasClass('type-selector-icon') && - $target.closest($element).length < 1 && - this._state !== "destroying") { - - this.set("showTypes", false); + + if (!$target.parents('.wizard-mapper .input').length) { + this.send('disableActive'); + } + + if (!$target.parents('.type-selector').length) { + this.send('hideTypes'); } }, @@ -147,14 +148,34 @@ export default Component.extend({ return this.activeType === type && this[`${type}Enabled`]; }, + removeClasses() { + removeMapperClasses(this); + }, + actions: { toggleType(type) { this.set('activeType', type); - this.set('showTypes', false); + this.send('hideTypes'); }, - toggleTypes() { - this.toggleProperty('showTypes') + // jquery is used here to ensure other selectors and types disable properly + + showTypes() { + this.removeClasses(); + $(this.element).find('.selector-types').addClass('show'); + }, + + hideTypes() { + $(this.element).find('.selector-types').removeClass('show'); + }, + + enableActive() { + this.removeClasses(); + $(this.element).addClass('active'); + }, + + disableActive() { + $(this.element).removeClass('active'); } } }) \ No newline at end of file diff --git a/assets/javascripts/discourse/controllers/admin-wizard.js.es6 b/assets/javascripts/discourse/controllers/admin-wizard.js.es6 index b5d4b3b6..42c3d534 100644 --- a/assets/javascripts/discourse/controllers/admin-wizard.js.es6 +++ b/assets/javascripts/discourse/controllers/admin-wizard.js.es6 @@ -7,6 +7,7 @@ import { dasherize } from "@ember/string"; import EmberObject from "@ember/object"; import { scheduleOnce, later } from "@ember/runloop"; import Controller from "@ember/controller"; +import copyText from "discourse/lib/copy-text"; export default Controller.extend({ hasName: notEmpty('model.name'), @@ -58,7 +59,7 @@ export default Controller.extend({ let stepFields = s.fields.map((f) => { return EmberObject.create({ id: f.id, - label: `${f.label} (${s.id})`, + label: `${f.label} (${s.id}, ${f.id})`, type: f.type }); }); @@ -94,14 +95,16 @@ export default Controller.extend({ } }).catch((result) => { this.set('saving', false); - - let error = true; + + let errorType = 'failed'; + let errorParams = {}; + if (result.error) { - let type = result.error.type; - let params = result.error.params || {}; - error = I18n.t(`admin.wizard.error.${type}`, params); + errorType = result.error.type; + errorParams = result.error.params; } - this.set('error', error); + + this.set('error', I18n.t(`admin.wizard.error.${errorType}`, errorParams)); later(() => this.set('error', null), 10000); }); @@ -127,6 +130,20 @@ export default Controller.extend({ toggleAdvanced() { this.toggleProperty('model.showAdvanced'); + }, + + copyUrl() { + const $copyRange = $('
'); + $copyRange.html(this.wizardUrl); + + $(document.body).append($copyRange); + + if (copyText(this.wizardUrl, $copyRange[0])) { + this.set("copiedUrl", true); + later(() => this.set("copiedUrl", false), 2000); + } + + $copyRange.remove(); } } }); diff --git a/assets/javascripts/discourse/lib/wizard-json.js.es6 b/assets/javascripts/discourse/lib/wizard-json.js.es6 index 070fdc6e..3ef519b1 100644 --- a/assets/javascripts/discourse/lib/wizard-json.js.es6 +++ b/assets/javascripts/discourse/lib/wizard-json.js.es6 @@ -134,7 +134,8 @@ function actionPatch(json) { function buildProperties(json) { let props = { - steps: A() + steps: A(), + actions: A() }; if (present(json)) { diff --git a/assets/javascripts/discourse/lib/wizard-mapper.js.es6 b/assets/javascripts/discourse/lib/wizard-mapper.js.es6 index 3d3ad034..533d852d 100644 --- a/assets/javascripts/discourse/lib/wizard-mapper.js.es6 +++ b/assets/javascripts/discourse/lib/wizard-mapper.js.es6 @@ -22,6 +22,12 @@ function inputTypesContent(options = {}) { mapInputTypes(selectableInputTypes); } +function removeMapperClasses(ctx) { + const $mapper = $(ctx.element).parents('.wizard-mapper'); + $mapper.find('.selector-types').removeClass('show'); + $mapper.find('.mapper-selector').removeClass('active'); +} + // Connectors const connectors = { @@ -154,6 +160,7 @@ export { defaultInputType, defaultSelectionType, defaultConnector, + removeMapperClasses, connectorContent, inputTypesContent, selectionTypes, diff --git a/assets/javascripts/discourse/lib/wizard.js.es6 b/assets/javascripts/discourse/lib/wizard.js.es6 index 7734c450..2f252fbe 100644 --- a/assets/javascripts/discourse/lib/wizard.js.es6 +++ b/assets/javascripts/discourse/lib/wizard.js.es6 @@ -126,7 +126,7 @@ const fieldProperties = { description: null, required: null, key: null, - type: 'text' + type: null }, types: { text: { @@ -138,15 +138,15 @@ const fieldProperties = { composer: { min_length: null }, + text_only: { + }, number: { }, + checkbox: { + }, url: { min_length: null }, - 'text-only': { - }, - 'user-selector': { - }, upload: { file_types: '.jpg,.png' }, @@ -168,6 +168,8 @@ const fieldProperties = { group: { prefill: null, content: null + }, + user_selector: { } }, mapped: [ @@ -193,7 +195,7 @@ const actionProperties = { basic: { id: null, run_after: 'wizard_completion', - type: 'create_topic' + type: null }, types: { create_topic: { @@ -280,7 +282,7 @@ const schema = { function listProperties(type, objectType = null) { let properties = Object.keys(schema[type].basic); - + if (schema[type].types && objectType) { properties = properties.concat(Object.keys(schema[type].types[objectType])); } diff --git a/assets/javascripts/discourse/models/custom-wizard.js.es6 b/assets/javascripts/discourse/models/custom-wizard.js.es6 index 3b789676..38768eb6 100644 --- a/assets/javascripts/discourse/models/custom-wizard.js.es6 +++ b/assets/javascripts/discourse/models/custom-wizard.js.es6 @@ -44,7 +44,7 @@ const CustomWizard = EmberObject.extend({ for (let property of listProperties(type, objectType)) { let value = object.get(property); - result = this.validateValue(property, value, type, result); + result = this.validateValue(property, value, object, type, result); if (result.error) { break; @@ -90,7 +90,7 @@ const CustomWizard = EmberObject.extend({ return result; }, - validateValue(property, value, type, result) { + validateValue(property, value, object, type, result) { if (schema[type].required.indexOf(property) > -1 && !value) { result.error = { type: 'required', @@ -129,6 +129,10 @@ const CustomWizard = EmberObject.extend({ let input = { type: inpt.type, }; + + if (inpt.connector) { + input.connector = inpt.connector; + } if (present(inpt.output)) { input.output = inpt.output; diff --git a/assets/javascripts/discourse/templates/admin-wizard.hbs b/assets/javascripts/discourse/templates/admin-wizard.hbs index 7029b9e0..ce813f66 100644 --- a/assets/javascripts/discourse/templates/admin-wizard.hbs +++ b/assets/javascripts/discourse/templates/admin-wizard.hbs @@ -8,6 +8,11 @@