Skip to content
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

New ViewManager for persisting named bundles of grid and other component state #3774

Closed
wants to merge 26 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
9b02ead
Persistence Manager
Ryanseanlee Sep 4, 2024
09db08d
Merge branch 'develop' into persistenceManager
Ryanseanlee Sep 4, 2024
b4b177c
Greg CR
Ryanseanlee Sep 5, 2024
b91d766
- Save and manage dialog model created once and open with isOpen state
Ryanseanlee Sep 6, 2024
8b1eb9c
Merge branch 'develop' into persistenceManager
Ryanseanlee Sep 6, 2024
e99cd7c
Remove new and add code default state
Ryanseanlee Sep 9, 2024
e58e1be
Add view tree getter for app specific custom component.
Ryanseanlee Sep 10, 2024
0bf7539
Favorites feature
Ryanseanlee Sep 11, 2024
b9b9447
Fix Favorites feature
Ryanseanlee Sep 12, 2024
78d95fc
Merge remote-tracking branch 'origin/develop' into persistenceManager
ghsolomon Sep 16, 2024
becede0
Merge branch 'develop' into persistenceManager
Ryanseanlee Sep 17, 2024
103dafa
Greg CR
Ryanseanlee Sep 17, 2024
0c591d2
Merge remote-tracking branch 'origin/persistenceManager' into persist…
Ryanseanlee Sep 17, 2024
9ca0fab
Favorites
Ryanseanlee Sep 20, 2024
c71ebfe
Grid popover
Ryanseanlee Sep 24, 2024
2982458
Remove persistence grid
Ryanseanlee Sep 27, 2024
afd6f7e
Update type
Ryanseanlee Sep 27, 2024
3ee7367
Remove ID and remove PersistenceGridPopover
Ryanseanlee Sep 27, 2024
bacb760
Merge branch 'develop' into persistenceManager
Ryanseanlee Sep 30, 2024
ee1beff
Add comments
Ryanseanlee Sep 30, 2024
a01060e
Replace Persistence -> View
Ryanseanlee Oct 3, 2024
bb518f5
Replace Persistence -> View
Ryanseanlee Oct 3, 2024
7ae18ec
add isWriteStateImmediately getter on persistenceProvider
Ryanseanlee Oct 7, 2024
9391c64
Merge branch 'develop' into persistenceManager
Ryanseanlee Oct 7, 2024
ac6e397
greg CR
Ryanseanlee Oct 16, 2024
c5536e2
greg CR
Ryanseanlee Oct 16, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion cmp/filter/FilterChooserModel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,10 @@ export class FilterChooserModel extends HoistModel {

this.addReaction({
track: () => this.persistState,
run: state => this.provider.write(state)
run: state => {
this.provider.write(state);
},
fireImmediately: this.provider.shouldWriteInitialState
});
} catch (e) {
this.logError(e);
Expand Down
10 changes: 7 additions & 3 deletions cmp/grid/GridModel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -630,8 +630,12 @@ export class GridModel extends HoistModel {
*
* @returns true if defaults were restored
*/
async restoreDefaultsAsync(): Promise<boolean> {
if (this.restoreDefaultsWarning) {
async restoreDefaultsAsync(
Ryanseanlee marked this conversation as resolved.
Show resolved Hide resolved
{skipWarning}: {skipWarning?: boolean} = {
skipWarning: !!this.restoreDefaultsWarning
}
): Promise<boolean> {
if (this.restoreDefaultsWarning && !skipWarning) {
const confirmed = await XH.confirm({
message: this.restoreDefaultsWarning,
confirmProps: {
Expand Down Expand Up @@ -1616,7 +1620,7 @@ export class GridModel extends HoistModel {
// Remove the width from any non-resizable column - we don't want to track those widths as
// they are set programmatically (e.g. fixed / action columns), and saved state should not
// conflict with any code-level updates to their widths.
if (!col.resizable) state = omit(state, 'width');
if (!col.resizable || !col.manuallySized) state = omit(state, 'width'); // TODO

// Remove all metadata other than the id and the hidden state from hidden columns, to save
// on space when storing user configs with large amounts of hidden fields.
Expand Down
13 changes: 9 additions & 4 deletions cmp/grid/impl/GridPersistenceModel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,8 @@ export class GridPersistenceModel extends HoistModel {
this.state = this.loadState() ?? this.legacyState() ?? {version: this.VERSION};
this.addReaction({
track: () => this.state,
run: state => this.provider.write(state)
run: state => this.provider.write(state),
fireImmediately: this.provider.shouldWriteInitialState
});
} catch (e) {
this.logError(e);
Expand All @@ -81,6 +82,7 @@ export class GridPersistenceModel extends HoistModel {

@action
clear() {
if (this.provider.shouldWriteInitialState) return;
this.state = {version: this.VERSION};
}

Expand All @@ -96,7 +98,8 @@ export class GridPersistenceModel extends HoistModel {
columns: gridModel.cleanColumnState(columnState),
autosize: autosizeState
});
}
},
fireImmediately: this.provider.shouldWriteInitialState
};
}

Expand All @@ -114,7 +117,8 @@ export class GridPersistenceModel extends HoistModel {
track: () => this.gridModel.sortBy,
run: sortBy => {
this.patchState({sortBy: sortBy.map(it => it.toString())});
}
},
fireImmediately: this.provider.shouldWriteInitialState
};
}

Expand All @@ -131,7 +135,8 @@ export class GridPersistenceModel extends HoistModel {
track: () => this.gridModel.groupBy,
run: groupBy => {
this.patchState({groupBy});
}
},
fireImmediately: this.provider.shouldWriteInitialState
};
}

Expand Down
3 changes: 2 additions & 1 deletion cmp/grouping/GroupingChooserModel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,8 @@ export class GroupingChooserModel extends HoistModel {

this.addReaction({
track: () => this.persistState,
run: state => this.provider.write(state)
run: state => this.provider.write(state),
fireImmediately: this.provider.shouldWriteInitialState
});
} catch (e) {
this.logError(e);
Expand Down
3 changes: 2 additions & 1 deletion cmp/tab/TabContainerModel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -402,7 +402,8 @@ export class TabContainerModel extends HoistModel {
if (this.provider) {
this.addReaction({
track: () => this.activeTabId,
run: activeTabId => this.provider.write({activeTabId})
run: activeTabId => this.provider.write({activeTabId}),
fireImmediately: this.provider.shouldWriteInitialState
});
}
}
Expand Down
9 changes: 6 additions & 3 deletions cmp/zoneGrid/impl/ZoneGridPersistenceModel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,8 @@ export class ZoneGridPersistenceModel extends HoistModel {
track: () => this.zoneGridModel.mappings,
run: mappings => {
this.patchState({mappings});
}
},
fireImmediately: this.provider.shouldWriteInitialState
};
}

Expand All @@ -108,7 +109,8 @@ export class ZoneGridPersistenceModel extends HoistModel {
track: () => this.zoneGridModel.sortBy,
run: sortBy => {
this.patchState({sortBy: sortBy?.toString()});
}
},
fireImmediately: this.provider.shouldWriteInitialState
};
}

