-
Notifications
You must be signed in to change notification settings - Fork 1
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
Persistence Manager #733
base: develop
Are you sure you want to change the base?
Persistence Manager #733
Changes from 2 commits
c4355ea
b39e1d2
40150c7
d26f88d
4075725
69be4ce
560d1ec
da6715d
e925b41
4d4e13d
7ce8105
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,18 +1,29 @@ | ||
import {hframe} from '@xh/hoist/cmp/layout'; | ||
import {creates, hoistCmp} from '@xh/hoist/core'; | ||
import {panel} from '@xh/hoist/desktop/cmp/panel'; | ||
import {toolbar} from '@xh/hoist/desktop/cmp/toolbar'; | ||
import {detailPanel} from './detail/DetailPanel'; | ||
import {gridPanel} from './GridPanel'; | ||
import {mapPanel} from './MapPanel'; | ||
import {PortfolioPanelModel} from './PortfolioPanelModel'; | ||
import {persistenceManager} from '@xh/hoist/desktop/cmp/persistenceManager'; | ||
|
||
export const portfolioPanel = hoistCmp.factory({ | ||
model: creates(PortfolioPanelModel), | ||
|
||
render() { | ||
return panel({ | ||
tbar: tbar(), | ||
mask: 'onLoad', | ||
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. Probably want to mask while the |
||
items: [hframe(gridPanel(), mapPanel()), detailPanel()] | ||
}); | ||
} | ||
}); | ||
|
||
const tbar = hoistCmp.factory<PortfolioPanelModel>({ | ||
render() { | ||
return toolbar({ | ||
item: persistenceManager() | ||
}); | ||
} | ||
}); |
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. In general, this is an annoying amount of boilerplate you had to write! I wonder if there'd be a way to generalize this and build a higher order component / model to avoid some of this. Just brainstorming - what if the Sorry for the flight of ideas - will think more on this, and maybe we can brainstorm together. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,18 +1,27 @@ | ||
import {HoistModel, managed, XH} from '@xh/hoist/core'; | ||
import {Store} from '@xh/hoist/data'; | ||
import {logInfo} from '@xh/hoist/utils/js'; | ||
import {GridPanelModel} from './GridPanelModel'; | ||
import {round} from 'lodash'; | ||
import {GroupingChooserModel} from '@xh/hoist/cmp/grouping'; | ||
import {PERSIST_MAIN} from './AppModel'; | ||
import {waitFor} from '@xh/hoist/promise'; | ||
import {wait, waitFor} from '@xh/hoist/promise'; | ||
import {SECONDS} from '@xh/hoist/utils/datetime'; | ||
import {PersistenceManagerModel} from '@xh/hoist/desktop/cmp/persistenceManager'; | ||
import {DetailPanelModel} from './detail/DetailPanelModel'; | ||
import {runInAction} from '@xh/hoist/mobx'; | ||
|
||
export class PortfolioPanelModel extends HoistModel { | ||
@managed session; | ||
|
||
@managed groupingChooserModel = this.createGroupingChooserModel(); | ||
@managed persistenceManagerModel: PersistenceManagerModel; | ||
@managed groupingChooserModel: GroupingChooserModel; | ||
@managed store = this.createStore(); | ||
@managed gridPanelModel = new GridPanelModel({parentModel: this}); | ||
@managed gridPanelModel: GridPanelModel; | ||
@managed detailPanelModel: DetailPanelModel; | ||
|
||
get prefKey(): string { | ||
return 'portfolioExample'; | ||
} | ||
|
||
get selectedPosition() { | ||
return this.gridPanelModel.selectedRecord; | ||
|
@@ -21,16 +30,40 @@ export class PortfolioPanelModel extends HoistModel { | |
constructor() { | ||
super(); | ||
const wsService = XH.webSocketService; | ||
|
||
this.persistenceManagerModel = new PersistenceManagerModel({ | ||
type: 'portfoioExample', | ||
noun: 'portfoio', | ||
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. sp: |
||
canManageGlobal: () => XH.getUser().hasRole('HOIST_ADMIN'), | ||
onChangeAsync: () => this.onViewChangeAsync(), | ||
newObjectFnAsync: async () => ({ | ||
portfolioAppGridState: {}, | ||
portfolioAppDetailState: {}, | ||
groupingChooser: {value: ['region', 'sector', 'symbol'], favorites: []} | ||
}), | ||
persistWith: {prefKey: this.prefKey} | ||
}); | ||
|
||
this.groupingChooserModel = this.createGroupingChooserModel(); | ||
this.detailPanelModel = this.createDetailPanelModel(); | ||
this.gridPanelModel = this.createGridPanelModel(); | ||
|
||
this.addReaction({ | ||
track: () => [this.groupingChooserModel.value, wsService.connected], | ||
run: () => this.loadAsync() | ||
}); | ||
this.addReaction({ | ||
track: () => this.selectedPosition, | ||
run: position => { | ||
this.detailPanelModel.positionId = position?.id ?? null; | ||
}, | ||
debounce: 300 | ||
}); | ||
} | ||
|
||
override async doLoadAsync(loadSpec) { | ||
const wsService = XH.webSocketService, | ||
{store, groupingChooserModel, gridPanelModel} = this, | ||
dims = groupingChooserModel.value; | ||
{store, gridPanelModel} = this; | ||
|
||
let {session} = this; | ||
session?.destroy(); | ||
|
@@ -41,6 +74,9 @@ export class PortfolioPanelModel extends HoistModel { | |
); | ||
if (loadSpec.isStale) return; | ||
|
||
const dims = this.persistenceManagerModel.provider.getData().groupingChooser?.value; | ||
if (!dims) return; | ||
|
||
session = await XH.portfolioService.getLivePositionsAsync(dims, 'mainApp').catchDefault(); | ||
|
||
store.loadData([session.initialPositions.root]); | ||
|
@@ -79,7 +115,43 @@ export class PortfolioPanelModel extends HoistModel { | |
return new GroupingChooserModel({ | ||
dimensions: ['fund', 'model', 'region', 'sector', 'symbol', 'trader'], | ||
initialValue: ['region', 'sector', 'symbol'], | ||
persistWith: PERSIST_MAIN | ||
persistWith: {...this.persistenceManagerModel.provider}, | ||
allowEmpty: true | ||
}); | ||
} | ||
|
||
private createGridPanelModel() { | ||
return new GridPanelModel({ | ||
persistWith: this.persistenceManagerModel.provider, | ||
parentModel: this | ||
}); | ||
} | ||
|
||
private createDetailPanelModel() { | ||
return new DetailPanelModel({ | ||
persistWith: this.persistenceManagerModel.provider, | ||
parentModel: this | ||
}); | ||
} | ||
|
||
private async onViewChangeAsync() { | ||
const start = Date.now(); | ||
|
||
await wait(); // allow masking to start | ||
|
||
const {persistenceManagerModel, gridPanelModel, detailPanelModel, groupingChooserModel} = | ||
this, | ||
newState = persistenceManagerModel.provider.getData(); | ||
groupingChooserModel.setValue(newState.groupingChooser?.value ?? []); | ||
gridPanelModel.updateState(newState); | ||
|
||
runInAction(() => { | ||
const detailPm = detailPanelModel.ordersPanelModel.gridModel.persistenceModel; | ||
detailPm.state = newState.portfolioAppDetailState; | ||
detailPm.updateGridColumns(); | ||
detailPm.updateGridSort(); | ||
}); | ||
|
||
logInfo(`Rebuilt view | took ${Date.now() - start}ms`, this); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since the tbar component is so minimal and doesn't react to any state changes, I would just specify the tbar items inline (i.e.
tbar: [persistenceManager()]
)