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

[useTree]: hook #1880

Merged
merged 310 commits into from
Apr 3, 2024
Merged

[useTree]: hook #1880

merged 310 commits into from
Apr 3, 2024

Conversation

Kuznietsov
Copy link
Collaborator

@Kuznietsov Kuznietsov commented Dec 22, 2023

Summary

New features

Feature/class/hook/field Description
BaseListViewProps.showSelectedOnly Enables returning of only selected rows from IDataSource.useView
useTree Hook, which is used to create trees of different types with further
access to loaded data
useLazyFetchingAdvisor Hook, which is used to advice if data should be reloaded/refetched/
some rows should be uploaded additionally
ItemsStorage A storage of items, loaded by trees. Is used to share data between
multiple trees/views
useItemsStorage Hook for creating new ItemsStorage or using the existing itemsMap/setItems
ItemsMap Immutable map for storing items.
ITree Tree interface, which is used in useDataRows. It can be
implemented by users, if they don't want to use our trees,
but want to render rows
useDataRows Hook, which builds rows
useCascadeSelectionService Hook, which allows to perform cascadeSelection for lazy trees.
BaseListViewProps.patchItems Map of items to be added to the provided dataset in a tree.
BaseListViewProps.isDeleted Getter for detecting if an item is deleted.
BaseListViewProps.fixItemBetweenSortings If enabled, positions of items between sorting changes are fixed.
BaseListViewProps.getNewItemPosition Function, which returns an relative position of a new item.
BaseListViewProps.getItemTemporaryOrder Function, which returns a temporary order of a new item.
BaseListViewProps.sortBy Function, which provides a value of a field to be sorted by.

API Updates

  • IDataSource.useView accepts new onValueChange function, which should handle updateValue callback.
  • DataTableProps accepts additional rows prop, along with getRows().
  • ITableState.setTableState function should handle both, value and updateValue callback.

Deprecation

Deprecated Suggestions
ArrayListView Use ArrayDataSource.useView instead
AsyncListView Use AsyncDataSource.useView instead
LazyListView Use LazyDataSource.useView instead
useList Use IDataSource.useView instead
IDataSource.unsubscribeView This functionality is built in IDataSourceView.useView hook
IDataSource.getView Use IDataSource.useView instead
IDataSourceView.activate This functionality is built in IDataSourceView.useView hook
IDataSourceView.deactivate This functionality is built in IDataSourceView.useView hook
IDataSourceView.getSelectedRows Pass showSelectedOnly = true to IDataSourceView.useView
options and access selected rows via IDataSourceView.getVisibleRows().
IDataSourceView.loadData -
IDataSourceView._forceUpdate -
LazyListViewProps.legacyLoadDataBehavior -

@Kuznietsov Kuznietsov self-assigned this Dec 22, 2023
Copy link

github-actions bot commented Jan 11, 2024

Generated by: track-bundle-size
Generated at: Wed, 03 Apr 2024 16:37:22 GMT
Bundle size diff (in kBytes). Not gzipped. Both CSS & JS included.
Baseline: v5.6.1 (2024-03-11)
CI Status: ok

Module Baseline Size
(v5.6.1)
Size Diff Within
Threshold
Threshold
(min - max)
templateApp 1041.48 1073.64 +32.16
js:+31.7
css:+0.46
🆗 937.33 - 1145.63
@epam/app 6402.7 6680.95 +278.25
js:+300.13
css:-21.88
🆗 5762.42 - 7042.96
@epam/draft-rte 53.77 53.78 +0.01
js:+0.01
css:+0
🆗 48.39 - 59.15
@epam/electric 4.46 4.49 +0.01
js:+0
css:+0.01
🆗 4.02 - 4.91
@epam/promo 55.29 55.14 -0.14
js:+0.06
css:-0.19
🆗 49.75 - 60.81
@epam/uui-extra 0.21 0.21 0
js:0
css:0
🆗 0.19 - 0.23
@epam/loveship 101.41 101.17 -0.24
js:+0
css:-0.24
🆗 91.27 - 111.55
@epam/uui-components 269.68 272.67 +3
js:+2.92
css:+0.08
🆗 242.71 - 296.64
@epam/uui-core 311.4 326.21 +14.81
js:+14.81
css:0
🆗 280.26 - 342.54
@epam/uui-db 42.31 42.31 0
js:0
css:0
🆗 38.08 - 46.54
@epam/uui-docs 192.53 199.12 +6.59
js:+6.5
css:+0.09
🆗 173.28 - 211.79
@epam/uui-editor 157.65 173.26 +15.61
js:+15.92
css:-0.31
🆗 141.89 - 173.42
@epam/uui-timeline 47.19 47.19 0
js:+0
css:0
🆗 42.47 - 51.91
@epam/uui 580.2 581.87 +1.67
js:+1.32
css:+0.35
🆗 522.18 - 638.23
new sizes (raw)

To set the sizes as a new baseline, you can copy/paste next content to the uui-build/config/bundleSizeBaseLine.json and commit the file.

{
  "version": "5.7.1",
  "timestamp": "2024-04-03",
  "sizes": {
    "templateApp": {
      "css": 284412,
      "js": 814992
    },
    "@epam/app": {
      "css": 1591977,
      "js": 5249310
    },
    "@epam/draft-rte": {
      "css": 9762,
      "js": 45308
    },
    "@epam/electric": {
      "css": 2289,
      "js": 2299
    },
    "@epam/promo": {
      "css": 40368,
      "js": 16101
    },
    "@epam/uui-extra": {
      "css": 0,
      "js": 213
    },
    "@epam/loveship": {
      "css": 49451,
      "js": 54148
    },
    "@epam/uui-components": {
      "css": 22214,
      "js": 257005
    },
    "@epam/uui-core": {
      "css": 0,
      "js": 334039
    },
    "@epam/uui-db": {
      "css": 0,
      "js": 43327
    },
    "@epam/uui-docs": {
      "css": 3189,
      "js": 200715
    },
    "@epam/uui-editor": {
      "css": 12625,
      "js": 164792
    },
    "@epam/uui-timeline": {
      "css": 2251,
      "js": 46073
    },
    "@epam/uui": {
      "css": 272887,
      "js": 322954
    }
  }
}

Generated by: generate-components-api
CI Status: ok

Total amount of exported types/props without JSDoc comments

Amount
Types 283 (+2) ⚠️🆗
Props 255 (-31) 🆗
New missing comments
NOTE: It's either a new exported types/props without JSDoc, or it's an existing code from which you deleted the JSDoc comments.
Types:
- @epam/uui-core:ArrayListViewProps
- @epam/uui-core:AsyncListViewProps
- @epam/uui-core:BaseArrayListViewProps
- @epam/uui-core:BaseListViewProps
- @epam/uui-core:ItemsMapParams
- @epam/uui-core:ItemsStorageParams
- @epam/uui-core:LazyListViewProps
- @epam/uui-core:ModificationOptions
- @epam/uui-core:OnUpdate
- @epam/uui-core:PatchOrderingType
- @epam/uui-core:RecordStatus
- @epam/uui-core:SortedPatchByParentId
- @epam/uui-core:UseLazyFetchingAdvisorProps
Props:
- @epam/uui-core:IImmutableMap/[Symbol.iterator]
- @epam/uui-core:IImmutableMap/get
- @epam/uui-core:IImmutableMap/has
- @epam/uui-core:IImmutableMap/size
- @epam/uui-core:ItemsMapParams/complexIds
- @epam/uui-core:ItemsMapParams/getId
- @epam/uui-core:ItemsStorageParams/items
- @epam/uui-core:ItemsStorageParams/params
- @epam/uui-core:ModificationOptions/on
- @epam/uui-core:ModificationOptions/reset
- @epam/uui-core:UseLazyFetchingAdvisorProps/backgroundReload
- @epam/uui-core:UseLazyFetchingAdvisorProps/dataSourceState
- @epam/uui-core:UseLazyFetchingAdvisorProps/filter
- @epam/uui-core:UseLazyFetchingAdvisorProps/forceReload
- @epam/uui-core:UseLazyFetchingAdvisorProps/showSelectedOnly


