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 `
${data.tasks}
@@ -177,8 +179,16 @@ $.fn.dataTable.render.AssignedTasksValue = function(data) {
`;
+ } 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'