HistoryStore for tracking relevant routes (#4305)
* HistoryStore for tracking relevant routes * Default route is still /accounts * Fix copyright date-merge issue
This commit is contained in:
		
							parent
							
								
									3e2d95b272
								
							
						
					
					
						commit
						7f3b1bd31e
					
				| @ -16,11 +16,15 @@ | |||||||
| 
 | 
 | ||||||
| import { | import { | ||||||
|   Accounts, Account, Addresses, Address, Application, |   Accounts, Account, Addresses, Address, Application, | ||||||
|   Contract, Contracts, Dapp, Dapps, |   Contract, Contracts, Dapp, Dapps, HistoryStore, | ||||||
|   Settings, SettingsBackground, SettingsParity, SettingsProxy, |   Settings, SettingsBackground, SettingsParity, SettingsProxy, | ||||||
|   SettingsViews, Signer, Status, |   SettingsViews, Signer, Status, | ||||||
|   Wallet, Web, WriteContract |   Wallet, Web, WriteContract | ||||||
| } from '~/views'; | } from '~/views'; | ||||||
|  | import builtinDapps from '~/views/Dapps/builtin.json'; | ||||||
|  | 
 | ||||||
|  | const accountsHistory = HistoryStore.get('accounts'); | ||||||
|  | const dappsHistory = HistoryStore.get('dapps'); | ||||||
| 
 | 
 | ||||||
| function handleDeprecatedRoute (nextState, replace) { | function handleDeprecatedRoute (nextState, replace) { | ||||||
|   const { address } = nextState.params; |   const { address } = nextState.params; | ||||||
| @ -46,7 +50,13 @@ function redirectTo (path) { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| const accountsRoutes = [ | const accountsRoutes = [ | ||||||
|   { path: ':address', component: Account }, |   { | ||||||
|  |     path: ':address', | ||||||
|  |     component: Account, | ||||||
|  |     onEnter: ({ params }) => { | ||||||
|  |       accountsHistory.add(params.address); | ||||||
|  |     } | ||||||
|  |   }, | ||||||
|   { path: '/wallet/:address', component: Wallet } |   { path: '/wallet/:address', component: Wallet } | ||||||
| ]; | ]; | ||||||
| 
 | 
 | ||||||
| @ -81,7 +91,7 @@ const routes = [ | |||||||
|   { path: '/settings', onEnter: redirectTo('/settings/views') } |   { path: '/settings', onEnter: redirectTo('/settings/views') } | ||||||
| ]; | ]; | ||||||
| 
 | 
 | ||||||
| const appRoutes = [ | const childRoutes = [ | ||||||
|   { |   { | ||||||
|     path: 'accounts', |     path: 'accounts', | ||||||
|     indexRoute: { component: Accounts }, |     indexRoute: { component: Accounts }, | ||||||
| @ -107,9 +117,16 @@ const appRoutes = [ | |||||||
|     component: Settings, |     component: Settings, | ||||||
|     childRoutes: settingsRoutes |     childRoutes: settingsRoutes | ||||||
|   }, |   }, | ||||||
| 
 |   { | ||||||
|  |     path: 'app/:id', | ||||||
|  |     component: Dapp, | ||||||
|  |     onEnter: ({ params }) => { | ||||||
|  |       if (!builtinDapps[params.id] || !builtinDapps[params.id].skipHistory) { | ||||||
|  |         dappsHistory.add(params.id); | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |   }, | ||||||
|   { path: 'apps', component: Dapps }, |   { path: 'apps', component: Dapps }, | ||||||
|   { path: 'app/:id', component: Dapp }, |  | ||||||
|   { path: 'web', component: Web }, |   { path: 'web', component: Web }, | ||||||
|   { path: 'web/:url', component: Web }, |   { path: 'web/:url', component: Web }, | ||||||
|   { path: 'signer', component: Signer } |   { path: 'signer', component: Signer } | ||||||
| @ -119,7 +136,7 @@ const appRoutes = [ | |||||||
| if (process.env.NODE_ENV !== 'production') { | if (process.env.NODE_ENV !== 'production') { | ||||||
|   const Playground = require('./playground').default; |   const Playground = require('./playground').default; | ||||||
| 
 | 
 | ||||||
|   appRoutes.push({ |   childRoutes.push({ | ||||||
|     path: 'playground', |     path: 'playground', | ||||||
|     component: Playground |     component: Playground | ||||||
|   }); |   }); | ||||||
| @ -128,7 +145,7 @@ if (process.env.NODE_ENV !== 'production') { | |||||||
| routes.push({ | routes.push({ | ||||||
|   path: '/', |   path: '/', | ||||||
|   component: Application, |   component: Application, | ||||||
|   childRoutes: appRoutes |   childRoutes | ||||||
| }); | }); | ||||||
| 
 | 
 | ||||||
| export default routes; | export default routes; | ||||||
|  | |||||||
| @ -72,7 +72,8 @@ | |||||||
|     "author": "Parity Team <admin@ethcore.io>", |     "author": "Parity Team <admin@ethcore.io>", | ||||||
|     "version": "1.0.0", |     "version": "1.0.0", | ||||||
|     "visible": true, |     "visible": true, | ||||||
|     "skipBuild": true |     "skipBuild": true, | ||||||
|  |     "skipHistory": true | ||||||
|   }, |   }, | ||||||
|   { |   { | ||||||
|     "id": "0xa635a9326814bded464190eddf0bdb90ce92d40ea2359cf553ea80e3c5a4076c", |     "id": "0xa635a9326814bded464190eddf0bdb90ce92d40ea2359cf553ea80e3c5a4076c", | ||||||
|  | |||||||
							
								
								
									
										61
									
								
								js/src/views/historyStore.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										61
									
								
								js/src/views/historyStore.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,61 @@ | |||||||
|  | // Copyright 2015-2017 Parity Technologies (UK) Ltd.
 | ||||||
|  | // This file is part of Parity.
 | ||||||
|  | 
 | ||||||
|  | // Parity is free software: you can redistribute it and/or modify
 | ||||||
|  | // it under the terms of the GNU General Public License as published by
 | ||||||
|  | // the Free Software Foundation, either version 3 of the License, or
 | ||||||
|  | // (at your option) any later version.
 | ||||||
|  | 
 | ||||||
|  | // Parity is distributed in the hope that it will be useful,
 | ||||||
|  | // but WITHOUT ANY WARRANTY; without even the implied warranty of
 | ||||||
|  | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | ||||||
|  | // GNU General Public License for more details.
 | ||||||
|  | 
 | ||||||
|  | // You should have received a copy of the GNU General Public License
 | ||||||
|  | // along with Parity.  If not, see <http://www.gnu.org/licenses/>.
 | ||||||
|  | 
 | ||||||
|  | import { action, observable } from 'mobx'; | ||||||
|  | import localStore from 'store'; | ||||||
|  | 
 | ||||||
|  | const LS_KEY = '_parity::history'; | ||||||
|  | const MAX_ENTRIES = 5; | ||||||
|  | 
 | ||||||
|  | const instances = {}; | ||||||
|  | 
 | ||||||
|  | export default class Store { | ||||||
|  |   @observable history = []; | ||||||
|  | 
 | ||||||
|  |   constructor (type) { | ||||||
|  |     this.historyKey = `${LS_KEY}::${type}`; | ||||||
|  |     this.load(); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   @action add = (entry) => { | ||||||
|  |     this.history = [{ | ||||||
|  |       timestamp: Date.now(), | ||||||
|  |       entry | ||||||
|  |     }].concat(this.history.filter((h) => h.entry !== entry)).slice(0, MAX_ENTRIES); | ||||||
|  |     this.save(); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   @action clear = () => { | ||||||
|  |     this.history = []; | ||||||
|  |     this.save(); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   @action load = () => { | ||||||
|  |     this.history = localStore.get(this.historyKey) || []; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   save = () => { | ||||||
|  |     return localStore.set(this.historyKey, this.history); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   static get (type) { | ||||||
|  |     if (!instances[type]) { | ||||||
|  |       instances[type] = new Store(type); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     return instances[type]; | ||||||
|  |   } | ||||||
|  | } | ||||||
							
								
								
									
										71
									
								
								js/src/views/historyStore.spec.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										71
									
								
								js/src/views/historyStore.spec.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,71 @@ | |||||||
|  | // Copyright 2015-2017 Parity Technologies (UK) Ltd.
 | ||||||
|  | // This file is part of Parity.
 | ||||||
|  | 
 | ||||||
|  | // Parity is free software: you can redistribute it and/or modify
 | ||||||
|  | // it under the terms of the GNU General Public License as published by
 | ||||||
|  | // the Free Software Foundation, either version 3 of the License, or
 | ||||||
|  | // (at your option) any later version.
 | ||||||
|  | 
 | ||||||
|  | // Parity is distributed in the hope that it will be useful,
 | ||||||
|  | // but WITHOUT ANY WARRANTY; without even the implied warranty of
 | ||||||
|  | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | ||||||
|  | // GNU General Public License for more details.
 | ||||||
|  | 
 | ||||||
|  | // You should have received a copy of the GNU General Public License
 | ||||||
|  | // along with Parity.  If not, see <http://www.gnu.org/licenses/>.
 | ||||||
|  | 
 | ||||||
|  | import Store from './historyStore'; | ||||||
|  | 
 | ||||||
|  | const TEST_ENTRY_1 = 'testing 1'; | ||||||
|  | const TEST_ENTRY_2 = 'testing 2'; | ||||||
|  | const TEST_ENTRY_3 = 'testing 3'; | ||||||
|  | 
 | ||||||
|  | let store; | ||||||
|  | 
 | ||||||
|  | function create () { | ||||||
|  |   store = Store.get('test'); | ||||||
|  |   store.clear(); | ||||||
|  | 
 | ||||||
|  |   return store; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | describe('views/HistoryStore', () => { | ||||||
|  |   beforeEach(() => { | ||||||
|  |     create(); | ||||||
|  |   }); | ||||||
|  | 
 | ||||||
|  |   describe('@action', () => { | ||||||
|  |     describe('add', () => { | ||||||
|  |       it('adds the url to the list (front)', () => { | ||||||
|  |         store.add(TEST_ENTRY_1); | ||||||
|  |         expect(store.history[0].entry).to.equal(TEST_ENTRY_1); | ||||||
|  |       }); | ||||||
|  | 
 | ||||||
|  |       it('adds multiples to the list', () => { | ||||||
|  |         store.add(TEST_ENTRY_1); | ||||||
|  |         store.add(TEST_ENTRY_2); | ||||||
|  | 
 | ||||||
|  |         expect(store.history.length).to.equal(2); | ||||||
|  |         expect(store.history[0].entry).to.equal(TEST_ENTRY_2); | ||||||
|  |         expect(store.history[1].entry).to.equal(TEST_ENTRY_1); | ||||||
|  |       }); | ||||||
|  | 
 | ||||||
|  |       it('does not add duplicates', () => { | ||||||
|  |         store.add(TEST_ENTRY_2); | ||||||
|  |         store.add(TEST_ENTRY_2); | ||||||
|  | 
 | ||||||
|  |         expect(store.history.length).to.equal(1); | ||||||
|  |         expect(store.history[0].entry).to.equal(TEST_ENTRY_2); | ||||||
|  |       }); | ||||||
|  |     }); | ||||||
|  | 
 | ||||||
|  |     describe('clear', () => { | ||||||
|  |       it('empties the list', () => { | ||||||
|  |         store.add(TEST_ENTRY_3); | ||||||
|  |         store.clear(); | ||||||
|  | 
 | ||||||
|  |         expect(store.history.length).to.equal(0); | ||||||
|  |       }); | ||||||
|  |     }); | ||||||
|  |   }); | ||||||
|  | }); | ||||||
| @ -21,15 +21,16 @@ import Addresses from './Addresses'; | |||||||
| import Application from './Application'; | import Application from './Application'; | ||||||
| import Contract from './Contract'; | import Contract from './Contract'; | ||||||
| import Contracts from './Contracts'; | import Contracts from './Contracts'; | ||||||
| import WriteContract from './WriteContract'; |  | ||||||
| import Dapp from './Dapp'; | import Dapp from './Dapp'; | ||||||
| import Web from './Web'; |  | ||||||
| import Dapps from './Dapps'; | import Dapps from './Dapps'; | ||||||
|  | import HistoryStore from './historyStore'; | ||||||
| import ParityBar from './ParityBar'; | import ParityBar from './ParityBar'; | ||||||
| import Settings, { SettingsBackground, SettingsParity, SettingsProxy, SettingsViews } from './Settings'; | import Settings, { SettingsBackground, SettingsParity, SettingsProxy, SettingsViews } from './Settings'; | ||||||
| import Signer from './Signer'; | import Signer from './Signer'; | ||||||
| import Status from './Status'; | import Status from './Status'; | ||||||
| import Wallet from './Wallet'; | import Wallet from './Wallet'; | ||||||
|  | import Web from './Web'; | ||||||
|  | import WriteContract from './WriteContract'; | ||||||
| 
 | 
 | ||||||
| export { | export { | ||||||
|   Account, |   Account, | ||||||
| @ -39,9 +40,9 @@ export { | |||||||
|   Application, |   Application, | ||||||
|   Contract, |   Contract, | ||||||
|   Contracts, |   Contracts, | ||||||
|   WriteContract, |  | ||||||
|   Dapp, |   Dapp, | ||||||
|   Dapps, |   Dapps, | ||||||
|  |   HistoryStore, | ||||||
|   ParityBar, |   ParityBar, | ||||||
|   Settings, |   Settings, | ||||||
|   SettingsBackground, |   SettingsBackground, | ||||||
| @ -51,5 +52,6 @@ export { | |||||||
|   Signer, |   Signer, | ||||||
|   Status, |   Status, | ||||||
|   Wallet, |   Wallet, | ||||||
|   Web |   Web, | ||||||
|  |   WriteContract | ||||||
| }; | }; | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user