decidim-time_tracker 0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (134) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE-AGPLv3.txt +661 -0
  3. data/README.md +174 -0
  4. data/Rakefile +40 -0
  5. data/app/assets/config/admin/decidim_time_tracker_manifest.css +2 -0
  6. data/app/assets/config/admin/decidim_time_tracker_manifest.js +1 -0
  7. data/app/assets/config/decidim_time_tracker_manifest.css +3 -0
  8. data/app/assets/config/decidim_time_tracker_manifest.js +1 -0
  9. data/app/assets/images/decidim/time_tracker/icon.svg +1 -0
  10. data/app/assets/javascripts/decidim/time_tracker/activity_ui.js.es6 +112 -0
  11. data/app/assets/javascripts/decidim/time_tracker/admin/assignations.js.es6 +35 -0
  12. data/app/assets/javascripts/decidim/time_tracker/reports/reports.js.es6 +19 -0
  13. data/app/assets/javascripts/decidim/time_tracker/time_tracker.js.es6 +82 -0
  14. data/app/assets/javascripts/decidim/time_tracker/timer_api.js.es6 +55 -0
  15. data/app/assets/stylesheets/decidim/time_tracker/_variables.scss +1 -0
  16. data/app/assets/stylesheets/decidim/time_tracker/admin/time_tracker.scss +59 -0
  17. data/app/assets/stylesheets/decidim/time_tracker/time_tracker.scss +118 -0
  18. data/app/cells/decidim/time_tracker/milestone/show.erb +42 -0
  19. data/app/cells/decidim/time_tracker/milestone_cell.rb +54 -0
  20. data/app/commands/decidim/time_tracker/admin/create_activity.rb +39 -0
  21. data/app/commands/decidim/time_tracker/admin/create_assignation.rb +75 -0
  22. data/app/commands/decidim/time_tracker/admin/create_task.rb +33 -0
  23. data/app/commands/decidim/time_tracker/admin/create_time_tracker.rb +76 -0
  24. data/app/commands/decidim/time_tracker/admin/destroy_activity.rb +43 -0
  25. data/app/commands/decidim/time_tracker/admin/destroy_assignation.rb +43 -0
  26. data/app/commands/decidim/time_tracker/admin/destroy_task.rb +43 -0
  27. data/app/commands/decidim/time_tracker/admin/export_time_tracker.rb +150 -0
  28. data/app/commands/decidim/time_tracker/admin/update_activity.rb +49 -0
  29. data/app/commands/decidim/time_tracker/admin/update_assignation.rb +42 -0
  30. data/app/commands/decidim/time_tracker/admin/update_task.rb +44 -0
  31. data/app/commands/decidim/time_tracker/create_milestone.rb +57 -0
  32. data/app/commands/decidim/time_tracker/create_request_assignation.rb +39 -0
  33. data/app/commands/decidim/time_tracker/start_time_event.rb +104 -0
  34. data/app/commands/decidim/time_tracker/stop_last_time_event.rb +45 -0
  35. data/app/controllers/concerns/decidim/time_tracker/admin/filterable_assignations.rb +50 -0
  36. data/app/controllers/decidim/time_tracker/activity_questionnaire_controller.rb +76 -0
  37. data/app/controllers/decidim/time_tracker/admin/activities_controller.rb +82 -0
  38. data/app/controllers/decidim/time_tracker/admin/activity_questionnaire_controller.rb +52 -0
  39. data/app/controllers/decidim/time_tracker/admin/application_controller.rb +22 -0
  40. data/app/controllers/decidim/time_tracker/admin/assignations_controller.rb +84 -0
  41. data/app/controllers/decidim/time_tracker/admin/assignee_questionnaire_controller.rb +58 -0
  42. data/app/controllers/decidim/time_tracker/admin/stats_controller.rb +24 -0
  43. data/app/controllers/decidim/time_tracker/admin/tasks_controller.rb +112 -0
  44. data/app/controllers/decidim/time_tracker/admin/time_tracker_exports_controller.rb +25 -0
  45. data/app/controllers/decidim/time_tracker/application_controller.rb +24 -0
  46. data/app/controllers/decidim/time_tracker/assignations_controller.rb +38 -0
  47. data/app/controllers/decidim/time_tracker/assignee_questionnaire_controller.rb +80 -0
  48. data/app/controllers/decidim/time_tracker/milestones_controller.rb +62 -0
  49. data/app/controllers/decidim/time_tracker/reports/user_controller.rb +38 -0
  50. data/app/controllers/decidim/time_tracker/time_events_controller.rb +68 -0
  51. data/app/controllers/decidim/time_tracker/time_tracker_controller.rb +43 -0
  52. data/app/forms/decidim/time_tracker/admin/activity_form.rb +27 -0
  53. data/app/forms/decidim/time_tracker/admin/assignation_form.rb +29 -0
  54. data/app/forms/decidim/time_tracker/admin/task_form.rb +22 -0
  55. data/app/forms/decidim/time_tracker/milestone_form.rb +32 -0
  56. data/app/forms/decidim/time_tracker/time_event_form.rb +47 -0
  57. data/app/helpers/decidim/time_tracker/admin/application_helper.rb +33 -0
  58. data/app/helpers/decidim/time_tracker/application_helper.rb +95 -0
  59. data/app/jobs/decidim/time_tracker/stop_counter_job.rb +29 -0
  60. data/app/models/decidim/time_tracker/activity.rb +135 -0
  61. data/app/models/decidim/time_tracker/application_record.rb +10 -0
  62. data/app/models/decidim/time_tracker/assignation.rb +68 -0
  63. data/app/models/decidim/time_tracker/assignee.rb +29 -0
  64. data/app/models/decidim/time_tracker/assignee_data.rb +19 -0
  65. data/app/models/decidim/time_tracker/milestone.rb +27 -0
  66. data/app/models/decidim/time_tracker/task.rb +44 -0
  67. data/app/models/decidim/time_tracker/time_event.rb +62 -0
  68. data/app/models/decidim/time_tracker/time_tracker.rb +46 -0
  69. data/app/models/decidim/time_tracker/tos_acceptance.rb +16 -0
  70. data/app/permissions/decidim/time_tracker/admin/permissions.rb +69 -0
  71. data/app/permissions/decidim/time_tracker/permissions.rb +69 -0
  72. data/app/presenters/decidim/time_tracker/admin_log/activity_presenter.rb +44 -0
  73. data/app/presenters/decidim/time_tracker/admin_log/assignation_presenter.rb +48 -0
  74. data/app/presenters/decidim/time_tracker/admin_log/task_presenter.rb +46 -0
  75. data/app/presenters/decidim/time_tracker/admin_log/value_types/activity_presenter.rb +28 -0
  76. data/app/presenters/decidim/time_tracker/admin_log/value_types/time_tracker_presenter.rb +28 -0
  77. data/app/views/decidim/time_tracker/admin/_breadcrumbs.html.erb +56 -0
  78. data/app/views/decidim/time_tracker/admin/activities/_form.html.erb +41 -0
  79. data/app/views/decidim/time_tracker/admin/activities/_index.html.erb +73 -0
  80. data/app/views/decidim/time_tracker/admin/activities/edit.html.erb +5 -0
  81. data/app/views/decidim/time_tracker/admin/activities/new.html.erb +5 -0
  82. data/app/views/decidim/time_tracker/admin/assignations/_form.html.erb +30 -0
  83. data/app/views/decidim/time_tracker/admin/assignations/index.html.erb +67 -0
  84. data/app/views/decidim/time_tracker/admin/assignations/new.html.erb +9 -0
  85. data/app/views/decidim/time_tracker/admin/questionnaires/_index.html.erb +27 -0
  86. data/app/views/decidim/time_tracker/admin/questionnaires/_questionnaire.html.erb +21 -0
  87. data/app/views/decidim/time_tracker/admin/stats/index.html.erb +50 -0
  88. data/app/views/decidim/time_tracker/admin/tasks/_assignations.html.erb +60 -0
  89. data/app/views/decidim/time_tracker/admin/tasks/_form.html.erb +7 -0
  90. data/app/views/decidim/time_tracker/admin/tasks/_index.html.erb +61 -0
  91. data/app/views/decidim/time_tracker/admin/tasks/edit.html.erb +16 -0
  92. data/app/views/decidim/time_tracker/admin/tasks/index.html.erb +5 -0
  93. data/app/views/decidim/time_tracker/admin/tasks/new.html.erb +12 -0
  94. data/app/views/decidim/time_tracker/milestones/index.html.erb +60 -0
  95. data/app/views/decidim/time_tracker/reports/user/index.html.erb +41 -0
  96. data/app/views/decidim/time_tracker/time_tracker/_activity.html.erb +43 -0
  97. data/app/views/decidim/time_tracker/time_tracker/_answer_questionnaire.html.erb +7 -0
  98. data/app/views/decidim/time_tracker/time_tracker/_assignee_data.html.erb +9 -0
  99. data/app/views/decidim/time_tracker/time_tracker/_callout_status.html.erb +3 -0
  100. data/app/views/decidim/time_tracker/time_tracker/_idle_activity.html.erb +27 -0
  101. data/app/views/decidim/time_tracker/time_tracker/_milestone_form.html.erb +35 -0
  102. data/app/views/decidim/time_tracker/time_tracker/_request_activity.html.erb +22 -0
  103. data/app/views/decidim/time_tracker/time_tracker/_sign_in.html.erb +5 -0
  104. data/app/views/decidim/time_tracker/time_tracker/index.html.erb +59 -0
  105. data/config/activity_questionnaire.yml +26 -0
  106. data/config/assignee_questionnaire.yml +37 -0
  107. data/config/i18n-tasks.yml +10 -0
  108. data/config/locales/ca.yml +394 -0
  109. data/config/locales/cs.yml +394 -0
  110. data/config/locales/en.yml +419 -0
  111. data/config/locales/es.yml +394 -0
  112. data/db/migrate/20200302115642_create_decidim_time_tracker_time_trackers.rb +10 -0
  113. data/db/migrate/20200302115654_create_decidim_time_tracker_tasks.rb +11 -0
  114. data/db/migrate/20200302115658_create_decidim_time_tracker_assignees.rb +12 -0
  115. data/db/migrate/20200302115700_create_decidim_time_tracker_activities.rb +19 -0
  116. data/db/migrate/20200302115708_create_decidim_time_tracker_milestones.rb +13 -0
  117. data/db/migrate/20200302115831_create_decidim_time_tracker_assignations.rb +16 -0
  118. data/db/migrate/20200302115840_create_decidim_time_tracker_time_events.rb +15 -0
  119. data/db/migrate/20201118153327_create_decidim_time_tracker_assignee_data.rb +10 -0
  120. data/db/migrate/20201223115130_create_decidim_time_tracker_tos_acceptances.rb +18 -0
  121. data/lib/decidim/time_tracker.rb +45 -0
  122. data/lib/decidim/time_tracker/admin.rb +10 -0
  123. data/lib/decidim/time_tracker/admin_engine.rb +51 -0
  124. data/lib/decidim/time_tracker/component.rb +248 -0
  125. data/lib/decidim/time_tracker/engine.rb +59 -0
  126. data/lib/decidim/time_tracker/reports.rb +10 -0
  127. data/lib/decidim/time_tracker/reports_engine.rb +34 -0
  128. data/lib/decidim/time_tracker/test/admin_log_presenter_examples.rb +34 -0
  129. data/lib/decidim/time_tracker/test/factories.rb +110 -0
  130. data/lib/decidim/time_tracker/test/time_tracker_context.rb +18 -0
  131. data/lib/decidim/time_tracker/time_tracker_activity_questionnaire_answers_serializer.rb +74 -0
  132. data/lib/decidim/time_tracker/version.rb +9 -0
  133. data/vendor/assets/javascripts/jsrender.min.js +4 -0
  134. metadata +276 -0
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ class CreateDecidimTimeTrackerMilestones < ActiveRecord::Migration[5.2]
4
+ def change
5
+ create_table :decidim_time_tracker_milestones do |t|
6
+ t.references :decidim_user, null: false, index: true
7
+ t.references :activity, foreign_key: { to_table: :decidim_time_tracker_activities }, null: false
8
+ t.string :title
9
+ t.string :description
10
+ t.timestamps
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ class CreateDecidimTimeTrackerAssignations < ActiveRecord::Migration[5.2]
4
+ def change
5
+ create_table :decidim_time_tracker_assignations do |t|
6
+ t.references :decidim_user, null: false, index: true
7
+ t.references :activity, foreign_key: { to_table: :decidim_time_tracker_activities }, null: false
8
+ t.integer :status, default: 0
9
+ t.datetime :invited_at
10
+ t.references :invited_by_user, foreign_key: { to_table: :decidim_users }
11
+ t.datetime :requested_at
12
+ t.datetime :tos_accepted_at
13
+ t.timestamps
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ class CreateDecidimTimeTrackerTimeEvents < ActiveRecord::Migration[5.2]
4
+ def change
5
+ create_table :decidim_time_tracker_time_events do |t|
6
+ t.references :decidim_user, foreign_key: { to_table: :decidim_users }
7
+ t.references :assignation, foreign_key: { to_table: :decidim_time_tracker_assignations }
8
+ t.references :activity, foreign_key: { to_table: :decidim_time_tracker_activities }
9
+ t.integer :start # timestamp (seconds)
10
+ t.integer :stop # timestamp (seconds)
11
+ t.integer :total_seconds, null: false, default: 0
12
+ t.timestamps
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ class CreateDecidimTimeTrackerAssigneeData < ActiveRecord::Migration[5.2]
4
+ def change
5
+ create_table :decidim_time_tracker_assignee_data do |t|
6
+ t.references :time_tracker, foreign_key: { to_table: :decidim_time_trackers }
7
+ t.timestamps
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ class CreateDecidimTimeTrackerTosAcceptances < ActiveRecord::Migration[5.2]
4
+ def up
5
+ create_table :decidim_time_tracker_tos_acceptances do |t|
6
+ t.references :assignee, foreign_key: { to_table: :decidim_time_tracker_assignees }
7
+ t.references :time_tracker, foreign_key: { to_table: :decidim_time_trackers }
8
+ t.timestamps
9
+ end
10
+
11
+ remove_column :decidim_time_tracker_assignations, :tos_accepted_at
12
+ end
13
+
14
+ def down
15
+ drop_table :decidim_time_tracker_tos_acceptances
16
+ add_column :decidim_time_tracker_assignations, :tos_accepted_at
17
+ end
18
+ end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "decidim/time_tracker/admin"
4
+ require "decidim/time_tracker/engine"
5
+ require "decidim/time_tracker/admin_engine"
6
+ require "decidim/time_tracker/reports"
7
+ require "decidim/time_tracker/reports_engine"
8
+ require "decidim/time_tracker/component"
9
+ module Decidim
10
+ # This namespace holds the logic of the `TimeTracker` component. This component
11
+ # allows users to create time_tracker in a participatory space.
12
+ module TimeTracker
13
+ include ActiveSupport::Configurable
14
+
15
+ autoload :TimeTrackerActivityQuestionnaireAnswersSerializer, "decidim/time_tracker/time_tracker_activity_questionnaire_answers_serializer"
16
+
17
+ # Returns a YAML with default seeds for activities questionnaire
18
+ config_accessor :default_activity_questionnaire_seeds do
19
+ YAML.load_file File.join(::Decidim::TimeTracker::Engine.root, "config", "activity_questionnaire.yml")
20
+ end
21
+
22
+ def self.default_activity_questionnaire
23
+ return unless config[:default_activity_questionnaire_seeds]
24
+
25
+ config.default_activity_questionnaire_seeds.deep_symbolize_keys
26
+ end
27
+
28
+ # Returns a YAML with default seeds for assignee data questionnaire
29
+ config_accessor :default_assignee_questionnaire_seeds do
30
+ YAML.load_file File.join(::Decidim::TimeTracker::Engine.root, "config", "assignee_questionnaire.yml")
31
+ end
32
+
33
+ def self.default_assignee_questionnaire
34
+ return unless config[:default_assignee_questionnaire_seeds]
35
+
36
+ config.default_assignee_questionnaire_seeds.deep_symbolize_keys
37
+ end
38
+ end
39
+ end
40
+
41
+ Decidim.register_global_engine(
42
+ :decidim_time_tracker, # this is the name of the global method to access engine routes
43
+ ::Decidim::TimeTracker::ReportsEngine,
44
+ at: "/timetracker"
45
+ )
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module TimeTracker
5
+ # This module contains all the domain logic associated to Decidim's TimeTracker
6
+ # component admin panel.
7
+ module Admin
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module TimeTracker
5
+ # This is the engine that runs on the public interface of `TimeTracker`.
6
+ class AdminEngine < ::Rails::Engine
7
+ isolate_namespace Decidim::TimeTracker::Admin
8
+
9
+ paths["db/migrate"] = nil
10
+ paths["lib/tasks"] = nil
11
+
12
+ routes do
13
+ # Add admin engine routes here
14
+ get :stats, to: "stats#index"
15
+
16
+ resources :tasks do
17
+ resources :activities do
18
+ resources :assignations
19
+ end
20
+ post "accept_all_pending_assignations", on: :collection
21
+ end
22
+
23
+ [:activity_questionnaire, :assignee_questionnaire].each do |questionnaire|
24
+ resource questionnaire, controller: questionnaire, only: [:edit, :update] do
25
+ get "/answer/:session_token", to: "#{questionnaire}#show", as: :show
26
+ get "/answer/:session_token/export", to: "#{questionnaire}#export_response", as: :export_response
27
+ get "/answers", to: "#{questionnaire}#index", as: :index
28
+ get "/answer_options", to: "#{questionnaire}#answer_options", as: :answer_options
29
+ end
30
+ end
31
+
32
+ get :time_tracker_exports, to: "time_tracker_exports#export"
33
+ # resource :time_tracker_exports, shallow: false do
34
+ # collection do
35
+ # get :export
36
+ # end
37
+ # end
38
+
39
+ root to: "tasks#index"
40
+ end
41
+
42
+ initializer "decidim_time_tracker.admin_assets" do |app|
43
+ app.config.assets.precompile += %w(admin/decidim_time_tracker_manifest.js admin/decidim_time_tracker_manifest.css)
44
+ end
45
+
46
+ def load_seed
47
+ nil
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,248 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_dependency "decidim/components/namer"
4
+
5
+ Decidim.register_component(:time_tracker) do |component|
6
+ component.engine = Decidim::TimeTracker::Engine
7
+ component.admin_engine = Decidim::TimeTracker::AdminEngine
8
+ component.admin_stylesheet = "decidim/time_tracker/admin/time_tracker"
9
+ component.icon = "decidim/time_tracker/icon.svg"
10
+ component.permissions_class_name = "Decidim::TimeTracker::Permissions"
11
+
12
+ component.data_portable_entities = ["Decidim::TimeTracker::Milestone"]
13
+
14
+ component.newsletter_participant_entities = ["Decidim::TimeTracker::Milestone"]
15
+
16
+ component.on(:copy) do |context|
17
+ Decidim::TimeTracker::Admin::CreateTimeTracker.call(context[:new_component]) do
18
+ on(:invalid) { raise "Can't create Time Tracker" }
19
+ end
20
+ end
21
+
22
+ component.on(:create) do |instance|
23
+ Decidim::TimeTracker::Admin::CreateTimeTracker.call(instance) do
24
+ on(:invalid) { raise "Can't create Time Tracker" }
25
+ end
26
+ end
27
+
28
+ component.on(:before_destroy) do |instance|
29
+ # Code executed before removing the component
30
+ time_tracker = Decidim::TimeTracker::TimeTracker.find_by(decidim_component_id: instance.id)
31
+
32
+ answers = Decidim::Forms::Answer.where(questionnaire: time_tracker.questionnaire)
33
+ tasks = Decidim::TimeTracker::Task.where(time_tracker: time_tracker)
34
+
35
+ raise StandardError, "Can't remove this component, there are resources associated" if [answers, assignation_answers, tasks].any?(&:any?)
36
+ end
37
+
38
+ # These actions permissions can be configured in the admin panel
39
+ # component.actions = %w()
40
+
41
+ component.settings(:global) do |settings|
42
+ # Add your global settings
43
+ # Available types: :integer, :boolean
44
+ settings.attribute :announcement, type: :text, translated: true, editor: true
45
+ settings.attribute :tasks_label, type: :string, translated: true, editor: true
46
+ settings.attribute :activities_label, type: :string, translated: true, editor: true
47
+ settings.attribute :assignations_label, type: :string, translated: true, editor: true
48
+ settings.attribute :time_events_label, type: :string, translated: true, editor: true
49
+ settings.attribute :milestones_label, type: :string, translated: true, editor: true
50
+ end
51
+
52
+ component.settings(:step) do |settings|
53
+ # Add your settings per step
54
+ settings.attribute :announcement, type: :text, translated: true, editor: true
55
+ end
56
+
57
+ component.register_resource(:milestone) do |resource|
58
+ # Register a optional resource that can be references from other resources.
59
+ resource.model_class_name = "Decidim::TimeTracker::Milestone"
60
+ # TODO!:
61
+ # resource.template = "decidim/time_tracker/time_tracker/linked_tasks"
62
+ resource.card = "decidim/time_tracker/milestone"
63
+ # resource.actions = %w(create)
64
+ # resource.searchable = true
65
+ end
66
+
67
+ component.register_stat :activities_count, primary: true, priority: Decidim::StatsRegistry::MEDIUM_PRIORITY do |components, start_at, end_at|
68
+ tasks = Decidim::TimeTracker::Task.joins(:time_tracker).where(decidim_time_trackers: { decidim_component_id: components })
69
+ activities = Decidim::TimeTracker::Activity.where(task: tasks).active
70
+ activities = activities.where("start_date >= ?", start_at) if start_at.present?
71
+ activities = activities.where("start_date <= ?", end_at) if end_at.present?
72
+ activities.count
73
+ end
74
+
75
+ component.register_stat :tasks_count, tag: :tasks, priority: Decidim::StatsRegistry::MEDIUM_PRIORITY do |components, _start_at, _end_at|
76
+ tasks = Decidim::TimeTracker::Task.joins(:time_tracker).where(decidim_time_trackers: { decidim_component_id: components })
77
+ tasks.count
78
+ end
79
+
80
+ component.register_stat :assignees_count, tag: :assignees, priority: Decidim::StatsRegistry::HIGH_PRIORITY do |components, start_at, end_at|
81
+ tasks = Decidim::TimeTracker::Task.joins(:time_tracker).where(decidim_time_trackers: { decidim_component_id: components })
82
+ assignations = Decidim::TimeTracker::Assignation.joins(:activity).where(decidim_time_tracker_activities: { task_id: tasks })
83
+ assignations = assignations.where("created_at >= ?", start_at) if start_at.present?
84
+ assignations = assignations.where("created_at <= ?", end_at) if end_at.present?
85
+ assignations.count
86
+ end
87
+
88
+ component.exports :time_tracker_activity_questionnaire_answers do |exports|
89
+ exports.collection do |f|
90
+ time_tracker = Decidim::TimeTracker::TimeTracker.find_by(component: f)
91
+
92
+ Decidim::Forms::Answer.joins(:questionnaire).where(questionnaire: time_tracker.activity_questionnaire)
93
+ .group_by do |answer|
94
+ answer.session_token.split("-").first
95
+ end.values
96
+ end
97
+
98
+ exports.serializer Decidim::TimeTracker::TimeTrackerActivityQuestionnaireAnswersSerializer
99
+
100
+ exports.formats %w(CSV JSON Excel FormPDF)
101
+ end
102
+
103
+ component.exports :time_tracker_assignee_questionnaire_answers do |exports|
104
+ exports.collection do |f|
105
+ time_tracker = Decidim::TimeTracker::TimeTracker.find_by(component: f)
106
+ Decidim::Forms::QuestionnaireUserAnswers.for(time_tracker.assignee_questionnaire)
107
+ end
108
+
109
+ exports.serializer Decidim::Forms::UserAnswersSerializer
110
+
111
+ exports.formats %w(CSV JSON Excel FormPDF)
112
+ end
113
+
114
+ component.seeds do |participatory_space|
115
+ # Add some seeds for this component
116
+ admin_user = Decidim::User.find_by(
117
+ organization: participatory_space.organization,
118
+ email: "admin@example.org"
119
+ )
120
+
121
+ params = {
122
+ name: Decidim::Components::Namer.new(participatory_space.organization.available_locales, :time_tracker).i18n_name,
123
+ manifest_name: :time_tracker,
124
+ published_at: Time.current,
125
+ participatory_space: participatory_space
126
+ }
127
+
128
+ component = Decidim.traceability.perform_action!(
129
+ "publish",
130
+ Decidim::Component,
131
+ admin_user,
132
+ visibility: "all"
133
+ ) do
134
+ Decidim::Component.create!(params)
135
+ end
136
+
137
+ time_tracker = Decidim::TimeTracker::TimeTracker.create!(
138
+ component: component,
139
+ questionnaire: Decidim::Forms::Questionnaire.new(
140
+ tos: Decidim::Faker::Localized.sentence(10),
141
+ title: Decidim::Faker::Localized.sentence(4),
142
+ description: Decidim::Faker::Localized.sentence(10)
143
+ )
144
+ )
145
+
146
+ assignee_data = Decidim::TimeTracker::AssigneeData.create!(
147
+ time_tracker: time_tracker,
148
+ questionnaire: Decidim::Forms::Questionnaire.new(
149
+ tos: Decidim::Faker::Localized.sentence(10),
150
+ title: Decidim::Faker::Localized.sentence(4),
151
+ description: Decidim::Faker::Localized.sentence(10)
152
+ )
153
+ )
154
+
155
+ questionnaire_parents = [time_tracker, assignee_data]
156
+
157
+ questionnaire_parents.each do |resource|
158
+ Decidim::Forms::Question.create!([
159
+ {
160
+ questionnaire: resource.questionnaire,
161
+ question_type: "short_answer",
162
+ body: Decidim::Faker::Localized.sentence(5),
163
+ position: 1
164
+ },
165
+ {
166
+ questionnaire: resource.questionnaire,
167
+ question_type: "single_option",
168
+ body: Decidim::Faker::Localized.sentence(5),
169
+ position: 2,
170
+ answer_options: 3.times.to_a.map { Decidim::Forms::AnswerOption.new(body: Decidim::Faker::Localized.sentence(5)) }
171
+ }
172
+ ])
173
+ end
174
+
175
+ # Create some tasks
176
+ 3.times do
177
+ task = Decidim.traceability.create!(
178
+ Decidim::TimeTracker::Task,
179
+ admin_user,
180
+ name: Decidim::Faker::Localized.sentence(2),
181
+ time_tracker: time_tracker
182
+ )
183
+
184
+ # Create activites for these tasks
185
+ 5.times do |index|
186
+ activity = Decidim.traceability.create!(
187
+ Decidim::TimeTracker::Activity,
188
+ admin_user,
189
+ description: Decidim::Faker::Localized.sentence(4),
190
+ active: [true, false].sample,
191
+ start_date: 1.week.ago + (index * 1.week),
192
+ end_date: 1.week.from_now + (index * 1.week),
193
+ max_minutes_per_day: [15, 30, 45, 60].sample,
194
+ requests_start_at: 1.week.ago + (index * 3.days),
195
+ task: task
196
+ )
197
+
198
+ # Add assignations
199
+ Decidim::User.confirmed.not_deleted.not_managed.where(admin: false).sample(10).each do |user|
200
+ assignee = Decidim.traceability.create!(
201
+ Decidim::TimeTracker::Assignee,
202
+ admin_user,
203
+ user: user
204
+ )
205
+
206
+ Decidim.traceability.create!(
207
+ Decidim::TimeTracker::TosAcceptance,
208
+ admin_user,
209
+ assignee: assignee,
210
+ time_tracker: time_tracker
211
+ )
212
+
213
+ Decidim.traceability.create!(
214
+ Decidim::TimeTracker::Assignation,
215
+ admin_user,
216
+ activity: activity,
217
+ user: user,
218
+ status: [:accepted, :rejected, :pending].sample,
219
+ invited_at: 1.week.ago,
220
+ invited_by_user: admin_user
221
+ )
222
+
223
+ questionnaire_parents.each do |resource|
224
+ resource.questionnaire.questions.each do |question|
225
+ answer = Decidim::Forms::Answer.new(
226
+ questionnaire: resource.questionnaire,
227
+ question: question,
228
+ session_token: activity.session_token(user)
229
+ )
230
+
231
+ answer.body = "My name is #{user.nickname}" if question.question_type == "short_answer"
232
+
233
+ answer.save!
234
+
235
+ next unless question.question_type == "single_option"
236
+
237
+ Decidim::Forms::AnswerChoice.create(
238
+ answer: answer,
239
+ answer_option: question.answer_options.sample,
240
+ body: question.body["en"]
241
+ )
242
+ end
243
+ end
244
+ end
245
+ end
246
+ end
247
+ end
248
+ end
@@ -0,0 +1,59 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rails"
4
+ require "decidim/core"
5
+
6
+ module Decidim
7
+ module TimeTracker
8
+ # This is the engine that runs on the public interface of time_tracker.
9
+ class Engine < ::Rails::Engine
10
+ isolate_namespace Decidim::TimeTracker
11
+
12
+ routes do
13
+ # Add engine routes here
14
+ # resources :time_tracker
15
+ resources :tasks do
16
+ resources :activities do
17
+ post :start, controller: "time_events"
18
+ post :stop, controller: "time_events"
19
+
20
+ resources :form, controller: "activity_questionnaire", only: [:show] do
21
+ member do
22
+ post :answer
23
+ # for admin preview actions
24
+ get :preview
25
+ post :preview
26
+ end
27
+ end
28
+ end
29
+ end
30
+
31
+ resource :assignee_questionnaire, controller: "assignee_questionnaire", only: [:show] do
32
+ member do
33
+ post :answer
34
+ # for admin preview actions
35
+ get :preview
36
+ post :preview
37
+ end
38
+ end
39
+
40
+ resources :milestones, only: [:create] do
41
+ get :index, on: :collection, path: "(:nickname)"
42
+ end
43
+
44
+ resources :assignations, only: [:create]
45
+
46
+ root to: "time_tracker#index"
47
+ end
48
+
49
+ initializer "decidim_time_tracker.assets" do |app|
50
+ app.config.assets.precompile += %w(decidim_time_tracker_manifest.js decidim_time_tracker_manifest.css)
51
+ end
52
+
53
+ initializer "decidim.time_tracker.add_cells_view_paths" do
54
+ Cell::ViewModel.view_paths << File.expand_path("#{Decidim::TimeTracker::Engine.root}/app/cells")
55
+ Cell::ViewModel.view_paths << File.expand_path("#{Decidim::TimeTracker::Engine.root}/app/views") # for partials
56
+ end
57
+ end
58
+ end
59
+ end