@itwin/presentation-components
Version:
React components based on iTwin.js Presentation library
125 lines • 5.12 kB
JavaScript
/*---------------------------------------------------------------------------------------------
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
* See LICENSE.md in the project root for license terms and full copyright notice.
*--------------------------------------------------------------------------------------------*/
import "../../common/DisposePolyfill.js";
import { useEffect, useMemo, useState } from "react";
import { from, map, mergeMap, toArray } from "rxjs";
import { DisplayValue, KeySet } from "@itwin/presentation-common";
import { Presentation } from "@itwin/presentation-frontend";
import { translate } from "../../common/Utils.js";
import { FILTER_WARNING_OPTION, ItemsLoader, VALUE_BATCH_SIZE } from "./ItemsLoader.js";
/** @internal */
export function useUniquePropertyValuesLoader({ imodel, ruleset, field, descriptorInputKeys, typeName, filterText, selectedValues, }) {
const [itemsLoader, setItemsLoader] = useState();
const [initialSelectedValues] = useState(selectedValues);
const [state, setLoadedOptions] = useState({
options: [],
isLoading: false,
});
// Get initial loader and values
useEffect(() => {
setLoadedOptions({ options: [], isLoading: false });
if (!ruleset || !field) {
return;
}
const loader = new ItemsLoader(() => {
setLoadedOptions((prev) => ({ ...prev, isLoading: true }));
}, (newItems) => {
setLoadedOptions((prev) => ({
options: [...prev.options, ...newItems],
isLoading: false,
}));
}, async (offset) => getItems({ imodel, offset, field: field.getFieldDescriptor(), ruleset, keys: new KeySet(descriptorInputKeys) }), (option) => option.displayValue);
void loader.loadMatchingItems(initialSelectedValues);
setItemsLoader(loader);
return () => {
loader[Symbol.dispose]();
};
}, [imodel, ruleset, field, descriptorInputKeys, initialSelectedValues]);
// On filter text change, check if more items need to be loaded
useEffect(() => {
if (!filterText || !itemsLoader) {
return;
}
const timeout = setTimeout(() => {
void itemsLoader.loadItems(filterText);
}, 250);
return () => {
clearTimeout(timeout);
};
}, [itemsLoader, filterText]);
return {
selectOptions: useMemo(() => {
const options = state.options.map((option) => {
return {
label: formatOptionLabel(option.displayValue, typeName),
value: option.displayValue,
};
});
if (options.length >= VALUE_BATCH_SIZE) {
options.push(FILTER_WARNING_OPTION);
}
return options;
}, [state.options, typeName]),
loadedOptions: state.options,
isLoading: state.isLoading,
};
}
function formatOptionLabel(displayValue, type) {
if (displayValue === "") {
return translate("unique-values-property-editor.empty-value");
}
switch (type) {
case "dateTime":
return new Date(displayValue).toLocaleString(undefined, {
year: "numeric",
month: "numeric",
day: "numeric",
hour: "numeric",
minute: "numeric",
second: "numeric",
fractionalSecondDigits: 3,
});
case "shortDate":
return new Date(displayValue).toLocaleDateString();
default:
return displayValue;
}
}
async function getItems({ imodel, field, offset, ruleset, keys, }) {
const requestProps = {
imodel,
descriptor: {},
fieldDescriptor: field,
rulesetOrId: ruleset,
paging: { start: offset, size: VALUE_BATCH_SIZE },
keys,
};
const items = await new Promise((resolve) => {
(Presentation.presentation.getDistinctValuesIterator
? from(Presentation.presentation.getDistinctValuesIterator(requestProps)).pipe(mergeMap((result) => result.items), toArray())
: // eslint-disable-next-line @typescript-eslint/no-deprecated
from(Presentation.presentation.getPagedDistinctValues(requestProps)).pipe(map((result) => result.items))).subscribe({
next: resolve,
error: () => resolve([]),
});
});
const hasMore = items.length === VALUE_BATCH_SIZE;
const options = [];
for (const option of items) {
if (option.displayValue === undefined || !DisplayValue.isPrimitive(option.displayValue)) {
continue;
}
const groupedValues = option.groupedRawValues.filter((value) => value !== undefined);
if (groupedValues.length !== 0) {
options.push({ displayValue: option.displayValue, groupedRawValues: groupedValues });
}
}
return {
options,
length: items.length,
hasMore,
};
}
//# sourceMappingURL=UseUniquePropertyValuesLoader.js.map