From 0a3ba6a366ac5d37200052a37d6497caedd2a8e3 Mon Sep 17 00:00:00 2001 From: Gregor Lasnibat Date: Sun, 22 Oct 2023 08:56:51 +0200 Subject: [PATCH 01/18] Fixed Item card smart annotation link [SCI-9583] --- app/services/smart_annotations/html_preview.rb | 2 +- app/views/shared/_atwho_user_container.html.erb | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/services/smart_annotations/html_preview.rb b/app/services/smart_annotations/html_preview.rb index b741bcbcd..3a37ce6ed 100644 --- a/app/services/smart_annotations/html_preview.rb +++ b/app/services/smart_annotations/html_preview.rb @@ -43,7 +43,7 @@ module SmartAnnotations if object&.repository repository_name = fetch_repository_name(object) "#{trim_repository_name(repository_name)}" \ + "class='sa-link record-info-link text-sn-science-blue hover:text-sn-science-blue hover:no-underline'>#{trim_repository_name(repository_name)}" \ "#{object.name} #{object.archived? ? I18n.t('atwho.res.archived') : ''}" else "Inv #{name} #{I18n.t('atwho.res.deleted')}" diff --git a/app/views/shared/_atwho_user_container.html.erb b/app/views/shared/_atwho_user_container.html.erb index 8c86db370..a6c627c6b 100644 --- a/app/views/shared/_atwho_user_container.html.erb +++ b/app/views/shared/_atwho_user_container.html.erb @@ -10,7 +10,7 @@ <% end %> <%= I18n.t('atwho.res.removed') %> <% end %> - \ No newline at end of file + From ee076c7f3b5ddc0054e05505d15399096699a0f7 Mon Sep 17 00:00:00 2001 From: Martin Artnik Date: Mon, 23 Oct 2023 11:50:24 +0200 Subject: [PATCH 02/18] Fix user smart annotations [SCI-9574] --- app/helpers/application_helper.rb | 3 +-- app/views/shared/_atwho_user_container.html.erb | 8 ++++---- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 8242d6be2..44e1dff6f 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -137,14 +137,13 @@ module ApplicationHelper # and outputs a popover with user information def smart_annotation_filter_users(text, team, base64_encoded_imgs: false) sa_user = /\[\@(.*?)~([0-9a-zA-Z]+)\]/ - new_text = text.gsub(sa_user) do |el| + text.gsub(sa_user) do |el| match = el.match(sa_user) user = User.find_by_id(match[2].base62_decode) next unless user popover_for_user_name(user, team, false, false, base64_encoded_imgs) end - sanitize_input(new_text) end # Generate smart annotation link for one user object diff --git a/app/views/shared/_atwho_user_container.html.erb b/app/views/shared/_atwho_user_container.html.erb index 8c86db370..85259560a 100644 --- a/app/views/shared/_atwho_user_container.html.erb +++ b/app/views/shared/_atwho_user_container.html.erb @@ -18,8 +18,8 @@ data-placement="top" data-toggle="popover" data-content="" - data-full-name="<%= user.full_name %>" - data-email="<%= user.email %>" + data-full-name="<%= escape_input(user.full_name) %>" + data-email="<%= escape_input(user.email) %>" data-popover-html="<%= popover_html %>" data-user-avatar-popover-absolute-url="<%= user_avatar_absolute_url( user, @@ -27,9 +27,9 @@ base64_encoded_imgs ) %>" > - <%= user.full_name %> + <%= escape_input(user.full_name) %> <% unless skip_user_status || user_still_in_team %> <%= I18n.t('atwho.res.removed') %> <% end %> - \ No newline at end of file + From 4f014394e2d5d7226a932d96f000ca009dbc79e4 Mon Sep 17 00:00:00 2001 From: Martin Artnik Date: Mon, 23 Oct 2023 13:31:27 +0200 Subject: [PATCH 03/18] Fix members filter [SCI-9585] --- app/assets/javascripts/projects/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/assets/javascripts/projects/index.js b/app/assets/javascripts/projects/index.js index ffb96ab65..e0fb54153 100644 --- a/app/assets/javascripts/projects/index.js +++ b/app/assets/javascripts/projects/index.js @@ -430,7 +430,7 @@ var ProjectsIndex = (function() { view_mode: $('.projects-index').data('view-mode'), sort: projectsCurrentSort, search: projectsViewSearch, - members: membersFilter, + members: membersFilter && membersFilter.map(m => m.value), created_on_from: createdOnFromFilter, created_on_to: createdOnToFilter, folders_search: lookInsideFolders, From 2850135e961cd8d5ceb7ce0813535f649f37d780 Mon Sep 17 00:00:00 2001 From: Martin Artnik Date: Tue, 24 Oct 2023 13:14:23 +0200 Subject: [PATCH 04/18] Revert "Fixed Item card smart annotation link [SCI-9583]" This reverts commit 0a3ba6a366ac5d37200052a37d6497caedd2a8e3. --- app/services/smart_annotations/html_preview.rb | 2 +- app/views/shared/_atwho_user_container.html.erb | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/services/smart_annotations/html_preview.rb b/app/services/smart_annotations/html_preview.rb index 3a37ce6ed..b741bcbcd 100644 --- a/app/services/smart_annotations/html_preview.rb +++ b/app/services/smart_annotations/html_preview.rb @@ -43,7 +43,7 @@ module SmartAnnotations if object&.repository repository_name = fetch_repository_name(object) "#{trim_repository_name(repository_name)}" \ + "class='sa-link record-info-link'>#{trim_repository_name(repository_name)}" \ "#{object.name} #{object.archived? ? I18n.t('atwho.res.archived') : ''}" else "Inv #{name} #{I18n.t('atwho.res.deleted')}" diff --git a/app/views/shared/_atwho_user_container.html.erb b/app/views/shared/_atwho_user_container.html.erb index b741d8365..5d217f46c 100644 --- a/app/views/shared/_atwho_user_container.html.erb +++ b/app/views/shared/_atwho_user_container.html.erb @@ -10,7 +10,7 @@ <% end %> <%= I18n.t('atwho.res.removed') %> <% end %> - + \ No newline at end of file From 0e3c7eaf266f802ace371f2525d60357dd04871b Mon Sep 17 00:00:00 2001 From: Martin Artnik Date: Tue, 24 Oct 2023 13:15:17 +0200 Subject: [PATCH 05/18] Fix issue with text value rendering [SCI-9583] --- .../repository_values/RepositoryTextValue.vue | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) 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 8c63fb785..f370c2e5a 100644 --- a/app/javascript/vue/repository_item_sidebar/repository_values/RepositoryTextValue.vue +++ b/app/javascript/vue/repository_item_sidebar/repository_values/RepositoryTextValue.vue @@ -46,8 +46,10 @@ export default { }, mounted() { this.$nextTick(() => { - const textHeight = this.$refs.textRef.scrollHeight - this.expandable = textHeight > 60 // 60px + if (this.$refs.textRef) { + const textHeight = this.$refs.textRef.scrollHeight + this.expandable = textHeight > 60 // 60px + } }) }, } From f278f490d9cbff4fb35b034cffc28915ca879523 Mon Sep 17 00:00:00 2001 From: ajugo Date: Tue, 24 Oct 2023 13:36:03 +0200 Subject: [PATCH 06/18] Fix api tests [SCI-9569] (#6519) * Fix api tests [SCI-9569] * Fix inventory status api index [SCI-9569] --- .../v1/inventory_status_items_controller.rb | 1 - spec/factories/teams.rb | 3 ++ .../api/v1/experiments_controller_spec.rb | 4 +-- ...roject_user_assignments_controller_spec.rb | 33 ++++++++++++++----- .../api/v1/projects_controller_spec.rb | 10 +++--- .../v1/protocol_templates_controller_spec.rb | 2 +- .../api/v1/results_controller_spec.rb | 6 ++-- .../task_inventory_items_controller_spec.rb | 12 +++---- spec/requests/api/v1/tasks_controller_spec.rb | 4 +-- 9 files changed, 46 insertions(+), 29 deletions(-) diff --git a/app/controllers/api/v1/inventory_status_items_controller.rb b/app/controllers/api/v1/inventory_status_items_controller.rb index 09d4cb032..45a519270 100644 --- a/app/controllers/api/v1/inventory_status_items_controller.rb +++ b/app/controllers/api/v1/inventory_status_items_controller.rb @@ -12,7 +12,6 @@ module Api timestamps_filter( @inventory_column.repository_status_items ) - .repository_status_items .page(params.dig(:page, :number)) .per(params.dig(:page, :size)) diff --git a/spec/factories/teams.rb b/spec/factories/teams.rb index 1700db19e..400eabab4 100644 --- a/spec/factories/teams.rb +++ b/spec/factories/teams.rb @@ -7,6 +7,9 @@ FactoryBot.define do description { Faker::Lorem.sentence } space_taken { 1048576 } without_templates { true } + after(:create) do |team| + team.created_by.update(current_team_id: team.id) + end trait :with_members do users { create_list :user, 3 } end diff --git a/spec/requests/api/v1/experiments_controller_spec.rb b/spec/requests/api/v1/experiments_controller_spec.rb index 1298ca708..e76d41697 100644 --- a/spec/requests/api/v1/experiments_controller_spec.rb +++ b/spec/requests/api/v1/experiments_controller_spec.rb @@ -44,7 +44,7 @@ RSpec.describe "Api::V1::ExperimentsController", type: :request do it 'Response with correct experiments, only active' do hash_body = nil - get api_v1_team_project_experiments_path(team_id: @teams.first.id, + get api_v1_team_project_experiments_path(team_id: @team1.id, project_id: @valid_project, filter: { archived: false }), headers: @valid_headers expect { hash_body = json }.not_to raise_exception expect(hash_body[:data].pluck('attributes').pluck('archived').none?).to be(true) @@ -60,7 +60,7 @@ RSpec.describe "Api::V1::ExperimentsController", type: :request do it 'Response with correct experiments, only archived' do hash_body = nil - get api_v1_team_project_experiments_path(team_id: @teams.first.id, + get api_v1_team_project_experiments_path(team_id: @team1.id, project_id: @valid_project, filter: { archived: true }), headers: @valid_headers expect { hash_body = json }.not_to raise_exception expect(hash_body[:data].pluck('attributes').pluck('archived').all?).to be(true) diff --git a/spec/requests/api/v1/project_user_assignments_controller_spec.rb b/spec/requests/api/v1/project_user_assignments_controller_spec.rb index 0fc8995af..f64ed9196 100644 --- a/spec/requests/api/v1/project_user_assignments_controller_spec.rb +++ b/spec/requests/api/v1/project_user_assignments_controller_spec.rb @@ -6,14 +6,21 @@ RSpec.describe "Api::V1::ProjectUserAssignmentsController", type: :request do before :all do @user = create(:user) @another_user = create(:user) + @first_project_owner_user = create(:user) @team = create(:team, created_by: @user) @normal_user_role = create :normal_user_role create_user_assignment(@team, @normal_user_role, @another_user) + create_user_assignment(@team, @normal_user_role, @first_project_owner_user) @own_project = create(:project, name: Faker::Name.unique.name, created_by: @user, team: @team) + @owner_role = UserRole.find_by(name: I18n.t('user_roles.predefined.owner')) + create_user_assignment(@own_project, @owner_role, @first_project_owner_user) @invalid_project = create(:project, name: Faker::Name.unique.name, created_by: @another_user, team: @team, visibility: :hidden) - @valid_headers = { 'Authorization': 'Bearer ' + generate_token(@user.id) } + @valid_headers = { Authorization: "Bearer #{generate_token(@user.id)}" } + @valid_headers_first_project_owner_user = { + Authorization: "Bearer #{generate_token(@first_project_owner_user.id)}" + } end describe 'GET #index' do @@ -29,15 +36,23 @@ RSpec.describe "Api::V1::ProjectUserAssignmentsController", type: :request do ) end - it 'When invalid request, user in not an owner of the project' do + it 'When invalid request, user is not an owner of the team and do not have access to project' do hash_body = nil get api_v1_team_project_users_path(team_id: @team.id, project_id: @invalid_project.id), - headers: @valid_headers + headers: @valid_headers_first_project_owner_user expect(response).to have_http_status(403) expect { hash_body = json }.not_to raise_exception expect(hash_body['errors'][0]).to include('status': 403) end + it 'When invalid request, user is an owner of the team and do not have access to project' do + hash_body = nil + get api_v1_team_project_users_path(team_id: @team.id, project_id: @invalid_project.id), + headers: @valid_headers + expect(response).to have_http_status(200) + expect { hash_body = json }.not_to raise_exception + end + it 'When invalid request, non existing project' do hash_body = nil get api_v1_team_project_users_path(team_id: @team.id, project_id: -1), headers: @valid_headers @@ -66,9 +81,9 @@ RSpec.describe "Api::V1::ProjectUserAssignmentsController", type: :request do get api_v1_team_project_user_path( team_id: @team.id, project_id: @invalid_project.id, id: -1 ), headers: @valid_headers - expect(response).to have_http_status(403) + expect(response).to have_http_status(404) expect { hash_body = json }.not_to raise_exception - expect(hash_body['errors'][0]).to include('status': 403) + expect(hash_body['errors'][0]).to include('status': 404) end it 'When invalid request, non existing project' do @@ -161,7 +176,7 @@ RSpec.describe "Api::V1::ProjectUserAssignmentsController", type: :request do project_id: @invalid_project.id ), params: request_body.to_json, - headers: @valid_headers + headers: @valid_headers_first_project_owner_user ) expect(response).to have_http_status(403) @@ -180,7 +195,7 @@ RSpec.describe "Api::V1::ProjectUserAssignmentsController", type: :request do api_v1_team_project_user_path( team_id: @own_project.team.id, project_id: @own_project.id, - id: @own_project.user_assignments.first.id + id: @own_project.user_assignments.last.id ), params: request_body.to_json, headers: @valid_headers @@ -246,7 +261,7 @@ RSpec.describe "Api::V1::ProjectUserAssignmentsController", type: :request do } end - it 'renders 403' do + it 'renders 404' do patch( api_v1_team_project_user_path( team_id: @invalid_project.team.id, @@ -257,7 +272,7 @@ RSpec.describe "Api::V1::ProjectUserAssignmentsController", type: :request do headers: @valid_headers ) - expect(response).to have_http_status(403) + expect(response).to have_http_status(404) end end end diff --git a/spec/requests/api/v1/projects_controller_spec.rb b/spec/requests/api/v1/projects_controller_spec.rb index cb868ab34..696247759 100644 --- a/spec/requests/api/v1/projects_controller_spec.rb +++ b/spec/requests/api/v1/projects_controller_spec.rb @@ -14,7 +14,7 @@ RSpec.describe 'Api::V1::ProjectsController', type: :request do project = create(:project, name: Faker::Name.unique.name, created_by: @user, team: @team1) end 2.times do - project = create(:project, name: Faker::Name.unique.name, created_by: @user, team: @teams.first, archived: true) + project = create(:project, name: Faker::Name.unique.name, created_by: @user, team: @team1, archived: true) end # unaccessable_projects @@ -44,14 +44,14 @@ RSpec.describe 'Api::V1::ProjectsController', type: :request do it 'Response with correct projects, only active' do hash_body = nil - get api_v1_team_projects_path(team_id: @teams.first.id, filter: { archived: false }), + get api_v1_team_projects_path(team_id: @team1.id, filter: { archived: false }), headers: @valid_headers expect { hash_body = json }.not_to raise_exception expect(hash_body[:data].pluck('attributes').pluck('archived').none?).to be(true) expect(hash_body[:data]).to match( JSON.parse( ActiveModelSerializers::SerializableResource - .new(@teams.first.projects.active, each_serializer: Api::V1::ProjectSerializer) + .new(@team1.projects.active, each_serializer: Api::V1::ProjectSerializer) .to_json )['data'] ) @@ -59,14 +59,14 @@ RSpec.describe 'Api::V1::ProjectsController', type: :request do it 'Response with correct projects, only archived' do hash_body = nil - get api_v1_team_projects_path(team_id: @teams.first.id, filter: { archived: true }), + get api_v1_team_projects_path(team_id: @team1.id, filter: { archived: true }), headers: @valid_headers expect { hash_body = json }.not_to raise_exception expect(hash_body[:data].pluck('attributes').pluck('archived').all?).to be(true) expect(hash_body[:data]).to match( JSON.parse( ActiveModelSerializers::SerializableResource - .new(@teams.first.projects.archived, each_serializer: Api::V1::ProjectSerializer) + .new(@team1.projects.archived, each_serializer: Api::V1::ProjectSerializer) .to_json )['data'] ) diff --git a/spec/requests/api/v1/protocol_templates_controller_spec.rb b/spec/requests/api/v1/protocol_templates_controller_spec.rb index 798c4f2fe..7fa54470f 100644 --- a/spec/requests/api/v1/protocol_templates_controller_spec.rb +++ b/spec/requests/api/v1/protocol_templates_controller_spec.rb @@ -14,7 +14,7 @@ RSpec.describe 'Api::V1::ProtocolTemplateController', type: :request do @protocol_published = create(:protocol, :in_repository_published_version, team: @team, added_by: @user, parent: @protocol_published_original, version_number: 2) @protocol_published_draft = create(:protocol, :in_repository_draft, team: @team, added_by: @user, parent: @protocol_published_original, version_number: 3, name: @protocol_published_original.name) - + @protocol_draft_second_team = create(:protocol, :in_repository_draft, team: @team2, added_by: @another_user) @valid_headers = { 'Authorization': 'Bearer ' + generate_token(@user.id) } diff --git a/spec/requests/api/v1/results_controller_spec.rb b/spec/requests/api/v1/results_controller_spec.rb index f3e2e131c..6f902431e 100644 --- a/spec/requests/api/v1/results_controller_spec.rb +++ b/spec/requests/api/v1/results_controller_spec.rb @@ -129,14 +129,14 @@ RSpec.describe 'Api::V1::ResultsController', type: :request do attributes: { text: 'Result text 1 ' + 'QVQIHWP8//8/AwMDExADAQAkBgMBOOSShwAAAABJRU5ErkJggg==" data-mce-token="1">' } }, { type: 'tiny_mce_assets', attributes: { file_data: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAIAA'\ 'AACCAIAAAD91JpzAAAACXBIWXMAAC4jAAAuIwF4pT92AAAAE0lE'\ 'QVQIHWP8//8/AwMDExADAQAkBgMBOOSShwAAAABJRU5ErkJggg==', - file_token: 'a1', + file_token: '1', file_name: 'test.png' } } ] @@ -198,7 +198,7 @@ RSpec.describe 'Api::V1::ResultsController', type: :request do it 'Response correct with old TinyMCE images' do hash_body = nil - @valid_tinymce_hash_body[:included][0][:attributes][:text] = 'Result text 1 [~tiny_mce_id:a1]' + @valid_tinymce_hash_body[:included][0][:attributes][:text] = 'Result text 1 [~tiny_mce_id:1]' post api_v1_team_project_experiment_task_results_path( team_id: @team1.id, project_id: @valid_project, diff --git a/spec/requests/api/v1/task_inventory_items_controller_spec.rb b/spec/requests/api/v1/task_inventory_items_controller_spec.rb index 8c8564084..c4f18baea 100644 --- a/spec/requests/api/v1/task_inventory_items_controller_spec.rb +++ b/spec/requests/api/v1/task_inventory_items_controller_spec.rb @@ -63,7 +63,7 @@ RSpec.describe 'Api::V1::TasksController', type: :request do expect(response).to have_http_status 200 expect(JSON.parse(response.body)['data'].map { |item| item['id'] }).to( - eq([@my_module_repository_row.id.to_s]) + eq([@repository_row.id.to_s]) ) end end @@ -76,14 +76,14 @@ RSpec.describe 'Api::V1::TasksController', type: :request do project_id: @project.id, experiment_id: @experiment.id, task_id: @my_module.id, - id: @my_module_repository_row.id + id: @repository_row.id ), headers: @valid_headers ) expect(response).to have_http_status 200 expect(JSON.parse(response.body)['data']['id']).to( - eq(@my_module_repository_row.id.to_s) + eq(@repository_row.id.to_s) ) end end @@ -112,7 +112,7 @@ RSpec.describe 'Api::V1::TasksController', type: :request do project_id: @project.id, experiment_id: @experiment.id, task_id: @my_module.id, - id: @my_module_repository_row.id + id: @repository_row.id ), params: request_body.to_json, headers: @valid_headers) @@ -130,7 +130,7 @@ RSpec.describe 'Api::V1::TasksController', type: :request do hash_including( data: hash_including( type: 'inventory_items', - attributes: hash_including(stock_consumption: "100.0") ) + attributes: hash_including(stock_consumption: '100.0')) ) ) end @@ -143,7 +143,7 @@ RSpec.describe 'Api::V1::TasksController', type: :request do project_id: @project.id, experiment_id: @experiment.id, task_id: @my_module.id, - id: @my_module_repository_row.id + id: @repository_row.id ), params: request_body.to_json, headers: @valid_headers) diff --git a/spec/requests/api/v1/tasks_controller_spec.rb b/spec/requests/api/v1/tasks_controller_spec.rb index 73bda2c00..0b43c1976 100644 --- a/spec/requests/api/v1/tasks_controller_spec.rb +++ b/spec/requests/api/v1/tasks_controller_spec.rb @@ -52,7 +52,7 @@ RSpec.describe 'Api::V1::TasksController', type: :request do it 'Response with correct tasks, only active' do hash_body = nil get api_v1_team_project_experiment_tasks_path( - team_id: @teams.first.id, + team_id: @team1.id, project_id: @valid_project, experiment_id: @valid_experiment, filter: { archived: false } @@ -71,7 +71,7 @@ RSpec.describe 'Api::V1::TasksController', type: :request do it 'Response with correct tasks, only archived' do hash_body = nil get api_v1_team_project_experiment_tasks_path( - team_id: @teams.first.id, + team_id: @team1.id, project_id: @valid_project, experiment_id: @valid_experiment, filter: { archived: true } From d0703f04dcdaac3fd84d1beefbee54a085ea92a3 Mon Sep 17 00:00:00 2001 From: Anton Date: Tue, 24 Oct 2023 13:41:13 +0200 Subject: [PATCH 07/18] Fix protocol header [SCI-9592] --- app/assets/stylesheets/protocols/index.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/assets/stylesheets/protocols/index.scss b/app/assets/stylesheets/protocols/index.scss index 662fa0065..7bb510962 100644 --- a/app/assets/stylesheets/protocols/index.scss +++ b/app/assets/stylesheets/protocols/index.scss @@ -20,7 +20,7 @@ width: 100%; .dataTables_scrollHead { - overflow: visible !important; + flex-shrink: 0; thead { .sci-checkbox-container { From 1eece29f848a6bde989bd986f45ce08311d7c6fc Mon Sep 17 00:00:00 2001 From: Alex Kriuchykhin Date: Tue, 24 Oct 2023 16:00:41 +0200 Subject: [PATCH 08/18] Fix error at filtering by date on project page [SCI-9590] (#6523) --- app/assets/javascripts/projects/index.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/app/assets/javascripts/projects/index.js b/app/assets/javascripts/projects/index.js index e0fb54153..7f063a0f1 100644 --- a/app/assets/javascripts/projects/index.js +++ b/app/assets/javascripts/projects/index.js @@ -549,6 +549,8 @@ var ProjectsIndex = (function() { var datePicker = $field.data('DateTimePicker'); if (datePicker && datePicker.date()) { return datePicker.date()._d.toUTCString(); + } else if ($field.val()) { + return moment($field.val(), $field.data('dateFormat'))._d.toUTCString(); } return null; } @@ -565,8 +567,8 @@ var ProjectsIndex = (function() { let $textFilter = $('#textSearchFilterInput', $projectsFilter); function getFilterValues() { - createdOnFromFilter = selectDate($createdOnFromFilter) || $createdOnFromFilter.val(); - createdOnToFilter = selectDate($createdOnToFilter) || $createdOnToFilter.val(); + createdOnFromFilter = selectDate($createdOnFromFilter); + createdOnToFilter = selectDate($createdOnToFilter); membersFilter = dropdownSelector.getData($('.members-filter')); lookInsideFolders = $foldersCB.prop('checked') || ''; archivedOnFromFilter = selectDate($archivedOnFromFilter) || $archivedOnFromFilter.val(); From e0f2677d1cdcb975a9156900bd301c3a37aa4439 Mon Sep 17 00:00:00 2001 From: Anton Date: Tue, 24 Oct 2023 16:31:20 +0200 Subject: [PATCH 09/18] Fix marvinJS in tinymce [SCI-9594] --- config/initializers/constants.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/config/initializers/constants.rb b/config/initializers/constants.rb index 54c5e5378..b1b035f19 100644 --- a/config/initializers/constants.rb +++ b/config/initializers/constants.rb @@ -325,6 +325,7 @@ class Constants config[:attributes][:all] << 'id' config[:attributes][:all] << 'contenteditable' config[:attributes]['img'] << 'data-mce-token' + config[:attributes]['img'] << 'data-source-type' config[:protocols]['img']['src'] << 'data' INPUT_SANITIZE_CONFIG = Sanitize::Config.freeze_config(config) From ac56cb429c43a30b31fd99d545d0134ae191b1fc Mon Sep 17 00:00:00 2001 From: Oleksii Kriuchykhin Date: Wed, 25 Oct 2023 11:33:51 +0200 Subject: [PATCH 10/18] Bump version to 1.29.1 --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index eb6c80e2b..83cf0d951 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.29.0.1 +1.29.1 From 0ffd3dcee3f01044209eaf8d81e7eae5f12a2e16 Mon Sep 17 00:00:00 2001 From: Anton Date: Thu, 26 Oct 2023 12:01:48 +0200 Subject: [PATCH 11/18] Add image paster [SCI-9588] --- app/assets/stylesheets/tailwind/inputs.css | 2 +- app/javascript/vue/protocol/container.vue | 26 ++++++- app/javascript/vue/protocol/step.vue | 16 +--- app/javascript/vue/results/result.vue | 3 +- app/javascript/vue/results/results.vue | 25 ++++++- .../attachments/clipboard_paste_modal.vue | 74 +++++++++++++++---- .../content/attachments/mixins/paste.js | 27 +++++++ config/locales/en.yml | 7 +- 8 files changed, 143 insertions(+), 37 deletions(-) create mode 100644 app/javascript/vue/shared/content/attachments/mixins/paste.js diff --git a/app/assets/stylesheets/tailwind/inputs.css b/app/assets/stylesheets/tailwind/inputs.css index 963aa94bd..805ce15b1 100644 --- a/app/assets/stylesheets/tailwind/inputs.css +++ b/app/assets/stylesheets/tailwind/inputs.css @@ -1,7 +1,7 @@ @layer components { .sci-label { - @apply text-sm font-medium text-sn-grey; + @apply text-sm font-medium text-sn-dark-grey; } .sci-input-container-v2 { diff --git a/app/javascript/vue/protocol/container.vue b/app/javascript/vue/protocol/container.vue index 3314ee999..aacbaa6ea 100644 --- a/app/javascript/vue/protocol/container.vue +++ b/app/javascript/vue/protocol/container.vue @@ -210,6 +210,14 @@ @publish="publishProtocol" @cancel="closePublishModal" /> + @@ -221,6 +229,8 @@ import Tinymce from '../shared/tinymce.vue' import ReorderableItemsModal from '../shared/reorderable_items_modal.vue' import PublishProtocol from './modals/publish_protocol.vue' + import clipboardPasteModal from '../shared/content/attachments/clipboard_paste_modal.vue' + import AssetPasteMixin from '../shared/content/attachments/mixins/paste.js' import UtilsMixin from '../mixins/utils.js' import stackableHeadersMixin from '../mixins/stackableHeadersMixin'; @@ -234,8 +244,8 @@ required: true } }, - components: { Step, InlineEdit, ProtocolOptions, Tinymce, ReorderableItemsModal, ProtocolMetadata, PublishProtocol}, - mixins: [UtilsMixin, stackableHeadersMixin, moduleNameObserver], + components: { Step, InlineEdit, ProtocolOptions, Tinymce, ReorderableItemsModal, ProtocolMetadata, PublishProtocol, clipboardPasteModal}, + mixins: [UtilsMixin, stackableHeadersMixin, moduleNameObserver, AssetPasteMixin], computed: { inRepository() { return this.protocol.attributes.in_repository @@ -245,7 +255,7 @@ }, urls() { return this.protocol.attributes.urls || {} - } + }, }, data() { return { @@ -433,6 +443,16 @@ $('.my_module-name .view-mode').trigger('click'); $('.my_module-name .input-field').focus(); }, 300) + }, + uploadFilesToStep(file, stepId) { + this.$children.find(child => child.step?.id == stepId).uploadFiles(file); + }, + firstObjectInViewport() { + let step = $('.step-container:not(.locked)').toArray().find(element => { + const { top, bottom } = element.getBoundingClientRect() + return bottom > 0 && top < window.innerHeight + }) + return step ? step.dataset.id : null } } } diff --git a/app/javascript/vue/protocol/step.vue b/app/javascript/vue/protocol/step.vue index 52f00dfa4..577da8d84 100644 --- a/app/javascript/vue/protocol/step.vue +++ b/app/javascript/vue/protocol/step.vue @@ -4,7 +4,8 @@ @drop.prevent="dropFile" @dragenter.prevent="dragEnter($event)" @dragover.prevent - :class="{ 'draging-file': dragingFile, 'editing-name': editingName }" + :data-id="step.id" + :class="{ 'draging-file': dragingFile, 'editing-name': editingName, 'locked': !urls.update_url }" >
{{ i18n.t('protocols.steps.drop_message', { position: step.attributes.position + 1 }) }} @@ -134,12 +135,6 @@
- { diff --git a/app/javascript/vue/results/result.vue b/app/javascript/vue/results/result.vue index 655bd3eac..2b51d941a 100644 --- a/app/javascript/vue/results/result.vue +++ b/app/javascript/vue/results/result.vue @@ -3,7 +3,8 @@ @drop.prevent="dropFile" @dragenter.prevent="dragEnter($event)" @dragover.prevent - :class="{ 'bg-sn-super-light-blue': dragingFile, 'bg-white': !dragingFile }" + :data-id="result.id" + :class="{ 'bg-sn-super-light-blue': dragingFile, 'bg-white': !dragingFile, 'locked': locked }" >
+ @@ -43,10 +51,13 @@ import stackableHeadersMixin from '../mixins/stackableHeadersMixin'; import moduleNameObserver from '../mixins/moduleNameObserver'; + import clipboardPasteModal from '../shared/content/attachments/clipboard_paste_modal.vue' + import AssetPasteMixin from '../shared/content/attachments/mixins/paste.js' + export default { name: 'Results', - components: { ResultsToolbar, Result }, - mixins: [stackableHeadersMixin, moduleNameObserver], + components: { ResultsToolbar, Result, clipboardPasteModal }, + mixins: [stackableHeadersMixin, moduleNameObserver, AssetPasteMixin], props: { url: { type: String, required: true }, canCreate: { type: String, required: true }, @@ -136,6 +147,16 @@ }, dragEnter(id) { this.activeDragResult = id; + }, + uploadFilesToResult(file, resultId) { + this.$children.find(child => child.result?.id == resultId).uploadFiles(file); + }, + firstObjectInViewport() { + let result = $('.result-wrapper:not(.locked)').toArray().find(element => { + const { top, bottom } = element.getBoundingClientRect() + return bottom > 0 && top < window.innerHeight + }) + return result ? result.dataset.id : null } } } diff --git a/app/javascript/vue/shared/content/attachments/clipboard_paste_modal.vue b/app/javascript/vue/shared/content/attachments/clipboard_paste_modal.vue index 9340e7924..67ad2e34a 100644 --- a/app/javascript/vue/shared/content/attachments/clipboard_paste_modal.vue +++ b/app/javascript/vue/shared/content/attachments/clipboard_paste_modal.vue @@ -12,29 +12,66 @@