Implement saving of table state to DB [SCI-9983]

This commit is contained in:
Ivan Kljun 2024-01-15 14:44:14 +01:00
parent 427f7a7b2e
commit c9490ca528
12 changed files with 105 additions and 43 deletions

View file

@ -0,0 +1,29 @@
# frozen_string_literal: true
module Users
module Settings
class UserSettingsController < ApplicationController
def show
render json: { data: current_user.settings[params[:key]] }
end
def update
settings_params = params.require(:settings)
settings_params.each do |setting|
key = setting[:key]
data = setting[:data]
current_user.settings[key] = data if Extends::WHITELISTED_USER_SETTINGS.include?(key.to_s)
end
if current_user.save
head :ok
else
render json: { error: 'Failed to update settings', details: current_user.errors.full_messages },
status: :unprocessable_entity
end
end
end
end
end

View file

@ -1,7 +1,7 @@
<template>
<DataTable
:columnDefs="columnDefs"
tableId="ExperimentsList"
tableId="ExperimentList"
:dataUrl="dataSource"
:reloadingTable="reloadingTable"
:toolbarActions="toolbarActions"

View file

@ -1,7 +1,7 @@
<template>
<div class="h-full">
<DataTable :columnDefs="columnDefs"
:tableId="'labelTemplates'"
:tableId="'LabelTemplates'"
:dataUrl="dataSource"
:reloadingTable="reloadingTable"
:toolbarActions="toolbarActions"

View file

@ -2,7 +2,7 @@
<DataTable
ref="table"
:columnDefs="columnDefs"
tableId="MyModulesList"
tableId="MyModuleList"
:dataUrl="dataSource"
:reloadingTable="reloadingTable"
:toolbarActions="toolbarActions"

View file

@ -1,6 +1,6 @@
<template>
<DataTable :columnDefs="columnDefs"
tableId="ProjectsList"
tableId="ProjectList"
:dataUrl="dataSource"
:reloadingTable="reloadingTable"
:toolbarActions="toolbarActions"

View file

@ -1,7 +1,7 @@
<template>
<div class="h-full">
<DataTable :columnDefs="columnDefs"
:tableId="'protocolTemplates'"
:tableId="'ProtocolTemplates'"
:dataUrl="dataSource"
:reloadingTable="reloadingTable"
:currentViewMode="currentViewMode"

View file

@ -1,7 +1,7 @@
<template>
<div class="h-full">
<DataTable :columnDefs="columnDefs"
:tableId="'reportTemplates'"
:tableId="'ReportTemplates'"
:dataUrl="dataSource"
:reloadingTable="reloadingTable"
:toolbarActions="toolbarActions"

View file

@ -1,7 +1,7 @@
<template>
<div class="h-full">
<DataTable :columnDefs="columnDefs"
tableId="repositories"
tableId="Repositories"
:dataUrl="dataSource"
:reloadingTable="reloadingTable"
:currentViewMode="currentViewMode"

View file

