From d577fcc824c90f5c3a13f403c8bb2eede1f337a7 Mon Sep 17 00:00:00 2001 From: artoscinote <85488244+artoscinote@users.noreply.github.com> Date: Wed, 9 Mar 2022 14:13:48 +0100 Subject: [PATCH] Implement basic logic for Date/DateTime/Stock reminders [SCI-6554] (#3911) * Implement basic logic for Date/DateTime/Stock reminders [SCI-6554] * Implement bell icon [SCI-6500] * Refactor reminder cells scope [SCI-6554] --- .../javascripts/my_modules/repositories.js | 4 ++-- .../repositories/renderers/view_renderers.js | 16 ++++++++++--- .../repositories/repository_datatable.js | 2 +- .../stylesheets/my_modules/repositories.scss | 12 +++++++--- .../repository/repository_table.scss | 15 ++++++++---- .../date_time_columns_controller.rb | 2 +- app/controllers/repository_rows_controller.rb | 6 ++++- app/helpers/repository_datatable_helper.rb | 11 ++++++++- .../reminder_repository_cell_joinable.rb | 24 +++++++++++++++++++ app/models/repository_cell.rb | 6 +++++ app/models/repository_column.rb | 2 ++ app/models/repository_row.rb | 8 ++++++- config/routes.rb | 1 + 13 files changed, 91 insertions(+), 18 deletions(-) create mode 100644 app/models/concerns/reminder_repository_cell_joinable.rb diff --git a/app/assets/javascripts/my_modules/repositories.js b/app/assets/javascripts/my_modules/repositories.js index 50791f220..70cb5844e 100644 --- a/app/assets/javascripts/my_modules/repositories.js +++ b/app/assets/javascripts/my_modules/repositories.js @@ -107,8 +107,8 @@ var MyModuleRepositories = (function() { searchable: false, className: 'assigned-column', sWidth: '1%', - render: function(data) { - return $.fn.dataTable.render.AssignedTasksValue(data); + render: function(data, type, row) { + return $.fn.dataTable.render.AssignedTasksValue(data, row); } }, { targets: 3, diff --git a/app/assets/javascripts/repositories/renderers/view_renderers.js b/app/assets/javascripts/repositories/renderers/view_renderers.js index 7a27530b3..3f9d65cfb 100644 --- a/app/assets/javascripts/repositories/renderers/view_renderers.js +++ b/app/assets/javascripts/repositories/renderers/view_renderers.js @@ -157,14 +157,16 @@ $.fn.dataTable.render.RepositoryNumberValue = function(data) { `; }; -$.fn.dataTable.render.AssignedTasksValue = function(data) { +$.fn.dataTable.render.AssignedTasksValue = function(data, row) { + let tasksLinkHTML; + if (data.tasks > 0) { let tooltip = I18n.t('repositories.table.assigned_tooltip', { tasks: data.tasks, experiments: data.experiments, projects: data.projects }); - return ` `; + } else { + tasksLinkHTML = "
0
"; } - return "
0
"; + + if (row.hasActiveReminders) { + return `` + + tasksLinkHTML; + } + + return tasksLinkHTML; }; $.fn.dataTable.render.RepositoryStockValue = function(data) { diff --git a/app/assets/javascripts/repositories/repository_datatable.js b/app/assets/javascripts/repositories/repository_datatable.js index 331f88442..3831bfc7f 100644 --- a/app/assets/javascripts/repositories/repository_datatable.js +++ b/app/assets/javascripts/repositories/repository_datatable.js @@ -431,7 +431,7 @@ var RepositoryDatatable = (function(global) { className: 'assigned-column', sWidth: '1%', render: function(data, type, row) { - let content = $.fn.dataTable.render.AssignedTasksValue(data); + let content = $.fn.dataTable.render.AssignedTasksValue(data, row); let icon; if (!row.recordEditable) { icon = ``; diff --git a/app/assets/stylesheets/my_modules/repositories.scss b/app/assets/stylesheets/my_modules/repositories.scss index e3a301787..87acba826 100644 --- a/app/assets/stylesheets/my_modules/repositories.scss +++ b/app/assets/stylesheets/my_modules/repositories.scss @@ -205,14 +205,20 @@ .assigned-column { position: relative; + .row-reminders-icon { + cursor: pointer; + display: inline-block; + line-height: 35px; + } + .assign-counter-container { border-radius: $border-radius-tag; cursor: pointer; + display: inline-block; line-height: 35px; + padding: 0 5px; position: absolute; - text-align: center; - top: 1px; - width: calc(100% - 16px); + right: 5px; .assign-counter { display: inline-block; diff --git a/app/assets/stylesheets/repository/repository_table.scss b/app/assets/stylesheets/repository/repository_table.scss index 96138c7f7..84343dd4e 100644 --- a/app/assets/stylesheets/repository/repository_table.scss +++ b/app/assets/stylesheets/repository/repository_table.scss @@ -34,7 +34,13 @@ .repository-row-edit-icon { cursor: pointer; - display: none; + display: inline-block; + opacity: 0; + } + + .row-reminders-icon { + cursor: pointer; + display: inline-block; } .assign-counter-container { @@ -42,8 +48,7 @@ display: inline-block; line-height: 35px; position: absolute; - right: 0; - width: calc(100% - 40px); + right: 5px; .assign-counter { display: inline-block; @@ -251,7 +256,7 @@ .assigned-column { .repository-row-edit-icon { - display: inline-block; + opacity: 1; } } } @@ -273,7 +278,7 @@ tr:hover { .assigned-column { .repository-row-edit-icon { - display: none; + opacity: 0; } .assign-counter-container { diff --git a/app/controllers/repository_columns/date_time_columns_controller.rb b/app/controllers/repository_columns/date_time_columns_controller.rb index 777778f8f..f318efa36 100644 --- a/app/controllers/repository_columns/date_time_columns_controller.rb +++ b/app/controllers/repository_columns/date_time_columns_controller.rb @@ -34,7 +34,7 @@ module RepositoryColumns private def repository_column_params - params.require(:repository_column).permit(:name) + params.require(:repository_column).permit(:name, :reminder_delta) end def column_type_param diff --git a/app/controllers/repository_rows_controller.rb b/app/controllers/repository_rows_controller.rb index 8654bcabe..339391bd1 100644 --- a/app/controllers/repository_rows_controller.rb +++ b/app/controllers/repository_rows_controller.rb @@ -9,7 +9,7 @@ class RepositoryRowsController < ApplicationController before_action :load_repository, except: %i(show print_modal print) before_action :load_repository_or_snapshot, only: %i(print_modal print) before_action :load_repository_row, only: %i(update assigned_task_list) - before_action :check_read_permissions, except: %i(show create update delete_records copy_records) + before_action :check_read_permissions, except: %i(show create update delete_records copy_records reminder_repository_cells) before_action :check_snapshotting_status, only: %i(create update delete_records copy_records) before_action :check_create_permissions, only: :create before_action :check_delete_permissions, only: %i(delete_records archive_records restore_records) @@ -224,6 +224,10 @@ class RepositoryRowsController < ApplicationController } end + def reminder_repository_cells + render json: @repository_row.repository_cells.with_active_reminder + end + def archive_records service = RepositoryActions::ArchiveRowsService.call(repository: @repository, repository_rows: selected_rows_in_repo_params, diff --git a/app/helpers/repository_datatable_helper.rb b/app/helpers/repository_datatable_helper.rb index 7d7aa13f3..897abc67f 100644 --- a/app/helpers/repository_datatable_helper.rb +++ b/app/helpers/repository_datatable_helper.rb @@ -4,6 +4,8 @@ module RepositoryDatatableHelper include InputSanitizeHelper def prepare_row_columns(repository_rows, repository, columns_mappings, team, options = {}) + repository_row_with_active_reminder_ids = repository_rows.with_active_reminders.pluck(:id) + repository_rows.map do |record| default_cells = { '1': assigned_row(record), @@ -18,7 +20,14 @@ module RepositoryDatatableHelper row = { 'DT_RowId': record.id, 'DT_RowAttr': { 'data-state': row_style(record) }, - 'recordInfoUrl': Rails.application.routes.url_helpers.repository_repository_row_path(repository, record) + 'recordInfoUrl': Rails.application.routes.url_helpers.repository_repository_row_path(repository, record), + 'hasActiveReminders': repository_row_with_active_reminder_ids.include?(record.id), + 'rowRemindersUrl': + Rails.application.routes.url_helpers + .active_reminder_repository_cells_repository_repository_row_url( + repository, + record + ) }.merge(default_cells) if record.repository.has_stock_management? diff --git a/app/models/concerns/reminder_repository_cell_joinable.rb b/app/models/concerns/reminder_repository_cell_joinable.rb new file mode 100644 index 000000000..53bb7fb05 --- /dev/null +++ b/app/models/concerns/reminder_repository_cell_joinable.rb @@ -0,0 +1,24 @@ +# frozen_string_literal: true + +module ReminderRepositoryCellJoinable + extend ActiveSupport::Concern + + included do + def self.reminder_repository_cells_scope(relation) + relation.joins( # datetime reminders + 'LEFT OUTER JOIN "repository_date_time_values" ON '\ + '"repository_date_time_values"."id" = "repository_cells"."value_id" AND '\ + '"repository_cells"."value_type" = \'RepositoryDateTimeValueBase\' '\ + 'AND repository_columns.metadata ? \'reminder_delta\' AND '\ + '(repository_date_time_values.data - NOW()) <= '\ + '(repository_columns.metadata -> \'reminder_delta\')::int * interval \'1 sec\'' + ).joins( # stock reminders + 'LEFT OUTER JOIN "repository_stock_values" ON "repository_stock_values"."id" = "repository_cells"."value_id" AND '\ + '"repository_cells"."value_type" = \'RepositoryStockValue\' AND '\ + 'repository_stock_values.amount <= repository_stock_values.low_stock_threshold' + ).where( + 'repository_date_time_values.id IS NOT NULL OR repository_stock_values.id IS NOT NULL' + ) + end + end +end diff --git a/app/models/repository_cell.rb b/app/models/repository_cell.rb index 057209235..06d81203c 100644 --- a/app/models/repository_cell.rb +++ b/app/models/repository_cell.rb @@ -1,6 +1,8 @@ # frozen_string_literal: true class RepositoryCell < ApplicationRecord + include ReminderRepositoryCellJoinable + attr_accessor :importing belongs_to :repository_row @@ -41,6 +43,10 @@ class RepositoryCell < ApplicationRecord uniqueness: { scope: :repository_column }, unless: :importing + scope :with_active_reminder, lambda { + reminder_repository_cells_scope(joins(:repository_column)) + } + def self.create_with_value!(row, column, data, user) cell = new(repository_row: row, repository_column: column) cell.transaction do diff --git a/app/models/repository_column.rb b/app/models/repository_column.rb index ce3cef07b..4e04e6f69 100644 --- a/app/models/repository_column.rb +++ b/app/models/repository_column.rb @@ -25,6 +25,8 @@ class RepositoryColumn < ApplicationRecord enum data_type: Extends::REPOSITORY_DATA_TYPES + store_accessor :metadata, %i(reminder_delta) + validates :data_type, uniqueness: { if: :repository_stock_value?, scope: :repository_id } validates :data_type, uniqueness: { if: :repository_stock_consumption_value?, scope: :repository_id } diff --git a/app/models/repository_row.rb b/app/models/repository_row.rb index d43206d0b..57ce75130 100644 --- a/app/models/repository_row.rb +++ b/app/models/repository_row.rb @@ -4,6 +4,7 @@ class RepositoryRow < ApplicationRecord include SearchableModel include SearchableByNameModel include ArchivableModel + include ReminderRepositoryCellJoinable ID_PREFIX = 'IT' include PrefixedIdModel @@ -34,7 +35,8 @@ class RepositoryRow < ApplicationRecord repository_date: 'RepositoryDateValue', repository_date_time_range: 'RepositoryDateTimeRangeValue', repository_time_range: 'RepositoryTimeRangeValue', - repository_date_range: 'RepositoryDateRangeValue' + repository_date_range: 'RepositoryDateRangeValue', + repository_stock: 'RepositoryStockValue' }.each do |relation, class_name| has_many "#{relation}_cells".to_sym, -> { where(value_type: class_name) }, class_name: 'RepositoryCell', inverse_of: :repository_row @@ -84,6 +86,10 @@ class RepositoryRow < ApplicationRecord scope :active, -> { where(archived: false) } scope :archived, -> { where(archived: true) } + scope :with_active_reminders, lambda { + reminder_repository_cells_scope(joins(repository_cells: :repository_column)).distinct + } + def code "#{ID_PREFIX}#{parent_id || id}" end diff --git a/config/routes.rb b/config/routes.rb index fa1324fe5..df54823f5 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -596,6 +596,7 @@ Rails.application.routes.draw do end member do get :assigned_task_list + get :active_reminder_repository_cells end member do get 'repository_stock_value/new', to: 'repository_stock_values#new', as: 'new_repository_stock'