dash-core-components
Version:
Core component suite for Dash
212 lines (207 loc) • 6.03 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _ramda = require("ramda");
var _react = _interopRequireDefault(require("react"));
var _propTypes = _interopRequireDefault(require("prop-types"));
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
/**
* Abstraction for the memory storage_type to work the same way as local/session
*
* Each memory Store component get it's own MemStore.
*/
class MemStore {
constructor() {
this._data = {};
this._modified = -1;
}
getItem(key) {
return this._data[key];
}
setItem(key, value) {
this._data[key] = value;
this.setModified(key);
}
removeItem(key) {
delete this._data[key];
this.setModified(key);
}
// noinspection JSUnusedLocalSymbols
setModified(_) {
this._modified = Date.now();
}
// noinspection JSUnusedLocalSymbols
getModified(_) {
return this._modified;
}
}
/**
* Abstraction for local/session storage_type.
*
* Single instances for localStorage, sessionStorage
*/
class WebStore {
constructor(storage) {
this._storage = storage;
}
getItem(key) {
try {
return JSON.parse(this._storage.getItem(key));
} catch (e) {
// in case we somehow got a non-JSON value in storage,
// just ignore it.
return null;
}
}
setItem(key, value) {
this._storage.setItem(key, JSON.stringify(value));
this.setModified(key);
}
removeItem(key) {
this._storage.removeItem(key);
this._storage.removeItem("".concat(key, "-timestamp"));
}
setModified(key) {
this._storage.setItem("".concat(key, "-timestamp"), Date.now());
}
getModified(key) {
return Number.parseInt(this._storage.getItem("".concat(key, "-timestamp")), 10) || -1;
}
}
/**
* Easily keep data on the client side with this component.
* The data is not inserted in the DOM.
* Data can be in memory, localStorage or sessionStorage.
* The data will be kept with the id as key.
*/
class Store extends _react.default.Component {
constructor(props) {
super(props);
if (props.storage_type === 'local') {
this._backstore = new WebStore(window.localStorage);
} else if (props.storage_type === 'session') {
this._backstore = new WebStore(window.sessionStorage);
} else if (props.storage_type === 'memory') {
this._backstore = new MemStore();
}
this.onStorageChange = this.onStorageChange.bind(this);
}
onStorageChange(e) {
var _this$props = this.props,
id = _this$props.id,
setProps = _this$props.setProps;
if (e.key === id && setProps && e.newValue !== e.oldValue) {
setProps({
data: JSON.parse(e.newValue),
modified_timestamp: this._backstore.getModified(id)
});
}
}
UNSAFE_componentWillMount() {
var _this$props2 = this.props,
setProps = _this$props2.setProps,
id = _this$props2.id,
data = _this$props2.data,
storage_type = _this$props2.storage_type;
if (storage_type !== 'memory') {
window.addEventListener('storage', this.onStorageChange);
}
var old = this._backstore.getItem(id);
if ((0, _ramda.isNil)(old) && !(0, _ramda.isNil)(data)) {
// Initial data mount
this._backstore.setItem(id, data);
setProps({
modified_timestamp: this._backstore.getModified(id)
});
return;
}
if (!(0, _ramda.equals)(old, data)) {
setProps({
data: old,
modified_timestamp: this._backstore.getModified(id)
});
}
}
componentWillUnmount() {
if (this.props.storage_type !== 'memory') {
window.removeEventListener('storage', this.onStorageChange);
}
}
componentDidUpdate() {
var _this$props3 = this.props,
data = _this$props3.data,
id = _this$props3.id,
clear_data = _this$props3.clear_data,
setProps = _this$props3.setProps;
if (clear_data) {
this._backstore.removeItem(id);
setProps({
clear_data: false,
data: null,
modified_timestamp: this._backstore.getModified(id)
});
return;
}
var old = this._backstore.getItem(id);
// Only set the data if it's not the same data.
// If the new data is undefined, we got here by overwriting the entire
// component with a new copy that has no `data` specified - so pull back
// out the old value.
// Note: this still allows you to set data to null
if (!(0, _ramda.equals)(data, old)) {
if (data === undefined) {
setProps({
data: old
});
} else {
this._backstore.setItem(id, data);
setProps({
modified_timestamp: this._backstore.getModified(id)
});
}
}
}
render() {
return null;
}
}
exports.default = Store;
Store.defaultProps = {
storage_type: 'memory',
clear_data: false,
modified_timestamp: -1
};
Store.propTypes = {
/**
* The ID of this component, used to identify dash components
* in callbacks. The ID needs to be unique across all of the
* components in an app.
*/
id: _propTypes.default.string.isRequired,
/**
* The type of the web storage.
*
* memory: only kept in memory, reset on page refresh.
* local: window.localStorage, data is kept after the browser quit.
* session: window.sessionStorage, data is cleared once the browser quit.
*/
storage_type: _propTypes.default.oneOf(['local', 'session', 'memory']),
/**
* The stored data for the id.
*/
data: _propTypes.default.oneOfType([_propTypes.default.object, _propTypes.default.array, _propTypes.default.number, _propTypes.default.string, _propTypes.default.bool]),
/**
* Set to true to remove the data contained in `data_key`.
*/
clear_data: _propTypes.default.bool,
/**
* The last time the storage was modified.
*/
modified_timestamp: _propTypes.default.number,
/**
* Dash-assigned callback that gets fired when the value changes.
*/
setProps: _propTypes.default.func
};