mirror of
https://github.com/scinote-eln/scinote-web.git
synced 2025-09-30 17:04:31 +08:00
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]
This commit is contained in:
parent
20ef08907a
commit
d577fcc824
13 changed files with 91 additions and 18 deletions
|
@ -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,
|
||||
|
|
|
@ -157,14 +157,16 @@ $.fn.dataTable.render.RepositoryNumberValue = function(data) {
|
|||
</span>`;
|
||||
};
|
||||
|
||||
$.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 `<div class="assign-counter-container dropdown" title="${tooltip}"
|
||||
tasksLinkHTML = `<div class="assign-counter-container dropdown" title="${tooltip}"
|
||||
data-task-list-url="${data.task_list_url}">
|
||||
<a href="#" class="assign-counter has-assigned"
|
||||
data-toggle="dropdown" aria-haspopup="true" aria-expanded="true">${data.tasks}</a>
|
||||
|
@ -177,8 +179,16 @@ $.fn.dataTable.render.AssignedTasksValue = function(data) {
|
|||
<div class="tasks"></div>
|
||||
</div>
|
||||
</div>`;
|
||||
} else {
|
||||
tasksLinkHTML = "<div class='assign-counter-container'><span class='assign-counter'>0</span></div>";
|
||||
}
|
||||
return "<div class='assign-counter-container'><span class='assign-counter'>0</span></div>";
|
||||
|
||||
if (row.hasActiveReminders) {
|
||||
return `<i class="fas fa-bell row-reminders-icon" data-row-reminders-url="${row.rowRemindersUrl}"></i>`
|
||||
+ tasksLinkHTML;
|
||||
}
|
||||
|
||||
return tasksLinkHTML;
|
||||
};
|
||||
|
||||
$.fn.dataTable.render.RepositoryStockValue = function(data) {
|
||||
|
|
|
@ -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 = `<i class="repository-row-lock-icon fas fa-lock" title="${I18n.t('repositories.table.locked_item')}"></i>`;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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?
|
||||
|
|
24
app/models/concerns/reminder_repository_cell_joinable.rb
Normal file
24
app/models/concerns/reminder_repository_cell_joinable.rb
Normal file
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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 }
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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'
|
||||
|
|
Loading…
Add table
Reference in a new issue