@itwin/presentation-components
Version:
React components based on iTwin.js Presentation library
208 lines • 8.3 kB
JavaScript
;
/*---------------------------------------------------------------------------------------------
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
* See LICENSE.md in the project root for license terms and full copyright notice.
*--------------------------------------------------------------------------------------------*/
/** @packageDocumentation
* @module Internal
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.ROWS_RELOAD_PAGE_SIZE = void 0;
exports.useRows = useRows;
const react_1 = require("react");
const rxjs_1 = require("rxjs");
const core_bentley_1 = require("@itwin/core-bentley");
const core_frontend_1 = require("@itwin/core-frontend");
const presentation_common_1 = require("@itwin/presentation-common");
const presentation_core_interop_1 = require("@itwin/presentation-core-interop");
const presentation_frontend_1 = require("@itwin/presentation-frontend");
const ContentBuilder_js_1 = require("../common/ContentBuilder.js");
const Utils_js_1 = require("../common/Utils.js");
/** @internal */
function useRows(props) {
const { imodel, ruleset, keys, pageSize, options } = props;
const setErrorState = (0, Utils_js_1.useErrorState)();
const [state, setState] = (0, react_1.useState)({
isLoading: false,
rows: [],
total: 0,
});
const loaderRef = (0, react_1.useRef)(noopRowsLoader);
(0, react_1.useEffect)(() => {
setState((prev) => ({ ...prev, rows: [], total: 0 }));
const { observable, ...loader } = createRowsLoader({
imodel,
ruleset,
keys,
pageSize,
options,
onPageLoadStart: () => setState((prev) => ({ ...prev, isLoading: true })),
});
loaderRef.current = loader;
const subscription = observable.subscribe({
next: ({ total, rowDefinitions, offset }) => {
setState((prev) => {
const newRows = [...prev.rows];
newRows.splice(offset, rowDefinitions.length, ...rowDefinitions);
return {
...prev,
isLoading: false,
rows: newRows,
total,
};
});
},
error: (err) => {
setErrorState(err);
},
});
loaderRef.current.loadPage(0);
return () => {
subscription.unsubscribe();
loaderRef.current = noopRowsLoader;
};
}, [imodel, ruleset, keys, pageSize, options, setErrorState]);
(0, react_1.useEffect)(() => {
return core_frontend_1.IModelApp.quantityFormatter.onActiveFormattingUnitSystemChanged.addListener(() => {
loaderRef.current.reload(state.rows.length);
});
}, [state.rows]);
return {
rows: state.rows,
isLoading: state.isLoading,
loadMoreRows: () => {
if (state.rows.length === state.total) {
return;
}
loaderRef.current.loadPage(state.rows.length);
},
};
}
function createRowsLoader({ imodel, ruleset, keys, pageSize, options, onPageLoadStart, }) {
const loaderSubject = new rxjs_1.Subject();
const loaderObservable = loaderSubject.pipe((0, rxjs_1.mergeMap)((loaderOptions) => {
if (keys.isEmpty) {
return rxjs_1.EMPTY;
}
switch (loaderOptions.action) {
case "load-page": {
onPageLoadStart();
return (0, rxjs_1.from)(loadRows(imodel, ruleset, keys, { start: loaderOptions.pageStart, size: pageSize }, options));
}
case "reload": {
return loaderOptions.loadedRowsCount === 0 ? rxjs_1.EMPTY : createReloadObs(imodel, ruleset, keys, options, loaderOptions.loadedRowsCount);
}
}
}));
return {
observable: loaderObservable,
loadPage: (pageStart) => {
loaderSubject.next({ action: "load-page", pageStart });
},
reload: (rowsCount) => {
loaderSubject.next({ action: "reload", loadedRowsCount: rowsCount });
},
};
}
/** @internal */
exports.ROWS_RELOAD_PAGE_SIZE = 1000;
function createReloadObs(imodel, ruleset, keys, options, loadedItemsCount) {
const lastPageIndex = Math.floor(loadedItemsCount / exports.ROWS_RELOAD_PAGE_SIZE);
const lastPageSize = loadedItemsCount % exports.ROWS_RELOAD_PAGE_SIZE;
const pages = [];
for (let i = 0; i <= lastPageIndex; i++) {
pages.push({
start: i * exports.ROWS_RELOAD_PAGE_SIZE,
size: i === lastPageIndex ? lastPageSize : exports.ROWS_RELOAD_PAGE_SIZE,
});
}
return (0, rxjs_1.from)(pages).pipe((0, rxjs_1.mergeMap)((pageOptions) => (0, rxjs_1.from)(loadRows(imodel, ruleset, keys, pageOptions, options))));
}
async function loadRows(imodel, ruleset, keys, paging, options) {
const requestProps = {
imodel,
keys: new presentation_common_1.KeySet(keys),
descriptor: {
displayType: presentation_common_1.DefaultContentDisplayTypes.Grid,
sorting: options.sorting,
fieldsFilterExpression: options.fieldsFilterExpression,
},
rulesetOrId: ruleset,
paging,
};
return new Promise((resolve, reject) => {
(presentation_frontend_1.Presentation.presentation.getContentIterator
? (0, rxjs_1.from)(presentation_frontend_1.Presentation.presentation.getContentIterator(requestProps)).pipe((0, rxjs_1.mergeMap)((result) => {
if (!result) {
return (0, rxjs_1.of)(undefined);
}
return (0, rxjs_1.from)(result.items).pipe((0, rxjs_1.toArray)(), (0, rxjs_1.map)((items) => ({ total: result.total, content: new presentation_common_1.Content(result.descriptor, items) })));
}))
: // eslint-disable-next-line @typescript-eslint/no-deprecated
(0, rxjs_1.from)(presentation_frontend_1.Presentation.presentation.getContentAndSize(requestProps)).pipe((0, rxjs_1.map)((result) => result
? {
total: result.size,
content: result.content,
}
: undefined)))
.pipe((0, rxjs_1.map)((result) => result
? {
rowDefinitions: createRows(result.content, imodel),
total: result.total,
offset: paging.start,
}
: {
rowDefinitions: [],
total: 0,
offset: 0,
}))
.subscribe({
next: resolve,
error: reject,
});
});
}
function createRows(content, imodel) {
const rowsBuilder = new RowsBuilder({ imodel });
(0, presentation_common_1.traverseContent)(rowsBuilder, content);
return rowsBuilder.rows;
}
class RowsBuilder extends ContentBuilder_js_1.InternalPropertyRecordsBuilder {
rows = [];
_currentRow = undefined;
constructor({ imodel }) {
super((item) => ({
item,
append: (record) => {
if (record.fieldHierarchy.field.isNestedContentField()) {
return;
}
(0, core_bentley_1.assert)(this._currentRow !== undefined);
this._currentRow.cells.push({
key: record.fieldHierarchy.field.name,
record: record.record,
});
},
}), (record) => {
record.imodelKey = (0, presentation_core_interop_1.createIModelKey)(imodel);
});
}
startItem(props) {
const key = JSON.stringify(props.item.primaryKeys[0]);
this._currentRow = { key, cells: [] };
return super.startItem(props);
}
finishItem() {
(0, core_bentley_1.assert)(this._currentRow !== undefined);
this.rows.push(this._currentRow);
this._currentRow = undefined;
super.finishItem();
}
}
/* c8 ignore start */
const noopRowsLoader = {
loadPage: () => { },
reload: () => { },
};
/* c8 ignore end */
//# sourceMappingURL=UseRows.js.map