Spiegel von
https://github.com/paviliondev/discourse-custom-wizard.git
synchronisiert 2024-11-09 11:52:54 +01:00
Add enabled setting && tests && file restructure
Dieser Commit ist enthalten in:
Ursprung
bbfc5abae1
Commit
f1fdc37a21
31 geänderte Dateien mit 597 neuen und 510 gelöschten Zeilen
|
@ -3,7 +3,11 @@ import DiscourseURL from 'discourse/lib/url';
|
|||
|
||||
export default {
|
||||
name: 'custom-wizard-edits',
|
||||
initialize() {
|
||||
initialize(container) {
|
||||
const siteSettings = container.lookup('site-settings:main');
|
||||
|
||||
if (!siteSettings.custom_wizard_enabled) return;
|
||||
|
||||
withPluginApi('0.8.12', api => {
|
||||
api.modifyClass('component:global-notice', {
|
||||
buildBuffer(buffer) {
|
||||
|
|
|
@ -6,8 +6,9 @@ export default {
|
|||
|
||||
initialize: function (container) {
|
||||
const messageBus = container.lookup('message-bus:main');
|
||||
const siteSettings = container.lookup('site-settings:main');
|
||||
|
||||
if (!messageBus) { return; }
|
||||
if (!siteSettings.custom_wizard_enabled || !messageBus) return;
|
||||
|
||||
messageBus.subscribe("/redirect_to_wizard", function (wizardId) {
|
||||
const wizardUrl = window.location.origin + '/w/' + wizardId;
|
||||
|
|
|
@ -21,6 +21,7 @@ en:
|
|||
no_valid_wizards: "File doesn't contain any valid wizards"
|
||||
|
||||
site_settings:
|
||||
custom_wizard_enabled: "Enable custom wizards."
|
||||
wizard_redirect_exclude_paths: "Routes excluded from wizard redirects."
|
||||
wizard_recognised_image_upload_formats: "File types which will result in upload displaying an image preview"
|
||||
wizard_national_flags_label_cue: "The characters that must appear in the dropdown field label for it to show a flag"
|
36
config/routes.rb
Normale Datei
36
config/routes.rb
Normale Datei
|
@ -0,0 +1,36 @@
|
|||
CustomWizard::Engine.routes.draw do
|
||||
get ':wizard_id' => 'wizard#index'
|
||||
put ':wizard_id/skip' => 'wizard#skip'
|
||||
get ':wizard_id/steps' => 'wizard#index'
|
||||
get ':wizard_id/steps/:step_id' => 'wizard#index'
|
||||
put ':wizard_id/steps/:step_id' => 'steps#update'
|
||||
end
|
||||
|
||||
Discourse::Application.routes.append do
|
||||
mount ::CustomWizard::Engine, at: 'w'
|
||||
post 'wizard/authorization/callback' => "custom_wizard/authorization#callback"
|
||||
|
||||
scope module: 'custom_wizard', constraints: AdminConstraint.new do
|
||||
get 'admin/wizards' => 'admin#index'
|
||||
get 'admin/wizards/field-types' => 'admin#field_types'
|
||||
get 'admin/wizards/custom' => 'admin#index'
|
||||
get 'admin/wizards/custom/new' => 'admin#index'
|
||||
get 'admin/wizards/custom/all' => 'admin#custom_wizards'
|
||||
get 'admin/wizards/custom/:wizard_id' => 'admin#find_wizard'
|
||||
put 'admin/wizards/custom/save' => 'admin#save'
|
||||
delete 'admin/wizards/custom/remove' => 'admin#remove'
|
||||
get 'admin/wizards/submissions' => 'admin#index'
|
||||
get 'admin/wizards/submissions/:wizard_id' => 'admin#submissions'
|
||||
get 'admin/wizards/apis' => 'api#list'
|
||||
get 'admin/wizards/apis/new' => 'api#index'
|
||||
get 'admin/wizards/apis/:name' => 'api#find'
|
||||
put 'admin/wizards/apis/:name' => 'api#save'
|
||||
delete 'admin/wizards/apis/:name' => 'api#remove'
|
||||
delete 'admin/wizards/apis/logs/:name' => 'api#clearlogs'
|
||||
get 'admin/wizards/apis/:name/redirect' => 'api#redirect'
|
||||
get 'admin/wizards/apis/:name/authorize' => 'api#authorize'
|
||||
get 'admin/wizards/transfer' => 'transfer#index'
|
||||
get 'admin/wizards/transfer/export' => 'transfer#export'
|
||||
post 'admin/wizards/transfer/import' => 'transfer#import'
|
||||
end
|
||||
end
|
|
@ -1,4 +1,5 @@
|
|||
plugins:
|
||||
custom_wizard_enabled: true
|
||||
wizard_redirect_exclude_paths:
|
||||
client: true
|
||||
type: list
|
||||
|
|
|
@ -77,112 +77,118 @@ class CustomWizard::Builder
|
|||
end
|
||||
|
||||
def build(build_opts = {}, params = {})
|
||||
unless (@wizard.completed? && !@wizard.multiple_submissions && !@wizard.user.admin) || !@steps || !@wizard.permitted?
|
||||
reset_submissions if build_opts[:reset]
|
||||
|
||||
@steps.each do |step_template|
|
||||
@wizard.append_step(step_template['id']) do |step|
|
||||
step.title = step_template['title'] if step_template['title']
|
||||
step.description = step_template['description'] if step_template['description']
|
||||
step.banner = step_template['banner'] if step_template['banner']
|
||||
step.key = step_template['key'] if step_template['key']
|
||||
step.permitted = true
|
||||
return @wizard if !SiteSetting.custom_wizard_enabled ||
|
||||
(!@wizard.multiple_submissions &&
|
||||
@wizard.completed? &&
|
||||
!@wizard.user.admin) ||
|
||||
!@steps ||
|
||||
!@wizard.permitted?
|
||||
|
||||
if permitted_params = step_template['permitted_params']
|
||||
permitted_data = {}
|
||||
reset_submissions if build_opts[:reset]
|
||||
|
||||
permitted_params.each do |param|
|
||||
key = param['key'].to_sym
|
||||
permitted_data[key] = params[key] if params[key]
|
||||
end
|
||||
@steps.each do |step_template|
|
||||
@wizard.append_step(step_template['id']) do |step|
|
||||
step.title = step_template['title'] if step_template['title']
|
||||
step.description = step_template['description'] if step_template['description']
|
||||
step.banner = step_template['banner'] if step_template['banner']
|
||||
step.key = step_template['key'] if step_template['key']
|
||||
step.permitted = true
|
||||
|
||||
if permitted_data.present?
|
||||
current_data = @submissions.last || {}
|
||||
save_submissions(current_data.merge(permitted_data), false)
|
||||
if permitted_params = step_template['permitted_params']
|
||||
permitted_data = {}
|
||||
|
||||
permitted_params.each do |param|
|
||||
key = param['key'].to_sym
|
||||
permitted_data[key] = params[key] if params[key]
|
||||
end
|
||||
|
||||
if permitted_data.present?
|
||||
current_data = @submissions.last || {}
|
||||
save_submissions(current_data.merge(permitted_data), false)
|
||||
end
|
||||
end
|
||||
|
||||
if required_data = step_template['required_data']
|
||||
if !@submissions.last && required_data.present?
|
||||
step.permitted = false
|
||||
next
|
||||
end
|
||||
|
||||
required_data.each do |rd|
|
||||
if rd['connector'] === 'equals'
|
||||
step.permitted = @submissions.last[rd['key']] == @submissions.last[rd['value']]
|
||||
end
|
||||
end
|
||||
|
||||
if required_data = step_template['required_data']
|
||||
if !@submissions.last && required_data.present?
|
||||
step.permitted = false
|
||||
next
|
||||
end
|
||||
|
||||
required_data.each do |rd|
|
||||
if rd['connector'] === 'equals'
|
||||
step.permitted = @submissions.last[rd['key']] == @submissions.last[rd['value']]
|
||||
end
|
||||
end
|
||||
|
||||
if !step.permitted
|
||||
step.permitted_message = step_template['required_data_message'] if step_template['required_data_message']
|
||||
next
|
||||
end
|
||||
if !step.permitted
|
||||
step.permitted_message = step_template['required_data_message'] if step_template['required_data_message']
|
||||
next
|
||||
end
|
||||
end
|
||||
|
||||
if step_template['fields'] && step_template['fields'].length
|
||||
step_template['fields'].each do |field_template|
|
||||
append_field(step, step_template, field_template, build_opts)
|
||||
end
|
||||
end
|
||||
|
||||
step.on_update do |updater|
|
||||
@updater = updater
|
||||
user = @wizard.user
|
||||
|
||||
if step_template['fields'] && step_template['fields'].length
|
||||
step_template['fields'].each do |field_template|
|
||||
append_field(step, step_template, field_template, build_opts)
|
||||
step_template['fields'].each do |field|
|
||||
validate_field(field, updater, step_template) if field['type'] != 'text-only'
|
||||
end
|
||||
end
|
||||
|
||||
step.on_update do |updater|
|
||||
@updater = updater
|
||||
user = @wizard.user
|
||||
next if updater.errors.any?
|
||||
|
||||
if step_template['fields'] && step_template['fields'].length
|
||||
step_template['fields'].each do |field|
|
||||
validate_field(field, updater, step_template) if field['type'] != 'text-only'
|
||||
end
|
||||
CustomWizard::Builder.step_handlers.each do |handler|
|
||||
if handler[:wizard_id] == @wizard.id
|
||||
handler[:block].call(self)
|
||||
end
|
||||
end
|
||||
|
||||
next if updater.errors.any?
|
||||
next if updater.errors.any?
|
||||
|
||||
CustomWizard::Builder.step_handlers.each do |handler|
|
||||
if handler[:wizard_id] == @wizard.id
|
||||
handler[:block].call(self)
|
||||
end
|
||||
data = updater.fields.to_h
|
||||
|
||||
## if the wizard has data from the previous steps make that accessible to the actions.
|
||||
if @submissions && @submissions.last && !@submissions.last.key?("submitted_at")
|
||||
submission = @submissions.last
|
||||
data = submission.merge(data)
|
||||
end
|
||||
|
||||
if step_template['actions'] && step_template['actions'].length && data
|
||||
step_template['actions'].each do |action|
|
||||
self.send(action['type'].to_sym, user, action, data)
|
||||
end
|
||||
end
|
||||
|
||||
next if updater.errors.any?
|
||||
final_step = updater.step.next.nil?
|
||||
|
||||
data = updater.fields.to_h
|
||||
if route_to = data['route_to']
|
||||
data.delete('route_to')
|
||||
end
|
||||
|
||||
## if the wizard has data from the previous steps make that accessible to the actions.
|
||||
if @submissions && @submissions.last && !@submissions.last.key?("submitted_at")
|
||||
submission = @submissions.last
|
||||
data = submission.merge(data)
|
||||
end
|
||||
if @wizard.save_submissions && updater.errors.empty?
|
||||
save_submissions(data, final_step)
|
||||
elsif final_step
|
||||
PluginStore.remove("#{@wizard.id}_submissions", @wizard.user.id)
|
||||
end
|
||||
|
||||
if step_template['actions'] && step_template['actions'].length && data
|
||||
step_template['actions'].each do |action|
|
||||
self.send(action['type'].to_sym, user, action, data)
|
||||
end
|
||||
end
|
||||
if final_step && @wizard.id === @wizard.user.custom_fields['redirect_to_wizard']
|
||||
@wizard.user.custom_fields.delete('redirect_to_wizard');
|
||||
@wizard.user.save_custom_fields(true)
|
||||
end
|
||||
|
||||
final_step = updater.step.next.nil?
|
||||
|
||||
if route_to = data['route_to']
|
||||
data.delete('route_to')
|
||||
end
|
||||
|
||||
if @wizard.save_submissions && updater.errors.empty?
|
||||
save_submissions(data, final_step)
|
||||
elsif final_step
|
||||
PluginStore.remove("#{@wizard.id}_submissions", @wizard.user.id)
|
||||
end
|
||||
|
||||
if final_step && @wizard.id === @wizard.user.custom_fields['redirect_to_wizard']
|
||||
@wizard.user.custom_fields.delete('redirect_to_wizard');
|
||||
@wizard.user.save_custom_fields(true)
|
||||
end
|
||||
|
||||
if updater.errors.empty?
|
||||
if final_step
|
||||
updater.result[:redirect_on_complete] = route_to || data['redirect_on_complete']
|
||||
elsif route_to
|
||||
updater.result[:redirect_on_next] = route_to
|
||||
end
|
||||
if updater.errors.empty?
|
||||
if final_step
|
||||
updater.result[:redirect_on_complete] = route_to || data['redirect_on_complete']
|
||||
elsif route_to
|
||||
updater.result[:redirect_on_next] = route_to
|
||||
end
|
||||
end
|
||||
end
|
6
lib/custom_wizard/engine.rb
Normale Datei
6
lib/custom_wizard/engine.rb
Normale Datei
|
@ -0,0 +1,6 @@
|
|||
module ::CustomWizard
|
||||
class Engine < ::Rails::Engine
|
||||
engine_name 'custom_wizard'
|
||||
isolate_namespace CustomWizard
|
||||
end
|
||||
end
|
|
@ -3,6 +3,8 @@ require_dependency 'wizard/field'
|
|||
require_dependency 'wizard/step_updater'
|
||||
require_dependency 'wizard/builder'
|
||||
|
||||
UserHistory.actions[:custom_wizard_step] = 1000
|
||||
|
||||
class CustomWizard::Wizard
|
||||
|
||||
attr_reader :steps, :user
|
|
@ -1,227 +0,0 @@
|
|||
require_dependency 'wizard'
|
||||
require_dependency 'wizard/field'
|
||||
require_dependency 'wizard/step'
|
||||
|
||||
::Wizard.class_eval do
|
||||
def self.user_requires_completion?(user)
|
||||
wizard_result = self.new(user).requires_completion?
|
||||
return wizard_result if wizard_result
|
||||
|
||||
custom_redirect = false
|
||||
|
||||
if user && user.first_seen_at.blank? && wizard_id = CustomWizard::Wizard.after_signup
|
||||
wizard = CustomWizard::Wizard.create(user, wizard_id)
|
||||
|
||||
if !wizard.completed? && wizard.permitted?
|
||||
custom_redirect = true
|
||||
CustomWizard::Wizard.set_wizard_redirect(user, wizard_id)
|
||||
end
|
||||
end
|
||||
|
||||
!!custom_redirect
|
||||
end
|
||||
end
|
||||
|
||||
::Wizard::Field.class_eval do
|
||||
attr_reader :label, :description, :image, :key, :min_length, :file_types, :limit, :property
|
||||
attr_accessor :dropdown_none
|
||||
|
||||
def initialize(attrs)
|
||||
@attrs = attrs || {}
|
||||
@id = attrs[:id]
|
||||
@type = attrs[:type]
|
||||
@required = !!attrs[:required]
|
||||
@description = attrs[:description]
|
||||
@image = attrs[:image]
|
||||
@key = attrs[:key]
|
||||
@min_length = attrs[:min_length]
|
||||
@value = attrs[:value]
|
||||
@choices = []
|
||||
@dropdown_none = attrs[:dropdown_none]
|
||||
@file_types = attrs[:file_types]
|
||||
@limit = attrs[:limit]
|
||||
@property = attrs[:property]
|
||||
end
|
||||
|
||||
def label
|
||||
@label ||= PrettyText.cook(@attrs[:label])
|
||||
end
|
||||
end
|
||||
|
||||
::Wizard::Choice.class_eval do
|
||||
def initialize(id, opts)
|
||||
@id = id
|
||||
@opts = opts
|
||||
@data = opts[:data]
|
||||
@extra_label = opts[:extra_label]
|
||||
@icon = opts[:icon]
|
||||
end
|
||||
|
||||
def label
|
||||
@label ||= PrettyText.cook(@opts[:label])
|
||||
end
|
||||
end
|
||||
|
||||
class ::Wizard::Step
|
||||
attr_accessor :title, :description, :key, :permitted, :permitted_message
|
||||
end
|
||||
|
||||
::WizardSerializer.class_eval do
|
||||
attributes :id,
|
||||
:name,
|
||||
:background,
|
||||
:completed,
|
||||
:required,
|
||||
:min_trust,
|
||||
:permitted,
|
||||
:user,
|
||||
:categories,
|
||||
:uncategorized_category_id
|
||||
|
||||
def id
|
||||
object.id
|
||||
end
|
||||
|
||||
def include_id?
|
||||
object.respond_to?(:id)
|
||||
end
|
||||
|
||||
def name
|
||||
object.name
|
||||
end
|
||||
|
||||
def include_name?
|
||||
object.respond_to?(:name)
|
||||
end
|
||||
|
||||
def background
|
||||
object.background
|
||||
end
|
||||
|
||||
def include_background?
|
||||
object.respond_to?(:background)
|
||||
end
|
||||
|
||||
def completed
|
||||
object.completed?
|
||||
end
|
||||
|
||||
def include_completed?
|
||||
object.completed? &&
|
||||
(!object.respond_to?(:multiple_submissions) || !object.multiple_submissions) &&
|
||||
!scope.is_admin?
|
||||
end
|
||||
|
||||
def min_trust
|
||||
object.min_trust
|
||||
end
|
||||
|
||||
def include_min_trust?
|
||||
object.respond_to?(:min_trust)
|
||||
end
|
||||
|
||||
def permitted
|
||||
object.permitted?
|
||||
end
|
||||
|
||||
def include_permitted?
|
||||
object.respond_to?(:permitted?)
|
||||
end
|
||||
|
||||
def include_start?
|
||||
object.start && include_steps?
|
||||
end
|
||||
|
||||
def include_steps?
|
||||
!include_completed?
|
||||
end
|
||||
|
||||
def required
|
||||
object.required
|
||||
end
|
||||
|
||||
def include_required?
|
||||
object.respond_to?(:required)
|
||||
end
|
||||
|
||||
def user
|
||||
object.user
|
||||
end
|
||||
|
||||
def categories
|
||||
begin
|
||||
site = ::Site.new(scope)
|
||||
::ActiveModel::ArraySerializer.new(site.categories, each_serializer: BasicCategorySerializer)
|
||||
rescue => e
|
||||
puts "HERE IS THE ERROR: #{e.inspect}"
|
||||
end
|
||||
end
|
||||
|
||||
def uncategorized_category_id
|
||||
SiteSetting.uncategorized_category_id
|
||||
end
|
||||
end
|
||||
|
||||
::WizardStepSerializer.class_eval do
|
||||
attributes :permitted, :permitted_message
|
||||
|
||||
def title
|
||||
return PrettyText.cook(object.title) if object.title
|
||||
PrettyText.cook(I18n.t("#{object.key || i18n_key}.title", default: ''))
|
||||
end
|
||||
|
||||
def description
|
||||
return object.description if object.description
|
||||
PrettyText.cook(I18n.t("#{object.key || i18n_key}.description", default: '', base_url: Discourse.base_url))
|
||||
end
|
||||
|
||||
def permitted
|
||||
object.permitted
|
||||
end
|
||||
|
||||
def permitted_message
|
||||
object.permitted_message
|
||||
end
|
||||
end
|
||||
|
||||
::WizardFieldSerializer.class_eval do
|
||||
attributes :dropdown_none, :image, :file_types, :limit, :property
|
||||
|
||||
def label
|
||||
return object.label if object.label.present?
|
||||
I18n.t("#{object.key || i18n_key}.label", default: '')
|
||||
end
|
||||
|
||||
def description
|
||||
return object.description if object.description.present?
|
||||
I18n.t("#{object.key || i18n_key}.description", default: '', base_url: Discourse.base_url)
|
||||
end
|
||||
|
||||
def image
|
||||
object.image
|
||||
end
|
||||
|
||||
def include_image?
|
||||
object.image.present?
|
||||
end
|
||||
|
||||
def placeholder
|
||||
I18n.t("#{object.key || i18n_key}.placeholder", default: '')
|
||||
end
|
||||
|
||||
def dropdown_none
|
||||
object.dropdown_none
|
||||
end
|
||||
|
||||
def file_types
|
||||
object.file_types
|
||||
end
|
||||
|
||||
def limit
|
||||
object.limit
|
||||
end
|
||||
|
||||
def property
|
||||
object.property
|
||||
end
|
||||
end
|
310
plugin.rb
310
plugin.rb
|
@ -8,11 +8,12 @@ register_asset 'stylesheets/wizard_custom_admin.scss'
|
|||
register_asset 'lib/jquery.timepicker.min.js'
|
||||
register_asset 'lib/jquery.timepicker.scss'
|
||||
|
||||
enabled_site_setting :custom_wizard_enabled
|
||||
|
||||
config = Rails.application.config
|
||||
config.assets.paths << Rails.root.join('plugins', 'discourse-custom-wizard', 'assets', 'javascripts')
|
||||
config.assets.paths << Rails.root.join('plugins', 'discourse-custom-wizard', 'assets', 'stylesheets', 'wizard')
|
||||
|
||||
|
||||
if Rails.env.production?
|
||||
config.assets.precompile += %w{
|
||||
wizard-custom-guest.js
|
||||
|
@ -35,79 +36,260 @@ if respond_to?(:register_svg_icon)
|
|||
end
|
||||
|
||||
after_initialize do
|
||||
UserHistory.actions[:custom_wizard_step] = 1000
|
||||
[
|
||||
'../lib/custom_wizard/engine.rb',
|
||||
'../config/routes.rb',
|
||||
'../controllers/custom_wizard/wizard.rb',
|
||||
'../controllers/custom_wizard/steps.rb',
|
||||
'../controllers/custom_wizard/admin.rb',
|
||||
'../controllers/custom_wizard/transfer.rb',
|
||||
'../controllers/custom_wizard/api.rb',
|
||||
'../jobs/clear_after_time_wizard.rb',
|
||||
'../jobs/refresh_api_access_token.rb',
|
||||
'../jobs/set_after_time_wizard.rb',
|
||||
'../lib/custom_wizard/builder.rb',
|
||||
'../lib/custom_wizard/field.rb',
|
||||
'../lib/custom_wizard/flags.rb',
|
||||
'../lib/custom_wizard/step_updater.rb',
|
||||
'../lib/custom_wizard/template.rb',
|
||||
'../lib/custom_wizard/wizard.rb',
|
||||
'../lib/custom_wizard/api/api.rb',
|
||||
'../lib/custom_wizard/api/authorization.rb',
|
||||
'../lib/custom_wizard/api/endpoint.rb',
|
||||
'../lib/custom_wizard/api/log_entry.rb',
|
||||
'../serializers/custom_wizard/api_serializer.rb',
|
||||
'../serializers/custom_wizard/basic_api_serializer.rb',
|
||||
'../serializers/custom_wizard/api/authorization_serializer.rb',
|
||||
'../serializers/custom_wizard/api/basic_endpoint_serializer.rb',
|
||||
'../serializers/custom_wizard/api/endpoint_serializer.rb',
|
||||
'../serializers/custom_wizard/api/log_serializer.rb'
|
||||
].each do |path|
|
||||
load File.expand_path(path, __FILE__)
|
||||
end
|
||||
|
||||
module ::CustomWizard
|
||||
class Engine < ::Rails::Engine
|
||||
engine_name 'custom_wizard'
|
||||
isolate_namespace CustomWizard
|
||||
::Wizard.class_eval do
|
||||
def self.user_requires_completion?(user)
|
||||
wizard_result = self.new(user).requires_completion?
|
||||
return wizard_result if wizard_result
|
||||
|
||||
custom_redirect = false
|
||||
|
||||
if user && user.first_seen_at.blank? && wizard_id = CustomWizard::Wizard.after_signup
|
||||
wizard = CustomWizard::Wizard.create(user, wizard_id)
|
||||
|
||||
if !wizard.completed? && wizard.permitted?
|
||||
custom_redirect = true
|
||||
CustomWizard::Wizard.set_wizard_redirect(user, wizard_id)
|
||||
end
|
||||
end
|
||||
|
||||
!!custom_redirect
|
||||
end
|
||||
end
|
||||
|
||||
CustomWizard::Engine.routes.draw do
|
||||
get ':wizard_id' => 'wizard#index'
|
||||
put ':wizard_id/skip' => 'wizard#skip'
|
||||
get ':wizard_id/steps' => 'wizard#index'
|
||||
get ':wizard_id/steps/:step_id' => 'wizard#index'
|
||||
put ':wizard_id/steps/:step_id' => 'steps#update'
|
||||
end
|
||||
::Wizard::Field.class_eval do
|
||||
attr_reader :label, :description, :image, :key, :min_length, :file_types, :limit, :property
|
||||
attr_accessor :dropdown_none
|
||||
|
||||
Discourse::Application.routes.append do
|
||||
mount ::CustomWizard::Engine, at: 'w'
|
||||
post 'wizard/authorization/callback' => "custom_wizard/authorization#callback"
|
||||
def initialize(attrs)
|
||||
@attrs = attrs || {}
|
||||
@id = attrs[:id]
|
||||
@type = attrs[:type]
|
||||
@required = !!attrs[:required]
|
||||
@description = attrs[:description]
|
||||
@image = attrs[:image]
|
||||
@key = attrs[:key]
|
||||
@min_length = attrs[:min_length]
|
||||
@value = attrs[:value]
|
||||
@choices = []
|
||||
@dropdown_none = attrs[:dropdown_none]
|
||||
@file_types = attrs[:file_types]
|
||||
@limit = attrs[:limit]
|
||||
@property = attrs[:property]
|
||||
end
|
||||
|
||||
scope module: 'custom_wizard', constraints: AdminConstraint.new do
|
||||
get 'admin/wizards' => 'admin#index'
|
||||
get 'admin/wizards/field-types' => 'admin#field_types'
|
||||
get 'admin/wizards/custom' => 'admin#index'
|
||||
get 'admin/wizards/custom/new' => 'admin#index'
|
||||
get 'admin/wizards/custom/all' => 'admin#custom_wizards'
|
||||
get 'admin/wizards/custom/:wizard_id' => 'admin#find_wizard'
|
||||
put 'admin/wizards/custom/save' => 'admin#save'
|
||||
delete 'admin/wizards/custom/remove' => 'admin#remove'
|
||||
get 'admin/wizards/submissions' => 'admin#index'
|
||||
get 'admin/wizards/submissions/:wizard_id' => 'admin#submissions'
|
||||
get 'admin/wizards/apis' => 'api#list'
|
||||
get 'admin/wizards/apis/new' => 'api#index'
|
||||
get 'admin/wizards/apis/:name' => 'api#find'
|
||||
put 'admin/wizards/apis/:name' => 'api#save'
|
||||
delete 'admin/wizards/apis/:name' => 'api#remove'
|
||||
delete 'admin/wizards/apis/logs/:name' => 'api#clearlogs'
|
||||
get 'admin/wizards/apis/:name/redirect' => 'api#redirect'
|
||||
get 'admin/wizards/apis/:name/authorize' => 'api#authorize'
|
||||
get 'admin/wizards/transfer' => 'transfer#index'
|
||||
get 'admin/wizards/transfer/export' => 'transfer#export'
|
||||
post 'admin/wizards/transfer/import' => 'transfer#import'
|
||||
def label
|
||||
@label ||= PrettyText.cook(@attrs[:label])
|
||||
end
|
||||
end
|
||||
|
||||
load File.expand_path('../jobs/clear_after_time_wizard.rb', __FILE__)
|
||||
load File.expand_path('../jobs/set_after_time_wizard.rb', __FILE__)
|
||||
load File.expand_path('../lib/builder.rb', __FILE__)
|
||||
load File.expand_path('../lib/field.rb', __FILE__)
|
||||
load File.expand_path('../lib/flags.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__)
|
||||
#transfer code
|
||||
load File.expand_path('../controllers/transfer.rb', __FILE__)
|
||||
::Wizard::Choice.class_eval do
|
||||
def initialize(id, opts)
|
||||
@id = id
|
||||
@opts = opts
|
||||
@data = opts[:data]
|
||||
@extra_label = opts[:extra_label]
|
||||
@icon = opts[:icon]
|
||||
end
|
||||
|
||||
load File.expand_path('../jobs/refresh_api_access_token.rb', __FILE__)
|
||||
load File.expand_path('../lib/api/api.rb', __FILE__)
|
||||
load File.expand_path('../lib/api/authorization.rb', __FILE__)
|
||||
load File.expand_path('../lib/api/endpoint.rb', __FILE__)
|
||||
load File.expand_path('../lib/api/log_entry.rb', __FILE__)
|
||||
load File.expand_path('../controllers/api.rb', __FILE__)
|
||||
load File.expand_path('../serializers/api/api_serializer.rb', __FILE__)
|
||||
load File.expand_path('../serializers/api/authorization_serializer.rb', __FILE__)
|
||||
load File.expand_path('../serializers/api/basic_api_serializer.rb', __FILE__)
|
||||
load File.expand_path('../serializers/api/endpoint_serializer.rb', __FILE__)
|
||||
load File.expand_path('../serializers/api/basic_endpoint_serializer.rb', __FILE__)
|
||||
load File.expand_path('../serializers/api/log_serializer.rb', __FILE__)
|
||||
def label
|
||||
@label ||= PrettyText.cook(@opts[:label])
|
||||
end
|
||||
end
|
||||
|
||||
class ::Wizard::Step
|
||||
attr_accessor :title, :description, :key, :permitted, :permitted_message
|
||||
end
|
||||
|
||||
::WizardSerializer.class_eval do
|
||||
attributes :id,
|
||||
:name,
|
||||
:background,
|
||||
:completed,
|
||||
:required,
|
||||
:min_trust,
|
||||
:permitted,
|
||||
:user,
|
||||
:categories,
|
||||
:uncategorized_category_id
|
||||
|
||||
def id
|
||||
object.id
|
||||
end
|
||||
|
||||
def include_id?
|
||||
object.respond_to?(:id)
|
||||
end
|
||||
|
||||
def name
|
||||
object.name
|
||||
end
|
||||
|
||||
def include_name?
|
||||
object.respond_to?(:name)
|
||||
end
|
||||
|
||||
def background
|
||||
object.background
|
||||
end
|
||||
|
||||
def include_background?
|
||||
object.respond_to?(:background)
|
||||
end
|
||||
|
||||
def completed
|
||||
object.completed?
|
||||
end
|
||||
|
||||
def include_completed?
|
||||
object.completed? &&
|
||||
(!object.respond_to?(:multiple_submissions) || !object.multiple_submissions) &&
|
||||
!scope.is_admin?
|
||||
end
|
||||
|
||||
def min_trust
|
||||
object.min_trust
|
||||
end
|
||||
|
||||
def include_min_trust?
|
||||
object.respond_to?(:min_trust)
|
||||
end
|
||||
|
||||
def permitted
|
||||
object.permitted?
|
||||
end
|
||||
|
||||
def include_permitted?
|
||||
object.respond_to?(:permitted?)
|
||||
end
|
||||
|
||||
def include_start?
|
||||
object.start && include_steps?
|
||||
end
|
||||
|
||||
def include_steps?
|
||||
!include_completed?
|
||||
end
|
||||
|
||||
def required
|
||||
object.required
|
||||
end
|
||||
|
||||
def include_required?
|
||||
object.respond_to?(:required)
|
||||
end
|
||||
|
||||
def user
|
||||
object.user
|
||||
end
|
||||
|
||||
def categories
|
||||
begin
|
||||
site = ::Site.new(scope)
|
||||
::ActiveModel::ArraySerializer.new(site.categories, each_serializer: BasicCategorySerializer)
|
||||
rescue => e
|
||||
puts "HERE IS THE ERROR: #{e.inspect}"
|
||||
end
|
||||
end
|
||||
|
||||
def uncategorized_category_id
|
||||
SiteSetting.uncategorized_category_id
|
||||
end
|
||||
end
|
||||
|
||||
::WizardStepSerializer.class_eval do
|
||||
attributes :permitted, :permitted_message
|
||||
|
||||
def title
|
||||
return PrettyText.cook(object.title) if object.title
|
||||
PrettyText.cook(I18n.t("#{object.key || i18n_key}.title", default: ''))
|
||||
end
|
||||
|
||||
def description
|
||||
return object.description if object.description
|
||||
PrettyText.cook(I18n.t("#{object.key || i18n_key}.description", default: '', base_url: Discourse.base_url))
|
||||
end
|
||||
|
||||
def permitted
|
||||
object.permitted
|
||||
end
|
||||
|
||||
def permitted_message
|
||||
object.permitted_message
|
||||
end
|
||||
end
|
||||
|
||||
::WizardFieldSerializer.class_eval do
|
||||
attributes :dropdown_none, :image, :file_types, :limit, :property
|
||||
|
||||
def label
|
||||
return object.label if object.label.present?
|
||||
I18n.t("#{object.key || i18n_key}.label", default: '')
|
||||
end
|
||||
|
||||
def description
|
||||
return object.description if object.description.present?
|
||||
I18n.t("#{object.key || i18n_key}.description", default: '', base_url: Discourse.base_url)
|
||||
end
|
||||
|
||||
def image
|
||||
object.image
|
||||
end
|
||||
|
||||
def include_image?
|
||||
object.image.present?
|
||||
end
|
||||
|
||||
def placeholder
|
||||
I18n.t("#{object.key || i18n_key}.placeholder", default: '')
|
||||
end
|
||||
|
||||
def dropdown_none
|
||||
object.dropdown_none
|
||||
end
|
||||
|
||||
def file_types
|
||||
object.file_types
|
||||
end
|
||||
|
||||
def limit
|
||||
object.limit
|
||||
end
|
||||
|
||||
def property
|
||||
object.property
|
||||
end
|
||||
end
|
||||
|
||||
::UsersController.class_eval do
|
||||
def wizard_path
|
||||
|
|
|
@ -3,156 +3,179 @@
|
|||
require 'rails_helper'
|
||||
|
||||
describe CustomWizard::Builder do
|
||||
it "returns a wizard when enabled" do
|
||||
## implement enabled site setting first
|
||||
fab!(:user) { Fabricate(:user) }
|
||||
|
||||
before do
|
||||
@template = File.open(
|
||||
"#{Rails.root}/plugins/discourse-custom-wizard/spec/fixtures/wizard.json"
|
||||
).read
|
||||
end
|
||||
|
||||
it "returns nothing when disabled" do
|
||||
## implement enabled site setting first
|
||||
it "returns no steps when disabled" do
|
||||
CustomWizard::Wizard.add_wizard(@template)
|
||||
SiteSetting.custom_wizard_enabled = false
|
||||
wizard = CustomWizard::Builder.new(user, 'welcome').build
|
||||
expect(wizard.steps.length).to eq(0)
|
||||
expect(wizard.name).to eq('Welcome')
|
||||
end
|
||||
|
||||
it 'returns a wizard with prefilled data if user has partially completed' do
|
||||
context 'enabled' do
|
||||
before do
|
||||
SiteSetting.custom_wizard_enabled = true
|
||||
end
|
||||
|
||||
end
|
||||
it "returns steps when enabled" do
|
||||
CustomWizard::Wizard.add_wizard(@template)
|
||||
wizard = CustomWizard::Builder.new(user, 'welcome').build
|
||||
expect(wizard.steps.length).to eq(2)
|
||||
end
|
||||
|
||||
it 'returns a wiard with no prefilled data if options include reset' do
|
||||
it 'returns no steps if the multiple submissions are disabled and user has completed' do
|
||||
@template['multiple_submissions'] = false
|
||||
CustomWizard::Wizard.add_wizard(@template)
|
||||
wizard = CustomWizard::Builder.new(user, 'welcome').build
|
||||
expect(wizard.steps.length).to eq(0)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
it 'returns nothing if the multiple submissions are disabled and user has completed' do
|
||||
|
||||
end
|
||||
|
||||
it 'returns nothing if the user is not permitted to see it' do
|
||||
|
||||
end
|
||||
|
||||
context 'building steps' do
|
||||
it 'returns step data correctly' do
|
||||
it 'returns nothing if the user is not permitted to see it' do
|
||||
|
||||
end
|
||||
|
||||
it 'saves permitted params' do
|
||||
it 'returns a wizard with prefilled data if user has partially completed' do
|
||||
|
||||
end
|
||||
|
||||
it 'ensures required data is present' do
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
context 'building fields' do
|
||||
it 'returns field data correctly' do
|
||||
it 'returns a wizard with no prefilled data if options include reset' do
|
||||
|
||||
end
|
||||
|
||||
it 'returns checkbox fields correctly' do
|
||||
|
||||
end
|
||||
|
||||
it 'returns upload fields correctly' do
|
||||
|
||||
end
|
||||
|
||||
it 'returns category fields correctly' do
|
||||
|
||||
end
|
||||
|
||||
it 'returns tag fields correctly' do
|
||||
|
||||
end
|
||||
|
||||
it 'returns custom dropdown fields correctly' do
|
||||
|
||||
end
|
||||
|
||||
it 'returns translated dropdown fields correctly' do
|
||||
|
||||
end
|
||||
|
||||
it 'returns preset dropdown fields correctly' do
|
||||
|
||||
end
|
||||
|
||||
it 'applies preset dropdown filters correctly' do
|
||||
|
||||
end
|
||||
|
||||
it 'prefils profile data correctly' do
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
context 'on update' do
|
||||
context 'validation' do
|
||||
it 'applies min length correctly' do
|
||||
context 'building steps' do
|
||||
it 'returns step data correctly' do
|
||||
|
||||
end
|
||||
|
||||
it 'standardises boolean entries' do
|
||||
it 'saves permitted params' do
|
||||
|
||||
end
|
||||
|
||||
it 'requires required fields' do
|
||||
## this may require additional work?
|
||||
it 'ensures required data is present' do
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
context 'building fields' do
|
||||
it 'returns field data correctly' do
|
||||
|
||||
end
|
||||
|
||||
context 'submisisons' do
|
||||
it 'saves submissions' do
|
||||
it 'returns checkbox fields correctly' do
|
||||
|
||||
end
|
||||
|
||||
it 'returns upload fields correctly' do
|
||||
|
||||
end
|
||||
|
||||
it 'returns category fields correctly' do
|
||||
|
||||
end
|
||||
|
||||
it 'returns tag fields correctly' do
|
||||
|
||||
end
|
||||
|
||||
it 'returns custom dropdown fields correctly' do
|
||||
|
||||
end
|
||||
|
||||
it 'returns translated dropdown fields correctly' do
|
||||
|
||||
end
|
||||
|
||||
it 'returns preset dropdown fields correctly' do
|
||||
|
||||
end
|
||||
|
||||
it 'applies preset dropdown filters correctly' do
|
||||
|
||||
end
|
||||
|
||||
it 'prefils profile data correctly' do
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
context 'on update' do
|
||||
context 'validation' do
|
||||
it 'applies min length correctly' do
|
||||
|
||||
end
|
||||
|
||||
it "doesn't save submissions if disabled" do
|
||||
it 'standardises boolean entries' do
|
||||
|
||||
end
|
||||
|
||||
it 'requires required fields' do
|
||||
## this may require additional work?
|
||||
end
|
||||
|
||||
context 'submisisons' do
|
||||
it 'saves submissions' do
|
||||
|
||||
end
|
||||
|
||||
it "doesn't save submissions if disabled" do
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'custom_step_handlers' do
|
||||
it 'runs custom step handlers' do
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'custom_step_handlers' do
|
||||
it 'runs custom step handlers' do
|
||||
context 'actions' do
|
||||
it 'runs all actions attached to a step' do
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'actions' do
|
||||
it 'runs all actions attached to a step' do
|
||||
it 'interpolates wizard and user data correctly' do
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
it 'interpolates wizard and user data correctly' do
|
||||
it 'creates a topic' do
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
it 'creates a topic' do
|
||||
it 'sends a message' do
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
it 'sends a message' do
|
||||
it 'doesnt sent a message if the required data is not present' do
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
it 'doesnt sent a message if the required data is not present' do
|
||||
it 'updates a profile' do
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
it 'updates a profile' do
|
||||
it 'calls an api' do
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
it 'calls an api' do
|
||||
it 'opens a composer' do
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
it 'opens a composer' do
|
||||
it 'adds a user to a group' do
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
it 'adds a user to a group' do
|
||||
|
||||
end
|
||||
|
||||
it 're-routes a user' do
|
||||
it 're-routes a user' do
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
52
spec/fixtures/wizard.json
gevendort
Normale Datei
52
spec/fixtures/wizard.json
gevendort
Normale Datei
|
@ -0,0 +1,52 @@
|
|||
{
|
||||
"id": "welcome",
|
||||
"name": "Welcome",
|
||||
"background": "#006da3",
|
||||
"save_submissions": true,
|
||||
"multiple_submissions": true,
|
||||
"after_signup": true,
|
||||
"theme_id": 4,
|
||||
"steps": [
|
||||
{
|
||||
"id": "step_1",
|
||||
"title": "Welcome to Pavilion",
|
||||
"raw_description": "Hey there, thanks for signing up.\n\nWe're Pavilion, an international freelancer cooperative that specialises in online communities.\n\nThis site is our own community, where we work with our clients, users of our open source work and our broader community.\n\n",
|
||||
"description": "<p>Hey there, thanks for signing up.</p>\n<p>We’re Pavilion, an international freelancer cooperative that specialises in online communities.</p>\n<p>This site is our own community, where we work with our clients, users of our open source work and our broader community.</p>"
|
||||
},
|
||||
{
|
||||
"id": "step_2",
|
||||
"title": "Tell us about you",
|
||||
"raw_description": "We'd like to know a little more about you. Add a your name and your website below. This will update your user profile.",
|
||||
"fields": [
|
||||
{
|
||||
"id": "name",
|
||||
"type": "text",
|
||||
"label": "Name",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"id": "field_3",
|
||||
"label": "Website",
|
||||
"type": "text"
|
||||
}
|
||||
],
|
||||
"actions": [
|
||||
{
|
||||
"id": "update_profile",
|
||||
"type": "update_profile",
|
||||
"profile_updates": [
|
||||
{
|
||||
"key": "name",
|
||||
"value": "name"
|
||||
},
|
||||
{
|
||||
"key": "field_3",
|
||||
"value": "website"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"description": "<p>We’d like to know a little more about you. Add a your name and your website below. This will update your user profile.</p>"
|
||||
}
|
||||
]
|
||||
}
|
Laden …
In neuem Issue referenzieren