diff --git a/app/controllers/repository_rows_controller.rb b/app/controllers/repository_rows_controller.rb index a08dc7650..458971463 100644 --- a/app/controllers/repository_rows_controller.rb +++ b/app/controllers/repository_rows_controller.rb @@ -385,7 +385,15 @@ class RepositoryRowsController < ApplicationController end def load_repository_row - @repository_row = @repository.repository_rows.eager_load(:repository_columns).find_by(id: params[:id]) + @repository_row = + if params[:form_repository_rows_field_value_id] + FormRepositoryRowsFieldValue + .find_by(id: params[:form_repository_rows_field_value_id]) + &.reified_repository_row_by_id(params[:id]) + else + @repository.repository_rows.eager_load(:repository_columns).find_by(id: params[:id]) + end + render_404 unless @repository_row end diff --git a/app/javascript/vue/forms/fields/repository_rows.vue b/app/javascript/vue/forms/fields/repository_rows.vue index 542d0cb51..f1aec6fe7 100644 --- a/app/javascript/vue/forms/fields/repository_rows.vue +++ b/app/javascript/vue/forms/fields/repository_rows.vue @@ -63,7 +63,7 @@ export default { }, methods: { itemCardUrl(row) { - return repository_repository_row_path(row.repository_id, row.id); + return repository_repository_row_path(row.repository_id, row.id, { form_repository_rows_field_value_id: this.field.field_value.id }); }, addValue(rows) { const rowIds = this.assignedIds; diff --git a/app/javascript/vue/repository_item_sidebar/RepositoryItemSidebar.vue b/app/javascript/vue/repository_item_sidebar/RepositoryItemSidebar.vue index 08d95dc2a..ec723f74e 100644 --- a/app/javascript/vue/repository_item_sidebar/RepositoryItemSidebar.vue +++ b/app/javascript/vue/repository_item_sidebar/RepositoryItemSidebar.vue @@ -10,7 +10,7 @@
@@ -466,7 +469,9 @@ export default { relationshipDetailsState: {}, selectedToUnlink: null, initialSectionId: null, - loadingError: false + loadingError: false, + snapshotAt: null, + snapshotByName: null }; }, provide() { @@ -624,6 +629,8 @@ export default { this.icons = result.icons; this.dataLoading = false; this.notification = result.notification; + this.snapshotByName = result.snapshot_by_name; + this.snapshotAt = result.snapshot_at; this.$nextTick(() => { this.generateBarCode(this.defaultColumns.code); diff --git a/app/javascript/vue/repository_item_sidebar/repository_values/RepositoryTextValue.vue b/app/javascript/vue/repository_item_sidebar/repository_values/RepositoryTextValue.vue index c017f061f..ec0204e42 100644 --- a/app/javascript/vue/repository_item_sidebar/repository_values/RepositoryTextValue.vue +++ b/app/javascript/vue/repository_item_sidebar/repository_values/RepositoryTextValue.vue @@ -13,35 +13,18 @@ }}
- -
- -
-
-
-
- {{ i18n.t("repositories.item_card.repository_text_value.no_text") }} -
+ diff --git a/app/javascript/vue/shared/content/form_response.vue b/app/javascript/vue/shared/content/form_response.vue index 8ffc8beca..c06eb5f87 100644 --- a/app/javascript/vue/shared/content/form_response.vue +++ b/app/javascript/vue/shared/content/form_response.vue @@ -166,12 +166,12 @@ export default { if (this.formFieldValues.find((formFieldValue) => formFieldValue.form_field_id === formFieldId)) { this.formFieldValues = this.formFieldValues.map((formFieldValue) => { if (formFieldValue.form_field_id === formFieldId) { - return response.data.data.attributes; + return { ...response.data.data.attributes, id: response.data.data.id }; } return formFieldValue; }); } else { - this.formFieldValues.push(response.data.data.attributes); + this.formFieldValues.push({ ...response.data.data.attributes, id: response.data.data.id }); } }); }, diff --git a/app/javascript/vue/shared/legacy/Textarea.vue b/app/javascript/vue/shared/legacy/Textarea.vue index 3a2e692ce..1a3ee6763 100644 --- a/app/javascript/vue/shared/legacy/Textarea.vue +++ b/app/javascript/vue/shared/legacy/Textarea.vue @@ -115,6 +115,8 @@ export default { }); }, enableEdit(e) { + if (!this.canEdit) return; + if (e && $(e.target).hasClass('atwho-user-popover')) return; if (e && $(e.target).hasClass('sa-name')) return; if (e && $(e.target).hasClass('sa-link')) return; diff --git a/app/models/form_repository_rows_field_value.rb b/app/models/form_repository_rows_field_value.rb index 0d4a4ebd0..add6b4818 100644 --- a/app/models/form_repository_rows_field_value.rb +++ b/app/models/form_repository_rows_field_value.rb @@ -25,6 +25,35 @@ class FormRepositoryRowsFieldValue < FormFieldValue data end + def reified_repository_row_by_id(repository_row_id) + # build an in-memory, read-only representation of the repository row in the snapshot + + row_attributes = data.find { |r| r['id'] == repository_row_id.to_i } + row = RepositoryRow.new(row_attributes.except('repository_cells')) + + row.repository_cells = row_attributes['repository_cells'].map do |cell_attributes| + repository_cell = row.repository_cells.build(cell_attributes.except('value', 'repository_column')) + repository_column = RepositoryColumn.new(cell_attributes['repository_column']) + repository_column.readonly! + + repository_cell.assign_attributes( + repository_column_id: cell_attributes['repository_column']['id'], + repository_row_id: repository_row_id.to_i, + repository_column: repository_column, + value: + cell_attributes['repository_column']['data_type'].constantize.new( + cell_attributes['value'].except('repository_column') + ) + ) + repository_cell.readonly! + repository_cell + end + + row.snapshot_by_name = User.find_by(id: row.snapshot_by_id)&.full_name + row.readonly! + row + end + def formatted value&.map { |i| "#{i['name']} (#{RepositoryRow::ID_PREFIX}#{i['id']})" }&.join(' | ') end diff --git a/app/models/repository_row.rb b/app/models/repository_row.rb index ce7988bec..e028210b8 100644 --- a/app/models/repository_row.rb +++ b/app/models/repository_row.rb @@ -112,7 +112,7 @@ class RepositoryRow < ApplicationRecord length: { maximum: Constants::NAME_MAX_LENGTH } validates :created_by, presence: true - attr_accessor :import_status, :import_message + attr_accessor :import_status, :import_message, :snapshot_at, :snapshot_by_id, :snapshot_by_name scope :active, -> { where(archived: false) } scope :archived, -> { where(archived: true) } diff --git a/app/serializers/form_field_value_serializer.rb b/app/serializers/form_field_value_serializer.rb index 7b633e83d..ef8b89f8b 100644 --- a/app/serializers/form_field_value_serializer.rb +++ b/app/serializers/form_field_value_serializer.rb @@ -3,7 +3,7 @@ class FormFieldValueSerializer < ActiveModel::Serializer include Canaid::Helpers::PermissionsHelper - attributes :form_field_id, :type, :value, :submitted_at, :submitted_by_full_name, + attributes :id, :form_field_id, :type, :value, :submitted_at, :submitted_by_full_name, :unit, :not_applicable, :selection, :datetime, :datetime_to def submitted_by_full_name diff --git a/app/views/repository_rows/show.json.jbuilder b/app/views/repository_rows/show.json.jbuilder index 8cb949385..63306b85a 100644 --- a/app/views/repository_rows/show.json.jbuilder +++ b/app/views/repository_rows/show.json.jbuilder @@ -1,10 +1,15 @@ # frozen_string_literal: true json.id @repository_row.id +if @repository_row.snapshot_at + json.snapshot_at DateTime.parse(@repository_row.snapshot_at).strftime("#{I18n.backend.date_format} %H:%M") + json.snapshot_by_name @repository_row.snapshot_by_name +end + json.repository do json.id @repository.id json.name @repository.name - json.is_snapshot @repository.is_a?(RepositorySnapshot) + json.is_snapshot @repository.is_a?(RepositorySnapshot) || !@repository_row.snapshot_at.nil? end json.editable @repository_row.editable? json.notification @notification @@ -12,9 +17,9 @@ json.notification @notification json.update_path update_cell_repository_repository_row_path(@repository, @repository_row) json.permissions do - json.can_export_repository_stock can_export_repository_stock?(@repository) - json.can_manage can_manage_repository_rows?(@repository) if @repository.is_a?(Repository) && !@repository.is_a?(SoftLockedRepository) - json.can_connect_rows can_connect_repository_rows?(@repository) if @repository.is_a?(Repository) && !@repository.is_a?(SoftLockedRepository) + json.can_export_repository_stock @repository_row.snapshot_at.nil? && can_export_repository_stock?(@repository) + json.can_manage @repository_row.snapshot_at.nil? && can_manage_repository_rows?(@repository) if @repository.is_a?(Repository) && !@repository.is_a?(SoftLockedRepository) + json.can_connect_rows @repository_row.snapshot_at.nil? && can_connect_repository_rows?(@repository) if @repository.is_a?(Repository) && !@repository.is_a?(SoftLockedRepository) end json.actions do @@ -106,7 +111,7 @@ end json.custom_columns do json.array! repository_columns_ordered_by_state(@repository_row.repository).each do |repository_column| - repository_cell = @repository_row.repository_cells.find_by(repository_column: repository_column) + repository_cell = @repository_row.repository_cells.find { |c| c.repository_column_id == repository_column.id } options = case repository_column.data_type when 'RepositoryListValue' diff --git a/config/locales/en.yml b/config/locales/en.yml index 7844878f8..5850af453 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -2714,6 +2714,7 @@ en: one: "day" other: "days" stock_export: "Export" + snapshot_label: "Snapshot on %{timestamp} by %{name}" custom_columns_label: "Custom columns" no_custom_columns_label: "No custom columns" repository_time_range_value: