wizard.rb 3.9 KB

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