diff --git a/assets/javascripts/wizard/initializers/custom.js.es6 b/assets/javascripts/wizard/initializers/custom.js.es6 index 62b0adbf..473e9f1f 100644 --- a/assets/javascripts/wizard/initializers/custom.js.es6 +++ b/assets/javascripts/wizard/initializers/custom.js.es6 @@ -25,7 +25,9 @@ export default { ApplicationRoute.reopen({ redirect() { this.transitionTo('custom'); - } + }, + + model() {} }); WizardStep.reopen({ diff --git a/app/controllers/admin.rb b/controllers/admin.rb similarity index 95% rename from app/controllers/admin.rb rename to controllers/admin.rb index 34015ddf..c0f197d1 100644 --- a/app/controllers/admin.rb +++ b/controllers/admin.rb @@ -39,7 +39,7 @@ class CustomWizard::AdminController < ::ApplicationController def custom_wizards rows = PluginStoreRow.where(plugin_name: 'custom_wizard').order(:id) - wizards = [*rows].map { |r| CustomWizard::Wizard.new(r.value) } + wizards = [*rows].map { |r| CustomWizard::Template.new(r.value) } render json: success_json.merge(wizards: wizards) end diff --git a/app/controllers/steps.rb b/controllers/steps.rb similarity index 100% rename from app/controllers/steps.rb rename to controllers/steps.rb diff --git a/app/controllers/wizard.rb b/controllers/wizard.rb similarity index 92% rename from app/controllers/wizard.rb rename to controllers/wizard.rb index a37b54d1..ab95b1cd 100644 --- a/app/controllers/wizard.rb +++ b/controllers/wizard.rb @@ -4,6 +4,7 @@ class CustomWizard::WizardController < ::ApplicationController end def index + puts "USING PROPER CONTROLLER" respond_to do |format| format.json do wizard = CustomWizard::Builder.new(current_user, params[:wizard_id].underscore).build diff --git a/lib/builder.rb b/lib/builder.rb index 968de8f4..b0a43d3f 100644 --- a/lib/builder.rb +++ b/lib/builder.rb @@ -4,13 +4,12 @@ class CustomWizard::Builder def initialize(user, wizard_id) data = PluginStore.get('custom_wizard', wizard_id) - @custom_wizard = CustomWizard::Wizard.new(data) - @wizard = Wizard.new(user, + @template = CustomWizard::Template.new(data) + @wizard = CustomWizard::Wizard.new(user, id: wizard_id, save_submissions: data['save_submissions'], multiple_submissions: data['multiple_submissions'], - background: data["background"], - custom: true + background: data["background"] ) end @@ -28,9 +27,9 @@ class CustomWizard::Builder end def build - unless (@wizard.completed? && !@custom_wizard.respond_to?(:multiple_submissions)) || - !@custom_wizard.steps - @custom_wizard.steps.each do |s| + unless (@wizard.completed? && !@template.respond_to?(:multiple_submissions)) || + !@template.steps + @template.steps.each do |s| @wizard.append_step(s['id']) do |step| step.title = s['title'] if s['title'] step.description = s['description'] if s['description'] @@ -180,6 +179,8 @@ class CustomWizard::Builder end end + puts "BUILDER: #{@wizard.respond_to?(:multiple_submissions)}" + @wizard end end diff --git a/lib/step_updater.rb b/lib/step_updater.rb new file mode 100644 index 00000000..05e60d76 --- /dev/null +++ b/lib/step_updater.rb @@ -0,0 +1,31 @@ +class CustomWizard::StepUpdater + include ActiveModel::Model + + attr_accessor :refresh_required, :fields, :result, :step + + def initialize(current_user, wizard, step, fields) + @current_user = current_user + @wizard = wizard + @step = step + @refresh_required = false + @fields = fields + end + + def update + @step.updater.call(self) if @step.present? && @step.updater.present? + + if success? + UserHistory.create(action: UserHistory.actions[:custom_wizard_step], + context: @wizard.id, + subject: @step.id) + end + end + + def success? + @errors.blank? + end + + def refresh_required? + @refresh_required + end +end diff --git a/lib/template.rb b/lib/template.rb new file mode 100644 index 00000000..6f03a013 --- /dev/null +++ b/lib/template.rb @@ -0,0 +1,14 @@ +class CustomWizard::Template + + attr_reader :id, :name, :steps, :background, :save_submissions, :multiple_submissions, :custom + + def initialize(data) + data = data.is_a?(String) ? ::JSON.parse(data) : data + @id = data['id'] + @name = data['name'] + @background = data['background'] + @save_submissions = data['save_submissions'] + @multiple_submissions = data['multiple_submissions'] + @steps = data['steps'] + end +end diff --git a/lib/wizard.rb b/lib/wizard.rb index e593b923..29bc545a 100644 --- a/lib/wizard.rb +++ b/lib/wizard.rb @@ -1,15 +1,80 @@ +require_dependency 'wizard/step' +require_dependency 'wizard/field' +require_dependency 'wizard/step_updater' +require_dependency 'wizard/builder' + class CustomWizard::Wizard - attr_reader :id, :name, :steps, :background, :save_submissions, :multiple_submissions, :custom + attr_reader :steps, :user + attr_accessor :id, :background, :save_submissions, :multiple_submissions - def initialize(data) - data = data.is_a?(String) ? ::JSON.parse(data) : data - @id = data['id'] - @name = data['name'] - @background = data['background'] - @save_submissions = data['save_submissions'] - @multiple_submissions = data['multiple_submissions'] - @steps = data['steps'] - @custom = true + def initialize(user, attrs = {}) + @steps = [] + @user = user + @first_step = nil + @id = attrs[:id] if attrs[:id] + @save_submissions = attrs[:save_submissions] if attrs[:save_submissions] + @multiple_submissions = attrs[:multiple_submissions] if attrs[:multiple_submissions] + @background = attrs[:background] if attrs[:background] + end + + def create_step(step_name) + ::Wizard::Step.new(step_name) + end + + def append_step(step) + step = create_step(step) if step.is_a?(String) + + yield step if block_given? + + last_step = @steps.last + + @steps << step + + # If it's the first step + if @steps.size == 1 + @first_step = step + step.index = 0 + elsif last_step.present? + last_step.next = step + step.previous = last_step + step.index = last_step.index + 1 + end + end + + def start + completed = ::UserHistory.where( + acting_user_id: @user.id, + action: ::UserHistory.actions[:custom_wizard_step] + ).where(context: @steps.map(&:id)) + .uniq.pluck(:context) + + @steps.each do |s| + return s unless completed.include?(s.id) + end + + @first_step + end + + def completed_steps?(steps) + steps = [steps].flatten.uniq + + completed = ::UserHistory.where( + acting_user_id: @user.id, + action: ::UserHistory.actions[:custom_wizard_step] + ).where(context: steps) + .distinct.order(:context).pluck(:context) + + steps.sort == completed + end + + def create_updater(step_id, fields) + step = @steps.find { |s| s.id == step_id.dasherize } + wizard = self + CustomWizard::StepUpdater.new(@user, wizard, step, fields) + end + + def completed? + completed_steps?(@steps.map(&:id)) end end diff --git a/lib/wizard_edits.rb b/lib/wizard_edits.rb new file mode 100644 index 00000000..20edb8d5 --- /dev/null +++ b/lib/wizard_edits.rb @@ -0,0 +1,80 @@ +require_dependency 'wizard/field' +require_dependency 'wizard/step' + +::Wizard::Field.class_eval do + attr_reader :label, :description, :key, :min_length + + def initialize(attrs) + attrs = attrs || {} + + @id = attrs[:id] + @type = attrs[:type] + @required = !!attrs[:required] + @label = attrs[:label] + @description = attrs[:description] + @key = attrs[:key] + @min_length = attrs[:min_length] + @value = attrs[:value] + @choices = [] + end +end + +class ::Wizard::Step + attr_accessor :title, :description, :key +end + +::WizardSerializer.class_eval do + attributes :id, :background, :completed + + def id + object.id + end + + def background + object.background + end + + def completed + object.completed? + end + + def include_completed? + object.completed? && !object.multiple_submissions && !scope.current_user.admin? + end + + def include_start? + object.start && include_steps? + end + + def include_steps? + !include_completed? + end +end + +::WizardStepSerializer.class_eval do + def title + return object.title if object.title + I18n.t("#{object.key || i18n_key}.title", default: '') + end + + def description + return object.description if object.description + I18n.t("#{object.key || i18n_key}.description", default: '') + end +end + +::WizardFieldSerializer.class_eval do + def label + return object.label if object.label + I18n.t("#{object.key || i18n_key}.label", default: '') + end + + def description + return object.description if object.description + I18n.t("#{object.key || i18n_key}.description", default: '') + end + + def placeholder + I18n.t("#{object.key || i18n_key}.placeholder", default: '') + end +end diff --git a/plugin.rb b/plugin.rb index 76f5a4f2..13906845 100644 --- a/plugin.rb +++ b/plugin.rb @@ -10,6 +10,8 @@ config.assets.paths << Rails.root.join("plugins", "discourse-custom-wizard", "as config.assets.paths << Rails.root.join("plugins", "discourse-custom-wizard", "assets", "stylesheets", "wizard") after_initialize do + UserHistory.actions[:custom_wizard_step] = 100 + require_dependency "application_controller" module ::CustomWizard class Engine < ::Rails::Engine @@ -18,13 +20,6 @@ after_initialize do end end - load File.expand_path('../lib/builder.rb', __FILE__) - load File.expand_path('../lib/field.rb', __FILE__) - load File.expand_path('../lib/wizard.rb', __FILE__) - load File.expand_path('../app/controllers/wizard.rb', __FILE__) - load File.expand_path('../app/controllers/steps.rb', __FILE__) - load File.expand_path('../app/controllers/admin.rb', __FILE__) - CustomWizard::Engine.routes.draw do get ':wizard_id' => 'wizard#index' get ':wizard_id/steps' => 'steps#index' @@ -51,138 +46,13 @@ after_initialize do end end - require_dependency 'wizard' - require_dependency 'wizard/step' - require_dependency 'wizard/step_updater' - require_dependency 'wizard/field' - - ::Wizard.class_eval do - attr_accessor :id, :background, :save_submissions, :multiple_submissions - - def initialize(user, attrs = {}) - @steps = [] - @user = user - @first_step = nil - @max_topics_to_require_completion = 15 - @id = attrs[:id] if attrs[:id] - @save_submissions = attrs[:save_submissions] if attrs[:save_submissions] - @multiple_submissions = attrs[:multiple_submissions] if attrs[:multiple_submissions] - @background = attrs[:background] if attrs[:background] - @custom = attrs[:custom] if attrs[:custom] - end - - def completed? - completed_steps?(@steps.map(&:id)) - end - - def completed_steps?(steps) - steps = [steps].flatten.uniq - - completed = UserHistory.where( - acting_user_id: @user.id, - action: UserHistory.actions[:wizard_step] - ).where(context: steps) - .distinct.order(:context).pluck(:context) - - steps.sort == completed - end - - def start - completed = UserHistory.where( - acting_user_id: @user.id, - action: UserHistory.actions[:wizard_step] - ).where(context: @steps.map(&:id)) - .uniq.pluck(:context) - - # First uncompleted step - steps = @custom ? @steps : steps_with_fields - steps.each do |s| - return s unless completed.include?(s.id) - end - - @first_step - end - end - - ::Wizard::Field.class_eval do - attr_reader :label, :description, :key, :min_length - - def initialize(attrs) - attrs = attrs || {} - - @id = attrs[:id] - @type = attrs[:type] - @required = !!attrs[:required] - @label = attrs[:label] - @description = attrs[:description] - @key = attrs[:key] - @min_length = attrs[:min_length] - @value = attrs[:value] - @choices = [] - end - end - - class ::Wizard::Step - attr_accessor :title, :description, :key - end - - class ::Wizard::StepUpdater - attr_accessor :result, :step - end - - ::WizardSerializer.class_eval do - attributes :id, :background, :completed - - def id - object.id - end - - def background - object.background - end - - def completed - object.completed? - end - - def include_completed? - object.completed? && !object.multiple_submissions && !scope.current_user.admin? - end - - def include_start? - object.start && include_steps? - end - - def include_steps? - !include_completed? - end - end - - ::WizardStepSerializer.class_eval do - def title - return object.title if object.title - I18n.t("#{object.key || i18n_key}.title", default: '') - end - - def description - return object.description if object.description - I18n.t("#{object.key || i18n_key}.description", default: '') - end - end - - ::WizardFieldSerializer.class_eval do - def label - return object.label if object.label - I18n.t("#{object.key || i18n_key}.label", default: '') - end - - def description - return object.description if object.description - I18n.t("#{object.key || i18n_key}.description", default: '') - end - - def placeholder - I18n.t("#{object.key || i18n_key}.placeholder", default: '') - end - end + load File.expand_path('../lib/builder.rb', __FILE__) + load File.expand_path('../lib/field.rb', __FILE__) + load File.expand_path('../lib/step_updater.rb', __FILE__) + load File.expand_path('../lib/template.rb', __FILE__) + load File.expand_path('../lib/wizard.rb', __FILE__) + load File.expand_path('../lib/wizard_edits.rb', __FILE__) + load File.expand_path('../controllers/wizard.rb', __FILE__) + load File.expand_path('../controllers/steps.rb', __FILE__) + load File.expand_path('../controllers/admin.rb', __FILE__) end diff --git a/app/views/layouts/custom_wizard.html.erb b/views/layouts/custom_wizard.html.erb similarity index 100% rename from app/views/layouts/custom_wizard.html.erb rename to views/layouts/custom_wizard.html.erb