1
0
Fork 0
discourse-custom-wizard-unl.../controllers/custom_wizard/admin.rb
Angus McLeod 024ab63006 various
2020-04-08 17:59:54 +10:00

229 Zeilen
5,8 KiB
Ruby

class CustomWizard::AdminController < ::ApplicationController
before_action :ensure_logged_in
before_action :ensure_admin
def index
render nothing: true
end
def field_types
render json: { types: CustomWizard::Field.types }
end
def save
result = build_wizard
if result[:error]
render json: { error: result[:error] }
else
wizard = result[:wizard]
existing_wizard = result[:existing_wizard]
ActiveRecord::Base.transaction do
PluginStore.set('custom_wizard', wizard["id"], wizard)
if wizard['after_time'] && result[:new_after_time]
Jobs.cancel_scheduled_job(:set_after_time_wizard, wizard_id: wizard['id'])
Jobs.enqueue_at(after_time_scheduled, :set_after_time_wizard, wizard_id: wizard['id'])
end
if existing_wizard && existing_wizard['after_time'] && !wizard['after_time']
Jobs.cancel_scheduled_job(:set_after_time_wizard, wizard_id: wizard['id'])
Jobs.enqueue(:clear_after_time_wizard, wizard_id: wizard['id'])
end
end
render json: success_json.merge(wizard: wizard)
end
end
def remove
params.require(:id)
wizard = PluginStore.get('custom_wizard', params[:id])
if wizard['after_time']
Jobs.cancel_scheduled_job(:set_after_time_wizard)
Jobs.enqueue(:clear_after_time_wizard, wizard_id: wizard['id'])
end
PluginStore.remove('custom_wizard', params[:id])
render json: success_json
end
def find_wizard
params.require(:wizard_id)
wizard = PluginStore.get('custom_wizard', params[:wizard_id].underscore)
render json: success_json.merge(wizard: wizard)
end
def custom_wizards
rows = PluginStoreRow.where(plugin_name: 'custom_wizard').order(:id)
wizards = [*rows].map { |r| CustomWizard::Template.new(r.value) }
render json: success_json.merge(wizards: wizards)
end
def submissions
params.require(:wizard_id)
rows = PluginStoreRow.where(plugin_name: "#{params[:wizard_id]}_submissions").order('id DESC')
all_submissions = [*rows].map do |r|
submissions = ::JSON.parse(r.value)
if user = User.find_by(id: r.key)
username = user.username
else
username = I18n.t('admin.wizard.submissions.no_user', id: r.key)
end
submissions.map { |s| { username: username }.merge!(s.except("redirect_to")) }
end.flatten
render json: success_json.merge(submissions: all_submissions)
end
private
def wizard_params
params.require(:wizard)
params[:wizard]
end
def required_properties
{
wizard: ['id', 'name', 'steps'],
step: ['id'],
field: ['id', 'type'],
action: ['id', 'type']
}
end
def dependent_properties
{
after_time: 'after_time_scheduled'
}
end
def check_required(object, type, error)
object.each do |property, value|
required = required_properties[type].include?(property)
if required && property.blank?
error = {
type: 'required',
params: { property: property }
}
end
end
error
end
def check_depdendent(object, error)
object.each do |property, value|
dependent = dependent_properties[property]
if dependent && object[dependent].blank?
error = {
type: 'dependent',
params: { dependent: dependent, property: property }
}
end
end
error
end
def validate_wizard(wizard)
error = nil
error = check_required(wizard, :wizard, error)
error = check_depdendent(wizard, error)
wizard['steps'].each do |step|
error = check_required(step, :step, error)
error = check_depdendent(step, error)
break if error.present?
if step['fields'].present?
step['fields'].each do |field|
error = check_required(field, :field, error)
error = check_depdendent(field, error)
break if error.present?
end
end
end
if wizard['actions'].present?
wizard['actions'].each do |action|
error = check_required(action, :action, error)
error = check_depdendent(action, error)
break if error.present?
end
end
if error
{ error: error }
else
{ success: true }
end
end
def validate_after_time(wizard, existing_wizard)
new = false
error = nil
if wizard["after_time"]
if !wizard["after_time_scheduled"] && !existing_wizard["after_time_scheduled"]
error = 'after_time_need_time'
else
after_time_scheduled = Time.parse(wizard["after_time_scheduled"]).utc
new = existing_wizard['after_time_scheduled'] ?
after_time_scheduled != Time.parse(existing_wizard['after_time_scheduled']).utc :
true
begin
error = 'after_time_invalid' if new && after_time_scheduled < Time.now.utc
rescue ArgumentError
error = 'after_time_invalid'
end
end
end
if error
{ error: { type: error } }
else
{ new: new }
end
end
def build_wizard
wizard = ::JSON.parse(wizard_params)
existing_wizard = PluginStore.get('custom_wizard', wizard['id']) || {}
validation = validate_wizard(wizard)
return validation[:error] if validation[:error]
after_time_validation = validate_after_time(wizard, existing_wizard)
return after_time_validation[:error] if after_time_validation[:error]
wizard['steps'].each do |step|
if step['raw_description']
step['description'] = PrettyText.cook(step['raw_description'])
end
end
result = {
wizard: wizard,
existing_wizard: existing_wizard,
new_after_time: after_time_validation[:new]
}
end
end