-
Notifications
You must be signed in to change notification settings - Fork 2
Advanced Routing Panel in "Other" tab #705
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
jacob-xhio
wants to merge
12
commits into
develop
Choose a base branch
from
advanced-routing
base: develop
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
12 commits
Select commit
Hold shift + click to select a range
26188c0
feat(other): advanced routing panel in other tab
jacob-xhio b4bc264
feat(other-advanced): add automatic encode/decode to AppModel
jacob-xhio 4a7852f
fix(other-advanced): implement selective route replacement
jacob-xhio d3f8864
feat(other-adv): provide switch to enable route deactivation prevention
jacob-xhio a6422e3
fix(advanced-routing): relocate code in AppModel, remove extraneous c…
jacob-xhio c521f59
fix(advanced-routing): remove extraneous condition on parseRouteParams
jacob-xhio d1af1a6
fix(advanced-routing): clear query parameters when navigating to othe…
jacob-xhio bd1e1a0
fix(advanced-routing): only clear route parameters when navigating aw…
jacob-xhio 864f023
fix(advanced-routing): preserve state encoding when returning from ot…
jacob-xhio 73a98c3
Merge branch 'develop' into advanced-routing
amcclain efa220a
Tweaks
amcclain 935dce6
Tweaks
amcclain File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
203 changes: 203 additions & 0 deletions
203
client-app/src/desktop/tabs/other/routing/AdvancedRoutingPanel.tsx
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,203 @@ | ||
| import {grid, GridModel} from '@xh/hoist/cmp/grid'; | ||
| import {span} from '@xh/hoist/cmp/layout'; | ||
| import {creates, hoistCmp, HoistModel, XH} from '@xh/hoist/core'; | ||
| import {select, switchInput} from '@xh/hoist/desktop/cmp/input'; | ||
| import {panel} from '@xh/hoist/desktop/cmp/panel'; | ||
| import {action, makeObservable, observable} from '@xh/hoist/mobx'; | ||
| import React from 'react'; | ||
| import {State} from 'router5'; | ||
| import {wrapper} from '../../../common'; | ||
|
|
||
| export const advancedRoutingPanel = hoistCmp.factory({ | ||
| displayName: 'AdvancedRoutingPanel', | ||
| model: creates(() => new AdvancedRoutingPanelModel()), | ||
|
|
||
| render({model}) { | ||
| return wrapper({ | ||
| description: [ | ||
| <p> | ||
| This example demonstrates how to use URL route parameters to store and restore | ||
| the state of a component. The state of the grid (grouping, sorting, and selected | ||
| record) is stored in the URL, and the state is restored when the URL is | ||
| revisited. | ||
| </p>, | ||
| <p> | ||
| Hoist applications are able to navigate to a specific URL and specify whether or | ||
| not to push onto the route history. In this example, selecting individual | ||
| records in the grid will not save the URL to the route history, but changing the{' '} | ||
| <code>groupBy</code> or <code>sortBy</code> fields will. Hoist also provides the | ||
| ability to prevent route deactivation, allowing the developer to present the | ||
| user with a pop-up before navigating away from the current route. | ||
| </p>, | ||
| <p> | ||
| The state is encoded in the URL as a <code>base64</code> string, which is then | ||
| decoded and parsed to restore the state. | ||
| </p>, | ||
| <p> | ||
| The current state encoding is: <br /> | ||
| <br /> | ||
| <code>groupBy: {XH.routerState.params.groupBy || 'None'}</code> | ||
| <br /> | ||
| <code>sortBy: {XH.routerState.params.sortBy || 'None'}</code> | ||
| <br /> | ||
| <code>selectedId: {XH.routerState.params.selectedId || 'None'}</code> | ||
| <br /> | ||
| </p>, | ||
| <p></p> | ||
| ], | ||
| item: panel({ | ||
| ref: model.panelRef, | ||
| mask: 'onLoad', | ||
| item: grid(), | ||
| tbar: [ | ||
| span('Group by:'), | ||
| select({ | ||
| bind: 'groupBy', | ||
| options: [ | ||
| {value: 'city', label: 'City'}, | ||
| {value: 'trade_date', label: 'Trade Date'}, | ||
| {value: 'city,trade_date', label: 'City › Trade Date'}, | ||
| {value: null, label: 'None'} | ||
| ], | ||
| width: 160 | ||
| }), | ||
| span('Sort by:'), | ||
| select({ | ||
| bind: 'sortBy', | ||
| options: [ | ||
| {value: 'id|desc', label: 'Company ID (Desc)'}, | ||
| {value: 'id|asc', label: 'Company ID (Asc)'}, | ||
| {value: 'company|desc', label: 'Company Name (Desc)'}, | ||
| {value: 'company|asc', label: 'Company Name (Asc)'}, | ||
| {value: 'city|desc', label: 'City (Desc)'}, | ||
| {value: 'city|asc', label: 'City (Asc)'}, | ||
| {value: 'trade_date|desc', label: 'Trade Date (Desc)'}, | ||
| {value: 'trade_date|asc', label: 'Trade Date (Asc)'}, | ||
| {value: null, label: 'None'} | ||
| ] | ||
| }), | ||
| switchInput({ | ||
| bind: 'preventDeactivate', | ||
| label: 'Prevent Route Deactivation' | ||
| }) | ||
| ] | ||
| }) | ||
| }); | ||
| } | ||
| }); | ||
|
|
||
| class AdvancedRoutingPanelModel extends HoistModel { | ||
| @observable groupBy = null; | ||
| @observable sortBy = null; | ||
| @observable preventDeactivate = false; | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. make this |
||
| gridModel: GridModel = null; | ||
|
|
||
| constructor() { | ||
| super(); | ||
| makeObservable(this); | ||
|
|
||
| this.gridModel = new GridModel({ | ||
| columns: [ | ||
| {field: 'id'}, | ||
| {field: 'company', flex: 1}, | ||
| {field: 'city', flex: 1}, | ||
| {field: 'trade_date', flex: 1} | ||
| ] | ||
| }); | ||
|
|
||
| this.addReaction( | ||
| { | ||
| track: () => XH.routerState, | ||
| run: (newState, oldState) => this.processRouterState(newState, oldState) | ||
| }, | ||
| { | ||
| track: () => [this.groupBy, this.sortBy, this.gridModel.selectedRecord?.id], | ||
| run: () => this.updateRoute() | ||
| } | ||
| ); | ||
|
|
||
| window.addEventListener('beforeunload', e => { | ||
| if (!XH.routerState.name.startsWith('default.other.advancedRouting')) { | ||
| delete e.returnValue; | ||
| return; | ||
| } | ||
| if (this.preventDeactivate) e.preventDefault(); | ||
| }); | ||
| } | ||
|
|
||
| @action | ||
| private setGroupBy(groupBy: string) { | ||
| this.groupBy = groupBy; | ||
|
|
||
| const groupByArr = groupBy ? groupBy.split(',') : []; | ||
| this.gridModel.setGroupBy(groupByArr); | ||
| } | ||
|
|
||
| @action | ||
| private setSortBy(sortBy: string) { | ||
| this.sortBy = sortBy; | ||
|
|
||
| const sortByArr = sortBy ? sortBy.split(',') : []; | ||
| this.gridModel.setSortBy(sortByArr); | ||
| } | ||
|
|
||
| @action | ||
| private async setSelected(recordId: string | number) { | ||
| await this.gridModel.selectAsync(Number(recordId)); | ||
| if (!this.gridModel.selectedId) { | ||
| XH.dangerToast(`Record ${recordId} not found`); | ||
| } | ||
| } | ||
|
|
||
| @action | ||
| private setPreventDeactivate(preventDeactivate: boolean) { | ||
| this.preventDeactivate = preventDeactivate; | ||
| } | ||
|
|
||
| @action | ||
| private async parseRouteParams() { | ||
| const {groupBy, sortBy, selectedId} = XH.routerState.params; | ||
| if (groupBy) this.setGroupBy(groupBy); | ||
| if (sortBy) this.setSortBy(sortBy); | ||
| if (selectedId) await this.setSelected(selectedId); | ||
| } | ||
|
|
||
| @action | ||
| private async processRouterState(newState?: State, oldState?: State) { | ||
| if ( | ||
| !newState.name.startsWith('default.other.advancedRouting') && | ||
| oldState.name.startsWith('default.other.advancedRouting') | ||
| ) | ||
| return XH.navigate(newState.name, null, {replace: true}); | ||
| else if ( | ||
| newState.name.startsWith('default.other.advancedRouting') && | ||
| !oldState.name.startsWith('default.other.advancedRouting') | ||
| ) | ||
| this.updateRoute(); | ||
| else if (newState.name.startsWith('default.other.advancedRouting')) | ||
| await this.parseRouteParams(); | ||
| } | ||
|
|
||
| @action | ||
| private updateRoute() { | ||
| if ( | ||
| XH.routerState.name.startsWith('default.other.advancedRouting') && | ||
| !this.gridModel.empty | ||
| ) { | ||
| const {groupBy, sortBy} = this; | ||
| const selectedId = this.gridModel.selectedRecord?.id; | ||
| XH.navigate( | ||
| 'default.other.advancedRouting', | ||
| {groupBy, sortBy, selectedId}, | ||
| // Only push URL to route history if groupBy or sortBy changes. | ||
| {replace: selectedId != XH.routerState.params.selectedId} | ||
| ); | ||
| } | ||
| } | ||
|
|
||
| override async doLoadAsync(loadSpec) { | ||
| const {trades} = await XH.fetchJson({url: 'trade'}); | ||
| this.gridModel.loadData(trades); | ||
| await this.parseRouteParams(); | ||
| } | ||
| } | ||
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.