wizard.rb 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. require_dependency 'wizard/step'
  2. require_dependency 'wizard/field'
  3. require_dependency 'wizard/step_updater'
  4. require_dependency 'wizard/builder'
  5. class CustomWizard::Wizard
  6. attr_reader :steps, :user
  7. attr_accessor :id,
  8. :name,
  9. :background,
  10. :save_submissions,
  11. :multiple_submissions,
  12. :min_trust,
  13. :after_time,
  14. :after_time_scheduled,
  15. :after_signup,
  16. :required,
  17. :prompt_completion
  18. def initialize(user, attrs = {})
  19. @steps = []
  20. @user = user
  21. @first_step = nil
  22. attrs.each do |key, value|
  23. setter = "#{key}="
  24. send(setter, value) if respond_to?(setter.to_sym, false)
  25. end
  26. end
  27. def create_step(step_name)
  28. ::Wizard::Step.new(step_name)
  29. end
  30. def append_step(step)
  31. step = create_step(step) if step.is_a?(String)
  32. yield step if block_given?
  33. last_step = @steps.last
  34. @steps << step
  35. # If it's the first step
  36. if @steps.size == 1
  37. @first_step = step
  38. step.index = 0
  39. elsif last_step.present?
  40. last_step.next = step
  41. step.previous = last_step
  42. step.index = last_step.index + 1
  43. end
  44. end
  45. def start
  46. if unfinished? && last_completed_step = ::UserHistory.where(
  47. acting_user_id: @user.id,
  48. action: ::UserHistory.actions[:custom_wizard_step],
  49. context: @id,
  50. subject: @steps.map(&:id)
  51. ).order("created_at").last
  52. step_id = last_completed_step.subject
  53. last_index = @steps.index { |s| s.id == step_id }
  54. @steps[last_index + 1]
  55. else
  56. @first_step
  57. end
  58. end
  59. def create_updater(step_id, fields)
  60. step = @steps.find { |s| s.id == step_id }
  61. wizard = self
  62. CustomWizard::StepUpdater.new(@user, wizard, step, fields)
  63. end
  64. def unfinished?
  65. most_recent = ::UserHistory.where(
  66. acting_user_id: @user.id,
  67. action: ::UserHistory.actions[:custom_wizard_step],
  68. context: @id,
  69. ).distinct.order('updated_at DESC').first
  70. if most_recent
  71. last_finished_step = most_recent.subject
  72. last_step = CustomWizard::Wizard.step_ids(@id).last
  73. last_finished_step != last_step
  74. else
  75. true
  76. end
  77. end
  78. def completed?
  79. steps = CustomWizard::Wizard.step_ids(@id)
  80. history = ::UserHistory.where(
  81. acting_user_id: @user.id,
  82. action: ::UserHistory.actions[:custom_wizard_step],
  83. context: @id
  84. )
  85. if @after_time
  86. history = history.where("updated_at > ?", @after_time_scheduled)
  87. end
  88. completed = history.distinct.order(:subject).pluck(:subject)
  89. (steps - completed).empty?
  90. end
  91. def permitted?
  92. user.staff? || user.trust_level.to_i >= min_trust.to_i
  93. end
  94. def self.after_signup
  95. rows = PluginStoreRow.where(plugin_name: 'custom_wizard')
  96. wizards = [*rows].select { |r| r.value['after_signup'] }
  97. if wizards.any?
  98. wizards.first.key
  99. else
  100. false
  101. end
  102. end
  103. def self.prompt_completion(user)
  104. rows = PluginStoreRow.where(plugin_name: 'custom_wizard')
  105. wizards = [*rows].select { |r| r.value['prompt_completion'] }
  106. if wizards.any?
  107. wizards.reduce([]) do |result, w|
  108. data = ::JSON.parse(w.value)
  109. id = data['id']
  110. name = data['name']
  111. wizard = CustomWizard::Wizard.new(user, id: id, name: name)
  112. result.push(id: id, name: name) if !wizard.completed?
  113. result
  114. end
  115. else
  116. false
  117. end
  118. end
  119. def self.steps(wizard_id)
  120. wizard = PluginStore.get('custom_wizard', wizard_id)
  121. wizard ? wizard['steps'] : nil
  122. end
  123. def self.step_ids(wizard_id)
  124. steps = self.steps(wizard_id)
  125. return [] if !steps
  126. steps.map { |s| s['id'] }.flatten.uniq
  127. end
  128. def self.field_ids(wizard_id, step_id)
  129. steps = self.steps(wizard_id)
  130. return [] if !steps
  131. step = steps.select { |s| s['id'] === step_id }.first
  132. if step && fields = step['fields']
  133. fields.map { |f| f['id'] }
  134. else
  135. []
  136. end
  137. end
  138. def self.add_wizard(json)
  139. wizard = ::JSON.parse(json)
  140. PluginStore.set('custom_wizard', wizard["id"], wizard)
  141. end
  142. def self.find(wizard_id)
  143. PluginStore.get('custom_wizard', wizard_id)
  144. end
  145. def self.create(user, wizard_id)
  146. CustomWizard::Wizard.new(user, self.find(wizard_id).to_h)
  147. end
  148. def self.set_submission_redirect(user, wizard_id, url)
  149. PluginStore.set("#{wizard_id.underscore}_submissions", user.id, [{ redirect_to: url }])
  150. end
  151. def self.set_wizard_redirect(user, wizard_id)
  152. wizard = CustomWizard::Wizard.create(user, wizard_id)
  153. if wizard.permitted?
  154. user.custom_fields['redirect_to_wizard'] = wizard_id
  155. user.save_custom_fields(true)
  156. else
  157. false
  158. end
  159. end
  160. end