From d221d65d7782f41b3526b2e48ed6984a20f04a4e Mon Sep 17 00:00:00 2001 From: Angus McLeod Date: Sat, 17 Oct 2020 12:31:07 +1100 Subject: [PATCH 1/8] init --- .../admin-wizards-custom-fields.js.es6 | 28 +++++++++ .../custom-wizard-admin-route-map.js.es6 | 2 + .../routes/admin-wizards-custom-fields.js.es6 | 13 ++++ .../templates/admin-wizards-custom-fields.hbs | 33 ++++++++++ .../discourse/templates/admin-wizards.hbs | 1 + .../components/wizard-custom-action.hbs | 1 + config/locales/client.en.yml | 6 ++ .../custom_wizard/admin/custom_fields.rb | 40 ++++++++++++ lib/custom_wizard/custom_fields.rb | 61 +++++++++++++++++++ lib/custom_wizard/wizard.rb | 4 ++ plugin.rb | 17 ++++++ .../custom_wizard/custom_fields_serializer.rb | 3 + 12 files changed, 209 insertions(+) create mode 100644 assets/javascripts/discourse/controllers/admin-wizards-custom-fields.js.es6 create mode 100644 assets/javascripts/discourse/routes/admin-wizards-custom-fields.js.es6 create mode 100644 assets/javascripts/discourse/templates/admin-wizards-custom-fields.hbs create mode 100644 controllers/custom_wizard/admin/custom_fields.rb create mode 100644 lib/custom_wizard/custom_fields.rb create mode 100644 serializers/custom_wizard/custom_fields_serializer.rb diff --git a/assets/javascripts/discourse/controllers/admin-wizards-custom-fields.js.es6 b/assets/javascripts/discourse/controllers/admin-wizards-custom-fields.js.es6 new file mode 100644 index 00000000..72a66137 --- /dev/null +++ b/assets/javascripts/discourse/controllers/admin-wizards-custom-fields.js.es6 @@ -0,0 +1,28 @@ +import Controller from "@ember/controller"; +import EmberObject from '@ember/object'; +import { ajax } from 'discourse/lib/ajax'; +import { popupAjaxError } from 'discourse/lib/ajax-error'; + +export default Controller.extend({ + fieldKeys: ['klass', 'name', 'type'], + classes: ['topic', 'user', 'group'], + + actions: { + addField() { + this.get('customFields').pushObject( + EmberObject.create({ + new: true + }) + ); + }, + + saveFields() { + ajax(`/admin/wizards/custom-fields`, { + type: 'PUT', + data: { + custom_fields: this.customFields + } + }).catch(popupAjaxError) + } + } +}); \ No newline at end of file diff --git a/assets/javascripts/discourse/custom-wizard-admin-route-map.js.es6 b/assets/javascripts/discourse/custom-wizard-admin-route-map.js.es6 index c2722816..97157964 100644 --- a/assets/javascripts/discourse/custom-wizard-admin-route-map.js.es6 +++ b/assets/javascripts/discourse/custom-wizard-admin-route-map.js.es6 @@ -7,6 +7,8 @@ export default { this.route('adminWizardsWizardShow', { path: '/:wizardId/', resetNamespace: true }); }); + this.route('adminWizardsCustomFields', { path: '/custom-fields', resetNamespace: true }); + this.route('adminWizardsSubmissions', { path: '/submissions', resetNamespace: true }, function() { this.route('adminWizardsSubmissionsShow', { path: '/:wizardId/', resetNamespace: true }); }) diff --git a/assets/javascripts/discourse/routes/admin-wizards-custom-fields.js.es6 b/assets/javascripts/discourse/routes/admin-wizards-custom-fields.js.es6 new file mode 100644 index 00000000..c6775477 --- /dev/null +++ b/assets/javascripts/discourse/routes/admin-wizards-custom-fields.js.es6 @@ -0,0 +1,13 @@ +import DiscourseRoute from "discourse/routes/discourse"; +import { ajax } from 'discourse/lib/ajax'; +import { A } from "@ember/array"; + +export default DiscourseRoute.extend({ + model() { + return ajax('/admin/wizards/custom-fields'); + }, + + setupController(controller, model) { + controller.set('customFields', A(model || [])); + } +}); \ No newline at end of file diff --git a/assets/javascripts/discourse/templates/admin-wizards-custom-fields.hbs b/assets/javascripts/discourse/templates/admin-wizards-custom-fields.hbs new file mode 100644 index 00000000..8dd340f0 --- /dev/null +++ b/assets/javascripts/discourse/templates/admin-wizards-custom-fields.hbs @@ -0,0 +1,33 @@ +
+

{{i18n 'admin.wizard.custom_fields.nav_label'}}

