@itwin/presentation-components
Version:
React components based on iTwin.js Presentation library
178 lines • 8.06 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 });
// note: using deprecated `traverseContent`, because we can't use the replacement `createContentTraverser` due to our peer dep version
// eslint-disable-next-line @typescript-eslint/no-deprecated
(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();
}
}
/* v8 ignore start -- @preserve */
const noopRowsLoader = { loadPage: () => { }, reload: () => { } };
/* v8 ignore stop -- @preserve */
//# sourceMappingURL=UseRows.js.map