decidim-time_tracker 0.3

Sign up to get free protection for your applications and to get access to all the features.
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,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module TimeTracker
5
+ # The data store for a Task in the Decidim::TimeTracker component.
6
+ class Task < ApplicationRecord
7
+ include Decidim::Traceable
8
+ include Decidim::Loggable
9
+
10
+ self.table_name = :decidim_time_tracker_tasks
11
+
12
+ belongs_to :time_tracker,
13
+ class_name: "Decidim::TimeTracker::TimeTracker"
14
+
15
+ has_many :activities,
16
+ class_name: "Decidim::TimeTracker::Activity",
17
+ dependent: :destroy
18
+
19
+ delegate :questionnaire, to: :time_tracker
20
+ delegate :component, to: :time_tracker
21
+
22
+ def starts_at
23
+ activities.order(start_date: :asc).first&.start_date
24
+ end
25
+
26
+ def ends_at
27
+ activities.order(end_date: :desc).first&.end_date
28
+ end
29
+
30
+ def assignations_count(filter: :accepted)
31
+ assignations = Assignation.where(activity: activities).send(filter)
32
+ assignations.count
33
+ end
34
+
35
+ def user_is_assignation?(user, filter: :accepted)
36
+ Assignation.where(user: user, activity: activities).send(filter).any?
37
+ end
38
+
39
+ def self.log_presenter_class_for(_log)
40
+ Decidim::TimeTracker::AdminLog::TaskPresenter
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,62 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module TimeTracker
5
+ # The data store for a time entry in the Decidim::TimeTracker component.
6
+ class TimeEvent < ApplicationRecord
7
+ self.table_name = :decidim_time_tracker_time_events
8
+
9
+ belongs_to :assignation,
10
+ class_name: "Decidim::TimeTracker::Assignation"
11
+
12
+ belongs_to :activity,
13
+ class_name: "Decidim::TimeTracker::Activity"
14
+
15
+ belongs_to :user,
16
+ foreign_key: "decidim_user_id",
17
+ class_name: "Decidim::User"
18
+
19
+ # note that with the default order reversed
20
+ # the "last" element needs to be found with .first
21
+ default_scope { order(start: :desc) }
22
+ scope :started_between, ->(start_date, end_date) { where("start >= ? AND start <= ?", start_date.to_i, end_date.to_i) }
23
+
24
+ # rubocop:disable Rails/FindBy
25
+ def self.last_for(user)
26
+ if user.is_a?(Assignation)
27
+ where(assignation: user).first
28
+ else
29
+ where(user: user).first
30
+ end
31
+ end
32
+ # rubocop:enable Rails/FindBy
33
+
34
+ # number of seconds since the counting started
35
+ # zero if activity is stopped
36
+ def seconds_elapsed
37
+ return 0 if stopped?
38
+ return 0 if start.blank?
39
+
40
+ @seconds_elapsed ||= Time.current.to_i - start.to_i
41
+ end
42
+
43
+ def stopped?
44
+ stop.to_i >= start
45
+ end
46
+
47
+ def start_time
48
+ Time.zone.at start
49
+ end
50
+
51
+ def stop_time
52
+ Time.zone.at stop
53
+ end
54
+
55
+ def stop!
56
+ self.stop = Time.current.to_i
57
+ self.total_seconds = stop - start
58
+ save!
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module TimeTracker
5
+ class TimeTracker < ApplicationRecord
6
+ include Decidim::HasComponent
7
+ include Decidim::Forms::HasQuestionnaire
8
+ include Decidim::Traceable
9
+ include Decidim::Loggable
10
+
11
+ self.table_name = :decidim_time_trackers
12
+
13
+ component_manifest_name "time_tracker"
14
+
15
+ has_many :tasks,
16
+ class_name: "Decidim::TimeTracker::Task",
17
+ dependent: :destroy
18
+
19
+ has_many :activities,
20
+ class_name: "Decidim::TimeTracker::Activity",
21
+ through: :tasks
22
+
23
+ has_many :assignations,
24
+ class_name: "Decidim::TimeTracker::Assignation",
25
+ through: :activities
26
+
27
+ has_one :assignee_data,
28
+ class_name: "Decidim::TimeTracker::AssigneeData"
29
+
30
+ has_one :assignee_questionnaire,
31
+ source: :questionnaire,
32
+ through: :assignee_data,
33
+ class_name: "Decidim::Forms::Questionnaire"
34
+
35
+ def has_questions?
36
+ questionnaire.questions.any?
37
+ end
38
+
39
+ def has_assignee_questions?
40
+ assignee_data.questionnaire.questions.any?
41
+ end
42
+
43
+ alias activity_questionnaire questionnaire
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module TimeTracker
5
+ # The data store for terms of service acceptance in the Decidim::TimeTracker component.
6
+ class TosAcceptance < ApplicationRecord
7
+ self.table_name = :decidim_time_tracker_tos_acceptances
8
+
9
+ belongs_to :assignee,
10
+ class_name: "Decidim::TimeTracker::Assignee"
11
+
12
+ belongs_to :time_tracker,
13
+ class_name: "Decidim::TimeTracker::TimeTracker"
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,69 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module TimeTracker
5
+ module Admin
6
+ class Permissions < Decidim::DefaultPermissions
7
+ def permissions
8
+ return permission_action if permission_action.scope != :admin
9
+
10
+ allowed_task_action?
11
+ allowed_questionnaire_action?
12
+ allowed_activity_action?
13
+ allowed_assignation_action?
14
+
15
+ permission_action
16
+ end
17
+
18
+ def allowed_task_action?
19
+ return unless permission_action.subject.in? [:task, :tasks]
20
+
21
+ case permission_action.action
22
+ when :index, :create, :update, :destroy
23
+ permission_action.allow!
24
+ end
25
+ end
26
+
27
+ def allowed_questionnaire_action?
28
+ return unless permission_action.subject.in? [:questionnaire, :questionnaire_answers]
29
+
30
+ if permission_action.subject == :questionnaire
31
+ case permission_action.action
32
+ when :export_answers, :update, :preview
33
+ permission_action.allow!
34
+ end
35
+ elsif permission_action.subject == :questionnaire_answers
36
+ case permission_action.action
37
+ when :show, :index, :export_response
38
+ permission_action.allow!
39
+ end
40
+ end
41
+ end
42
+
43
+ def allowed_activity_action?
44
+ return unless permission_action.subject.in? [:activity, :activities]
45
+
46
+ case permission_action.action
47
+ when :index, :create, :update, :destroy
48
+ permission_action.allow!
49
+ end
50
+ end
51
+
52
+ def allowed_assignation_action?
53
+ return unless permission_action.subject.in? [:assignation, :assignations]
54
+
55
+ case permission_action.action
56
+ when :update
57
+ permission_action.allow! if assignation.can_change_status?
58
+ when :index, :create, :destroy
59
+ permission_action.allow!
60
+ end
61
+ end
62
+
63
+ def assignation
64
+ @assignation ||= context.fetch(:assignation, nil)
65
+ end
66
+ end
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,69 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module TimeTracker
5
+ class Permissions < Decidim::DefaultPermissions
6
+ def permissions
7
+ # for the moment, we let public views for milestones
8
+ allow! if permission_action.subject == :milestone && permission_action.action == :show
9
+
10
+ return permission_action unless user
11
+
12
+ return Decidim::TimeTracker::Admin::Permissions.new(user, permission_action, context).permissions if permission_action.scope == :admin
13
+
14
+ case permission_action.subject
15
+ when :questionnaire
16
+ allow_answer?
17
+ when :assignation
18
+ allow_assignation?
19
+ when :milestone
20
+ allow_milestone?
21
+ else
22
+ allow!
23
+ end
24
+
25
+ permission_action
26
+ end
27
+
28
+ def allow_answer?
29
+ return unless permission_action.action == :answer
30
+
31
+ allow! if current_component&.published?
32
+ end
33
+
34
+ def allow_assignation?
35
+ return allow! unless activity
36
+
37
+ if permission_action.action == :create
38
+ return if activity.has_assignation? user
39
+
40
+ return unless activity.status.in? [:open, :not_started]
41
+
42
+ allow!
43
+ end
44
+ end
45
+
46
+ def allow_milestone?
47
+ return unless activity
48
+
49
+ if permission_action.action == :create
50
+ return unless activity.assignation_accepted? user
51
+
52
+ return if activity.status.in? [:inactive]
53
+
54
+ allow!
55
+ end
56
+ end
57
+
58
+ private
59
+
60
+ def activity
61
+ @activity ||= context.fetch(:activity, nil)
62
+ end
63
+
64
+ def current_component
65
+ @current_component ||= context.fetch(:current_component, nil)
66
+ end
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module TimeTracker
5
+ module AdminLog
6
+ # This class holds the logic to present a `Decidim::TimeTracker::Activity`
7
+ # for the `AdminLog` log.
8
+ #
9
+ # Usage should be automatic and you shouldn't need to call this class
10
+ # directly, but here's an example:
11
+ #
12
+ # action_log = Decidim::ActionLog.last
13
+ # view_helpers # => this comes from the views
14
+ # ActivityPresenter.new(action_log, view_helpers).present
15
+ class ActivityPresenter < Decidim::Log::BasePresenter
16
+ private
17
+
18
+ def diff_fields_mapping
19
+ {
20
+ description: :i18n,
21
+ active: :boolean
22
+ }
23
+ end
24
+
25
+ def i18n_labels_scope
26
+ "activemodel.attributes.time_tracker.activity"
27
+ end
28
+
29
+ def action_string
30
+ case action
31
+ when "create", "delete", "update"
32
+ "decidim.time_tracker.admin_log.activity.#{action}"
33
+ else
34
+ super
35
+ end
36
+ end
37
+
38
+ def has_diff?
39
+ action == "delete" || super
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module TimeTracker
5
+ module AdminLog
6
+ # This class holds the logic to present a `Decidim::TimeTracker::Assignation`
7
+ # for the `AdminLog` log.
8
+ #
9
+ # Usage should be automatic and you shouldn't need to call this class
10
+ # directly, but here's an example:
11
+ #
12
+ # action_log = Decidim::ActionLog.last
13
+ # view_helpers # => this comes from the views
14
+ # AssignationPresenter.new(action_log, view_helpers).present
15
+ class AssignationPresenter < Decidim::Log::BasePresenter
16
+ private
17
+
18
+ def diff_fields_mapping
19
+ {
20
+ status: :string,
21
+ decidim_user_id: :user,
22
+ activity_id: "Decidim::TimeTracker::AdminLog::ValueTypes::ActivityPresenter",
23
+ invited_at: :date,
24
+ invited_by_user: :user,
25
+ requested_at: :date
26
+ }
27
+ end
28
+
29
+ def i18n_labels_scope
30
+ "activemodel.attributes.time_tracker.assignation"
31
+ end
32
+
33
+ def action_string
34
+ case action
35
+ when "create", "delete", "update"
36
+ "decidim.time_tracker.admin_log.assignation.#{action}"
37
+ else
38
+ super
39
+ end
40
+ end
41
+
42
+ def has_diff?
43
+ action == "delete" || super
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module TimeTracker
5
+ module AdminLog
6
+ # This class holds the logic to present a `Decidim::TimeTracker::Task`
7
+ # for the `AdminLog` log.
8
+ #
9
+ # Usage should be automatic and you shouldn't need to call this class
10
+ # directly, but here's an example:
11
+ #
12
+ # action_log = Decidim::ActionLog.last
13
+ # view_helpers # => this comes from the views
14
+ # TaskPresenter.new(action_log, view_helpers).present
15
+ class TaskPresenter < Decidim::Log::BasePresenter
16
+ private
17
+
18
+ def diff_fields_mapping
19
+ {
20
+ name: :i18n,
21
+ time_tracker_id: "Decidim::TimeTracker::AdminLog::ValueTypes::TimeTrackerPresenter",
22
+ active: :boolean,
23
+ updated_at: :date
24
+ }
25
+ end
26
+
27
+ def i18n_labels_scope
28
+ "activemodel.attributes.time_tracker.task"
29
+ end
30
+
31
+ def action_string
32
+ case action
33
+ when "create", "delete", "update"
34
+ "decidim.time_tracker.admin_log.task.#{action}"
35
+ else
36
+ super
37
+ end
38
+ end
39
+
40
+ def has_diff?
41
+ action == "delete" || super
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end