Store filter/column settings in localStorage

The filter and column settings in tables are stored per project and
context in the browsers localStorage. This makes the table keep the
settings even if the browser is refreshed or restarted.

The table emits a "componentStateChanged" event containing the tables
current state (filter/column settings) which then is saved by the top
level component.
This commit is contained in:
2019-03-28 10:29:13 +01:00
parent 67d1e05d10
commit a7c1f5aa39
7 changed files with 160 additions and 102 deletions

View File

@@ -13,8 +13,10 @@ const TEMPLATE =`
:project="project"
:selectedIds="selectedIds"
:canChangeSelectionCB="canChangeSelectionCB"
:componentState="initialTableState"
@selectItemsChanged="onSelectItemsChanged"
@isInitialized="onTableInitialized"
@componentStateChanged="onTableStateChanged"
/>
</div>
<div class="col-splitter"/>
@@ -27,6 +29,23 @@ const TEMPLATE =`
</div>
`;
class ComponentState {
/**
* Serializable state of this component.
*
* @param {Object} tableState
*/
constructor(tableState) {
this.tableState = tableState;
}
}
/**
* Component wrapping a table for selecting attract_task/asset/shot nodes, and a editor to edit the selected node(s).
* Selected row filters and visible columns are stored in localStorage per project/context. This makes the settings
* sticky between sessions in the same browser.
* Selected nodes are stored in window.history. This makes it possible to move back/forward in browser and the selection
* will change accordingly.
*/
Vue.component('attract-app', {
template: TEMPLATE,
mixins: [BrowserHistoryState],
@@ -98,7 +117,22 @@ Vue.component('attract-app', {
return `/attract/${projectUrl}/${this.contextType}/${selected._id}`;
}
}
},
stateStorageKey() {
return `attract.${this.projectId}.${this.contextType}`;
},
initialAppState() {
let stateJsonStr;
try {
stateJsonStr = localStorage.getItem(this.stateStorageKey);
} catch (error) {
// Log and ignore.
console.warn('Unable to restore state:', error);
}
return stateJsonStr ? JSON.parse(stateJsonStr) : undefined;
},
initialTableState() {
return this.initialAppState ? this.initialAppState.tableState : undefined;
}
},
watch: {
@@ -127,6 +161,20 @@ Vue.component('attract-app', {
onTableInitialized() {
this.isTableInited = true;
},
/**
* Save table state to localStorage per project and context
* @param {Object} newState
*/
onTableStateChanged(newState) {
let appState = new ComponentState(newState);
let stateJsonStr = JSON.stringify(appState);
try {
localStorage.setItem(this.stateStorageKey, stateJsonStr);
} catch (error) {
// Log and ignore.
console.warn('Unable to save state:', error);
}
},
canChangeSelectionCB() {
if(this.isEditing) {
let retval = confirm("You have unsaved data. Do you want to discard it?");