@ -168,7 +168,9 @@ export default {
currentViewRender: 'table',
cardCheckboxes: [],
dataLoading: true,
lastPage: false
lastPage: false,
tableState: null,
userSettingsUrl: null
};
},
components: {
@ -185,11 +187,6 @@ export default {
perPageOptions() {
return [10, 20, 50, 100].map((value) => ([value, `${value} ${this.i18n.t('datatable.rows')}`]));
},
tableState() {
if (!localStorage.getItem(`datatable:${this.tableId}_columns_state`)) return null;
return JSON.parse(localStorage.getItem(`datatable:${this.tableId}_columns_state`));
},
actionsParams() {
return {
items: JSON.stringify(this.selectedRows.map((row) => ({ id: row.id, type: row.type })))
@ -247,6 +244,9 @@ export default {
}
return columns;
},
stateKey() {
return `${this.tableId}_${this.currentViewMode}_state`;
}
},
watch: {
@ -264,14 +264,8 @@ export default {
this.saveTableState();
}
},
created() {
if (this.tableState) {
this.currentViewRender = this.tableState.currentViewRender || 'table';
this.perPage = this.tableState.perPage || 20;
this.order = this.tableState.order;
}
},
mounted() {
this.userSettingsUrl = document.querySelector('meta[name="user-settings-url"]').getAttribute('content');
this.loadData();
window.addEventListener('resize', this.resize);
},
@ -294,6 +288,39 @@ export default {
this.loadData();
}
},
fetchAndApplyTableState() {
axios
.get(this.userSettingsUrl, {
params: {
key: this.stateKey
}
})
.then((response) => {
if (response.data.data) {
const { currentViewRender, columnsState, perPage, order } = response.data.data;
this.tableState = response.data.data;
this.currentViewRender = currentViewRender;
this.columnsState = columnsState;
this.perPage = perPage;
this.order = order;
if (this.order) {
this.tableState.columnsState.forEach((column) => {
const updatedColumn = column;
updatedColumn.sort = this.order.column === column.colId ? this.order.dir : null;
return updatedColumn;
});
}
this.columnApi.applyColumnState({
state: this.tableState.columnsState,
applyOrder: true
});
}
setTimeout(() => {
this.initializing = false;
}, 200);
});
},
getRowClass() {
if (this.currentViewMode === 'archived') {
return '!bg-sn-light-grey';
@ -370,22 +397,7 @@ export default {
this.gridApi = params.api;
this.columnApi = params.columnApi;
if (this.tableState) {
if (this.order) {
this.tableState.columnsState.forEach((column) => {
const updatedColumn = column;
updatedColumn.sort = this.order.column === column.colId ? this.order.dir : null;
return updatedColumn;
});
}
this.columnApi.applyColumnState({
state: this.tableState.columnsState,
applyOrder: true
});
}
setTimeout(() => {
this.initializing = false;
}, 200);
this.fetchAndApplyTableState();
},
onFirstDataRendered() {
this.resize();
@ -408,17 +420,18 @@ export default {
this.reloadTable();
},
saveTableState() {
let columnsState = this.tableState?.columnsState;
if (this.columnApi) {
columnsState = this.columnApi.getColumnState();
}
const columnsState = this.columnApi ? this.columnApi.getColumnState() : this.tableState?.columnsState || [];
const tableState = {
columnsState: columnsState || [],
columnsState,
order: this.order,
currentViewRender: this.currentViewRender,
perPage: this.perPage
};
localStorage.setItem(`datatable:${this.tableId}_columns_state`, JSON.stringify(tableState));
const settings = {
key: this.stateKey,
data: tableState
};
axios.put(this.userSettingsUrl, { settings: [settings] });
},
setSelectedRows() {
this.selectedRows = this.gridApi.getSelectedRows();

View file

@ -10,6 +10,7 @@
<% if user_signed_in? %>
<meta name="expiration-url" content="<%= users_expire_in_path %>">
<meta name="revive-url" content="<%= users_revive_session_path %>">
<meta name="user-settings-url" content="<%= users_settings_user_settings_path %>">
<% end %>
<%= stylesheet_link_tag "tailwind", "data-turbo-track": "reload" %>
<%= stylesheet_link_tag 'bootstrap_pack', media: 'all' %>

View file

@ -629,6 +629,23 @@ class Extends
in_app: true
}
}
WHITELISTED_USER_SETTINGS = %w(
LabelTemplates_active_state
LabelTemplates_archived_state
ExperimentList_active_state
ExperimentList_archived_state
MyModuleList_active_state
MyModuleList_archived_state
ProjectList_active_state
ProjectList_archived_state
ProtocolTemplates_active_state
ProtocolTemplates_archived_state
ReportTemplates_active_state
ReportTemplates_archived_state
Repositories_active_state
Repositories_archived_state
).freeze
end
# rubocop:enable Style/MutableConstant

View file

@ -136,11 +136,14 @@ Rails.application.routes.draw do
namespace :users do
namespace :settings do
resource :user_settings, only: %i(show update)
resources :teams, only: [] do
collection do
post :switch
end
end
resources :webhooks, only: %i(index create update destroy) do
collection do
post :destroy_filter
@ -150,7 +153,6 @@ Rails.application.routes.draw do
end
end
# Invite users
devise_scope :user do
post '/invite',