Spiegel von
https://github.com/paviliondev/discourse-custom-wizard.git
synchronisiert 2024-11-22 09:20:29 +01:00
First working version
Dieser Commit ist enthalten in:
Ursprung
c1007e78f5
Commit
7d2e876584
22 geänderte Dateien mit 267 neuen und 126 gelöschten Zeilen
|
@ -1,5 +1,5 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
class CustomWizard::StepsController < ::ApplicationController
|
class CustomWizard::StepsController < ::CustomWizard::WizardClientController
|
||||||
before_action :ensure_can_update
|
before_action :ensure_can_update
|
||||||
|
|
||||||
def update
|
def update
|
||||||
|
@ -21,7 +21,7 @@ class CustomWizard::StepsController < ::ApplicationController
|
||||||
|
|
||||||
if updater.success?
|
if updater.success?
|
||||||
wizard_id = update_params[:wizard_id]
|
wizard_id = update_params[:wizard_id]
|
||||||
builder = CustomWizard::Builder.new(wizard_id, current_user)
|
builder = CustomWizard::Builder.new(wizard_id, current_user, guest_id)
|
||||||
@wizard = builder.build(force: true)
|
@wizard = builder.build(force: true)
|
||||||
|
|
||||||
current_step = @wizard.find_step(update[:step_id])
|
current_step = @wizard.find_step(update[:step_id])
|
||||||
|
@ -84,7 +84,6 @@ class CustomWizard::StepsController < ::ApplicationController
|
||||||
private
|
private
|
||||||
|
|
||||||
def ensure_can_update
|
def ensure_can_update
|
||||||
@builder = CustomWizard::Builder.new(update_params[:wizard_id], current_user)
|
|
||||||
raise Discourse::InvalidParameters.new(:wizard_id) if @builder.template.nil?
|
raise Discourse::InvalidParameters.new(:wizard_id) if @builder.template.nil?
|
||||||
raise Discourse::InvalidAccess.new if !@builder.wizard || !@builder.wizard.can_access?
|
raise Discourse::InvalidAccess.new if !@builder.wizard || !@builder.wizard.can_access?
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
class CustomWizard::WizardController < ::ApplicationController
|
class CustomWizard::WizardController < ::CustomWizard::WizardClientController
|
||||||
before_action :ensure_plugin_enabled
|
|
||||||
|
|
||||||
def show
|
def show
|
||||||
if wizard.present?
|
if wizard.present?
|
||||||
render json: CustomWizard::WizardSerializer.new(wizard, scope: guardian, root: false).as_json, status: 200
|
render json: CustomWizard::WizardSerializer.new(wizard, scope: guardian, root: false).as_json, status: 200
|
||||||
|
@ -34,19 +32,8 @@ class CustomWizard::WizardController < ::ApplicationController
|
||||||
|
|
||||||
def wizard
|
def wizard
|
||||||
@wizard ||= begin
|
@wizard ||= begin
|
||||||
builder = CustomWizard::Builder.new(params[:wizard_id].underscore, current_user)
|
return nil unless @builder.present?
|
||||||
return nil unless builder.present?
|
@builder.build({ reset: params[:reset] }, params)
|
||||||
opts = {}
|
|
||||||
opts[:reset] = params[:reset]
|
|
||||||
builder.build(opts, params)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
def ensure_plugin_enabled
|
|
||||||
unless SiteSetting.custom_wizard_enabled
|
|
||||||
redirect_to path("/")
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
23
app/controllers/custom_wizard/wizard_client.rb
Normale Datei
23
app/controllers/custom_wizard/wizard_client.rb
Normale Datei
|
@ -0,0 +1,23 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
class CustomWizard::WizardClientController < ::ApplicationController
|
||||||
|
before_action :ensure_plugin_enabled
|
||||||
|
before_action :set_builder
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def ensure_plugin_enabled
|
||||||
|
unless SiteSetting.custom_wizard_enabled
|
||||||
|
redirect_to path("/")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def guest_id
|
||||||
|
return nil if current_user.present?
|
||||||
|
cookies[:custom_wizard_guest_id] ||= CustomWizard::Wizard.generate_guest_id
|
||||||
|
cookies[:custom_wizard_guest_id]
|
||||||
|
end
|
||||||
|
|
||||||
|
def set_builder
|
||||||
|
@builder = CustomWizard::Builder.new(params[:wizard_id].underscore, current_user, guest_id)
|
||||||
|
end
|
||||||
|
end
|
|
@ -2,12 +2,15 @@
|
||||||
class CustomWizard::SubmissionSerializer < ApplicationSerializer
|
class CustomWizard::SubmissionSerializer < ApplicationSerializer
|
||||||
attributes :id,
|
attributes :id,
|
||||||
:fields,
|
:fields,
|
||||||
:submitted_at
|
:submitted_at,
|
||||||
|
:user
|
||||||
has_one :user, serializer: ::BasicUserSerializer, embed: :objects
|
|
||||||
|
|
||||||
def include_user?
|
def include_user?
|
||||||
object.user.present?
|
object.wizard.user.present?
|
||||||
|
end
|
||||||
|
|
||||||
|
def user
|
||||||
|
::BasicUserSerializer.new(object.wizard.user).as_json
|
||||||
end
|
end
|
||||||
|
|
||||||
def fields
|
def fields
|
||||||
|
|
|
@ -209,7 +209,7 @@ const action = {
|
||||||
const filters = {
|
const filters = {
|
||||||
allow_guests: {
|
allow_guests: {
|
||||||
action: {
|
action: {
|
||||||
type: ['route_to']
|
type: ['route_to', 'send_message']
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,7 +53,8 @@ en:
|
||||||
after_signup_after_time: "You can't use 'after time' and 'after signup' on the same wizard."
|
after_signup_after_time: "You can't use 'after time' and 'after signup' on the same wizard."
|
||||||
after_time: "After time setting is invalid."
|
after_time: "After time setting is invalid."
|
||||||
liquid_syntax_error: "Liquid syntax error in %{attribute}: %{message}"
|
liquid_syntax_error: "Liquid syntax error in %{attribute}: %{message}"
|
||||||
subscription: "%{type} %{property} is subscription only"
|
subscription: "%{type} %{property} is subscription only"
|
||||||
|
allow_guests: "%{object_id} is not permitted when allow_guests is enabled"
|
||||||
|
|
||||||
site_settings:
|
site_settings:
|
||||||
custom_wizard_enabled: "Enable custom wizards."
|
custom_wizard_enabled: "Enable custom wizards."
|
||||||
|
|
|
@ -10,7 +10,6 @@ class CustomWizard::Action
|
||||||
create_topic
|
create_topic
|
||||||
update_profile
|
update_profile
|
||||||
open_composer
|
open_composer
|
||||||
send_message
|
|
||||||
watch_categories
|
watch_categories
|
||||||
add_to_group
|
add_to_group
|
||||||
]
|
]
|
||||||
|
@ -91,7 +90,6 @@ class CustomWizard::Action
|
||||||
end
|
end
|
||||||
|
|
||||||
def send_message
|
def send_message
|
||||||
|
|
||||||
if action['required'].present?
|
if action['required'].present?
|
||||||
required = CustomWizard::Mapper.new(
|
required = CustomWizard::Mapper.new(
|
||||||
inputs: action['required'],
|
inputs: action['required'],
|
||||||
|
@ -138,13 +136,14 @@ class CustomWizard::Action
|
||||||
|
|
||||||
params[:archetype] = Archetype.private_message
|
params[:archetype] = Archetype.private_message
|
||||||
|
|
||||||
creator = PostCreator.new(user, params)
|
poster = @wizard.allow_guests ? Discourse.system_user : user
|
||||||
|
creator = PostCreator.new(poster, params)
|
||||||
post = creator.create
|
post = creator.create
|
||||||
|
|
||||||
if creator.errors.present?
|
if creator.errors.present?
|
||||||
messages = creator.errors.full_messages.join(" ")
|
messages = creator.errors.full_messages.join(" ")
|
||||||
log_error("failed to create message", messages)
|
log_error("failed to create message", messages)
|
||||||
elsif action['skip_redirect'].blank?
|
elsif user && action['skip_redirect'].blank?
|
||||||
@submission.redirect_on_complete = post.topic.url
|
@submission.redirect_on_complete = post.topic.url
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -778,10 +777,12 @@ class CustomWizard::Action
|
||||||
end
|
end
|
||||||
|
|
||||||
def save_log
|
def save_log
|
||||||
|
username = user ? user.username : @wizard.actor_id
|
||||||
|
|
||||||
CustomWizard::Log.create(
|
CustomWizard::Log.create(
|
||||||
@wizard.id,
|
@wizard.id,
|
||||||
action['type'],
|
action['type'],
|
||||||
user.username,
|
username,
|
||||||
@log.join('; ')
|
@log.join('; ')
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
|
@ -2,10 +2,10 @@
|
||||||
class CustomWizard::Builder
|
class CustomWizard::Builder
|
||||||
attr_accessor :wizard, :updater, :template
|
attr_accessor :wizard, :updater, :template
|
||||||
|
|
||||||
def initialize(wizard_id, user = nil)
|
def initialize(wizard_id, user = nil, guest_id = nil)
|
||||||
@template = CustomWizard::Template.create(wizard_id)
|
@template = CustomWizard::Template.create(wizard_id)
|
||||||
return nil if @template.nil?
|
return nil if @template.nil?
|
||||||
@wizard = CustomWizard::Wizard.new(template.data, user)
|
@wizard = CustomWizard::Wizard.new(template.data, user, guest_id)
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.sorted_handlers
|
def self.sorted_handlers
|
||||||
|
@ -182,7 +182,7 @@ class CustomWizard::Builder
|
||||||
if field_template['description'].present?
|
if field_template['description'].present?
|
||||||
params[:description] = mapper.interpolate(
|
params[:description] = mapper.interpolate(
|
||||||
field_template['description'],
|
field_template['description'],
|
||||||
user: @wizard.user.present?,
|
user: @wizard.user,
|
||||||
value: true,
|
value: true,
|
||||||
wizard: true,
|
wizard: true,
|
||||||
template: true
|
template: true
|
||||||
|
@ -192,7 +192,7 @@ class CustomWizard::Builder
|
||||||
if field_template['preview_template'].present?
|
if field_template['preview_template'].present?
|
||||||
preview_template = mapper.interpolate(
|
preview_template = mapper.interpolate(
|
||||||
field_template['preview_template'],
|
field_template['preview_template'],
|
||||||
user: @wizard.user.present?,
|
user: @wizard.user,
|
||||||
value: true,
|
value: true,
|
||||||
wizard: true,
|
wizard: true,
|
||||||
template: true
|
template: true
|
||||||
|
@ -204,7 +204,7 @@ class CustomWizard::Builder
|
||||||
if field_template['placeholder'].present?
|
if field_template['placeholder'].present?
|
||||||
params[:placeholder] = mapper.interpolate(
|
params[:placeholder] = mapper.interpolate(
|
||||||
field_template['placeholder'],
|
field_template['placeholder'],
|
||||||
user: @wizard.user.present?,
|
user: @wizard.user,
|
||||||
value: true,
|
value: true,
|
||||||
wizard: true,
|
wizard: true,
|
||||||
template: true
|
template: true
|
||||||
|
@ -248,7 +248,7 @@ class CustomWizard::Builder
|
||||||
if step_template['description']
|
if step_template['description']
|
||||||
step.description = mapper.interpolate(
|
step.description = mapper.interpolate(
|
||||||
step_template['description'],
|
step_template['description'],
|
||||||
user: @wizard.user.present?,
|
user: @wizard.user,
|
||||||
value: true,
|
value: true,
|
||||||
wizard: true,
|
wizard: true,
|
||||||
template: true
|
template: true
|
||||||
|
|
|
@ -203,6 +203,8 @@ class CustomWizard::Mapper
|
||||||
end
|
end
|
||||||
|
|
||||||
def map_user_field(value)
|
def map_user_field(value)
|
||||||
|
return nil unless user
|
||||||
|
|
||||||
if value.include?(User::USER_FIELD_PREFIX)
|
if value.include?(User::USER_FIELD_PREFIX)
|
||||||
user.custom_fields[value]
|
user.custom_fields[value]
|
||||||
elsif PROFILE_FIELDS.include?(value)
|
elsif PROFILE_FIELDS.include?(value)
|
||||||
|
|
|
@ -5,8 +5,7 @@ class CustomWizard::StepUpdater
|
||||||
attr_accessor :refresh_required, :result
|
attr_accessor :refresh_required, :result
|
||||||
attr_reader :step, :submission
|
attr_reader :step, :submission
|
||||||
|
|
||||||
def initialize(current_user, wizard, step, submission)
|
def initialize(wizard, step, submission)
|
||||||
@current_user = current_user
|
|
||||||
@wizard = wizard
|
@wizard = wizard
|
||||||
@step = step
|
@step = step
|
||||||
@refresh_required = false
|
@refresh_required = false
|
||||||
|
@ -22,9 +21,9 @@ class CustomWizard::StepUpdater
|
||||||
|
|
||||||
@step.updater.call(self)
|
@step.updater.call(self)
|
||||||
|
|
||||||
UserHistory.create(
|
CustomWizard::UserHistory.create(
|
||||||
action: UserHistory.actions[:custom_wizard_step],
|
action: CustomWizard::UserHistory.actions[:step],
|
||||||
acting_user_id: @current_user.id,
|
actor_id: @wizard.actor_id,
|
||||||
context: @wizard.id,
|
context: @wizard.id,
|
||||||
subject: @step.id
|
subject: @step.id
|
||||||
)
|
)
|
||||||
|
|
|
@ -7,8 +7,6 @@ class CustomWizard::Submission
|
||||||
META ||= %w(updated_at submitted_at route_to redirect_on_complete redirect_to)
|
META ||= %w(updated_at submitted_at route_to redirect_on_complete redirect_to)
|
||||||
|
|
||||||
attr_reader :id,
|
attr_reader :id,
|
||||||
:user,
|
|
||||||
:user_id,
|
|
||||||
:wizard
|
:wizard
|
||||||
|
|
||||||
attr_accessor :fields,
|
attr_accessor :fields,
|
||||||
|
@ -18,15 +16,8 @@ class CustomWizard::Submission
|
||||||
class_eval { attr_accessor attr }
|
class_eval { attr_accessor attr }
|
||||||
end
|
end
|
||||||
|
|
||||||
def initialize(wizard, data = {}, user_id = nil)
|
def initialize(wizard, data = {})
|
||||||
@wizard = wizard
|
@wizard = wizard
|
||||||
@user_id = user_id
|
|
||||||
|
|
||||||
if user_id
|
|
||||||
@user = User.find_by(id: user_id)
|
|
||||||
else
|
|
||||||
@user = wizard.user
|
|
||||||
end
|
|
||||||
|
|
||||||
data = (data || {}).with_indifferent_access
|
data = (data || {}).with_indifferent_access
|
||||||
@id = data['id'] || SecureRandom.hex(12)
|
@id = data['id'] || SecureRandom.hex(12)
|
||||||
|
@ -44,13 +35,13 @@ class CustomWizard::Submission
|
||||||
return nil unless wizard.save_submissions
|
return nil unless wizard.save_submissions
|
||||||
validate
|
validate
|
||||||
|
|
||||||
submission_list = self.class.list(wizard, user_id: user.id)
|
submission_list = self.class.list(wizard)
|
||||||
submissions = submission_list.submissions.select { |submission| submission.id != self.id }
|
submissions = submission_list.submissions.select { |submission| submission.id != self.id }
|
||||||
self.updated_at = Time.now.iso8601
|
self.updated_at = Time.now.iso8601
|
||||||
submissions.push(self)
|
submissions.push(self)
|
||||||
|
|
||||||
submission_data = submissions.map { |submission| data_to_save(submission) }
|
submission_data = submissions.map { |submission| data_to_save(submission) }
|
||||||
PluginStore.set("#{wizard.id}_#{KEY}", user.id, submission_data)
|
PluginStore.set("#{wizard.id}_#{KEY}", wizard.actor_id, submission_data)
|
||||||
end
|
end
|
||||||
|
|
||||||
def validate
|
def validate
|
||||||
|
@ -93,25 +84,21 @@ class CustomWizard::Submission
|
||||||
data
|
data
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.get(wizard, user_id)
|
def self.get(wizard)
|
||||||
data = PluginStore.get("#{wizard.id}_#{KEY}", user_id).last
|
data = PluginStore.get("#{wizard.id}_#{KEY}", wizard.actor_id).last
|
||||||
new(wizard, data, user_id)
|
new(wizard, data)
|
||||||
end
|
end
|
||||||
|
|
||||||
def remove
|
def remove
|
||||||
if present?
|
if present?
|
||||||
user_id = @user.id
|
data = PluginStore.get("#{@wizard.id}_#{KEY}", wizard.actor_id)
|
||||||
wizard_id = @wizard.id
|
data.delete_if { |sub| sub["id"] == @id }
|
||||||
submission_id = @id
|
PluginStore.set("#{@wizard.id}_#{KEY}", wizard.actor_id, data)
|
||||||
data = PluginStore.get("#{wizard_id}_#{KEY}", user_id)
|
|
||||||
data.delete_if { |sub| sub["id"] == submission_id }
|
|
||||||
PluginStore.set("#{wizard_id}_#{KEY}", user_id, data)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.cleanup_incomplete_submissions(wizard)
|
def self.cleanup_incomplete_submissions(wizard)
|
||||||
user_id = wizard.user.id
|
all_submissions = list(wizard)
|
||||||
all_submissions = list(wizard, user_id: user_id)
|
|
||||||
sorted_submissions = all_submissions.submissions.sort_by do |submission|
|
sorted_submissions = all_submissions.submissions.sort_by do |submission|
|
||||||
zero_epoch_time = DateTime.strptime("0", '%s')
|
zero_epoch_time = DateTime.strptime("0", '%s')
|
||||||
[
|
[
|
||||||
|
@ -129,12 +116,12 @@ class CustomWizard::Submission
|
||||||
end
|
end
|
||||||
|
|
||||||
valid_data = valid_submissions.map { |submission| submission.data_to_save(submission) }
|
valid_data = valid_submissions.map { |submission| submission.data_to_save(submission) }
|
||||||
PluginStore.set("#{wizard.id}_#{KEY}", user_id, valid_data)
|
PluginStore.set("#{wizard.id}_#{KEY}", wizard.actor_id, valid_data)
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.list(wizard, user_id: nil, order_by: nil, page: nil)
|
def self.list(wizard, order_by: nil, page: nil)
|
||||||
params = { plugin_name: "#{wizard.id}_#{KEY}" }
|
params = { plugin_name: "#{wizard.id}_#{KEY}" }
|
||||||
params[:key] = user_id if user_id.present?
|
params[:key] = wizard.actor_id if wizard.actor_id
|
||||||
|
|
||||||
query = PluginStoreRow.where(params)
|
query = PluginStoreRow.where(params)
|
||||||
result = OpenStruct.new(submissions: [], total: nil)
|
result = OpenStruct.new(submissions: [], total: nil)
|
||||||
|
@ -142,7 +129,7 @@ class CustomWizard::Submission
|
||||||
query.each do |record|
|
query.each do |record|
|
||||||
if (submission_data = ::JSON.parse(record.value)).any?
|
if (submission_data = ::JSON.parse(record.value)).any?
|
||||||
submission_data.each do |data|
|
submission_data.each do |data|
|
||||||
result.submissions.push(new(wizard, data, record.key))
|
result.submissions.push(new(wizard, data))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -137,7 +137,6 @@ class CustomWizard::Subscription
|
||||||
end
|
end
|
||||||
|
|
||||||
def business?
|
def business?
|
||||||
return true
|
|
||||||
@subscription.product_id === BUSINESS_PRODUCT_ID
|
@subscription.product_id === BUSINESS_PRODUCT_ID
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -23,7 +23,6 @@ class CustomWizard::Template
|
||||||
normalize_data
|
normalize_data
|
||||||
validate_data
|
validate_data
|
||||||
prepare_data
|
prepare_data
|
||||||
|
|
||||||
return false if errors.any?
|
return false if errors.any?
|
||||||
|
|
||||||
ActiveRecord::Base.transaction do
|
ActiveRecord::Base.transaction do
|
||||||
|
|
54
lib/custom_wizard/user_history.rb
Normale Datei
54
lib/custom_wizard/user_history.rb
Normale Datei
|
@ -0,0 +1,54 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
UserHistory.actions[:custom_wizard_step] = 1000
|
||||||
|
|
||||||
|
class CustomWizard::UserHistory
|
||||||
|
def self.where(actor_id: nil, action: nil, context: nil, subject: nil)
|
||||||
|
::UserHistory.where(where_opts(actor_id, action, context, subject))
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.create(actor_id: nil, action: nil, context: nil, subject: nil)
|
||||||
|
::UserHistory.create(create_opts(actor_id, action, context, subject))
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.create!(actor_id: nil, action: nil, context: nil, subject: nil)
|
||||||
|
::UserHistory.create!(create_opts(actor_id, action, context, subject))
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.actions
|
||||||
|
@actions ||=
|
||||||
|
Enum.new(
|
||||||
|
step: UserHistory.actions[:custom_wizard_step]
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.where_opts(actor_id, action, context, subject)
|
||||||
|
opts = {
|
||||||
|
context: context
|
||||||
|
}
|
||||||
|
opts[:action] = action if action
|
||||||
|
opts[:subject] = subject if subject
|
||||||
|
add_actor(opts, actor_id)
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.create_opts(actor_id, action, context, subject)
|
||||||
|
opts = {
|
||||||
|
action: action,
|
||||||
|
context: context
|
||||||
|
}
|
||||||
|
opts[:subject] = subject if subject
|
||||||
|
add_actor(opts, actor_id)
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.add_actor(opts, actor_id)
|
||||||
|
acting_user_id = actor_id
|
||||||
|
|
||||||
|
if actor_id.is_a?(String) && actor_id.include?(CustomWizard::Wizard::GUEST_ID_PREFIX)
|
||||||
|
opts[:acting_user_id] = Discourse.system_user.id
|
||||||
|
opts[:details] = actor_id
|
||||||
|
else
|
||||||
|
opts[:acting_user_id] = actor_id
|
||||||
|
end
|
||||||
|
|
||||||
|
opts
|
||||||
|
end
|
||||||
|
end
|
|
@ -83,7 +83,7 @@ class CustomWizard::TemplateValidator
|
||||||
|
|
||||||
def validate_action(action)
|
def validate_action(action)
|
||||||
if @data[:allow_guests] && CustomWizard::Action::REQUIRES_USER.include?(action[:type])
|
if @data[:allow_guests] && CustomWizard::Action::REQUIRES_USER.include?(action[:type])
|
||||||
errors.add :base, I18n.t("wizard.validation.conflict", wizard_id: action[:id])
|
errors.add :base, I18n.t("wizard.validation.allow_guests", object_id: action[:id])
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -4,8 +4,6 @@ require_dependency 'wizard/field'
|
||||||
require_dependency 'wizard/step_updater'
|
require_dependency 'wizard/step_updater'
|
||||||
require_dependency 'wizard/builder'
|
require_dependency 'wizard/builder'
|
||||||
|
|
||||||
UserHistory.actions[:custom_wizard_step] = 1000
|
|
||||||
|
|
||||||
class CustomWizard::Wizard
|
class CustomWizard::Wizard
|
||||||
include ActiveModel::SerializerSupport
|
include ActiveModel::SerializerSupport
|
||||||
|
|
||||||
|
@ -32,13 +30,21 @@ class CustomWizard::Wizard
|
||||||
:actions,
|
:actions,
|
||||||
:action_ids,
|
:action_ids,
|
||||||
:user,
|
:user,
|
||||||
|
:guest_id,
|
||||||
:submissions,
|
:submissions,
|
||||||
:template
|
:template
|
||||||
|
|
||||||
attr_reader :all_step_ids
|
attr_reader :all_step_ids
|
||||||
|
|
||||||
def initialize(attrs = {}, user = nil)
|
GUEST_ID_PREFIX ||= "guest"
|
||||||
@user = user
|
|
||||||
|
def initialize(attrs = {}, user = nil, guest_id = nil)
|
||||||
|
if user
|
||||||
|
@user = user
|
||||||
|
elsif guest_id
|
||||||
|
@guest_id = guest_id
|
||||||
|
end
|
||||||
|
|
||||||
attrs = attrs.with_indifferent_access
|
attrs = attrs.with_indifferent_access
|
||||||
|
|
||||||
@id = attrs['id']
|
@id = attrs['id']
|
||||||
|
@ -83,6 +89,10 @@ class CustomWizard::Wizard
|
||||||
@template = attrs
|
@template = attrs
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def actor_id
|
||||||
|
user ? user.id : guest_id
|
||||||
|
end
|
||||||
|
|
||||||
def cast_bool(val)
|
def cast_bool(val)
|
||||||
val.nil? ? false : ActiveRecord::Type::Boolean.new.cast(val)
|
val.nil? ? false : ActiveRecord::Type::Boolean.new.cast(val)
|
||||||
end
|
end
|
||||||
|
@ -143,17 +153,16 @@ class CustomWizard::Wizard
|
||||||
end
|
end
|
||||||
|
|
||||||
def last_completed_step_id
|
def last_completed_step_id
|
||||||
if user && unfinished? && last_completed_step = ::UserHistory.where(
|
return nil unless actor_id && unfinished?
|
||||||
acting_user_id: user.id,
|
|
||||||
action: ::UserHistory.actions[:custom_wizard_step],
|
|
||||||
context: id,
|
|
||||||
subject: all_step_ids
|
|
||||||
).order("created_at").last
|
|
||||||
|
|
||||||
last_completed_step.subject
|
last_completed_step = CustomWizard::UserHistory.where(
|
||||||
else
|
actor_id: actor_id,
|
||||||
nil
|
action: CustomWizard::UserHistory.actions[:step],
|
||||||
end
|
context: id,
|
||||||
|
subject: all_step_ids
|
||||||
|
).order("created_at").last
|
||||||
|
|
||||||
|
last_completed_step&.subject
|
||||||
end
|
end
|
||||||
|
|
||||||
def find_step(step_id)
|
def find_step(step_id)
|
||||||
|
@ -163,15 +172,15 @@ class CustomWizard::Wizard
|
||||||
def create_updater(step_id, submission)
|
def create_updater(step_id, submission)
|
||||||
step = @steps.find { |s| s.id == step_id }
|
step = @steps.find { |s| s.id == step_id }
|
||||||
wizard = self
|
wizard = self
|
||||||
CustomWizard::StepUpdater.new(user, wizard, step, submission)
|
CustomWizard::StepUpdater.new(wizard, step, submission)
|
||||||
end
|
end
|
||||||
|
|
||||||
def unfinished?
|
def unfinished?
|
||||||
return nil if !user
|
return nil unless actor_id
|
||||||
|
|
||||||
most_recent = ::UserHistory.where(
|
most_recent = CustomWizard::UserHistory.where(
|
||||||
acting_user_id: user.id,
|
actor_id: actor_id,
|
||||||
action: ::UserHistory.actions[:custom_wizard_step],
|
action: CustomWizard::UserHistory.actions[:step],
|
||||||
context: id,
|
context: id,
|
||||||
).distinct.order('updated_at DESC').first
|
).distinct.order('updated_at DESC').first
|
||||||
|
|
||||||
|
@ -185,11 +194,11 @@ class CustomWizard::Wizard
|
||||||
end
|
end
|
||||||
|
|
||||||
def completed?
|
def completed?
|
||||||
return nil if !user
|
return nil unless actor_id
|
||||||
|
|
||||||
history = ::UserHistory.where(
|
history = CustomWizard::UserHistory.where(
|
||||||
acting_user_id: user.id,
|
actor_id: actor_id,
|
||||||
action: ::UserHistory.actions[:custom_wizard_step],
|
action: CustomWizard::UserHistory.actions[:step],
|
||||||
context: id
|
context: id
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -202,6 +211,7 @@ class CustomWizard::Wizard
|
||||||
end
|
end
|
||||||
|
|
||||||
def permitted?
|
def permitted?
|
||||||
|
return nil unless actor_id
|
||||||
return true if allow_guests
|
return true if allow_guests
|
||||||
return false unless user
|
return false unless user
|
||||||
return true if user.admin? || permitted.blank?
|
return true if user.admin? || permitted.blank?
|
||||||
|
@ -230,6 +240,7 @@ class CustomWizard::Wizard
|
||||||
end
|
end
|
||||||
|
|
||||||
def can_access?
|
def can_access?
|
||||||
|
return nil unless actor_id
|
||||||
return true if allow_guests
|
return true if allow_guests
|
||||||
return false unless user
|
return false unless user
|
||||||
return true if user.admin
|
return true if user.admin
|
||||||
|
@ -237,9 +248,11 @@ class CustomWizard::Wizard
|
||||||
end
|
end
|
||||||
|
|
||||||
def reset
|
def reset
|
||||||
::UserHistory.create(
|
return nil unless actor_id
|
||||||
action: ::UserHistory.actions[:custom_wizard_step],
|
|
||||||
acting_user_id: user.id,
|
CustomWizard::UserHistory.create(
|
||||||
|
action: CustomWizard::UserHistory.actions[:step],
|
||||||
|
actor_id: actor_id,
|
||||||
context: id,
|
context: id,
|
||||||
subject: "reset"
|
subject: "reset"
|
||||||
)
|
)
|
||||||
|
@ -267,8 +280,7 @@ class CustomWizard::Wizard
|
||||||
end
|
end
|
||||||
|
|
||||||
def submissions
|
def submissions
|
||||||
return nil unless user.present?
|
@submissions ||= CustomWizard::Submission.list(self).submissions
|
||||||
@submissions ||= CustomWizard::Submission.list(self, user_id: user.id).submissions
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def current_submission
|
def current_submission
|
||||||
|
@ -304,15 +316,17 @@ class CustomWizard::Wizard
|
||||||
end
|
end
|
||||||
|
|
||||||
def remove_user_redirect
|
def remove_user_redirect
|
||||||
|
return unless user.present?
|
||||||
|
|
||||||
if id == user.redirect_to_wizard
|
if id == user.redirect_to_wizard
|
||||||
user.custom_fields.delete('redirect_to_wizard')
|
user.custom_fields.delete('redirect_to_wizard')
|
||||||
user.save_custom_fields(true)
|
user.save_custom_fields(true)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.create(wizard_id, user = nil)
|
def self.create(wizard_id, user = nil, guest_id = nil)
|
||||||
if template = CustomWizard::Template.find(wizard_id)
|
if template = CustomWizard::Template.find(wizard_id)
|
||||||
new(template.to_h, user)
|
new(template.to_h, user, guest_id)
|
||||||
else
|
else
|
||||||
false
|
false
|
||||||
end
|
end
|
||||||
|
@ -384,4 +398,8 @@ class CustomWizard::Wizard
|
||||||
false
|
false
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def self.generate_guest_id
|
||||||
|
"#{self::GUEST_ID_PREFIX}_#{SecureRandom.hex(12)}"
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -41,6 +41,7 @@ after_initialize do
|
||||||
../app/controllers/custom_wizard/admin/logs.rb
|
../app/controllers/custom_wizard/admin/logs.rb
|
||||||
../app/controllers/custom_wizard/admin/manager.rb
|
../app/controllers/custom_wizard/admin/manager.rb
|
||||||
../app/controllers/custom_wizard/admin/custom_fields.rb
|
../app/controllers/custom_wizard/admin/custom_fields.rb
|
||||||
|
../app/controllers/custom_wizard/wizard_client.rb
|
||||||
../app/controllers/custom_wizard/wizard.rb
|
../app/controllers/custom_wizard/wizard.rb
|
||||||
../app/controllers/custom_wizard/steps.rb
|
../app/controllers/custom_wizard/steps.rb
|
||||||
../app/controllers/custom_wizard/realtime_validations.rb
|
../app/controllers/custom_wizard/realtime_validations.rb
|
||||||
|
@ -65,6 +66,7 @@ after_initialize do
|
||||||
../lib/custom_wizard/subscription.rb
|
../lib/custom_wizard/subscription.rb
|
||||||
../lib/custom_wizard/template.rb
|
../lib/custom_wizard/template.rb
|
||||||
../lib/custom_wizard/wizard.rb
|
../lib/custom_wizard/wizard.rb
|
||||||
|
../lib/custom_wizard/user_history.rb
|
||||||
../lib/custom_wizard/api/api.rb
|
../lib/custom_wizard/api/api.rb
|
||||||
../lib/custom_wizard/api/authorization.rb
|
../lib/custom_wizard/api/authorization.rb
|
||||||
../lib/custom_wizard/api/endpoint.rb
|
../lib/custom_wizard/api/endpoint.rb
|
||||||
|
|
|
@ -76,8 +76,8 @@ describe CustomWizard::Action do
|
||||||
updater.update
|
updater.update
|
||||||
|
|
||||||
expect(updater.success?).to eq(true)
|
expect(updater.success?).to eq(true)
|
||||||
expect(UserHistory.where(
|
expect(CustomWizard::UserHistory.where(
|
||||||
acting_user_id: user.id,
|
actor_id: user.id,
|
||||||
context: "super_mega_fun_wizard",
|
context: "super_mega_fun_wizard",
|
||||||
subject: "step_3"
|
subject: "step_3"
|
||||||
).exists?).to eq(true)
|
).exists?).to eq(true)
|
||||||
|
@ -285,6 +285,28 @@ describe CustomWizard::Action do
|
||||||
expect(topic.first.allowed_groups.map(&:name)).to include('cool_group', 'cool_group_1')
|
expect(topic.first.allowed_groups.map(&:name)).to include('cool_group', 'cool_group_1')
|
||||||
expect(post.exists?).to eq(true)
|
expect(post.exists?).to eq(true)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it "send_message works with allow_guests enabled" do
|
||||||
|
wizard_template["allow_guests"] = true
|
||||||
|
wizard_template.delete("actions")
|
||||||
|
wizard_template['actions'] = [send_message]
|
||||||
|
update_template(wizard_template)
|
||||||
|
|
||||||
|
User.create(username: 'angus1', email: "angus1@email.com")
|
||||||
|
|
||||||
|
wizard = CustomWizard::Builder.new(wizard_template["id"], nil, CustomWizard::Wizard.generate_guest_id).build
|
||||||
|
wizard.create_updater(wizard.steps[0].id, {}).update
|
||||||
|
updater = wizard.create_updater(wizard.steps[1].id, {})
|
||||||
|
updater.update
|
||||||
|
|
||||||
|
topic = Topic.where(archetype: Archetype.private_message, title: "Message title")
|
||||||
|
post = Post.where(topic_id: topic.pluck(:id))
|
||||||
|
|
||||||
|
expect(topic.exists?).to eq(true)
|
||||||
|
expect(topic.first.topic_allowed_users.first.user.username).to eq('angus1')
|
||||||
|
expect(topic.first.topic_allowed_users.second.user.username).to eq(Discourse.system_user.username)
|
||||||
|
expect(post.exists?).to eq(true)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context "business subscription actions" do
|
context "business subscription actions" do
|
||||||
|
|
|
@ -80,14 +80,11 @@ describe CustomWizard::Builder do
|
||||||
|
|
||||||
it 'returns no steps if user has completed it' do
|
it 'returns no steps if user has completed it' do
|
||||||
@template[:steps].each do |step|
|
@template[:steps].each do |step|
|
||||||
UserHistory.create!(
|
CustomWizard::UserHistory.create!(
|
||||||
{
|
action: CustomWizard::UserHistory.actions[:step],
|
||||||
action: UserHistory.actions[:custom_wizard_step],
|
actor_id: user.id,
|
||||||
acting_user_id: user.id,
|
context: @template[:id],
|
||||||
context: @template[:id]
|
subject: step[:id]
|
||||||
}.merge(
|
|
||||||
subject: step[:id]
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@ describe CustomWizard::Submission do
|
||||||
fab!(:user) { Fabricate(:user) }
|
fab!(:user) { Fabricate(:user) }
|
||||||
fab!(:user2) { Fabricate(:user) }
|
fab!(:user2) { Fabricate(:user) }
|
||||||
let(:template_json) { get_wizard_fixture("wizard") }
|
let(:template_json) { get_wizard_fixture("wizard") }
|
||||||
|
let(:guest_id) { CustomWizard::Wizard.generate_guest_id }
|
||||||
|
|
||||||
before do
|
before do
|
||||||
CustomWizard::Template.save(template_json, skip_jobs: true)
|
CustomWizard::Template.save(template_json, skip_jobs: true)
|
||||||
|
@ -13,10 +14,20 @@ describe CustomWizard::Submission do
|
||||||
|
|
||||||
it "saves a user's submission" do
|
it "saves a user's submission" do
|
||||||
expect(
|
expect(
|
||||||
described_class.get(@wizard, user.id).fields["step_1_field_1"]
|
described_class.get(@wizard).fields["step_1_field_1"]
|
||||||
).to eq("I am user submission")
|
).to eq("I am user submission")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it "saves a guest's submission" do
|
||||||
|
CustomWizard::Template.save(template_json, skip_jobs: true)
|
||||||
|
@wizard = CustomWizard::Wizard.create(template_json["id"], nil, guest_id)
|
||||||
|
described_class.new(@wizard, step_1_field_1: "I am guest submission").save
|
||||||
|
|
||||||
|
expect(
|
||||||
|
described_class.get(@wizard).fields["step_1_field_1"]
|
||||||
|
).to eq("I am guest submission")
|
||||||
|
end
|
||||||
|
|
||||||
describe "#list" do
|
describe "#list" do
|
||||||
before do
|
before do
|
||||||
freeze_time Time.now
|
freeze_time Time.now
|
||||||
|
@ -37,14 +48,17 @@ describe CustomWizard::Submission do
|
||||||
end
|
end
|
||||||
|
|
||||||
it "list submissions by wizard" do
|
it "list submissions by wizard" do
|
||||||
|
@wizard.user = nil
|
||||||
expect(described_class.list(@wizard).total).to eq(@count + 2)
|
expect(described_class.list(@wizard).total).to eq(@count + 2)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "list submissions by wizard and user" do
|
it "list submissions by wizard and user" do
|
||||||
expect(described_class.list(@wizard, user_id: user.id).total).to eq(@count + 1)
|
@wizard.user = user
|
||||||
|
expect(described_class.list(@wizard).total).to eq(@count + 1)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "paginates submission lists" do
|
it "paginates submission lists" do
|
||||||
|
@wizard.user = nil
|
||||||
expect(described_class.list(@wizard, page: 1).submissions.size).to eq((@count + 2) - CustomWizard::Submission::PAGE_LIMIT)
|
expect(described_class.list(@wizard, page: 1).submissions.size).to eq((@count + 2) - CustomWizard::Submission::PAGE_LIMIT)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -59,7 +73,7 @@ describe CustomWizard::Submission do
|
||||||
described_class.new(@wizard, step_1_field_1: "I am the second submission").save
|
described_class.new(@wizard, step_1_field_1: "I am the second submission").save
|
||||||
builder = CustomWizard::Builder.new(@wizard.id, @wizard.user)
|
builder = CustomWizard::Builder.new(@wizard.id, @wizard.user)
|
||||||
builder.build
|
builder.build
|
||||||
submissions = described_class.list(@wizard, user_id: @wizard.user.id).submissions
|
submissions = described_class.list(@wizard).submissions
|
||||||
|
|
||||||
expect(submissions.length).to eq(1)
|
expect(submissions.length).to eq(1)
|
||||||
expect(submissions.first.fields["step_1_field_1"]).to eq("I am the second submission")
|
expect(submissions.first.fields["step_1_field_1"]).to eq("I am the second submission")
|
||||||
|
@ -75,7 +89,7 @@ describe CustomWizard::Submission do
|
||||||
PluginStore.set("#{@wizard.id}_submissions", @wizard.user.id, sub_data)
|
PluginStore.set("#{@wizard.id}_submissions", @wizard.user.id, sub_data)
|
||||||
builder = CustomWizard::Builder.new(@wizard.id, @wizard.user)
|
builder = CustomWizard::Builder.new(@wizard.id, @wizard.user)
|
||||||
builder.build
|
builder.build
|
||||||
submissions = described_class.list(@wizard, user_id: @wizard.user.id).submissions
|
submissions = described_class.list(@wizard).submissions
|
||||||
|
|
||||||
expect(submissions.length).to eq(1)
|
expect(submissions.length).to eq(1)
|
||||||
expect(submissions.first.fields["step_1_field_1"]).to eq("I am the second submission")
|
expect(submissions.first.fields["step_1_field_1"]).to eq("I am the second submission")
|
||||||
|
@ -92,7 +106,7 @@ describe CustomWizard::Submission do
|
||||||
|
|
||||||
builder = CustomWizard::Builder.new(@wizard.id, @wizard.user)
|
builder = CustomWizard::Builder.new(@wizard.id, @wizard.user)
|
||||||
builder.build
|
builder.build
|
||||||
submissions = described_class.list(@wizard, user_id: @wizard.user.id).submissions
|
submissions = described_class.list(@wizard).submissions
|
||||||
|
|
||||||
expect(submissions.length).to eq(1)
|
expect(submissions.length).to eq(1)
|
||||||
expect(submissions.first.fields["step_1_field_1"]).to eq("I am the third submission")
|
expect(submissions.first.fields["step_1_field_1"]).to eq("I am the third submission")
|
||||||
|
|
|
@ -21,10 +21,10 @@ describe CustomWizard::Wizard do
|
||||||
@wizard.update!
|
@wizard.update!
|
||||||
end
|
end
|
||||||
|
|
||||||
def progress_step(step_id, acting_user: user, wizard: @wizard)
|
def progress_step(step_id, actor_id: user.id, wizard: @wizard)
|
||||||
UserHistory.create(
|
CustomWizard::UserHistory.create(
|
||||||
action: UserHistory.actions[:custom_wizard_step],
|
action: CustomWizard::UserHistory.actions[:step],
|
||||||
acting_user_id: acting_user.id,
|
actor_id: actor_id,
|
||||||
context: wizard.id,
|
context: wizard.id,
|
||||||
subject: step_id
|
subject: step_id
|
||||||
)
|
)
|
||||||
|
@ -158,9 +158,9 @@ describe CustomWizard::Wizard do
|
||||||
it "lets a permitted user access a complete wizard with multiple submissions" do
|
it "lets a permitted user access a complete wizard with multiple submissions" do
|
||||||
append_steps
|
append_steps
|
||||||
|
|
||||||
progress_step("step_1", acting_user: trusted_user)
|
progress_step("step_1", actor_id: trusted_user.id)
|
||||||
progress_step("step_2", acting_user: trusted_user)
|
progress_step("step_2", actor_id: trusted_user.id)
|
||||||
progress_step("step_3", acting_user: trusted_user)
|
progress_step("step_3", actor_id: trusted_user.id)
|
||||||
|
|
||||||
@permitted_template["multiple_submissions"] = true
|
@permitted_template["multiple_submissions"] = true
|
||||||
|
|
||||||
|
@ -172,9 +172,9 @@ describe CustomWizard::Wizard do
|
||||||
it "does not let an unpermitted user access a complete wizard without multiple submissions" do
|
it "does not let an unpermitted user access a complete wizard without multiple submissions" do
|
||||||
append_steps
|
append_steps
|
||||||
|
|
||||||
progress_step("step_1", acting_user: trusted_user)
|
progress_step("step_1", actor_id: trusted_user.id)
|
||||||
progress_step("step_2", acting_user: trusted_user)
|
progress_step("step_2", actor_id: trusted_user.id)
|
||||||
progress_step("step_3", acting_user: trusted_user)
|
progress_step("step_3", actor_id: trusted_user.id)
|
||||||
|
|
||||||
@permitted_template['multiple_submissions'] = false
|
@permitted_template['multiple_submissions'] = false
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,40 @@ describe CustomWizard::StepsController do
|
||||||
CustomWizard::Template.save(wizard_template, skip_jobs: true)
|
CustomWizard::Template.save(wizard_template, skip_jobs: true)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context "with guest" do
|
||||||
|
it "does not perform a step update" do
|
||||||
|
put '/w/super-mega-fun-wizard/steps/step_1.json', params: {
|
||||||
|
fields: {
|
||||||
|
step_1_field_1: "Text input"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect(response.status).to eq(403)
|
||||||
|
end
|
||||||
|
|
||||||
|
context "with allow_guests enabled" do
|
||||||
|
before do
|
||||||
|
new_template = wizard_template.dup
|
||||||
|
new_template["allow_guests"] = true
|
||||||
|
new_template.delete("actions")
|
||||||
|
result = CustomWizard::Template.save(new_template, skip_jobs: true)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "performs a step update" do
|
||||||
|
put '/w/super-mega-fun-wizard/steps/step_1.json', params: {
|
||||||
|
fields: {
|
||||||
|
step_1_field_1: "Text input"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect(response.status).to eq(200)
|
||||||
|
expect(response.parsed_body['wizard']['start']).to eq("step_2")
|
||||||
|
|
||||||
|
wizard_id = response.parsed_body['wizard']['id']
|
||||||
|
wizard = CustomWizard::Wizard.create(wizard_id, nil, cookies[:custom_wizard_guest_id])
|
||||||
|
expect(wizard.current_submission.fields['step_1_field_1']).to eq("Text input")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
context "with user" do
|
context "with user" do
|
||||||
before do
|
before do
|
||||||
sign_in(user)
|
sign_in(user)
|
||||||
|
|
Laden …
In neuem Issue referenzieren