Spiegel von
https://github.com/paviliondev/discourse-custom-wizard.git
synchronisiert 2024-11-22 17:30:29 +01:00
229 Zeilen
5,8 KiB
Ruby
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
|