Expand All @@ -125,7 +127,8 @@ export class ZoneGridPersistenceModel extends HoistModel {
track: () => this.zoneGridModel.groupBy,
run: groupBy => {
this.patchState({groupBy});
}
},
fireImmediately: this.provider.shouldWriteInitialState
};
}

Expand Down
3 changes: 2 additions & 1 deletion core/HoistBase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,8 @@ export abstract class HoistBase {
}
this.addReaction({
track: () => this[property],
run: data => provider.write(data)
run: data => provider.write(data),
fireImmediately: provider.shouldWriteInitialState
});
} catch (e) {
this.logError(
Expand Down
8 changes: 6 additions & 2 deletions core/persist/PersistOptions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
*/

import {DebounceSpec} from '../';
import {ViewManagerModel} from './viewManager';

/**
* Options governing persistence.
Expand All @@ -18,8 +19,8 @@ export interface PersistOptions {
debounce?: DebounceSpec;

/**
* Type of PersistenceProvider to create. If not provided, defaulted based
* on the presence of `prefKey`, `localStorageKey`, `dashViewModel`, `getData` and `setData`.
* Type of PersistenceProvider to create. If not provided, defaulted based on the presence of
* `prefKey`, `localStorageKey`, `dashViewModel`, `viewManagerModel`, `getData` and `setData`.
*/
type?: string;

Expand All @@ -32,6 +33,9 @@ export interface PersistOptions {
/** DashViewModel used to read / write view state. */
dashViewModel?: object;

/** ViewManagerModel used to read / write view state. */
viewManagerModel?: ViewManagerModel;

/**
* Function returning blob of data to be used for reading state.
* Ignored if `prefKey`, `localStorageKey` or `dashViewModel` are provided.
Expand Down
9 changes: 9 additions & 0 deletions core/persist/PersistenceProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
LocalStorageProvider,
PrefProvider,
DashViewProvider,
ViewManagerProvider,
CustomProvider,
PersistOptions
} from './';
Expand Down Expand Up @@ -45,6 +46,11 @@ export class PersistenceProvider {
path: string;
debounce: DebounceSpec;

// TODO - to discuss
get shouldWriteInitialState(): boolean {
return false;
}

/**
* Construct an instance of this class.
*/
Expand All @@ -53,6 +59,7 @@ export class PersistenceProvider {
if (rest.prefKey) type = 'pref';
if (rest.localStorageKey) type = 'localStorage';
if (rest.dashViewModel) type = 'dashView';
if (rest.viewManagerModel) type = 'viewManagerModel';
if (rest.getData || rest.setData) type = 'custom';
}

Expand All @@ -63,6 +70,8 @@ export class PersistenceProvider {
return new LocalStorageProvider(rest);
case `dashView`:
return new DashViewProvider(rest);
case 'viewManagerModel':
return new ViewManagerProvider(rest);
case 'custom':
return new CustomProvider(rest);
default:
Expand Down
40 changes: 40 additions & 0 deletions core/persist/ViewManagerProvider.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*
* This file belongs to Hoist, an application development toolkit
* developed by Extremely Heavy Industries (www.xh.io | [email protected])
*
* Copyright © 2024 Extremely Heavy Industries Inc.
*/

import {cloneDeep} from 'lodash';
import {PersistenceProvider, PersistOptions} from './';
import {throwIf} from '@xh/hoist/utils/js';
import {ViewManagerModel} from './viewManager';

/**
* PersistenceProvider that stores state for ViewManager.
*/
export class ViewManagerProvider extends PersistenceProvider {
viewManagerModel: ViewManagerModel;

override get shouldWriteInitialState(): boolean {
return true;
}

constructor({viewManagerModel, ...rest}: PersistOptions) {
throwIf(!viewManagerModel, `ViewManagerProvider requires a 'viewManagerModel'.`);
super(rest);
this.viewManagerModel = viewManagerModel;
}

//----------------
// Implementation
//----------------
override readRaw() {
const {pendingValue, value} = this.viewManagerModel;
return cloneDeep(pendingValue ?? value ?? {});
}

override writeRaw(data) {
this.viewManagerModel.mergePendingValue(data);
}
}
1 change: 1 addition & 0 deletions core/persist/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ export * from './LocalStorageProvider';
export * from './DashViewProvider';
export * from './PrefProvider';
export * from './CustomProvider';
export * from './ViewManagerProvider';
32 changes: 32 additions & 0 deletions core/persist/viewManager/Types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import {PlainObject} from '@xh/hoist/core';
import {LocalDate} from '@xh/hoist/utils/datetime';

export interface View<T extends PlainObject = PlainObject> {
acl: string;
archived: boolean;
dateCreated: LocalDate;
description: string;
lastUpdated: LocalDate;
lastUpdatedBy: string;
name: string;
owner: string;
token: string;
type: string;
group: string;
isShared: boolean;
value: T;
}

export type ViewTree = {
text: string;
selected: boolean;
} & (
| {
type: 'directory';
items: ViewTree[];
}
| {
type: 'view';
token: string;
}
);
Loading
Loading