1
0
mirror of https://github.com/ascribe/onion.git synced 2024-12-22 17:33:14 +01:00

Add first cut on persistent stores

This commit is contained in:
Tim Daubenschütz 2015-10-29 17:15:26 +01:00
parent c7ef23ee40
commit bed067f9bc
6 changed files with 151 additions and 9 deletions

View File

@ -3,6 +3,8 @@
import { altUser } from '../alt'; import { altUser } from '../alt';
import UserFetcher from '../fetchers/user_fetcher'; import UserFetcher from '../fetchers/user_fetcher';
import UserStore from '../stores/user_store';
class UserActions { class UserActions {
constructor() { constructor() {
@ -23,6 +25,19 @@ class UserActions {
}); });
} }
/*fetchCurrentUser() {
if(UserStore.getState().currentUser && !UserStore.getState().currentUser.email) {
UserFetcher.fetchOne()
.then((res) => {
this.actions.updateCurrentUser(res.users[0]);
})
.catch((err) => {
console.logGlobal(err);
this.actions.updateCurrentUser({});
});
}
}*/
logoutCurrentUser() { logoutCurrentUser() {
UserFetcher.logout() UserFetcher.logout()
.then(() => { .then(() => {

View File

@ -0,0 +1,98 @@
'use strict';
import { sanitize } from '../utils/general_utils';
/**
* A tiny wrapper around HTML5's `webStorage`,
* to enable saving JSON objects directly into `webStorage`
*/
export default class AscribeStorage {
/**
* @param {String} `name` A unique storage name
*/
constructor(type, name) {
if(type === 'localStorage' || type === 'sessionStorage') {
this.storage = window[type];
} else {
throw new Error('"type" can only be either "localStorage" or "sessionStorage"');
}
this.name = name;
}
/**
* Private method, do not use from the outside.
* Constructs a unique identifier for a item in the global `webStorage`,
* by appending the `ÀscribeStorage`'s name
* @param {string} key A unique identifier
* @return {string} A globally unique identifier for a value in `webStorage`
*/
_constructStorageKey(key) {
return `${this.name}-${key}`;
}
_deconstructStorageKey(key) {
return key.replace(`${this.name}-`, '');
}
/**
* Saves a JSON-serializeble object or a string into `webStorage`
* @param {string} key Used as a unique identifier
* @param {oneOfType([String, object])} value Either JSON-serializeble or a string
*/
setItem(key, value) {
// We're "try-catching" errors in this method ourselves, to be able to
// yield more readable error messages
if(!key || !value) {
throw new Error('"key" or "value" cannot be "falsy" values');
} else if(typeof value === 'string') {
// since `value` is a string, we can directly write
// it into `this.storage`
this.storage.setItem(this._constructStorageKey(key), value);
} else {
// if `value` is not a string, we need to JSON-serialize it and then
// put it into `this.storage`
let serializedValue;
try {
serializedValue = JSON.stringify(value);
} catch(err) {
throw new Error('You didn\'t pass valid JSON as "value" into setItem.');
}
try {
this.storage.setItem(this._constructStorageKey(key), serializedValue);
} catch(err) {
throw new Error('Failure saving a "serializedValue" in setItem');
}
}
}
getItem(key) {
let deserializedValue;
const serializedValue = this.storage.getItem(this._constructStorageKey(key));
try {
deserializedValue = JSON.parse(serializedValue);
} catch(err) {
deserializedValue = serializedValue;
}
return deserializedValue;
}
toObject() {
let obj = {};
const storageCopy = JSON.parse(JSON.stringify(this.storage));
const sanitizedStore = sanitize(storageCopy, s => !s.match(`${this.name}-`), true);
Object
.keys(sanitizedStore)
.forEach((key) => {
obj[this._deconstructStorageKey(key)] = JSON.parse(sanitizedStore[key]);
});
return obj;
}
}

View File

@ -0,0 +1,21 @@
'use strict';
import AscribeStorage from '../models/ascribe_storage';
export default class SessionPersistentStore extends AscribeStorage {
constructor(name) {
super('sessionStorage', name);
}
setItem(key, value) {
this[key] = value;
super.setItem(key, value);
}
}
SessionPersistentStore.config = {
getState() {
return new AscribeStorage('sessionStorage', this.displayName).toObject();
}
};

View File

@ -3,15 +3,21 @@
import { altUser } from '../alt'; import { altUser } from '../alt';
import UserActions from '../actions/user_actions'; import UserActions from '../actions/user_actions';
import SessionPersistentStore from './session_persistent_store';
class UserStore { // import AscribeStorage from '../models/ascribe_storage';
// import { sessionStorageAvailable } from '../utils/feature_detection_utils';
class UserStore extends SessionPersistentStore {
constructor() { constructor() {
super('UserStore');
this.currentUser = {}; this.currentUser = {};
this.bindActions(UserActions); this.bindActions(UserActions);
} }
onUpdateCurrentUser(user) { onUpdateCurrentUser(user) {
this.currentUser = user; this.setItem('currentUser', user);
} }
onDeleteCurrentUser() { onDeleteCurrentUser() {
this.currentUser = {}; this.currentUser = {};

View File

@ -51,11 +51,8 @@ function storageAvailable(type) {
} }
/** /**
* Function detects whether sessionStorage is both supported * Const that detects whether sessionStorage is both supported
* and available. * and available.
* @return {bool} Is sessionStorage available on this browser
*/ */
export function sessionStorageAvailable() { export const sessionStorageAvailable = storageAvailable('sessionStorage');
return storageAvailable('sessionStorage');
}

View File

@ -6,9 +6,12 @@
* tagged as false by the passed in filter function * tagged as false by the passed in filter function
* *
* @param {object} obj regular javascript object * @param {object} obj regular javascript object
* @param {function} filterFn a filter function for filtering either by key or value
* @param {bool} filterByKey a boolean for choosing whether the object should be filtered by
* key or value
* @return {object} regular javascript object without null values or empty strings * @return {object} regular javascript object without null values or empty strings
*/ */
export function sanitize(obj, filterFn) { export function sanitize(obj, filterFn, filterByKey) {
if(!filterFn) { if(!filterFn) {
// By matching null with a double equal, we can match undefined and null // By matching null with a double equal, we can match undefined and null
// http://stackoverflow.com/a/15992131 // http://stackoverflow.com/a/15992131
@ -18,7 +21,9 @@ export function sanitize(obj, filterFn) {
Object Object
.keys(obj) .keys(obj)
.map((key) => { .map((key) => {
if(filterFn(obj[key])) { const filterCondition = filterByKey ? filterFn(key) : filterFn(obj[key]);
if(filterCondition) {
delete obj[key]; delete obj[key];
} }
}); });