diff --git a/app/controllers/users/settings/user_settings_controller.rb b/app/controllers/users/settings/user_settings_controller.rb index ec56c576a..2b106bc17 100644 --- a/app/controllers/users/settings/user_settings_controller.rb +++ b/app/controllers/users/settings/user_settings_controller.rb @@ -14,7 +14,14 @@ module Users key = setting[:key] data = setting[:data] - current_user.settings[key] = data if Extends::WHITELISTED_USER_SETTINGS.include?(key.to_s) + next unless Extends::WHITELISTED_USER_SETTINGS.include?(key.to_s) + + case key.to_s + when 'task_step_states' + update_task_step_states(data) + else + current_user.settings[key] = data + end end if current_user.save @@ -24,6 +31,22 @@ module Users status: :unprocessable_entity end end + + private + + def update_task_step_states(task_step_states_data) + current_states = current_user.settings.fetch('task_step_states', {}) + + task_step_states_data.each do |step_id, collapsed| + if collapsed + current_states[step_id] = true + else + current_states.delete(step_id) + end + end + + current_user.settings['task_step_states'] = current_states + end end end end diff --git a/app/javascript/vue/protocol/container.vue b/app/javascript/vue/protocol/container.vue index 0d43309d0..30a1e9cb5 100644 --- a/app/javascript/vue/protocol/container.vue +++ b/app/javascript/vue/protocol/container.vue @@ -183,6 +183,7 @@ @step:move_attachment="reloadStep" @step:drag_enter="dragEnter" :reorderStepUrl="steps.length > 1 ? urls.reorder_steps_url : null" + :userSettingsUrl="userSettingsUrl" :assignableMyModuleId="protocol.attributes.assignable_my_module_id" />
@@ -237,7 +238,7 @@ 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 axios from '../../packs/custom_axios'; import UtilsMixin from '../mixins/utils.js'; import stackableHeadersMixin from '../mixins/stackableHeadersMixin'; import moduleNameObserver from '../mixins/moduleNameObserver'; @@ -277,10 +278,12 @@ export default { reordering: false, publishing: false, stepToReload: null, - activeDragStep: null + activeDragStep: null, + userSettingsUrl: null }; }, mounted() { + this.userSettingsUrl = document.querySelector('meta[name="user-settings-url"]').getAttribute('content'); $.get(this.protocolUrl, (result) => { this.protocol = result.data; this.$nextTick(() => { @@ -309,9 +312,24 @@ export default { }, collapseSteps() { $('.step-container .collapse').collapse('hide'); + this.updateStepStateSettings(true); }, expandSteps() { $('.step-container .collapse').collapse('show'); + this.updateStepStateSettings(false); + }, + updateStepStateSettings(newState) { + const updatedData = this.steps.reduce((acc, currentStep) => { + acc[currentStep.id] = newState; + return acc; + }, {}); + + const settings = { + key: 'task_step_states', + data: updatedData + }; + + axios.put(this.userSettingsUrl, { settings: [settings] }); }, deleteSteps() { $.post(this.urls.delete_steps_url, () => { diff --git a/app/javascript/vue/protocol/step.vue b/app/javascript/vue/protocol/step.vue index 6806bba67..448e93abf 100644 --- a/app/javascript/vue/protocol/step.vue +++ b/app/javascript/vue/protocol/step.vue @@ -183,6 +183,9 @@ reorderStepUrl: { required: false }, + userSettingsUrl: { + required: false + }, assignableMyModuleId: { type: Number, required: false @@ -249,6 +252,15 @@ } }, mounted() { + this.$nextTick(() => { + const stepId = `#stepBody${this.step.id}`; + this.isCollapsed = this.step.attributes.collapsed; + if (this.isCollapsed) { + $(stepId).collapse('hide'); + } else { + $(stepId).collapse('show'); + } + }); $(this.$refs.comments).data('closeCallback', this.closeCommentsSidebar); $(this.$refs.comments).data('openCallback', this.closeCommentsSidebar); $(this.$refs.actionsDropdownButton).on('shown.bs.dropdown hidden.bs.dropdown', () => { @@ -402,6 +414,13 @@ }, toggleCollapsed() { this.isCollapsed = !this.isCollapsed; + + const settings = { + key: 'task_step_states', + data: { [this.step.id]: this.isCollapsed } + }; + + axios.put(this.userSettingsUrl, { settings: [settings] }); }, showDeleteModal() { this.confirmingDelete = true; diff --git a/app/serializers/step_serializer.rb b/app/serializers/step_serializer.rb index 6da21dcbb..91851d85b 100644 --- a/app/serializers/step_serializer.rb +++ b/app/serializers/step_serializer.rb @@ -10,7 +10,12 @@ class StepSerializer < ActiveModel::Serializer attributes :name, :position, :completed, :attachments_manageble, :urls, :assets_view_mode, :marvinjs_enabled, :marvinjs_context, :created_by, :created_at, :assets_order, :wopi_enabled, :wopi_context, :comments_count, :unseen_comments, :storage_limit, - :type, :open_vector_editor_context + :type, :open_vector_editor_context, :collapsed + + def collapsed + step_states = @instance_options[:user].settings.fetch('task_step_states', {}) + step_states[object.id.to_s] == true + end def marvinjs_enabled MarvinJsService.enabled? diff --git a/config/initializers/extends.rb b/config/initializers/extends.rb index b7a391da2..10aab7add 100644 --- a/config/initializers/extends.rb +++ b/config/initializers/extends.rb @@ -650,6 +650,7 @@ class Extends ReportTemplates_archived_state Repositories_active_state Repositories_archived_state + task_step_states ).freeze end