1 | import Cookie from '../cookie';
|
2 | import {root} from '../root';
|
3 |
|
4 | const JSON = root.JSON;
|
5 | const localStorage = root.localStorage;
|
6 | const location = root.location;
|
7 |
|
8 | /**
|
9 | * Checks if browser has Storage feature
|
10 | */
|
11 | export const hasStorage = () => {
|
12 | return 'Storage' in root;
|
13 | };
|
14 |
|
15 | /**
|
16 | * Stores the features state in browser's local storage or cookie
|
17 | *
|
18 | * @export
|
19 | * @class Storage
|
20 | */
|
21 | export class Storage {
|
22 |
|
23 | /**
|
24 | * Creates an instance of Storage
|
25 | *
|
26 | * @param {State} state Instance of State
|
27 | */
|
28 | constructor(state) {
|
29 |
|
30 | /**
|
31 | * State object
|
32 | * @type {State}
|
33 | * @private
|
34 | */
|
35 | this.state = state;
|
36 |
|
37 | /**
|
38 | * TableFilter object
|
39 | * @type {TableFilter}
|
40 | * @private
|
41 | */
|
42 | this.tf = state.tf;
|
43 |
|
44 | /**
|
45 | * Persist with local storage
|
46 | * @type {Boolean}
|
47 | * @private
|
48 | */
|
49 | this.enableLocalStorage = state.enableLocalStorage && hasStorage();
|
50 |
|
51 | /**
|
52 | * Persist with cookie
|
53 | * @type {Boolean}
|
54 | * @private
|
55 | */
|
56 | this.enableCookie = state.enableCookie && !this.enableLocalStorage;
|
57 |
|
58 | /**
|
59 | * Emitter object
|
60 | * @type {Emitter}
|
61 | * @private
|
62 | */
|
63 | this.emitter = state.emitter;
|
64 |
|
65 | /**
|
66 | * Cookie duration in hours from state object
|
67 | * @type {Number}
|
68 | * @private
|
69 | */
|
70 | this.duration = state.cookieDuration;
|
71 | }
|
72 |
|
73 |
|
74 | /**
|
75 | * Initializes the Storage object
|
76 | */
|
77 | init() {
|
78 | this.emitter.on(['state-changed'], (tf, state) => this.save(state));
|
79 | this.emitter.on(['initialized'], () => this.sync());
|
80 | }
|
81 |
|
82 | /**
|
83 | * Persists the features state on state changes
|
84 | *
|
85 | * @param {State} state Instance of State
|
86 | */
|
87 | save(state) {
|
88 | if (this.enableLocalStorage) {
|
89 | localStorage[this.getKey()] = JSON.stringify(state);
|
90 | } else {
|
91 | Cookie.write(this.getKey(), JSON.stringify(state), this.duration);
|
92 | }
|
93 | }
|
94 |
|
95 | /**
|
96 | * Turns stored string into a State JSON object
|
97 | *
|
98 | * @returns {Object} JSON object
|
99 | */
|
100 | retrieve() {
|
101 | let state = null;
|
102 | if (this.enableLocalStorage) {
|
103 | state = localStorage[this.getKey()];
|
104 | } else {
|
105 | state = Cookie.read(this.getKey());
|
106 | }
|
107 |
|
108 | if (!state) {
|
109 | return null;
|
110 | }
|
111 | return JSON.parse(state);
|
112 | }
|
113 |
|
114 | /**
|
115 | * Removes persisted state from storage
|
116 | */
|
117 | remove() {
|
118 | if (this.enableLocalStorage) {
|
119 | localStorage.removeItem(this.getKey());
|
120 | } else {
|
121 | Cookie.remove(this.getKey());
|
122 | }
|
123 | }
|
124 |
|
125 | /**
|
126 | * Applies persisted state to features
|
127 | */
|
128 | sync() {
|
129 | let state = this.retrieve();
|
130 | if (!state) {
|
131 | return;
|
132 | }
|
133 | // override current state with persisted one and sync features
|
134 | this.state.overrideAndSync(state);
|
135 | }
|
136 |
|
137 | /**
|
138 | * Returns the storage key
|
139 | *
|
140 | * @returns {String} Key
|
141 | */
|
142 | getKey() {
|
143 | return JSON.stringify({
|
144 | key: `${this.tf.prfxTf}_${this.tf.id}`,
|
145 | path: location.pathname
|
146 | });
|
147 | }
|
148 |
|
149 | /**
|
150 | * Release Storage event subscriptions and clear fields
|
151 | */
|
152 | destroy() {
|
153 | this.emitter.off(['state-changed'], (tf, state) => this.save(state));
|
154 | this.emitter.off(['initialized'], () => this.sync());
|
155 |
|
156 | this.remove();
|
157 |
|
158 | this.state = null;
|
159 | this.emitter = null;
|
160 | }
|
161 | }
|