+ + {{d-button + label="add" + icon="plus" + action="addField"}} +
+ +
+ {{#if model}} + + + {{#each fieldKeys as |key|}} + + {{/each}} + + {{#each customFields as |field|}} + + {{#if field.new}} + + + + {{else}} + {{#each-in field as |k v|}} + + {{/each-in}} + {{/if}} + + {{/each}} +
{{i18n (concat "admin.wizard.custom_fields." key)}}
{{combo-box value=field.klass content=classes onChange=(action (mut field.klass))}}{{input value=field.name}}{{combo-box value=field.type content=types onChange=(action (mut field.type))}}{{v}}
+ {{/if}} +
diff --git a/assets/javascripts/discourse/templates/admin-wizards.hbs b/assets/javascripts/discourse/templates/admin-wizards.hbs index c0bd6b27..1e6399ab 100644 --- a/assets/javascripts/discourse/templates/admin-wizards.hbs +++ b/assets/javascripts/discourse/templates/admin-wizards.hbs @@ -1,5 +1,6 @@ {{#admin-nav}} {{nav-item route='adminWizardsWizard' label='admin.wizard.nav_label'}} + {{nav-item route='adminWizardsCustomFields' label='admin.wizard.custom_fields.nav_label'}} {{nav-item route='adminWizardsSubmissions' label='admin.wizard.submissions.nav_label'}} {{#if siteSettings.wizard_apis_enabled}} {{nav-item route='adminWizardsApi' label='admin.wizard.api.nav_label'}} diff --git a/assets/javascripts/discourse/templates/components/wizard-custom-action.hbs b/assets/javascripts/discourse/templates/components/wizard-custom-action.hbs index 272c3155..c212deab 100644 --- a/assets/javascripts/discourse/templates/components/wizard-custom-action.hbs +++ b/assets/javascripts/discourse/templates/components/wizard-custom-action.hbs @@ -731,6 +731,7 @@ options=(hash inputTypes='association' wizardFieldSelection='value' + wizardActionSelection='value' userFieldSelection='value' keyPlaceholder='admin.wizard.action.custom_fields.key' context='action' diff --git a/config/locales/client.en.yml b/config/locales/client.en.yml index 65e31c96..db02af96 100644 --- a/config/locales/client.en.yml +++ b/config/locales/client.en.yml @@ -274,6 +274,12 @@ en: visibility_level: Visibility Level members_visibility_level: Members Visibility Level + custom_fields: + nav_label: "Custom Fields" + klass: "Class" + name: "Name" + type: "Type" + submissions: nav_label: "Submissions" title: "{{name}} Submissions" diff --git a/controllers/custom_wizard/admin/custom_fields.rb b/controllers/custom_wizard/admin/custom_fields.rb new file mode 100644 index 00000000..24b5310d --- /dev/null +++ b/controllers/custom_wizard/admin/custom_fields.rb @@ -0,0 +1,40 @@ +class CustomWizard::CustomFieldsController < CustomWizard::AdminController + def index + render_custom_field_list + end + + def update + field_data = params[:custom_fields] + + custom_fields = field_data.map { |data| CustomWizard::CustomFields.new(data) } + + custom_fields.each do |field_data| + custom_field.validate + + unless custom_field.valid? + raise Discourse::InvalidParameters, "Invalid field: '#{custom_field.name}'" + end + end + + all_fields_saved = true + + custom_fields.each do |field| + unless field.save + all_fields_saved = false + end + end + + if all_fields_saved + render_custom_field_list + else + render json: error_json + end + end + + def render_custom_field_list + render_serialized( + CustomWizard::CustomFields.list, + CustomWizard::CustomFieldsSerializer + ) + end +end \ No newline at end of file diff --git a/lib/custom_wizard/custom_fields.rb b/lib/custom_wizard/custom_fields.rb new file mode 100644 index 00000000..98c3cc01 --- /dev/null +++ b/lib/custom_wizard/custom_fields.rb @@ -0,0 +1,61 @@ +class ::CustomWizard::CustomFields + include HasErrors + include ActiveModel::Serialization + + CLASSES ||= ["topic", "user", "group", "category"] + ATTRS ||= ["name", "klass", "type"] + KEY ||= "custom_wizard_custom_fields" + + def initialize(data) + data = data.with_indifferent_access + + ATTRS.each do |attr| + self.class.class_eval { attr_accessor attr } + send("#{attr}=", data[attr]) if data[attr].present? + end + end + + def save + validate + + if valid? + data = {} + name = nil + + ATTRS.each do |attr| + value = send(attr) + + if attr == 'name' + name = value + else + data[attr] = value + end + end + + PluginStore.set(KEY, name, data) + else + false + end + end + + def validate + ATTRS.each do |attr| + value = send(attr) + add_error("Attribute required: #{attr}") if value.blank? + add_error("Unsupported class: #{value}") if CLASSES.exclude?(value) + end + end + + def valid? + errors.blank? + end + + def self.list + PluginStoreRow.where(plugin_name: KEY) + .map do |record| + data = JSON.parse(record.value) + data[:name] = record.key + self.new(data) + end + end +end \ No newline at end of file diff --git a/lib/custom_wizard/wizard.rb b/lib/custom_wizard/wizard.rb index 04308a7f..549b0422 100644 --- a/lib/custom_wizard/wizard.rb +++ b/lib/custom_wizard/wizard.rb @@ -320,6 +320,10 @@ class CustomWizard::Wizard Jobs.cancel_scheduled_job(:set_after_time_wizard, wizard_id: wizard[:id]) Jobs.enqueue(:clear_after_time_wizard, wizard_id: wizard[:id]) end + + if serialize_fields.present? + + end end wizard[:id] diff --git a/plugin.rb b/plugin.rb index dfe3d063..01852f63 100644 --- a/plugin.rb +++ b/plugin.rb @@ -42,6 +42,7 @@ after_initialize do ../controllers/custom_wizard/admin/submissions.rb ../controllers/custom_wizard/admin/api.rb ../controllers/custom_wizard/admin/logs.rb + ../controllers/custom_wizard/admin/custom_fields.rb ../controllers/custom_wizard/wizard.rb ../controllers/custom_wizard/steps.rb ../controllers/custom_wizard/transfer.rb @@ -51,6 +52,7 @@ after_initialize do ../lib/custom_wizard/action_result.rb ../lib/custom_wizard/action.rb ../lib/custom_wizard/builder.rb + ../lib/custom_wizard/custom_fields.rb ../lib/custom_wizard/field.rb ../lib/custom_wizard/mapper.rb ../lib/custom_wizard/log.rb @@ -68,6 +70,7 @@ after_initialize do ../serializers/custom_wizard/api_serializer.rb ../serializers/custom_wizard/basic_api_serializer.rb ../serializers/custom_wizard/basic_wizard_serializer.rb + ../serializers/custom_wizard/custom_fields_serializer.rb ../serializers/custom_wizard/wizard_field_serializer.rb ../serializers/custom_wizard/wizard_step_serializer.rb ../serializers/custom_wizard/wizard_serializer.rb @@ -160,5 +163,19 @@ after_initialize do CustomWizard::Wizard.register_styles + CustomWizard::CustomFields.list.each do |field| + add_to_class(field.klass.to_sym, field.name.to_sym) do + custom_fields[field.name] + end + + add_to_serializer(field.klass.to_sym, field.name.to_sym) do + if field.klass === 'topic' + object.topic.send(field.name) + else + object.send(field.name) + end + end + end + DiscourseEvent.trigger(:custom_wizard_ready) end diff --git a/serializers/custom_wizard/custom_fields_serializer.rb b/serializers/custom_wizard/custom_fields_serializer.rb new file mode 100644 index 00000000..fe8c14f6 --- /dev/null +++ b/serializers/custom_wizard/custom_fields_serializer.rb @@ -0,0 +1,3 @@ +class CustomWizard::CustomFieldsSerializer < ApplicationSerializer + attributes :klass, :name, :type +end \ No newline at end of file From 3e86d0ffa6883b55950637c3aeda7c0f7c036e24 Mon Sep 17 00:00:00 2001 From: Angus McLeod Date: Tue, 20 Oct 2020 11:42:10 +1100 Subject: [PATCH 2/8] FEATURE: suppress notifications setting for post actions --- .../components/wizard-custom-action.js.es6 | 2 +- .../discourse/lib/wizard-schema.js.es6 | 7 +++++-- .../components/wizard-custom-action.hbs | 16 +++++++++++++++- config/locales/client.en.yml | 3 +++ controllers/custom_wizard/admin/wizard.rb | 1 + lib/custom_wizard/action.rb | 2 ++ 6 files changed, 27 insertions(+), 4 deletions(-) diff --git a/assets/javascripts/discourse/components/wizard-custom-action.js.es6 b/assets/javascripts/discourse/components/wizard-custom-action.js.es6 index 8fcca367..dbfa4e93 100644 --- a/assets/javascripts/discourse/components/wizard-custom-action.js.es6 +++ b/assets/javascripts/discourse/components/wizard-custom-action.js.es6 @@ -29,7 +29,7 @@ export default Component.extend(UndoChanges, { hasCustomFields: or('basicTopicFields', 'updateProfile', 'createGroup', 'createCategory'), basicTopicFields: or('createTopic', 'sendMessage', 'openComposer'), publicTopicFields: or('createTopic', 'openComposer'), - showSkipRedirect: or('createTopic', 'sendMessage'), + showPostAdvanced: or('createTopic', 'sendMessage'), actionTypes: Object.keys(wizardSchema.action.types).map(type => { return { id: type, diff --git a/assets/javascripts/discourse/lib/wizard-schema.js.es6 b/assets/javascripts/discourse/lib/wizard-schema.js.es6 index 840b84a5..7d34a79d 100644 --- a/assets/javascripts/discourse/lib/wizard-schema.js.es6 +++ b/assets/javascripts/discourse/lib/wizard-schema.js.es6 @@ -117,7 +117,8 @@ const action = { tags: null, visible: null, custom_fields: null, - skip_redirect: null + skip_redirect: null, + suppress_notifications: null, }, send_message: { title: null, @@ -127,7 +128,8 @@ const action = { skip_redirect: null, custom_fields: null, required: null, - recipient: null + recipient: null, + suppress_notifications: null }, open_composer: { title: null, @@ -218,6 +220,7 @@ const action = { 'code', 'custom_fields', 'skip_redirect', + 'suppress_notifications', 'required' ], required: [ diff --git a/assets/javascripts/discourse/templates/components/wizard-custom-action.hbs b/assets/javascripts/discourse/templates/components/wizard-custom-action.hbs index 272c3155..682f179b 100644 --- a/assets/javascripts/discourse/templates/components/wizard-custom-action.hbs +++ b/assets/javascripts/discourse/templates/components/wizard-custom-action.hbs @@ -761,7 +761,7 @@ {{/if}} - {{#if showSkipRedirect}} + {{#if showPostAdvanced}}
@@ -775,6 +775,20 @@
+ +
+
+ +
+ +
+ {{input type='checkbox' checked=action.suppress_notifications}} + + + {{i18n 'admin.wizard.action.suppress_notifications.description' type='topic'}} + +
+
{{/if}} {{#if routeTo}} diff --git a/config/locales/client.en.yml b/config/locales/client.en.yml index 65e31c96..e191f83a 100644 --- a/config/locales/client.en.yml +++ b/config/locales/client.en.yml @@ -203,6 +203,9 @@ en: skip_redirect: label: "Redirect" description: "Don't redirect the user to this {{type}} after the wizard completes" + suppress_notifications: + label: "Suppress Notifications" + description: "Suppress normal notifications triggered by post creation" send_message: label: "Send Message" recipient: "Recipient" diff --git a/controllers/custom_wizard/admin/wizard.rb b/controllers/custom_wizard/admin/wizard.rb index ac5eeb8a..2caa3dde 100644 --- a/controllers/custom_wizard/admin/wizard.rb +++ b/controllers/custom_wizard/admin/wizard.rb @@ -114,6 +114,7 @@ class CustomWizard::AdminWizardController < CustomWizard::AdminController :type, :code, :skip_redirect, + :suppress_notifications, :post, :post_builder, :post_template, diff --git a/lib/custom_wizard/action.rb b/lib/custom_wizard/action.rb index e37a9a4c..65ad3cef 100644 --- a/lib/custom_wizard/action.rb +++ b/lib/custom_wizard/action.rb @@ -443,6 +443,8 @@ class CustomWizard::Action mapper.interpolate(action['post_template']) : data[action['post']] + params[:import_mode] = ActiveRecord::Type::Boolean.new.cast(action['suppress_notifications']) + add_custom_fields(params) end From b14d3348294764377c5aeb4dc673baa75e4f4358 Mon Sep 17 00:00:00 2001 From: Angus McLeod Date: Tue, 20 Oct 2020 16:40:23 +1100 Subject: [PATCH 3/8] Complete custom field management --- .../components/custom-field-input.js.es6 | 45 +++++++++++++++++++ .../components/wizard-mapper-selector.js.es6 | 14 ++++-- .../admin-wizards-custom-fields.js.es6 | 24 +++++++--- .../discourse/lib/wizard-mapper.js.es6 | 3 +- .../routes/admin-wizards-wizard-show.js.es6 | 2 + .../routes/admin-wizards-wizard.js.es6 | 6 ++- .../templates/admin-wizards-custom-fields.hbs | 41 +++++++++-------- .../discourse/templates/admin-wizards.hbs | 2 +- .../components/custom-field-input.hbs | 44 ++++++++++++++++++ .../components/wizard-custom-action.hbs | 1 + assets/stylesheets/common/wizard-admin.scss | 18 ++++++++ config/locales/client.en.yml | 31 ++++++++++--- config/routes.rb | 3 ++ controllers/custom_wizard/admin/admin.rb | 4 ++ .../custom_wizard/admin/custom_fields.rb | 33 ++++++++------ controllers/custom_wizard/admin/wizard.rb | 3 +- lib/custom_wizard/action.rb | 39 ++++++++++++---- .../{custom_fields.rb => custom_field.rb} | 33 +++++++++++--- lib/custom_wizard/wizard.rb | 4 -- plugin.rb | 23 ++++++---- .../custom_wizard/custom_field_serializer.rb | 3 ++ .../custom_wizard/custom_fields_serializer.rb | 3 -- 22 files changed, 300 insertions(+), 79 deletions(-) create mode 100644 assets/javascripts/discourse/components/custom-field-input.js.es6 create mode 100644 assets/javascripts/discourse/templates/components/custom-field-input.hbs rename lib/custom_wizard/{custom_fields.rb => custom_field.rb} (52%) create mode 100644 serializers/custom_wizard/custom_field_serializer.rb delete mode 100644 serializers/custom_wizard/custom_fields_serializer.rb diff --git a/assets/javascripts/discourse/components/custom-field-input.js.es6 b/assets/javascripts/discourse/components/custom-field-input.js.es6 new file mode 100644 index 00000000..b5dbec5b --- /dev/null +++ b/assets/javascripts/discourse/components/custom-field-input.js.es6 @@ -0,0 +1,45 @@ +import Component from "@ember/component"; +import discourseComputed, { discourseObserve } from "discourse-common/utils/decorators"; +import { or } from "@ember/object/computed"; + +const generateContent = function(array, type) { + return array.map(key => ({ + id: key, + name: I18n.t(`admin.wizard.custom_field.${type}.${key}`) + })); +} + +export default Component.extend({ + tagName: 'tr', + topicSerializers: ['topic_view', 'topic_list_item'], + postSerializers: ['post'], + categorySerializers: ['basic_category', 'topic_view', 'topic_list_item'], + klassContent: generateContent(['topic', 'post', 'group', 'category'], 'klass'), + typeContent: generateContent(['string', 'boolean', 'json'], 'type'), + showInputs: or('field.new', 'field.edit'), + + @discourseComputed('field.klass') + serializerContent(klass) { + const serializers = this.get(`${klass}Serializers`); + + if (serializers) { + return generateContent(serializers, 'serializers'); + } else { + return []; + } + }, + + actions: { + edit() { + this.set('field.edit', true); + }, + + close() { + if (this.field.edit) { + this.set('field.edit', false); + } else { + this.removeField(this.field); + } + } + } +}); \ 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 7d37f74f..5a8c7d63 100644 --- a/assets/javascripts/discourse/components/wizard-mapper-selector.js.es6 +++ b/assets/javascripts/discourse/components/wizard-mapper-selector.js.es6 @@ -21,9 +21,11 @@ export default Component.extend({ showGroup: computed('activeType', function() { return this.showInput('group') }), showUser: computed('activeType', function() { return this.showInput('user') }), showList: computed('activeType', function() { return this.showInput('list') }), + showCustomField: computed('activeType', function() { return this.showInput('customField') }), textEnabled: computed('options.textSelection', 'inputType', function() { return this.optionEnabled('textSelection') }), wizardFieldEnabled: computed('options.wizardFieldSelection', 'inputType', function() { return this.optionEnabled('wizardFieldSelection') }), wizardActionEnabled: computed('options.wizardActionSelection', 'inputType', function() { return this.optionEnabled('wizardActionSelection') }), + customFieldEnabled: computed('options.customFieldSelection', 'inputType', function() { return this.optionEnabled('customFieldSelection') }), userFieldEnabled: computed('options.userFieldSelection', 'inputType', function() { return this.optionEnabled('userFieldSelection') }), userFieldOptionsEnabled: computed('options.userFieldOptionsSelection', 'inputType', function() { return this.optionEnabled('userFieldOptionsSelection') }), categoryEnabled: computed('options.categorySelection', 'inputType', function() { return this.optionEnabled('categorySelection') }), @@ -34,7 +36,7 @@ export default Component.extend({ groups: alias('site.groups'), categories: alias('site.categories'), - showComboBox: or('showWizardField', 'showWizardAction', 'showUserField', 'showUserFieldOptions'), + showComboBox: or('showWizardField', 'showWizardAction', 'showUserField', 'showUserFieldOptions', 'showCustomField'), showMultiSelect: or('showCategory', 'showGroup'), hasTypes: gt('selectorTypes.length', 1), showTypes: false, @@ -88,7 +90,8 @@ export default Component.extend({ 'showController.wizard.actions.[]', 'showController.userFields.[]', 'showController.currentField.id', - 'showController.currentAction.id' + 'showController.currentAction.id', + 'showController.customFields' ) comboBoxContent( activeType, @@ -96,7 +99,8 @@ export default Component.extend({ wizardActions, userFields, currentFieldId, - currentActionId + currentActionId, + customFields ) { let content; @@ -139,6 +143,10 @@ export default Component.extend({ content = userFields; } + if (activeType === 'customField') { + content = customFields; + } + return content; }, diff --git a/assets/javascripts/discourse/controllers/admin-wizards-custom-fields.js.es6 b/assets/javascripts/discourse/controllers/admin-wizards-custom-fields.js.es6 index 72a66137..9ed7762c 100644 --- a/assets/javascripts/discourse/controllers/admin-wizards-custom-fields.js.es6 +++ b/assets/javascripts/discourse/controllers/admin-wizards-custom-fields.js.es6 @@ -4,8 +4,7 @@ import { ajax } from 'discourse/lib/ajax'; import { popupAjaxError } from 'discourse/lib/ajax-error'; export default Controller.extend({ - fieldKeys: ['klass', 'name', 'type'], - classes: ['topic', 'user', 'group'], + fieldKeys: ['klass', 'type', 'serializers', 'name'], actions: { addField() { @@ -16,13 +15,28 @@ export default Controller.extend({ ); }, - saveFields() { + removeField(field) { + this.get('customFields').removeObject(field); + }, + + saveFields() { + this.set('saving', true); ajax(`/admin/wizards/custom-fields`, { type: 'PUT', - data: { + dataType: 'json', + contentType: 'application/json', + data: JSON.stringify({ custom_fields: this.customFields + }) + }).then(result => { + if (result.success) { + this.set('saveIcon', 'check'); + } else { + this.set('saveIcon', 'times'); } - }).catch(popupAjaxError) + setTimeout(() => this.set('saveIcon', ''), 5000); + }).finally(() => this.set('saving', false)) + .catch(popupAjaxError); } } }); \ No newline at end of file diff --git a/assets/javascripts/discourse/lib/wizard-mapper.js.es6 b/assets/javascripts/discourse/lib/wizard-mapper.js.es6 index 470a78c4..6fc50588 100644 --- a/assets/javascripts/discourse/lib/wizard-mapper.js.es6 +++ b/assets/javascripts/discourse/lib/wizard-mapper.js.es6 @@ -86,7 +86,8 @@ const selectionTypes = [ 'group', 'category', 'tag', - 'user' + 'user', + 'customField' ] function defaultSelectionType(inputType, options = {}) { diff --git a/assets/javascripts/discourse/routes/admin-wizards-wizard-show.js.es6 b/assets/javascripts/discourse/routes/admin-wizards-wizard-show.js.es6 index f8dd8479..21f3bb1b 100644 --- a/assets/javascripts/discourse/routes/admin-wizards-wizard-show.js.es6 +++ b/assets/javascripts/discourse/routes/admin-wizards-wizard-show.js.es6 @@ -2,6 +2,7 @@ import CustomWizard from '../models/custom-wizard'; import { ajax } from 'discourse/lib/ajax'; import DiscourseRoute from "discourse/routes/discourse"; import I18n from "I18n"; +import { selectKitContent } from '../lib/wizard'; export default DiscourseRoute.extend({ model(params) { @@ -32,6 +33,7 @@ export default DiscourseRoute.extend({ wizardList: parentModel.wizard_list, fieldTypes, userFields: parentModel.userFields, + customFields: selectKitContent(parentModel.custom_fields.map(f => f.name)), apis: parentModel.apis, themes: parentModel.themes, wizard, diff --git a/assets/javascripts/discourse/routes/admin-wizards-wizard.js.es6 b/assets/javascripts/discourse/routes/admin-wizards-wizard.js.es6 index 0ba204f3..588936f8 100644 --- a/assets/javascripts/discourse/routes/admin-wizards-wizard.js.es6 +++ b/assets/javascripts/discourse/routes/admin-wizards-wizard.js.es6 @@ -1,6 +1,7 @@ import DiscourseRoute from "discourse/routes/discourse"; import { buildFieldTypes } from '../lib/wizard-schema'; -import { set } from "@ember/object"; +import EmberObject, { set } from "@ember/object"; +import { A } from "@ember/array"; import { all } from "rsvp"; import { ajax } from 'discourse/lib/ajax'; @@ -62,7 +63,8 @@ export default DiscourseRoute.extend({ setupController(controller, model) { controller.setProperties({ wizardList: model.wizard_list, - wizardId: this.currentWizard() + wizardId: this.currentWizard(), + custom_fields: A(model.custom_fields.map(f => EmberObject.create(f))) }); }, diff --git a/assets/javascripts/discourse/templates/admin-wizards-custom-fields.hbs b/assets/javascripts/discourse/templates/admin-wizards-custom-fields.hbs index 8dd340f0..a79ff3a9 100644 --- a/assets/javascripts/discourse/templates/admin-wizards-custom-fields.hbs +++ b/assets/javascripts/discourse/templates/admin-wizards-custom-fields.hbs @@ -1,32 +1,37 @@
-

{{i18n 'admin.wizard.custom_fields.nav_label'}}

+

{{i18n 'admin.wizard.custom_field.nav_label'}}

- {{d-button - label="add" - icon="plus" - action="addField"}} +
+ {{#if saving}} + {{loading-spinner size="small"}} + {{else}} + {{#if saveIcon}} + {{d-icon saveIcon}} + {{/if}} + {{/if}} + {{d-button + label="admin.wizard.custom_field.save" + action="saveFields"}} + {{d-button + label="admin.wizard.custom_field.add" + icon="plus" + action="addField"}} +
- {{#if model}} + {{#if customFields}} {{#each fieldKeys as |key|}} - + {{/each}} + {{#each customFields as |field|}} - - {{#if field.new}} - - - - {{else}} - {{#each-in field as |k v|}} - - {{/each-in}} - {{/if}} - + {{custom-field-input + field=field + removeField=(action 'removeField')}} {{/each}}
{{i18n (concat "admin.wizard.custom_fields." key)}}{{i18n (concat "admin.wizard.custom_field." key ".label")}}
{{combo-box value=field.klass content=classes onChange=(action (mut field.klass))}}{{input value=field.name}}{{combo-box value=field.type content=types onChange=(action (mut field.type))}}{{v}}
{{/if}} diff --git a/assets/javascripts/discourse/templates/admin-wizards.hbs b/assets/javascripts/discourse/templates/admin-wizards.hbs index 1e6399ab..53ec86a6 100644 --- a/assets/javascripts/discourse/templates/admin-wizards.hbs +++ b/assets/javascripts/discourse/templates/admin-wizards.hbs @@ -1,6 +1,6 @@ {{#admin-nav}} {{nav-item route='adminWizardsWizard' label='admin.wizard.nav_label'}} - {{nav-item route='adminWizardsCustomFields' label='admin.wizard.custom_fields.nav_label'}} + {{nav-item route='adminWizardsCustomFields' label='admin.wizard.custom_field.nav_label'}} {{nav-item route='adminWizardsSubmissions' label='admin.wizard.submissions.nav_label'}} {{#if siteSettings.wizard_apis_enabled}} {{nav-item route='adminWizardsApi' label='admin.wizard.api.nav_label'}} diff --git a/assets/javascripts/discourse/templates/components/custom-field-input.hbs b/assets/javascripts/discourse/templates/components/custom-field-input.hbs new file mode 100644 index 00000000..fdb3d26d --- /dev/null +++ b/assets/javascripts/discourse/templates/components/custom-field-input.hbs @@ -0,0 +1,44 @@ +{{#if showInputs}} + + {{combo-box + value=field.klass + content=klassContent + none="admin.wizard.custom_field.klass.select" + onChange=(action (mut field.klass))}} + + + {{combo-box + value=field.type + content=typeContent + none="admin.wizard.custom_field.type.select" + onChange=(action (mut field.type))}} + + + {{multi-select + value=field.serializers + content=serializerContent + none="admin.wizard.custom_field.serializers.select" + onChange=(action (mut field.serializers))}} + + + {{input + value=field.name + placeholder=(i18n "admin.wizard.custom_field.klass.select")}} + + + {{d-button action="close" icon="times"}} + +{{else}} + + + + {{#each field.serializers as |serializer|}} + + {{/each}} + + + + {{d-button action="edit" icon="pencil-alt"}} + {{d-button action="close" icon="times"}} + +{{/if}} \ No newline at end of file diff --git a/assets/javascripts/discourse/templates/components/wizard-custom-action.hbs b/assets/javascripts/discourse/templates/components/wizard-custom-action.hbs index 98840175..137cf0f8 100644 --- a/assets/javascripts/discourse/templates/components/wizard-custom-action.hbs +++ b/assets/javascripts/discourse/templates/components/wizard-custom-action.hbs @@ -730,6 +730,7 @@ onUpdate=(action 'mappedFieldUpdated') options=(hash inputTypes='association' + customFieldSelection='key' wizardFieldSelection='value' wizardActionSelection='value' userFieldSelection='value' diff --git a/assets/stylesheets/common/wizard-admin.scss b/assets/stylesheets/common/wizard-admin.scss index 99fa857e..1c7c29b2 100644 --- a/assets/stylesheets/common/wizard-admin.scss +++ b/assets/stylesheets/common/wizard-admin.scss @@ -535,3 +535,21 @@ background-color: $secondary; border: 1px solid $primary-medium; } + +.admin-wizards-custom-fields { + .select-kit { + width: 200px; + } + + .select-kit.multi-select { + width: 250px; + } + + input[type="text"] { + margin: 0; + } + + td:last-of-type { + text-align: right; + } +} diff --git a/config/locales/client.en.yml b/config/locales/client.en.yml index 2ec64e81..0a7b4682 100644 --- a/config/locales/client.en.yml +++ b/config/locales/client.en.yml @@ -102,6 +102,7 @@ en: tag: "tag" group: "group" list: "list" + custom_field: "custom field" placeholder: text: "Enter text" @@ -115,6 +116,7 @@ en: tag: "Select tag" group: "Select group" list: "Enter item" + custom_field: "Select field" error: failed: "failed to save wizard" @@ -277,12 +279,31 @@ en: visibility_level: Visibility Level members_visibility_level: Members Visibility Level - custom_fields: + custom_field: nav_label: "Custom Fields" - klass: "Class" - name: "Name" - type: "Type" - + add: "Add Custom Field" + save: "Save Custom Fields" + name: + label: "Name" + select: "Enter a name" + type: + label: "Type" + select: "Select a type" + string: "String" + boolean: "Boolean" + json: "JSON" + klass: + label: "Class" + select: "Select a class" + topic: "Topic" + group: "Group" + user: "User" + serializers: + label: "Serializers" + select: "Select serializers" + topic_view: "Topic View" + topic_list_item: "Topic List Item" + submissions: nav_label: "Submissions" title: "{{name}} Submissions" diff --git a/config/routes.rb b/config/routes.rb index 908e9656..4050d810 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -19,6 +19,9 @@ Discourse::Application.routes.append do put 'admin/wizards/wizard/:wizard_id' => 'admin_wizard#save' delete 'admin/wizards/wizard/:wizard_id' => 'admin_wizard#remove' + get 'admin/wizards/custom-fields' => 'admin_custom_fields#index' + put 'admin/wizards/custom-fields' => 'admin_custom_fields#update' + get 'admin/wizards/submissions' => 'admin_submissions#index' get 'admin/wizards/submissions/:wizard_id' => 'admin_submissions#show' get 'admin/wizards/submissions/:wizard_id/download' => 'admin_submissions#download' diff --git a/controllers/custom_wizard/admin/admin.rb b/controllers/custom_wizard/admin/admin.rb index 2dd87e86..3f70b542 100644 --- a/controllers/custom_wizard/admin/admin.rb +++ b/controllers/custom_wizard/admin/admin.rb @@ -10,4 +10,8 @@ class CustomWizard::AdminController < ::Admin::AdminController params.require(:wizard_id) @wizard = CustomWizard::Wizard.create(params[:wizard_id].underscore) end + + def custom_field_list + serialize_data(CustomWizard::CustomField.list, CustomWizard::CustomFieldSerializer) + end end \ No newline at end of file diff --git a/controllers/custom_wizard/admin/custom_fields.rb b/controllers/custom_wizard/admin/custom_fields.rb index 24b5310d..6359d08f 100644 --- a/controllers/custom_wizard/admin/custom_fields.rb +++ b/controllers/custom_wizard/admin/custom_fields.rb @@ -1,18 +1,19 @@ -class CustomWizard::CustomFieldsController < CustomWizard::AdminController +class CustomWizard::AdminCustomFieldsController < CustomWizard::AdminController def index - render_custom_field_list + render_json_dump(custom_field_list) end - def update - field_data = params[:custom_fields] + def update + custom_fields = custom_field_params[:custom_fields].map do |data| + CustomWizard::CustomField.new(data.to_h) + end - custom_fields = field_data.map { |data| CustomWizard::CustomFields.new(data) } - - custom_fields.each do |field_data| + custom_fields.each do |custom_field| custom_field.validate unless custom_field.valid? - raise Discourse::InvalidParameters, "Invalid field: '#{custom_field.name}'" + raise Discourse::InvalidParameters, + custom_field.errors.full_messages.join("\n\n") end end @@ -25,16 +26,22 @@ class CustomWizard::CustomFieldsController < CustomWizard::AdminController end if all_fields_saved - render_custom_field_list + render json: success_json else render json: error_json end end - def render_custom_field_list - render_serialized( - CustomWizard::CustomFields.list, - CustomWizard::CustomFieldsSerializer + private + + def custom_field_params + params.permit( + custom_fields: [ + :klass, + :name, + :type, + serializers: [] + ] ) end end \ No newline at end of file diff --git a/controllers/custom_wizard/admin/wizard.rb b/controllers/custom_wizard/admin/wizard.rb index 2caa3dde..a4515008 100644 --- a/controllers/custom_wizard/admin/wizard.rb +++ b/controllers/custom_wizard/admin/wizard.rb @@ -7,7 +7,8 @@ class CustomWizard::AdminWizardController < CustomWizard::AdminController CustomWizard::Wizard.list, each_serializer: CustomWizard::BasicWizardSerializer ), - field_types: CustomWizard::Field.types + field_types: CustomWizard::Field.types, + custom_fields: custom_field_list ) end diff --git a/lib/custom_wizard/action.rb b/lib/custom_wizard/action.rb index 65ad3cef..5f657dc7 100644 --- a/lib/custom_wizard/action.rb +++ b/lib/custom_wizard/action.rb @@ -60,12 +60,18 @@ class CustomWizard::Action end def send_message - if action['required'].present? && data[action['required']].blank? - log_error( - "required not present", - "required: #{action['required']}; data: #{data[action['required']]}" - ) - return + + if action['required'].present? + required = CustomWizard::Mapper.new( + inputs: action['required'], + data: data, + user: user + ).perform + + if required.blank? + log_error("required input not present") + return + end end params = basic_topic_params @@ -410,17 +416,32 @@ class CustomWizard::Action user: user ).perform + registered_fields = CustomWizard::CustomField.list + field_map.each do |field| keyArr = field[:key].split('.') value = field[:value] - if keyArr.first === 'topic' + if keyArr.length > 1 + klass = keyArr.first + name = keyArr.last + else + name = keyArr.first + end + + + registered = registered_fields.select { |f| f.name == name } + if registered.first.present? + klass = registered.first.klass + end + + if klass === 'topic' params[:topic_opts] ||= {} params[:topic_opts][:custom_fields] ||= {} - params[:topic_opts][:custom_fields][keyArr.last] = value + params[:topic_opts][:custom_fields][name] = value else params[:custom_fields] ||= {} - params[:custom_fields][keyArr.last.to_sym] = value + params[:custom_fields][name] = value end end end diff --git a/lib/custom_wizard/custom_fields.rb b/lib/custom_wizard/custom_field.rb similarity index 52% rename from lib/custom_wizard/custom_fields.rb rename to lib/custom_wizard/custom_field.rb index 98c3cc01..d7e1b61b 100644 --- a/lib/custom_wizard/custom_fields.rb +++ b/lib/custom_wizard/custom_field.rb @@ -1,9 +1,11 @@ -class ::CustomWizard::CustomFields +class ::CustomWizard::CustomField include HasErrors include ActiveModel::Serialization - CLASSES ||= ["topic", "user", "group", "category"] - ATTRS ||= ["name", "klass", "type"] + CLASSES ||= ["topic", "group", "category", "post"] + SERIALIZERS ||= ["topic_view", "topic_list_item", "post", "basic_category"] + TYPES ||= ["string", "boolean", "json"] + ATTRS ||= ["name", "klass", "type", "serializers"] KEY ||= "custom_wizard_custom_fields" def initialize(data) @@ -26,7 +28,7 @@ class ::CustomWizard::CustomFields value = send(attr) if attr == 'name' - name = value + name = value.parameterize(separator: '_') else data[attr] = value end @@ -41,8 +43,27 @@ class ::CustomWizard::CustomFields def validate ATTRS.each do |attr| value = send(attr) - add_error("Attribute required: #{attr}") if value.blank? - add_error("Unsupported class: #{value}") if CLASSES.exclude?(value) + + if value.blank? + add_error("Attribute required: #{attr}") + next + end + + if attr == 'klass' && CLASSES.exclude?(value) + add_error("Unsupported class: #{value}") + end + + if attr == 'serializers' && (SERIALIZERS & value).empty? + add_error("Unsupported serializer: #{value}") + end + + if attr == 'type' && TYPES.exclude?(value) + add_error("Unsupported type: #{value}") + end + + if attr == 'name' && value.length < 3 + add_error("Field name is too short") + end end end diff --git a/lib/custom_wizard/wizard.rb b/lib/custom_wizard/wizard.rb index 549b0422..04308a7f 100644 --- a/lib/custom_wizard/wizard.rb +++ b/lib/custom_wizard/wizard.rb @@ -320,10 +320,6 @@ class CustomWizard::Wizard Jobs.cancel_scheduled_job(:set_after_time_wizard, wizard_id: wizard[:id]) Jobs.enqueue(:clear_after_time_wizard, wizard_id: wizard[:id]) end - - if serialize_fields.present? - - end end wizard[:id] diff --git a/plugin.rb b/plugin.rb index 01852f63..bf840879 100644 --- a/plugin.rb +++ b/plugin.rb @@ -52,7 +52,7 @@ after_initialize do ../lib/custom_wizard/action_result.rb ../lib/custom_wizard/action.rb ../lib/custom_wizard/builder.rb - ../lib/custom_wizard/custom_fields.rb + ../lib/custom_wizard/custom_field.rb ../lib/custom_wizard/field.rb ../lib/custom_wizard/mapper.rb ../lib/custom_wizard/log.rb @@ -70,7 +70,7 @@ after_initialize do ../serializers/custom_wizard/api_serializer.rb ../serializers/custom_wizard/basic_api_serializer.rb ../serializers/custom_wizard/basic_wizard_serializer.rb - ../serializers/custom_wizard/custom_fields_serializer.rb + ../serializers/custom_wizard/custom_field_serializer.rb ../serializers/custom_wizard/wizard_field_serializer.rb ../serializers/custom_wizard/wizard_step_serializer.rb ../serializers/custom_wizard/wizard_serializer.rb @@ -163,16 +163,23 @@ after_initialize do CustomWizard::Wizard.register_styles - CustomWizard::CustomFields.list.each do |field| + CustomWizard::CustomField.list.each do |field| + self.send("register_#{field.klass}_custom_field_type", field.name, field.type.to_sym) + add_to_class(field.klass.to_sym, field.name.to_sym) do custom_fields[field.name] end - add_to_serializer(field.klass.to_sym, field.name.to_sym) do - if field.klass === 'topic' - object.topic.send(field.name) - else - object.send(field.name) + if field.serializers.any? + field.serializers.each do |klass| + klass = klass.to_sym + add_to_serializer(klass, field.name.to_sym) do + if klass == :topic_view + object.topic.send(field.name) + else + object.send(field.name) + end + end end end end diff --git a/serializers/custom_wizard/custom_field_serializer.rb b/serializers/custom_wizard/custom_field_serializer.rb new file mode 100644 index 00000000..14e3fb32 --- /dev/null +++ b/serializers/custom_wizard/custom_field_serializer.rb @@ -0,0 +1,3 @@ +class CustomWizard::CustomFieldSerializer < ApplicationSerializer + attributes :klass, :name, :type, :serializers +end \ No newline at end of file diff --git a/serializers/custom_wizard/custom_fields_serializer.rb b/serializers/custom_wizard/custom_fields_serializer.rb deleted file mode 100644 index fe8c14f6..00000000 --- a/serializers/custom_wizard/custom_fields_serializer.rb +++ /dev/null @@ -1,3 +0,0 @@ -class CustomWizard::CustomFieldsSerializer < ApplicationSerializer - attributes :klass, :name, :type -end \ No newline at end of file From 0094be83527331091a9160e8b316738e40a336d5 Mon Sep 17 00:00:00 2001 From: Angus McLeod Date: Tue, 20 Oct 2020 17:07:59 +1100 Subject: [PATCH 4/8] Custom field management locale and style updates --- assets/stylesheets/common/wizard-admin.scss | 16 +++++++++++++++- config/locales/client.en.yml | 4 ++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/assets/stylesheets/common/wizard-admin.scss b/assets/stylesheets/common/wizard-admin.scss index 1c7c29b2..0b07475d 100644 --- a/assets/stylesheets/common/wizard-admin.scss +++ b/assets/stylesheets/common/wizard-admin.scss @@ -542,13 +542,27 @@ } .select-kit.multi-select { - width: 250px; + width: 200px; + + .choices .choice, + .select-kit-filter .filter-input { + height: 25px; + min-height: 25px; + } } input[type="text"] { margin: 0; } + td { + vertical-align: top; + } + + td:not(:last-of-type) { + min-width: 230px; + } + td:last-of-type { text-align: right; } diff --git a/config/locales/client.en.yml b/config/locales/client.en.yml index 0a7b4682..8b21c663 100644 --- a/config/locales/client.en.yml +++ b/config/locales/client.en.yml @@ -295,6 +295,8 @@ en: klass: label: "Class" select: "Select a class" + post: "Post" + category: "Category" topic: "Topic" group: "Group" user: "User" @@ -303,6 +305,8 @@ en: select: "Select serializers" topic_view: "Topic View" topic_list_item: "Topic List Item" + basic_category: "Category" + post: "Post" submissions: nav_label: "Submissions" From cf8b06bbd0b39241f8f1ddf23ee511f540c55541 Mon Sep 17 00:00:00 2001 From: Angus McLeod Date: Tue, 20 Oct 2020 17:40:10 +1100 Subject: [PATCH 5/8] Don't require serializer for custom field --- lib/custom_wizard/custom_field.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/custom_wizard/custom_field.rb b/lib/custom_wizard/custom_field.rb index d7e1b61b..0b6483c6 100644 --- a/lib/custom_wizard/custom_field.rb +++ b/lib/custom_wizard/custom_field.rb @@ -53,7 +53,7 @@ class ::CustomWizard::CustomField add_error("Unsupported class: #{value}") end - if attr == 'serializers' && (SERIALIZERS & value).empty? + if attr == 'serializers' && value.present? && (SERIALIZERS & value).empty? add_error("Unsupported serializer: #{value}") end From 4e094edc7beb760c51a3a56cde2e58414bddbff8 Mon Sep 17 00:00:00 2001 From: Angus McLeod Date: Tue, 20 Oct 2020 18:24:27 +1100 Subject: [PATCH 6/8] Add integer data type to custom field feature --- .../javascripts/discourse/components/custom-field-input.js.es6 | 2 +- config/locales/client.en.yml | 1 + lib/custom_wizard/custom_field.rb | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/assets/javascripts/discourse/components/custom-field-input.js.es6 b/assets/javascripts/discourse/components/custom-field-input.js.es6 index b5dbec5b..4b1be935 100644 --- a/assets/javascripts/discourse/components/custom-field-input.js.es6 +++ b/assets/javascripts/discourse/components/custom-field-input.js.es6 @@ -15,7 +15,7 @@ export default Component.extend({ postSerializers: ['post'], categorySerializers: ['basic_category', 'topic_view', 'topic_list_item'], klassContent: generateContent(['topic', 'post', 'group', 'category'], 'klass'), - typeContent: generateContent(['string', 'boolean', 'json'], 'type'), + typeContent: generateContent(['string', 'boolean', 'integer', 'json'], 'type'), showInputs: or('field.new', 'field.edit'), @discourseComputed('field.klass') diff --git a/config/locales/client.en.yml b/config/locales/client.en.yml index 8b21c663..39137f57 100644 --- a/config/locales/client.en.yml +++ b/config/locales/client.en.yml @@ -290,6 +290,7 @@ en: label: "Type" select: "Select a type" string: "String" + integer: "Integer" boolean: "Boolean" json: "JSON" klass: diff --git a/lib/custom_wizard/custom_field.rb b/lib/custom_wizard/custom_field.rb index 0b6483c6..96c21ebb 100644 --- a/lib/custom_wizard/custom_field.rb +++ b/lib/custom_wizard/custom_field.rb @@ -4,7 +4,7 @@ class ::CustomWizard::CustomField CLASSES ||= ["topic", "group", "category", "post"] SERIALIZERS ||= ["topic_view", "topic_list_item", "post", "basic_category"] - TYPES ||= ["string", "boolean", "json"] + TYPES ||= ["string", "boolean", "integer", "json"] ATTRS ||= ["name", "klass", "type", "serializers"] KEY ||= "custom_wizard_custom_fields" From 54d244c1d873546a6f07acd8ddf62bd70339c368 Mon Sep 17 00:00:00 2001 From: Angus McLeod Date: Tue, 20 Oct 2020 20:02:13 +1100 Subject: [PATCH 7/8] Make custom field metaprogramming dynamic --- .../custom_wizard/admin/custom_fields.rb | 1 + lib/custom_wizard/custom_field.rb | 28 +++++++++++++++++++ plugin.rb | 21 +------------- 3 files changed, 30 insertions(+), 20 deletions(-) diff --git a/controllers/custom_wizard/admin/custom_fields.rb b/controllers/custom_wizard/admin/custom_fields.rb index 6359d08f..259150a0 100644 --- a/controllers/custom_wizard/admin/custom_fields.rb +++ b/controllers/custom_wizard/admin/custom_fields.rb @@ -26,6 +26,7 @@ class CustomWizard::AdminCustomFieldsController < CustomWizard::AdminController end if all_fields_saved + CustomWizard::CustomField.register_fields render json: success_json else render json: error_json diff --git a/lib/custom_wizard/custom_field.rb b/lib/custom_wizard/custom_field.rb index 96c21ebb..3009bf12 100644 --- a/lib/custom_wizard/custom_field.rb +++ b/lib/custom_wizard/custom_field.rb @@ -79,4 +79,32 @@ class ::CustomWizard::CustomField self.new(data) end end + + def self.register_fields + self.list.each do |field| + klass = field.klass.classify.constantize + + klass.register_custom_field_type(field.name, field.type.to_sym) + + klass.define_method(field.name) do + custom_fields[field.name] + end + + if field.serializers.any? + field.serializers.each do |serializer| + serializer_klass = "#{serializer}_serializer".classify.constantize + + serializer_klass.class_eval { attributes(field.name.to_sym) } + + serializer_klass.define_method(field.name) do + if serializer == 'topic_view' + object.topic.send(field.name) + else + object.send(field.name) + end + end + end + end + end + end end \ No newline at end of file diff --git a/plugin.rb b/plugin.rb index bf840879..1510983b 100644 --- a/plugin.rb +++ b/plugin.rb @@ -163,26 +163,7 @@ after_initialize do CustomWizard::Wizard.register_styles - CustomWizard::CustomField.list.each do |field| - self.send("register_#{field.klass}_custom_field_type", field.name, field.type.to_sym) - - add_to_class(field.klass.to_sym, field.name.to_sym) do - custom_fields[field.name] - end - - if field.serializers.any? - field.serializers.each do |klass| - klass = klass.to_sym - add_to_serializer(klass, field.name.to_sym) do - if klass == :topic_view - object.topic.send(field.name) - else - object.send(field.name) - end - end - end - end - end + CustomWizard::CustomField.register_fields DiscourseEvent.trigger(:custom_wizard_ready) end From 9d260635ca8d2f16aac1288509182c6284ba5264 Mon Sep 17 00:00:00 2001 From: Angus McLeod Date: Fri, 23 Oct 2020 11:53:39 +1100 Subject: [PATCH 8/8] Move to more reliable custom field metaprogramming --- .../custom_wizard/admin/custom_fields.rb | 1 - lib/custom_wizard/custom_field.rb | 30 ++++--------------- plugin.rb | 27 +++++++++++++++-- 3 files changed, 31 insertions(+), 27 deletions(-) diff --git a/controllers/custom_wizard/admin/custom_fields.rb b/controllers/custom_wizard/admin/custom_fields.rb index 259150a0..6359d08f 100644 --- a/controllers/custom_wizard/admin/custom_fields.rb +++ b/controllers/custom_wizard/admin/custom_fields.rb @@ -26,7 +26,6 @@ class CustomWizard::AdminCustomFieldsController < CustomWizard::AdminController end if all_fields_saved - CustomWizard::CustomField.register_fields render json: success_json else render json: error_json diff --git a/lib/custom_wizard/custom_field.rb b/lib/custom_wizard/custom_field.rb index 3009bf12..b658a958 100644 --- a/lib/custom_wizard/custom_field.rb +++ b/lib/custom_wizard/custom_field.rb @@ -80,31 +80,13 @@ class ::CustomWizard::CustomField end end - def self.register_fields - self.list.each do |field| - klass = field.klass.classify.constantize - - klass.register_custom_field_type(field.name, field.type.to_sym) - - klass.define_method(field.name) do - custom_fields[field.name] + def self.list_by(attr, value) + self.list.select do |cf| + if attr == 'serializers' + cf.send(attr).include?(value) + else + cf.send(attr) == value end - - if field.serializers.any? - field.serializers.each do |serializer| - serializer_klass = "#{serializer}_serializer".classify.constantize - - serializer_klass.class_eval { attributes(field.name.to_sym) } - - serializer_klass.define_method(field.name) do - if serializer == 'topic_view' - object.topic.send(field.name) - else - object.send(field.name) - end - end - end - end end end end \ No newline at end of file diff --git a/plugin.rb b/plugin.rb index 1510983b..82ee9855 100644 --- a/plugin.rb +++ b/plugin.rb @@ -162,8 +162,31 @@ after_initialize do ::Wizard::Step.prepend CustomWizardStepExtension CustomWizard::Wizard.register_styles + + CustomWizard::CustomField::CLASSES.each do |klass| + add_model_callback(klass.to_sym, :after_initialize) do + CustomWizard::CustomField.list_by('klass', klass).each do |field| + klass.classify + .constantize + .register_custom_field_type(field.name, field.type.to_sym) + end + end + end - CustomWizard::CustomField.register_fields - + CustomWizard::CustomField::SERIALIZERS.each do |serializer_klass| + "#{serializer_klass}_serializer".classify.constantize.class_eval do + CustomWizard::CustomField.list_by('serializers', serializer_klass).each do |field| + attributes(field.name.to_sym) + class_eval %{def #{field.name} + if "#{serializer_klass}" == "topic_view" + object.topic.custom_fields["#{field.name}"] + else + object.custom_fields["#{field.name}"] + end + end} + end + end + end + DiscourseEvent.trigger(:custom_wizard_ready) end