diff --git a/app/assets/javascripts/experiments/table.js b/app/assets/javascripts/experiments/table.js index e47606f88..d7831ce54 100644 --- a/app/assets/javascripts/experiments/table.js +++ b/app/assets/javascripts/experiments/table.js @@ -491,29 +491,37 @@ var ExperimnetTable = { } }); }, - initFilters: function() { - this.filterDropdown = filterDropdown.init(); + getFilterValues: function() { let $experimentFilter = $('#experimentTable .my-modules-filters'); + $.each(this.filters, (_i, filter) => { + this.activeFilters[filter.name] = filter.apply($experimentFilter); + }); + + // filters are active if they have any non-empty value + let filtersEmpty = Object.values(this.activeFilters).every(value => /^\s+$/.test(value) + || value === null + || value === undefined + || (value && value.length === 0)); + this.filtersActive = !filtersEmpty; + }, + filtersEnabled: function() { + this.getFilterValues(); + + return this.filters.some((filter) => { + return filter.active(this.activeFilters[filter.name]); + }); + }, + initFilters: function() { + let $experimentFilter = $('#experimentTable .my-modules-filters'); + + this.filterDropdown = filterDropdown.init(() => this.filtersEnabled()); $.each(this.filters, (_i, filter) => { filter.init($experimentFilter); }); this.filterDropdown.on('filter:apply', () => { - $.each(this.filters, (_i, filter) => { - this.activeFilters[filter.name] = filter.apply($experimentFilter); - }); - - // filters are active if they have any non-empty value - let filtersEmpty = Object.values(this.activeFilters).every(value => /^\s+$/.test(value) || value === null || value === undefined || value && value.length === 0); - this.filtersActive = !filtersEmpty; - - filterDropdown.toggleFilterMark( - this.filterDropdown, - this.filters.some((filter) => { - return filter.active(this.activeFilters[filter.name]); - }) - ); + filterDropdown.toggleFilterMark(this.filterDropdown, this.filtersEnabled()); this.loadTable(); }); diff --git a/app/assets/javascripts/my_modules/protocols.js b/app/assets/javascripts/my_modules/protocols.js index a6a50a29f..8353c1f09 100644 --- a/app/assets/javascripts/my_modules/protocols.js +++ b/app/assets/javascripts/my_modules/protocols.js @@ -40,8 +40,9 @@ function initLinkUpdate() { var modalTitle = modal.find('.modal-title'); var modalMessage = modal.find('.modal-body .message'); var updateBtn = modal.find(".modal-footer [data-action='submit']"); - $("[data-action='unlink'], [data-action='revert'], [data-action='update-parent'], [data-action='update-self']") - .on('ajax:success', function(e, data) { + $('.protocol-options-dropdown') + .on('ajax:success', "[data-action='unlink'], [data-action='revert'], [data-action='update-parent']," + + "[data-action='update-self']", function(e, data) { modalTitle.html(data.title); modalMessage.html(data.message); updateBtn.text(data.btn_text); diff --git a/app/assets/javascripts/projects/index.js b/app/assets/javascripts/projects/index.js index d2e20665a..918a42585 100644 --- a/app/assets/javascripts/projects/index.js +++ b/app/assets/javascripts/projects/index.js @@ -559,7 +559,7 @@ var ProjectsIndex = (function() { } function initProjectsFilters() { - var $filterDropdown = filterDropdown.init(); + var $filterDropdown = filterDropdown.init(filtersEnabled); let $projectsFilter = $('.projects-index .projects-filters'); let $membersFilter = $('.members-filter', $projectsFilter); let $foldersCB = $('#folder_search', $projectsFilter); @@ -569,15 +569,30 @@ var ProjectsIndex = (function() { let $archivedOnToFilter = $('.archived-on-filter .to-date', $projectsFilter); let $textFilter = $('#textSearchFilterInput', $projectsFilter); + function getFilterValues() { + createdOnFromFilter = selectDate($createdOnFromFilter); + createdOnToFilter = selectDate($createdOnToFilter); + membersFilter = dropdownSelector.getValues($('.members-filter')); + lookInsideFolders = $foldersCB.prop('checked') ? 'true' : ''; + archivedOnFromFilter = selectDate($archivedOnFromFilter); + archivedOnToFilter = selectDate($archivedOnToFilter); + projectsViewSearch = $textFilter.val(); + } + + function filtersEnabled() { + getFilterValues(); + + return projectsViewSearch + || createdOnFromFilter + || createdOnToFilter + || (membersFilter && membersFilter.length !== 0) + || lookInsideFolders + || archivedOnFromFilter + || archivedOnToFilter; + } + function appliedFiltersMark() { - let filtersEnabled = projectsViewSearch - || createdOnFromFilter - || createdOnToFilter - || (membersFilter && membersFilter.length !== 0) - || lookInsideFolders - || archivedOnFromFilter - || archivedOnToFilter; - filterDropdown.toggleFilterMark($filterDropdown, filtersEnabled); + filterDropdown.toggleFilterMark($filterDropdown, filtersEnabled()); } dropdownSelector.init($membersFilter, { @@ -602,14 +617,6 @@ var ProjectsIndex = (function() { }); $filterDropdown.on('filter:apply', function() { - createdOnFromFilter = selectDate($createdOnFromFilter); - createdOnToFilter = selectDate($createdOnToFilter); - membersFilter = dropdownSelector.getValues($('.members-filter')); - lookInsideFolders = $foldersCB.prop('checked') ? 'true' : ''; - archivedOnFromFilter = selectDate($archivedOnFromFilter); - archivedOnToFilter = selectDate($archivedOnToFilter); - projectsViewSearch = $textFilter.val(); - appliedFiltersMark(); refreshCurrentView(); }); diff --git a/app/assets/javascripts/projects/show.js b/app/assets/javascripts/projects/show.js index c5a8efe49..ea8292bf6 100644 --- a/app/assets/javascripts/projects/show.js +++ b/app/assets/javascripts/projects/show.js @@ -147,7 +147,7 @@ } function initExperimentsFilters() { - var $filterDropdown = filterDropdown.init(); + var $filterDropdown = filterDropdown.init(filtersEnabled); let $experimentsFilter = $('.experiments-filters'); let $startedOnFromFilter = $('.started-on-filter .from-date', $experimentsFilter); @@ -158,18 +158,7 @@ let $archivedOnToFilter = $('.archived-on-filter .to-date', $experimentsFilter); let $textFilter = $('#textSearchFilterInput', $experimentsFilter); - function appliedFiltersMark() { - let filtersEnabled = experimentsViewSearch - || startedOnFromFilter - || startedOnToFilter - || modifiedOnFromFilter - || modifiedOnToFilter - || archivedOnFromFilter - || archivedOnToFilter; - filterDropdown.toggleFilterMark($filterDropdown, filtersEnabled); - } - - $filterDropdown.on('filter:apply', function() { + function getFilterValues() { startedOnFromFilter = selectDate($startedOnFromFilter); startedOnToFilter = selectDate($startedOnToFilter); modifiedOnFromFilter = selectDate($modifiedOnFromFilter); @@ -177,6 +166,26 @@ archivedOnFromFilter = selectDate($archivedOnFromFilter); archivedOnToFilter = selectDate($archivedOnToFilter); experimentsViewSearch = $textFilter.val(); + } + + function filtersEnabled() { + getFilterValues(); + + return experimentsViewSearch + || startedOnFromFilter + || startedOnToFilter + || modifiedOnFromFilter + || modifiedOnToFilter + || archivedOnFromFilter + || archivedOnToFilter; + } + + + function appliedFiltersMark() { + filterDropdown.toggleFilterMark($filterDropdown, filtersEnabled()); + } + + $filterDropdown.on('filter:apply', function() { appliedFiltersMark(); refreshCurrentView(); }); diff --git a/app/assets/javascripts/protocols/index.js b/app/assets/javascripts/protocols/index.js index 05e010a96..7f7dc6a44 100644 --- a/app/assets/javascripts/protocols/index.js +++ b/app/assets/javascripts/protocols/index.js @@ -51,7 +51,7 @@ var ProtocolsIndex = (function() { } function initProtocolsFilters() { - var $filterDropdown = filterDropdown.init(); + var $filterDropdown = filterDropdown.init(filtersEnabled); let $protocolsFilter = $('.protocols-index .protocols-filters'); let $publishedByFilter = $('.published-by-filter', $protocolsFilter); let $accessByFilter = $('.access-by-filter', $protocolsFilter); @@ -64,18 +64,36 @@ var ProtocolsIndex = (function() { let $archivedOnToFilter = $('.archived-on-filter .to-date', $protocolsFilter); let $textFilter = $('#textSearchFilterInput', $protocolsFilter); + function getFilterValues() { + publishedOnFromFilter = selectDate($publishedOnFromFilter); + publishedOnToFilter = selectDate($publishedOnToFilter); + modifiedOnFromFilter = selectDate($modifiedOnFromFilter); + modifiedOnToFilter = selectDate($modifiedOnToFilter); + publishedByFilter = dropdownSelector.getValues($('.published-by-filter')); + accessByFilter = dropdownSelector.getValues($('.access-by-filter')); + hasDraftFilter = $hasDraft.prop('checked') ? 'true' : ''; + archivedOnFromFilter = selectDate($archivedOnFromFilter); + archivedOnToFilter = selectDate($archivedOnToFilter); + protocolsViewSearch = $textFilter.val(); + } + + function filtersEnabled() { + getFilterValues(); + + return protocolsViewSearch + || publishedOnFromFilter + || publishedOnToFilter + || modifiedOnFromFilter + || modifiedOnToFilter + || (publishedByFilter && publishedByFilter.length !== 0) + || (accessByFilter && accessByFilter.length !== 0) + || hasDraftFilter + || archivedOnFromFilter + || archivedOnToFilter; + } + function appliedFiltersMark() { - let filtersEnabled = protocolsViewSearch - || publishedOnFromFilter - || publishedOnToFilter - || modifiedOnFromFilter - || modifiedOnToFilter - || (publishedByFilter && publishedByFilter.length !== 0) - || (accessByFilter && accessByFilter.length !== 0) - || hasDraftFilter - || archivedOnFromFilter - || archivedOnToFilter; - filterDropdown.toggleFilterMark($filterDropdown, filtersEnabled); + filterDropdown.toggleFilterMark($filterDropdown, filtersEnabled()); } $.each([$publishedByFilter, $accessByFilter], function(_i, selector) { @@ -97,17 +115,6 @@ var ProtocolsIndex = (function() { }); $filterDropdown.on('filter:apply', function() { - publishedOnFromFilter = selectDate($publishedOnFromFilter); - publishedOnToFilter = selectDate($publishedOnToFilter); - modifiedOnFromFilter = selectDate($modifiedOnFromFilter); - modifiedOnToFilter = selectDate($modifiedOnToFilter); - publishedByFilter = dropdownSelector.getValues($('.published-by-filter')); - accessByFilter = dropdownSelector.getValues($('.access-by-filter')); - hasDraftFilter = $hasDraft.prop('checked') ? 'true' : ''; - archivedOnFromFilter = selectDate($archivedOnFromFilter); - archivedOnToFilter = selectDate($archivedOnToFilter); - protocolsViewSearch = $textFilter.val(); - appliedFiltersMark(); protocolsDatatable.ajax.reload(); }); diff --git a/app/assets/javascripts/protocols/new_protocol.js b/app/assets/javascripts/protocols/new_protocol.js index eab55ab33..6221ed085 100644 --- a/app/assets/javascripts/protocols/new_protocol.js +++ b/app/assets/javascripts/protocols/new_protocol.js @@ -7,7 +7,7 @@ }) .on('show.bs.modal', function() { $(`${protocolModal} #protocol_name`).parent().removeClass('error'); - $(`${protocolModal} form[data-action="new"] #protocol_name`).val(''); + $(`${protocolModal} #protocol_name`).val(''); }); let roleSelector = `${protocolModal} #protocol_role_selector`; diff --git a/app/assets/javascripts/sitewide/filter_dropdown.js b/app/assets/javascripts/sitewide/filter_dropdown.js index 994b62d8f..9569040ed 100644 --- a/app/assets/javascripts/sitewide/filter_dropdown.js +++ b/app/assets/javascripts/sitewide/filter_dropdown.js @@ -1,5 +1,6 @@ var filterDropdown = (function() { var $filterContainer = ''; + var $filtersEnabled = false; function initClearButton() { $('.clear-button', $filterContainer).click(function(e) { @@ -21,7 +22,7 @@ var filterDropdown = (function() { }); } - function initSearchField() { + function initSearchField(filtersEnabledFunction) { var $textFilter = $('#textSearchFilterInput', $filterContainer); $filterContainer.on('show.bs.dropdown', function() { @@ -47,7 +48,9 @@ var filterDropdown = (function() { }).on('hide.bs.dropdown', function(e) { if (e.target === e.currentTarget) { $('#textSearchFilterHistory').hide(); - $('.apply-filters', $filterContainer).click(); + if (filtersEnabledFunction() || $filtersEnabled) { + $('.apply-filters', $filterContainer).click(); + } } }); @@ -98,15 +101,17 @@ var filterDropdown = (function() { } return { - init: function() { + init: function(filtersEnabledFunction) { $filterContainer = $('.filter-container'); + $filtersEnabled = false; initClearButton(); preventDropdownClose(); initApplyButton(); - initSearchField(); + initSearchField(filtersEnabledFunction); return $filterContainer; }, toggleFilterMark: function(filterContainer, filtersEnabled) { + $filtersEnabled = filtersEnabled; if (filtersEnabled) { filterContainer.addClass('filters-applied'); } else { diff --git a/app/assets/stylesheets/my_modules/protocols/index.scss b/app/assets/stylesheets/my_modules/protocols/index.scss index 2faba7ff4..e27dfe9b8 100644 --- a/app/assets/stylesheets/my_modules/protocols/index.scss +++ b/app/assets/stylesheets/my_modules/protocols/index.scss @@ -426,10 +426,10 @@ left: -125px; max-width: 100vw; width: 506px; - padding: 15px 0; + padding: 0; .dropdown-content { - padding: 24px; + padding: 12px 24px; } .dropdown-header, @@ -489,16 +489,19 @@ } } } + } + + .dropdown-footer { + border-top: $border-tertiary; .notification-line { @include font-button; color: $color-silver-chalice; display: flex; - margin: 8px 0; .fas { line-height: 21px; - margin-right: 3px; + margin-right: 11px; } &.new-parent-version { @@ -510,10 +513,6 @@ } } } - - .dropdown-footer { - border-top: $border-tertiary; - } } } diff --git a/app/assets/stylesheets/protocols/index.scss b/app/assets/stylesheets/protocols/index.scss index a896a06e4..27ac008bb 100644 --- a/app/assets/stylesheets/protocols/index.scss +++ b/app/assets/stylesheets/protocols/index.scss @@ -20,6 +20,14 @@ width: 100%; tbody { + td { + vertical-align: middle; + } + + td:first-child { + padding-top: 4px; + } + td:not(:first-child) { max-width: 30rem; overflow: hidden; @@ -78,7 +86,7 @@ } td:not(:first-child) { - padding: 14px 8px; + padding: 12px 8px; } } diff --git a/app/assets/stylesheets/protocols/protocol.scss b/app/assets/stylesheets/protocols/protocol.scss index c6215b97b..52a90ffdb 100644 --- a/app/assets/stylesheets/protocols/protocol.scss +++ b/app/assets/stylesheets/protocols/protocol.scss @@ -96,12 +96,17 @@ padding-left: 20px; } } + .protocol-details { .protocol-metadata { margin-bottom: 2em; .data-block { margin-bottom: 16px; + + > :nth-child(2) { + margin-left: 8px; + } } .authors-data { @@ -113,12 +118,18 @@ flex-basis: calc(100% - 90px); flex-grow: 1; line-height: 32px; - margin-left: .75em; + margin-left: 8px; + font-weight: bold; } * { flex-shrink: 0; } + + .sci-inline-edit__view, + textarea { + padding-left: 10px; + } } .keywords-data { @@ -133,6 +144,11 @@ .dropdown-selector-container { padding-right: 10px; + margin-left: 0; + + .input-field { + margin-left: 0; + } &:not(.active) { .input-field { @@ -146,7 +162,7 @@ &.active { .input-field { - border: 1px solid $color-alto; + border: 1px solid $brand-focus; } } } diff --git a/app/assets/stylesheets/shared/datatable.scss b/app/assets/stylesheets/shared/datatable.scss index 23968d2d1..714728f7c 100644 --- a/app/assets/stylesheets/shared/datatable.scss +++ b/app/assets/stylesheets/shared/datatable.scss @@ -64,6 +64,20 @@ .btn { margin-right: .25em; } + + .btn:focus { + box-shadow: 0 0 0 3px $brand-focus; + } + + .btn-light { + &:active { + background-color: $color-alto !important; + } + + &:hover { + background: $color-white; + } + } } .pagination-info, diff --git a/app/assets/stylesheets/themes/scinote.scss b/app/assets/stylesheets/themes/scinote.scss index ca0978bb2..3f41b2773 100644 --- a/app/assets/stylesheets/themes/scinote.scss +++ b/app/assets/stylesheets/themes/scinote.scss @@ -554,9 +554,12 @@ mark,.mark { table tbody tr .breadcrumb { padding: 0 5px; + position: relative; + right: 15px; & li + li::before { - content: "> "; + color: $color-volcano; + content: "/ "; } } @@ -573,6 +576,10 @@ mark,.mark { } } +.no-linked-children { + padding: 16px 0; +} + a.edit-name-link small { margin-left: 5px; display: none; diff --git a/app/javascript/vue/protocol/container.vue b/app/javascript/vue/protocol/container.vue index 5dcc2c1a6..1259a32b9 100644 --- a/app/javascript/vue/protocol/container.vue +++ b/app/javascript/vue/protocol/container.vue @@ -189,6 +189,9 @@ inRepository() { return this.protocol.attributes.in_repository }, + linked() { + return this.protocol.attributes.linked; + }, urls() { return this.protocol.attributes.urls || {} } @@ -232,21 +235,34 @@ if (this.inRepository) return // legacy method from app/assets/javascripts/my_modules/protocols.js refreshProtocolStatusBar(); + + // Update protocol options drowpdown for linked tasks + this.refreshProtocolDropdownOptions(); + }, + refreshProtocolDropdownOptions() { + if (!this.linked && this.inRepository) return + + $.get(this.protocolUrl, (result) => { + this.protocol.attributes.urls = result.data.attributes.urls; + }); }, updateProtocol(attributes) { this.protocol.attributes = attributes }, updateName(newName) { this.protocol.attributes.name = newName; - this.refreshProtocolStatus(); $.ajax({ type: 'PATCH', url: this.urls.update_protocol_name_url, - data: { protocol: { name: newName } } + data: { protocol: { name: newName } }, + success: () => { + this.refreshProtocolStatus(); + } }); }, updateDescription(protocol) { this.protocol.attributes = protocol.attributes + this.refreshProtocolStatus(); }, addStep(position) { $.post(this.urls.add_step_url, {position: position}, (result) => { @@ -257,8 +273,8 @@ if(position === this.steps.length - 1) { this.$nextTick(() => this.scrollToBottom()); } + this.refreshProtocolStatus(); }) - this.refreshProtocolStatus(); }, updateStepsPosition(step, action = 'add') { let position = step.attributes.position; diff --git a/app/javascript/vue/protocol/mixins/attachments.js b/app/javascript/vue/protocol/mixins/attachments.js index dcc8cac92..9d2c11c1c 100644 --- a/app/javascript/vue/protocol/mixins/attachments.js +++ b/app/javascript/vue/protocol/mixins/attachments.js @@ -86,7 +86,9 @@ export default { }); filesUploadedCntr += 1; if (filesUploadedCntr === filesToUploadCntr) { - this.$emit('stepUpdated'); + setTimeout(() => { + this.$emit('stepUpdated'); + }, 1000); resolve('done'); } } diff --git a/app/javascript/vue/protocol/protocolMetadata.vue b/app/javascript/vue/protocol/protocolMetadata.vue index 4ccdac5d5..6c831d2b3 100644 --- a/app/javascript/vue/protocol/protocolMetadata.vue +++ b/app/javascript/vue/protocol/protocolMetadata.vue @@ -25,19 +25,19 @@

- {{ i18n.t("protocols.header.version") }} + {{ i18n.t("protocols.header.version") }} {{ protocol.attributes.version }}

- {{ i18n.t("protocols.header.updated_at") }} + {{ i18n.t("protocols.header.updated_at") }} {{ protocol.attributes.updated_at_formatted }}

- {{ i18n.t("protocols.header.created_at") }} + {{ i18n.t("protocols.header.created_at") }} {{ protocol.attributes.created_at_formatted }}

- {{ i18n.t("protocols.header.added_by") }} + {{ i18n.t("protocols.header.added_by") }} {{ protocol.attributes.added_by.name }}

diff --git a/app/javascript/vue/protocol/step.vue b/app/javascript/vue/protocol/step.vue index 95b8a7220..3d3baa57a 100644 --- a/app/javascript/vue/protocol/step.vue +++ b/app/javascript/vue/protocol/step.vue @@ -419,6 +419,7 @@ $.post(this.urls[`create_${elementType}_url`], (result) => { result.data.isNew = true; this.elements.push(result.data) + this.$emit('stepUpdated') }).error(() => { HelperModule.flashAlertMsg(this.i18n.t('errors.general'), 'danger'); }) diff --git a/app/serializers/protocol_serializer.rb b/app/serializers/protocol_serializer.rb index aa2230752..431aeeefa 100644 --- a/app/serializers/protocol_serializer.rb +++ b/app/serializers/protocol_serializer.rb @@ -8,7 +8,7 @@ class ProtocolSerializer < ActiveModel::Serializer attributes :name, :id, :urls, :description, :description_view, :updated_at, :in_repository, :created_at_formatted, :updated_at_formatted, :added_by, :authors, :keywords, :version, :code, - :published, :version_comment, :archived, :disabled_drafting + :published, :version_comment, :archived, :linked, :disabled_drafting def updated_at object.updated_at.to_i @@ -95,6 +95,10 @@ class ProtocolSerializer < ActiveModel::Serializer true end end + + def linked + object.linked? + end private diff --git a/app/views/protocols/index/_linked_children_modal_body.html.erb b/app/views/protocols/index/_linked_children_modal_body.html.erb index 9cbaadbf7..61456f10f 100644 --- a/app/views/protocols/index/_linked_children_modal_body.html.erb +++ b/app/views/protocols/index/_linked_children_modal_body.html.erb @@ -11,7 +11,7 @@
<% else %> -
+
<%= t("protocols.index.linked_children.no_linked_children") %>
-<% end %> \ No newline at end of file +<% end %>