const view = dataSource.useView(value, onValueChange, {});
const { listProps, visibleRows } = useDataRows({
Copy link
Contributor

@jakobz jakobz Jan 15, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's try to adjust useDataRows output and DataTable's props to be compatible, and more convenient.

My proposal:

const { rowsCount, rows, totalCount } = useDataRows(); // to use separately

// to pass-thru to the table: 
const rowProps = useDataRows();
<DataTable { ...rowsProps } />

DataTable needs a minimal adjustments to allow rows prop, as alternative to getVisibleRows.

I also believe that rows is better than visibleRows, as 'visible' doesn't add any clarification in this case.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree on rows. It can be aligned without any problem.
There is a problem with the pass-through approach.

interface DataRowsResult<TItem, TId> {
  rows: DataRowProps<TItem, TId>[];
  getSelectedRows: : ({ topIndex, visibleCount }?: VirtualListRange) => DataRowProps<TItem, TId>[];
  getSelectedRowsCount: : () => number;
  getById:  (id: TId, index: number) => DataRowProps<TItem, TId>;
  clearAllChecked: () => void;
        
  listProps: DataSourceListProps;

  selectAll: {
    value: boolean;
    onValueChange: (isChecked: boolean) => void;
    indeterminate: boolean;
    isDisabled?: undefined;
  } | {
    value: boolean;
    onValueChange: () => void;
    isDisabled: boolean;
    indeterminate: boolean;
  },
}

This is a return type of useDataRows hook. Sometimes, all the properties, returned from this hook, are required. And not all of them should be passed to the DataTable. If listProps is spread too, it will turn into a mess. Don't you think that the best idea is to leave it as a separate property, which collects all the stats about the datasource.

Otherwise, we'll face the further issue:

const {
    getSelectedRows,
    getSelectedRowsCount,
    getById,
    clearAllChecked,
    selectAll,
    ...tableProps,
} = useDataRows(props);

<DataTable { ...tableProps } />;

To pass necessary data to a DataTable it will be required to destruct all the other props, which looks weird.
It seems to me, it is much better to extract only rows and listProps:

const { rows, listProps } = useDataRows(props);

<DataTable rows={ rows } { ...listProps } />;

@jakobz, WDYT about it?

@@ -58,6 +59,33 @@ export function prop<TObject, TKey extends keyof TObject>(name: TKey): ILensImpl
};
}

export function get<TItem, TId>(id: TId): ILensImpl<ItemsMap<TId, TItem>, TItem> {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's:

  • generalize this Lens to support any Map-like object. We can re-use the trick we used to abstract Map in Tree via IMap interface. This approach allows to support a native Map, as well as other Map-like objects. Including immutable Maps like I.Map - they can implement constructor as no-op.
  • we need a better name for both ILensImpl and LensBuilder method. I suggest mapItem, but let's discuss - probably there'll be a better ideas.

@@ -0,0 +1,96 @@
export type OnUpdate<TId, TItem> = (newItemsMap: ItemsMap<TId, TItem>) => void;

interface ModificationOptions {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can be more explicit in this API - just tell callee how we got these items:

interface ModificationOptions {
  /** Where new/updated items came from:
  * api - received them from the recent api call
  * edit - received from dataRow.onValueChange callback
  */
  source: 'api' | 'edit'; 
}

Users can then decide what to do in each case:

setItems((updatedItems, options) => {
   let items = new Map(myState.items);   
   if (options.source === 'api') {
      items = new Map([...updatedItems, ...items]) // items from state take precedence, to not override edited items
   } else {
      items = new Map([...items, ...updatedItem]) // items from state take precedence, to not override edited items
   }
})

Kuznietsov and others added 21 commits April 1, 2024 11:37
…ure/use-tree-hook

# Conflicts:
#	app/src/sandbox/editableTable/ProjectTableDemo.tsx
@NatalliaAlieva
Copy link
Collaborator

Released in 5.8.0 ver.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Archived in project
Development

Successfully merging this pull request may close these issues.

4 participants