wizard.rb 4.0 KB

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