Add localstorage support for saving view state

This PR adds support to remember the view state even after the browser
tab has been closed. This helps someone who is always looking at the
table view of a certain topology to which currently they have to perform
a minimum of 2 clicks.

* app view state is backed up in localStorage
* when visiting Scope with no URL view state, the localStorage state is
 used (i.e. the URL state has priority)
This commit is contained in:
David Kaltschmidt
2016-09-06 15:32:06 +02:00
parent 39be421141
commit d9fe7eb32c
2 changed files with 39 additions and 1 deletions

View File

@@ -1,6 +1,7 @@
import page from 'page';
import { route } from '../actions/app-actions';
import { storageGet, storageSet } from './storage-utils';
//
// page.js won't match the routes below if ":state" has a slash in it, so replace those before we
@@ -10,6 +11,7 @@ const SLASH = '/';
const SLASH_REPLACEMENT = '<SLASH>';
const PERCENT = '%';
const PERCENT_REPLACEMENT = '<PERCENT>';
const STORAGE_STATE_KEY = 'scopeViewState';
function encodeURL(url) {
return url
@@ -70,6 +72,9 @@ export function updateRoute(getState) {
.replace('#!/', '') || '{}';
const prevState = JSON.parse(decodeURL(urlStateString));
// back up state in storage as well
storageSet(STORAGE_STATE_KEY, stateUrl);
if (shouldReplaceState(prevState, state)) {
// Replace the top of the history rather than pushing on a new item.
page.replace(`/state/${stateUrl}`, state, dispatch);
@@ -84,7 +89,17 @@ export function getRouter(dispatch, initialState) {
page.base(window.location.pathname.replace(/\/$/, ''));
page('/', () => {
dispatch(route(initialState));
// recover from storage state on empty URL
const storageState = storageGet(STORAGE_STATE_KEY);
if (storageState) {
// push storage state to URL
window.location.hash = `!/state/${storageState}`;
const parsedState = JSON.parse(decodeURL(storageState));
const mergedState = Object.assign(initialState, parsedState);
dispatch(route(mergedState));
} else {
dispatch(route(initialState));
}
});
page('/state/:state', (ctx) => {

View File

@@ -0,0 +1,23 @@
import debug from 'debug';
const log = debug('scope:storage-utils');
// localStorage detection
const storage = typeof(Storage) !== 'undefined' ? window.localStorage : null;
export function storageGet(key, defaultValue) {
if (storage && storage[key] !== undefined) {
return storage.getItem(key);
}
return defaultValue;
}
export function storageSet(key, value) {
if (storage) {
try {
storage.setItem(key, value);
} catch (e) {
log('Error storing value in storage. Maybe full? Could not store key.', key);
}
}
}