@powerportalspro/react-fluent 5.1.0 → 6.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/EULA.txt +263 -0
- package/README.md +38 -0
- package/dist/index.cjs +392 -48
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +5 -1
- package/dist/index.d.ts +5 -1
- package/dist/index.js +395 -51
- package/dist/index.js.map +1 -1
- package/package.json +7 -6
package/dist/index.d.cts
CHANGED
|
@@ -4635,7 +4635,11 @@ interface MainGridProps {
|
|
|
4635
4635
|
* Set to `'virtualize'` for infinite-scroll — the pager footer is
|
|
4636
4636
|
* hidden, rows accumulate across page boundaries, and the next page
|
|
4637
4637
|
* fetches automatically when the user scrolls past the rendered
|
|
4638
|
-
* bottom.
|
|
4638
|
+
* bottom. Pages are requested sequentially with the previous page's
|
|
4639
|
+
* Dataverse paging cookie (cursor paging), and loading stops when the
|
|
4640
|
+
* server reports no more records — not when the accumulated rows reach
|
|
4641
|
+
* the total count, which can never happen if per-row permission
|
|
4642
|
+
* handlers drop rows after Dataverse has counted them.
|
|
4639
4643
|
*/
|
|
4640
4644
|
pagingMode?: PagingMode;
|
|
4641
4645
|
/**
|
package/dist/index.d.ts
CHANGED
|
@@ -4635,7 +4635,11 @@ interface MainGridProps {
|
|
|
4635
4635
|
* Set to `'virtualize'` for infinite-scroll — the pager footer is
|
|
4636
4636
|
* hidden, rows accumulate across page boundaries, and the next page
|
|
4637
4637
|
* fetches automatically when the user scrolls past the rendered
|
|
4638
|
-
* bottom.
|
|
4638
|
+
* bottom. Pages are requested sequentially with the previous page's
|
|
4639
|
+
* Dataverse paging cookie (cursor paging), and loading stops when the
|
|
4640
|
+
* server reports no more records — not when the accumulated rows reach
|
|
4641
|
+
* the total count, which can never happen if per-row permission
|
|
4642
|
+
* handlers drop rows after Dataverse has counted them.
|
|
4639
4643
|
*/
|
|
4640
4644
|
pagingMode?: PagingMode;
|
|
4641
4645
|
/**
|
package/dist/index.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { makeStyles, mergeClasses, Input, tokens, Toolbar, ToolbarButton, ToolbarDivider, Menu, MenuTrigger, MenuPopover, MenuList, MenuItemRadio, Button, createLightTheme, createDarkTheme, makeStaticStyles, MessageBar, MessageBarBody, Dropdown, Option, Spinner, Field, Textarea, Switch, Checkbox, Label, TabList, Tab, Tooltip, Dialog, DialogSurface, DialogBody, DialogTitle, DialogContent, DialogActions, RadioGroup, Radio, useId as useId$1, Text, Overflow, OverflowItem, SearchBox, CounterBadge, Popover, PopoverTrigger, PopoverSurface, MenuItem, Combobox, TagPicker, TagPickerControl, TagPickerGroup, Tag, TagPickerInput, TagPickerList, TagPickerOption, webDarkTheme, webLightTheme, teamsDarkTheme, teamsLightTheme, FluentProvider, Avatar, Divider, OverlayDrawer, DrawerHeader, DrawerHeaderTitle, DrawerBody, useOverflowMenu, useIsOverflowItemVisible, Title3, Table, TableHeader, TableRow, TableHeaderCell, TableBody, TableCell, MessageBarTitle, DialogTrigger } from '@fluentui/react-components';
|
|
2
|
-
import { MaskMode, useMaskedTextField, useT, usePowerPortalsPro, useRecordContext, useColumnMetadata, useLocale, MainContext, useTableMetadata, useWarnAboutUnsavedChanges, useMainContext, useViewsForTable, useViewMetadata, QueryStatus, useGridData, RecordContext, DialogServiceProvider, useUrlCultureStrategy, useDefaultLocale, useSupportedLocales, setAspNetCultureCookie, buildLocalePath, useAuth, AuthStatus, useOverlayServiceState, OverlayServiceProvider, useOverlayForTarget, useLocalization, useLocalizationLoaded, useValidationContext, useDialogService, useRunWithOverlay, useRecordContextOptional, useOrganizationSettings, useUnsavedChangesGuard, useColumnValidationErrors } from '@powerportalspro/react';
|
|
1
|
+
import { makeStyles, mergeClasses, Input, tokens, Toolbar, ToolbarButton, ToolbarDivider, Menu, MenuTrigger, MenuPopover, MenuList, MenuItemRadio, Button, createLightTheme, createDarkTheme, makeStaticStyles, MessageBar, MessageBarBody, Dropdown, Option, Spinner, Field, Textarea, Switch, Checkbox, Label, TabList, Tab, Tooltip, Dialog, DialogSurface, DialogBody, DialogTitle, DialogContent, DialogActions, RadioGroup, Radio, useId as useId$1, Text, Overflow, OverflowItem, SearchBox, CounterBadge, Popover, PopoverTrigger, PopoverSurface, MenuItem, Combobox, TagPicker, TagPickerControl, TagPickerGroup, Tag, TagPickerInput, TagPickerList, TagPickerOption, webDarkTheme, webLightTheme, teamsDarkTheme, teamsLightTheme, FluentProvider, Avatar, Divider, OverlayDrawer, DrawerHeader, DrawerHeaderTitle, DrawerBody, useOverflowMenu, useIsOverflowItemVisible, Title3, Table, TableHeader, TableRow, TableHeaderCell, TableBody, TableCell, createTableColumn, DataGrid, DataGridHeader, DataGridRow, DataGridHeaderCell, DataGridBody, DataGridCell, MessageBarTitle, DialogTrigger } from '@fluentui/react-components';
|
|
2
|
+
import { MaskMode, useMaskedTextField, useT, usePowerPortalsPro, useRecordContext, useColumnMetadata, useLocale, MainContext, useTableMetadata, useWarnAboutUnsavedChanges, useMainContext, useViewsForTable, useViewMetadata, QueryStatus, useGridData, RecordContext, DialogServiceProvider, useUrlCultureStrategy, useDefaultLocale, useSupportedLocales, setAspNetCultureCookie, buildLocalePath, useAuth, AuthStatus, useOverlayServiceState, OverlayServiceProvider, useOverlayForTarget, useLocalization, useLocalizationLoaded, useValidationContext, useDialogService, useRunWithOverlay, useRecordContextOptional, useOrganizationSettings, useUnsavedChangesGuard, useColumnValidationErrors, isKeyModeEnabled } from '@powerportalspro/react';
|
|
3
3
|
import { forwardRef, useRef, useImperativeHandle, useState, useEffect, useCallback, createContext, useMemo, useId, useLayoutEffect, useContext, useTransition, Children, isValidElement } from 'react';
|
|
4
4
|
import { jsx, Fragment, jsxs } from 'react/jsx-runtime';
|
|
5
|
-
import { ArrowRotateCounterclockwise20Regular, ArrowRotateClockwise20Regular, FlipHorizontal20Regular, FlipVertical20Regular, ZoomIn20Regular, ZoomOut20Regular, ArrowReset20Regular, ChevronDown16Regular, Grid20Regular, Crop20Regular, FullScreenMinimize20Regular, FullScreenMaximize20Regular, ArrowDownload20Regular, Prohibited20Regular, Checkmark20Filled, ArrowDownload24Regular, ArrowClockwise24Regular, ChevronUp12Regular, ChevronDown12Regular, DocumentArrowLeft24Regular, ChevronDown20Regular, ChevronRight20Regular, Folder20Regular, Document20Regular, ErrorCircle20Regular, Eye20Regular, Dismiss20Regular, Edit20Regular, Add16Regular, Edit16Regular, LinkAdd16Regular, LinkDismiss16Regular, Delete16Regular, Settings20Regular, Search20Regular, ArrowClockwise20Regular, ArrowSortDown16Regular, ArrowSortUp16Regular, Dismiss24Regular, LinkAdd20Regular, QuestionCircle24Regular, Info24Regular, DismissCircle24Regular, Warning24Regular, CheckmarkCircle24Regular, ArrowExit20Regular, PersonEdit20Regular, ArrowSwap20Regular, SignOut20Regular, MoreVerticalRegular, ArrowSyncRegular, ArrowDownloadRegular, Save24Regular, Delete24Regular, Add20Regular, Delete20Regular, LinkDismiss20Regular, ArrowUpload32Regular, ArrowUpload24Regular, ArrowSync24Regular, DrawerArrowDownload24Regular, Money20Regular, ErrorCircle12Filled, DocumentText20Regular, FolderZip20Regular, MusicNote220Regular, Video20Regular, Image20Regular, SlideText20Regular, DocumentTable20Regular, DocumentPdf20Regular, MoreHorizontal20Regular, ChevronDoubleLeft20Regular, ChevronLeft20Regular, ChevronDoubleRight20Regular, Info12Regular, Checkmark16Regular, Dismiss16Regular } from '@fluentui/react-icons';
|
|
5
|
+
import { ArrowRotateCounterclockwise20Regular, ArrowRotateClockwise20Regular, FlipHorizontal20Regular, FlipVertical20Regular, ZoomIn20Regular, ZoomOut20Regular, ArrowReset20Regular, ChevronDown16Regular, Grid20Regular, Crop20Regular, FullScreenMinimize20Regular, FullScreenMaximize20Regular, ArrowDownload20Regular, Prohibited20Regular, Checkmark20Filled, ArrowDownload24Regular, ArrowClockwise24Regular, ChevronUp12Regular, ChevronDown12Regular, DocumentArrowLeft24Regular, ChevronDown20Regular, ChevronRight20Regular, Folder20Regular, Document20Regular, ErrorCircle20Regular, Eye20Regular, Dismiss20Regular, Edit20Regular, Add16Regular, Edit16Regular, LinkAdd16Regular, LinkDismiss16Regular, Delete16Regular, Settings20Regular, Search20Regular, ArrowClockwise20Regular, ArrowSortDown16Regular, ArrowSortUp16Regular, Dismiss24Regular, LinkAdd20Regular, QuestionCircle24Regular, Info24Regular, DismissCircle24Regular, Warning24Regular, CheckmarkCircle24Regular, ArrowExit20Regular, PersonEdit20Regular, ArrowSwap20Regular, SignOut20Regular, MoreVerticalRegular, ArrowSyncRegular, EyeRegular, ArrowDownloadRegular, SearchRegular, DismissRegular, Save24Regular, Delete24Regular, Add20Regular, Delete20Regular, LinkDismiss20Regular, ArrowUpload32Regular, ArrowUpload24Regular, ArrowSync24Regular, DrawerArrowDownload24Regular, Money20Regular, ErrorCircle12Filled, DocumentText20Regular, FolderZip20Regular, MusicNote220Regular, Video20Regular, Image20Regular, SlideText20Regular, DocumentTable20Regular, DocumentPdf20Regular, MoreHorizontal20Regular, ChevronDoubleLeft20Regular, ChevronLeft20Regular, ChevronDoubleRight20Regular, Info12Regular, Checkmark16Regular, Dismiss16Regular } from '@fluentui/react-icons';
|
|
6
6
|
import { RequiredLevel, DateTimeBehavior, getRecordReferenceId, RelationshipFilterMode, SwitchIdentityResult, TableSecurityPermission } from '@powerportalspro/core';
|
|
7
7
|
import { DatePicker } from '@fluentui/react-datepicker-compat';
|
|
8
8
|
import { TimePicker } from '@fluentui/react-timepicker-compat';
|
|
@@ -8304,6 +8304,36 @@ function MainGridVirtualizeFooter({
|
|
|
8304
8304
|
] });
|
|
8305
8305
|
}
|
|
8306
8306
|
|
|
8307
|
+
// src/grids/virtualize-paging.ts
|
|
8308
|
+
function hasMoreRowsToLoad(state) {
|
|
8309
|
+
if (state.moreRecords === false) return false;
|
|
8310
|
+
if (state.moreRecords === true) return true;
|
|
8311
|
+
if (state.lastPageEmpty) return false;
|
|
8312
|
+
if (state.totalCount === void 0) return true;
|
|
8313
|
+
return state.accumulatedCount < state.totalCount;
|
|
8314
|
+
}
|
|
8315
|
+
var VirtualizePagingCookies = class {
|
|
8316
|
+
key;
|
|
8317
|
+
byPage = /* @__PURE__ */ new Map();
|
|
8318
|
+
/** Store the cookie the response for `page` came back with (no-op for a null / empty cookie). */
|
|
8319
|
+
record(key, page, cookie) {
|
|
8320
|
+
if (this.key !== key) {
|
|
8321
|
+
this.key = key;
|
|
8322
|
+
this.byPage = /* @__PURE__ */ new Map();
|
|
8323
|
+
}
|
|
8324
|
+
if (cookie) this.byPage.set(page, cookie);
|
|
8325
|
+
}
|
|
8326
|
+
/**
|
|
8327
|
+
* The cookie to send when requesting `page` under `key`: the one page
|
|
8328
|
+
* `page - 1` returned, or `undefined` when it isn't known (page 1, a
|
|
8329
|
+
* non-sequential jump, or a key the store has no cookies for).
|
|
8330
|
+
*/
|
|
8331
|
+
cookieFor(key, page) {
|
|
8332
|
+
if (this.key !== key || page <= 1) return void 0;
|
|
8333
|
+
return this.byPage.get(page - 1);
|
|
8334
|
+
}
|
|
8335
|
+
};
|
|
8336
|
+
|
|
8307
8337
|
// src/grids/persisted-grid-state.ts
|
|
8308
8338
|
function readPersistedGridStateFromUrl(queryParameterName) {
|
|
8309
8339
|
if (!queryParameterName) return null;
|
|
@@ -8835,8 +8865,22 @@ function MainGridImpl({
|
|
|
8835
8865
|
`[MainGrid] Declared <GridColumn> children override the column projection of the supplied fetchXml (columns: ${columnsKey.split(",").join(", ")}). Drop the children \u2014 or remove the conflicting <attribute> elements from the fetchXml \u2014 to silence this message.`
|
|
8836
8866
|
);
|
|
8837
8867
|
}, [columnsKey, useInlineFetchXml]);
|
|
8868
|
+
const accumulatorResetKey = useMemo(
|
|
8869
|
+
() => [
|
|
8870
|
+
resolvedViewId ?? "",
|
|
8871
|
+
useInlineFetchXml ? inlineFetchXml ?? "" : "",
|
|
8872
|
+
debouncedSearchText,
|
|
8873
|
+
sort.map((s) => `${s.columnName}:${s.descending ? "d" : "a"}`).join("|"),
|
|
8874
|
+
filtersKey,
|
|
8875
|
+
pageSize,
|
|
8876
|
+
tableName ?? ""
|
|
8877
|
+
].join("|"),
|
|
8878
|
+
[resolvedViewId, useInlineFetchXml, inlineFetchXml, debouncedSearchText, sort, filtersKey, pageSize, tableName]
|
|
8879
|
+
);
|
|
8880
|
+
const [virtualizeCookies] = useState(() => new VirtualizePagingCookies());
|
|
8838
8881
|
const searchRequest = useMemo(() => {
|
|
8839
8882
|
const trimmed = debouncedSearchText.trim();
|
|
8883
|
+
const pagingCookie = isVirtualize ? virtualizeCookies.cookieFor(accumulatorResetKey, page) : void 0;
|
|
8840
8884
|
return {
|
|
8841
8885
|
...useInlineFetchXml && inlineFetchXml ? { fetchXml: inlineFetchXml } : resolvedViewId !== void 0 && { viewId: resolvedViewId },
|
|
8842
8886
|
...trimmed && { searchText: trimmed },
|
|
@@ -8856,7 +8900,8 @@ function MainGridImpl({
|
|
|
8856
8900
|
},
|
|
8857
8901
|
...columnsOverride && { columns: [...columnsOverride] },
|
|
8858
8902
|
pageNumber: page,
|
|
8859
|
-
pageSize
|
|
8903
|
+
pageSize,
|
|
8904
|
+
...pagingCookie && { pagingCookie }
|
|
8860
8905
|
};
|
|
8861
8906
|
}, [
|
|
8862
8907
|
resolvedViewId,
|
|
@@ -8867,7 +8912,9 @@ function MainGridImpl({
|
|
|
8867
8912
|
page,
|
|
8868
8913
|
pageSize,
|
|
8869
8914
|
filtersKey,
|
|
8870
|
-
columnsKey
|
|
8915
|
+
columnsKey,
|
|
8916
|
+
isVirtualize,
|
|
8917
|
+
accumulatorResetKey
|
|
8871
8918
|
]);
|
|
8872
8919
|
const transformPending = !!transformViewAsync || isCustomActiveView;
|
|
8873
8920
|
const recordsResult = useGridData(searchRequest, {
|
|
@@ -9015,7 +9062,13 @@ function MainGridImpl({
|
|
|
9015
9062
|
(row) => row.properties?.[columnName],
|
|
9016
9063
|
{
|
|
9017
9064
|
id: columnName,
|
|
9018
|
-
|
|
9065
|
+
// Headers normally show the server-resolved Dataverse display name, which bypasses the
|
|
9066
|
+
// client `t()` — so the ?ppp-show-keys aid couldn't reach them. Consult key-mode here too:
|
|
9067
|
+
// when it's on, show the column's localization key (the one a consumer would override),
|
|
9068
|
+
// keyed by the column's OWN owning table (`resolvedColumn.tableName` — the related table
|
|
9069
|
+
// for a linked-entity column, not the grid's primary table). For linked columns the name
|
|
9070
|
+
// is a dotted alias path, so take the segment after the last dot as the real column name.
|
|
9071
|
+
header: () => isKeyModeEnabled() ? `tables.${resolvedColumn.tableName}.columns.${columnName.split(".").pop() ?? columnName}.label` : resolvedColumn.displayName,
|
|
9019
9072
|
cell: (cellCtx) => {
|
|
9020
9073
|
const rowRecord = cellCtx.row.original;
|
|
9021
9074
|
const rowId = rowRecord.id;
|
|
@@ -9158,18 +9211,6 @@ function MainGridImpl({
|
|
|
9158
9211
|
]);
|
|
9159
9212
|
const pageRecords = dataSource ? dataSource.rows : recordsResult.data?.tableRecords ?? EMPTY_RECORDS;
|
|
9160
9213
|
const [accumulatedRows, setAccumulatedRows] = useState(null);
|
|
9161
|
-
const accumulatorResetKey = useMemo(
|
|
9162
|
-
() => [
|
|
9163
|
-
resolvedViewId ?? "",
|
|
9164
|
-
useInlineFetchXml ? inlineFetchXml ?? "" : "",
|
|
9165
|
-
debouncedSearchText,
|
|
9166
|
-
sort.map((s) => `${s.columnName}:${s.descending ? "d" : "a"}`).join("|"),
|
|
9167
|
-
filtersKey,
|
|
9168
|
-
pageSize,
|
|
9169
|
-
tableName ?? ""
|
|
9170
|
-
].join("|"),
|
|
9171
|
-
[resolvedViewId, useInlineFetchXml, inlineFetchXml, debouncedSearchText, sort, filtersKey, pageSize, tableName]
|
|
9172
|
-
);
|
|
9173
9214
|
const resetVirtualizedView = useCallback(() => {
|
|
9174
9215
|
setAccumulatedRows([]);
|
|
9175
9216
|
setPage(1);
|
|
@@ -9195,6 +9236,12 @@ function MainGridImpl({
|
|
|
9195
9236
|
return [...base, ...additions];
|
|
9196
9237
|
});
|
|
9197
9238
|
}, [isVirtualize, recordsResult.status, pageRecords]);
|
|
9239
|
+
useEffect(() => {
|
|
9240
|
+
if (!isVirtualize) return;
|
|
9241
|
+
const landed = recordsResult.data;
|
|
9242
|
+
if (!landed) return;
|
|
9243
|
+
virtualizeCookies.record(accumulatorResetKey, page, landed.pagingInfo?.pagingCookie);
|
|
9244
|
+
}, [isVirtualize, recordsResult.data]);
|
|
9198
9245
|
const data = isVirtualize ? accumulatedRows ?? EMPTY_RECORDS : pageRecords;
|
|
9199
9246
|
const [pendingRowUpdates, setPendingRowUpdates] = useState(() => /* @__PURE__ */ new Map());
|
|
9200
9247
|
const [pendingRowCreates, setPendingRowCreates] = useState(() => []);
|
|
@@ -9675,7 +9722,15 @@ function MainGridImpl({
|
|
|
9675
9722
|
if (raw == null) return void 0;
|
|
9676
9723
|
return typeof raw === "number" ? raw : Number(raw);
|
|
9677
9724
|
})();
|
|
9678
|
-
const
|
|
9725
|
+
const hasMoreRowsToLoad2 = isVirtualize && hasMoreRowsToLoad({
|
|
9726
|
+
accumulatedCount: accumulatedRows?.length ?? 0,
|
|
9727
|
+
totalCount,
|
|
9728
|
+
moreRecords: dataSource ? dataSource.moreRecords : recordsResult.data?.pagingInfo?.moreRecords,
|
|
9729
|
+
// "A page has landed and it carried no rows." In standalone mode
|
|
9730
|
+
// `data` is only ever defined for a landed response (errors wipe it);
|
|
9731
|
+
// the datasource has no data handle, so idle-after-success stands in.
|
|
9732
|
+
lastPageEmpty: dataSource ? dataSource.status === QueryStatus.Success && !dataSource.isFetching && dataSource.rows.length === 0 : recordsResult.data !== void 0 && pageRecords.length === 0
|
|
9733
|
+
});
|
|
9679
9734
|
useEffect(() => {
|
|
9680
9735
|
if (!isVirtualize) return;
|
|
9681
9736
|
const sentinel = loadMoreSentinelRef.current;
|
|
@@ -9686,7 +9741,7 @@ function MainGridImpl({
|
|
|
9686
9741
|
const entry = entries[0];
|
|
9687
9742
|
if (!entry?.isIntersecting) return;
|
|
9688
9743
|
if (recordsResult.isFetching) return;
|
|
9689
|
-
if (!
|
|
9744
|
+
if (!hasMoreRowsToLoad2) return;
|
|
9690
9745
|
setPage(page + 1);
|
|
9691
9746
|
},
|
|
9692
9747
|
{
|
|
@@ -9699,7 +9754,7 @@ function MainGridImpl({
|
|
|
9699
9754
|
);
|
|
9700
9755
|
observer.observe(sentinel);
|
|
9701
9756
|
return () => observer.disconnect();
|
|
9702
|
-
}, [isVirtualize,
|
|
9757
|
+
}, [isVirtualize, hasMoreRowsToLoad2, recordsResult.isFetching, page, setPage]);
|
|
9703
9758
|
const handlePageChange = (nextPage) => {
|
|
9704
9759
|
if (nextPage === page) return;
|
|
9705
9760
|
setPage(nextPage);
|
|
@@ -10319,7 +10374,7 @@ function MainGridImpl({
|
|
|
10319
10374
|
}
|
|
10320
10375
|
),
|
|
10321
10376
|
displayedData.length === 0 && /* @__PURE__ */ jsx("div", { className: styles.emptyStateRow, children: t("app.components.grid.empty-content") }),
|
|
10322
|
-
isVirtualize &&
|
|
10377
|
+
isVirtualize && hasMoreRowsToLoad2 && // No spinner here: the full-body `refetchScrim` overlay below is the
|
|
10323
10378
|
// single load indicator. Rendering a `size="tiny"` spinner in the
|
|
10324
10379
|
// sentinel as well meant a deps-change refetch (refresh / sort /
|
|
10325
10380
|
// search / view switch) — which resets the accumulator to empty and
|
|
@@ -13558,27 +13613,57 @@ function NavMenu({ children, width, className, style }) {
|
|
|
13558
13613
|
useNavSelectedStyles();
|
|
13559
13614
|
const location = useLocation();
|
|
13560
13615
|
const navigate = useNavigate();
|
|
13561
|
-
const { allRoutes,
|
|
13616
|
+
const { allRoutes, groups, defaultOpenIndexes } = useMemo(
|
|
13562
13617
|
() => collectNavTree(children),
|
|
13563
13618
|
[children]
|
|
13564
13619
|
);
|
|
13565
|
-
const
|
|
13620
|
+
const selectedRoute = useMemo(
|
|
13566
13621
|
() => bestRouteMatch(allRoutes, location.pathname),
|
|
13567
13622
|
[allRoutes, location.pathname]
|
|
13568
13623
|
);
|
|
13624
|
+
const [openIndexes, setOpenIndexes] = useState(
|
|
13625
|
+
() => /* @__PURE__ */ new Set([
|
|
13626
|
+
...defaultOpenIndexes,
|
|
13627
|
+
// Seed the active route's group too, so it's open on first paint
|
|
13628
|
+
// (the effect below only fires after mount).
|
|
13629
|
+
...selectedRoute && selectedRoute.groupIndex >= 0 ? [selectedRoute.groupIndex] : []
|
|
13630
|
+
])
|
|
13631
|
+
);
|
|
13632
|
+
const selectedGroupIndex = selectedRoute?.groupIndex ?? -1;
|
|
13633
|
+
useEffect(() => {
|
|
13634
|
+
if (selectedGroupIndex < 0) return;
|
|
13635
|
+
setOpenIndexes(
|
|
13636
|
+
(prev) => prev.has(selectedGroupIndex) ? prev : new Set(prev).add(selectedGroupIndex)
|
|
13637
|
+
);
|
|
13638
|
+
}, [selectedGroupIndex]);
|
|
13639
|
+
const openCategories = useMemo(
|
|
13640
|
+
() => groups.filter((_, index) => openIndexes.has(index)),
|
|
13641
|
+
[groups, openIndexes]
|
|
13642
|
+
);
|
|
13569
13643
|
const handleSelect = (_, data) => {
|
|
13570
13644
|
const value = data.value;
|
|
13571
13645
|
if (typeof value === "string" && value.startsWith("/")) {
|
|
13572
13646
|
navigate(value);
|
|
13573
13647
|
}
|
|
13574
13648
|
};
|
|
13649
|
+
const handleCategoryToggle = (_, data) => {
|
|
13650
|
+
const index = groups.indexOf(data.value);
|
|
13651
|
+
if (index < 0) return;
|
|
13652
|
+
setOpenIndexes((prev) => {
|
|
13653
|
+
const next = new Set(prev);
|
|
13654
|
+
if (next.has(index)) next.delete(index);
|
|
13655
|
+
else next.add(index);
|
|
13656
|
+
return next;
|
|
13657
|
+
});
|
|
13658
|
+
};
|
|
13575
13659
|
const navStyle = width ? { ...style, minWidth: width, maxWidth: width } : style;
|
|
13576
13660
|
return /* @__PURE__ */ jsx(
|
|
13577
13661
|
Nav,
|
|
13578
13662
|
{
|
|
13579
|
-
selectedValue:
|
|
13663
|
+
selectedValue: selectedRoute?.to ?? "",
|
|
13580
13664
|
onNavItemSelect: handleSelect,
|
|
13581
|
-
|
|
13665
|
+
openCategories,
|
|
13666
|
+
onNavCategoryItemToggle: handleCategoryToggle,
|
|
13582
13667
|
className: mergeClasses("ppp-nav-menu", styles.nav, className),
|
|
13583
13668
|
style: navStyle,
|
|
13584
13669
|
children
|
|
@@ -13608,42 +13693,46 @@ function NavItem({ to, icon, children }) {
|
|
|
13608
13693
|
}
|
|
13609
13694
|
function collectNavTree(children) {
|
|
13610
13695
|
const allRoutes = [];
|
|
13611
|
-
const
|
|
13612
|
-
const
|
|
13696
|
+
const groups = [];
|
|
13697
|
+
const defaultOpenIndexes = [];
|
|
13698
|
+
const visit = (nodes, groupIndex) => {
|
|
13613
13699
|
Children.forEach(nodes, (child) => {
|
|
13614
13700
|
if (!isValidElement(child)) return;
|
|
13615
13701
|
if (child.type === NavGroup) {
|
|
13616
13702
|
const props = child.props;
|
|
13617
13703
|
const value = props.value ?? `group:${props.label}`;
|
|
13618
|
-
|
|
13619
|
-
|
|
13704
|
+
const index = groups.length;
|
|
13705
|
+
groups.push(value);
|
|
13706
|
+
if (props.defaultExpanded) defaultOpenIndexes.push(index);
|
|
13707
|
+
visit(props.children, index);
|
|
13620
13708
|
return;
|
|
13621
13709
|
}
|
|
13622
13710
|
if (child.type === NavItem) {
|
|
13623
13711
|
const props = child.props;
|
|
13624
13712
|
allRoutes.push({
|
|
13625
13713
|
to: props.to,
|
|
13626
|
-
match: props.match ?? (props.to === "/" ? "exact" : "prefix")
|
|
13714
|
+
match: props.match ?? (props.to === "/" ? "exact" : "prefix"),
|
|
13715
|
+
groupIndex
|
|
13627
13716
|
});
|
|
13628
13717
|
return;
|
|
13629
13718
|
}
|
|
13630
13719
|
const wrapperChildren = child.props.children;
|
|
13631
|
-
if (wrapperChildren !== void 0) visit(wrapperChildren);
|
|
13720
|
+
if (wrapperChildren !== void 0) visit(wrapperChildren, groupIndex);
|
|
13632
13721
|
});
|
|
13633
13722
|
};
|
|
13634
|
-
visit(children);
|
|
13635
|
-
return { allRoutes,
|
|
13723
|
+
visit(children, -1);
|
|
13724
|
+
return { allRoutes, groups, defaultOpenIndexes };
|
|
13636
13725
|
}
|
|
13637
13726
|
function bestRouteMatch(routes, pathname) {
|
|
13638
13727
|
const normalize = (p) => p.length > 1 && p.endsWith("/") ? p.slice(0, -1) : p;
|
|
13639
13728
|
const target = normalize(pathname);
|
|
13640
13729
|
let best;
|
|
13641
13730
|
let bestLen = -1;
|
|
13642
|
-
for (const
|
|
13643
|
-
const route = normalize(to);
|
|
13644
|
-
const matches = route === target || match === "prefix" && (route === "/" || target.startsWith(route + "/"));
|
|
13731
|
+
for (const candidate of routes) {
|
|
13732
|
+
const route = normalize(candidate.to);
|
|
13733
|
+
const matches = route === target || candidate.match === "prefix" && (route === "/" || target.startsWith(route + "/"));
|
|
13645
13734
|
if (matches && route.length > bestLen) {
|
|
13646
|
-
best =
|
|
13735
|
+
best = candidate;
|
|
13647
13736
|
bestLen = route.length;
|
|
13648
13737
|
}
|
|
13649
13738
|
}
|
|
@@ -14386,8 +14475,40 @@ var useStyles12 = makeStyles({
|
|
|
14386
14475
|
mergedButtons: {
|
|
14387
14476
|
display: "flex",
|
|
14388
14477
|
flexWrap: "wrap",
|
|
14389
|
-
gap: tokens.
|
|
14478
|
+
gap: tokens.spacingHorizontalL
|
|
14479
|
+
},
|
|
14480
|
+
// One culture group: language label + inspect button + download button, kept together.
|
|
14481
|
+
mergedCulture: {
|
|
14482
|
+
display: "flex",
|
|
14483
|
+
alignItems: "center",
|
|
14484
|
+
gap: tokens.spacingHorizontalXS
|
|
14485
|
+
},
|
|
14486
|
+
mergedCultureLabel: { fontSize: tokens.fontSizeBase200 },
|
|
14487
|
+
dialogSurface: { maxWidth: "1100px", width: "90vw" },
|
|
14488
|
+
dialogToolbar: {
|
|
14489
|
+
display: "flex",
|
|
14490
|
+
alignItems: "center",
|
|
14491
|
+
gap: tokens.spacingHorizontalM,
|
|
14492
|
+
flexWrap: "wrap",
|
|
14493
|
+
marginBottom: tokens.spacingVerticalS
|
|
14494
|
+
},
|
|
14495
|
+
// Scroll viewport for the merged grid so a tall result set scrolls inside the dialog.
|
|
14496
|
+
dialogGrid: { maxHeight: "60vh", overflowY: "auto", overflowX: "auto" },
|
|
14497
|
+
// Merged-snapshot cells. Keys and sources are long single tokens (dotted keys,
|
|
14498
|
+
// backslash-only absolute paths) with no natural break opportunity, so without
|
|
14499
|
+
// this the text paints straight over the neighbouring column. `overflow-wrap:
|
|
14500
|
+
// anywhere` (not just `break-word`) is what makes the flex cell honour its
|
|
14501
|
+
// column width — it counts the soft breaks toward min-content — so the token
|
|
14502
|
+
// wraps inside the column instead of stretching it. Same recipe as
|
|
14503
|
+
// `sourceCell` in the per-source loads table above.
|
|
14504
|
+
mergedCell: {
|
|
14505
|
+
whiteSpace: "normal",
|
|
14506
|
+
overflowWrap: "anywhere",
|
|
14507
|
+
wordBreak: "break-word"
|
|
14390
14508
|
},
|
|
14509
|
+
filterInput: { minWidth: "260px" },
|
|
14510
|
+
pager: { display: "flex", alignItems: "center", gap: tokens.spacingHorizontalS },
|
|
14511
|
+
grow: { flex: 1 },
|
|
14391
14512
|
sectionBody: {
|
|
14392
14513
|
display: "flex",
|
|
14393
14514
|
flexDirection: "column",
|
|
@@ -14406,6 +14527,15 @@ function downloadBytes(fileName, data, contentType = "application/json") {
|
|
|
14406
14527
|
anchor.click();
|
|
14407
14528
|
URL.revokeObjectURL(url);
|
|
14408
14529
|
}
|
|
14530
|
+
var kindKeyOf = (kind) => KIND_KEY[Number(kind)] ?? "tablemetadata";
|
|
14531
|
+
function cultureLabel(culture) {
|
|
14532
|
+
try {
|
|
14533
|
+
const name = new Intl.DisplayNames(void 0, { type: "language" }).of(culture);
|
|
14534
|
+
return name && name.toLowerCase() !== culture.toLowerCase() ? `${name} (${culture})` : culture;
|
|
14535
|
+
} catch {
|
|
14536
|
+
return culture;
|
|
14537
|
+
}
|
|
14538
|
+
}
|
|
14409
14539
|
function LocalizationAdmin({ className }) {
|
|
14410
14540
|
const styles = useStyles12();
|
|
14411
14541
|
const t = useT();
|
|
@@ -14415,6 +14545,7 @@ function LocalizationAdmin({ className }) {
|
|
|
14415
14545
|
const [isReloading, setIsReloading] = useState(false);
|
|
14416
14546
|
const [isDownloading, setIsDownloading] = useState(false);
|
|
14417
14547
|
const [message, setMessage] = useState();
|
|
14548
|
+
const [mergedDialogCulture, setMergedDialogCulture] = useState(null);
|
|
14418
14549
|
const loadOverview = useCallback(async () => {
|
|
14419
14550
|
try {
|
|
14420
14551
|
const value = await ppp.getLocalizationOverviewAsync();
|
|
@@ -14572,17 +14703,44 @@ function LocalizationAdmin({ className }) {
|
|
|
14572
14703
|
/* @__PURE__ */ jsx(LocalizationTranslator, {}),
|
|
14573
14704
|
availableCultures.length > 0 && /* @__PURE__ */ jsx(Section, { headerText: t("app.localization-admin.download-merged-title"), borderVisible: true, children: /* @__PURE__ */ jsx(SectionColumn, { children: /* @__PURE__ */ jsxs("div", { className: styles.sectionBody, children: [
|
|
14574
14705
|
/* @__PURE__ */ jsx(Text, { children: t("app.localization-admin.download-merged-description") }),
|
|
14575
|
-
/* @__PURE__ */ jsx("div", { className: styles.mergedButtons, children: availableCultures.map((culture) => /* @__PURE__ */
|
|
14576
|
-
|
|
14577
|
-
|
|
14578
|
-
|
|
14579
|
-
|
|
14580
|
-
|
|
14581
|
-
|
|
14582
|
-
|
|
14583
|
-
|
|
14584
|
-
|
|
14585
|
-
|
|
14706
|
+
/* @__PURE__ */ jsx("div", { className: styles.mergedButtons, children: availableCultures.map((culture) => /* @__PURE__ */ jsxs("div", { className: styles.mergedCulture, children: [
|
|
14707
|
+
/* @__PURE__ */ jsx("span", { className: styles.mergedCultureLabel, children: cultureLabel(culture) }),
|
|
14708
|
+
/* @__PURE__ */ jsx(
|
|
14709
|
+
Tooltip,
|
|
14710
|
+
{
|
|
14711
|
+
content: t("app.localization-admin.view-merged-tooltip", [
|
|
14712
|
+
cultureLabel(culture)
|
|
14713
|
+
]),
|
|
14714
|
+
relationship: "label",
|
|
14715
|
+
children: /* @__PURE__ */ jsx(
|
|
14716
|
+
Button,
|
|
14717
|
+
{
|
|
14718
|
+
appearance: "outline",
|
|
14719
|
+
icon: /* @__PURE__ */ jsx(EyeRegular, {}),
|
|
14720
|
+
onClick: () => setMergedDialogCulture(culture)
|
|
14721
|
+
}
|
|
14722
|
+
)
|
|
14723
|
+
}
|
|
14724
|
+
),
|
|
14725
|
+
/* @__PURE__ */ jsx(
|
|
14726
|
+
Tooltip,
|
|
14727
|
+
{
|
|
14728
|
+
content: t("app.localization-admin.download-merged-tooltip", [
|
|
14729
|
+
cultureLabel(culture)
|
|
14730
|
+
]),
|
|
14731
|
+
relationship: "label",
|
|
14732
|
+
children: /* @__PURE__ */ jsx(
|
|
14733
|
+
Button,
|
|
14734
|
+
{
|
|
14735
|
+
appearance: "subtle",
|
|
14736
|
+
disabled: isDownloading,
|
|
14737
|
+
icon: /* @__PURE__ */ jsx(ArrowDownloadRegular, {}),
|
|
14738
|
+
onClick: () => onDownloadMerged(culture)
|
|
14739
|
+
}
|
|
14740
|
+
)
|
|
14741
|
+
}
|
|
14742
|
+
)
|
|
14743
|
+
] }, culture)) })
|
|
14586
14744
|
] }) }) }),
|
|
14587
14745
|
/* @__PURE__ */ jsx(Section, { headerText: t("app.localization-admin.sources-title"), borderVisible: true, children: /* @__PURE__ */ jsx(SectionColumn, { children: /* @__PURE__ */ jsxs("div", { className: styles.sectionBody, children: [
|
|
14588
14746
|
/* @__PURE__ */ jsx(Text, { children: t("app.localization-admin.sources-description") }),
|
|
@@ -14613,7 +14771,22 @@ function LocalizationAdmin({ className }) {
|
|
|
14613
14771
|
] }) }) })
|
|
14614
14772
|
] });
|
|
14615
14773
|
}
|
|
14616
|
-
return /* @__PURE__ */
|
|
14774
|
+
return /* @__PURE__ */ jsxs("div", { className: mergeClasses("ppp-localization-admin", styles.root, className), children: [
|
|
14775
|
+
content,
|
|
14776
|
+
mergedDialogCulture !== null && /* @__PURE__ */ jsx(
|
|
14777
|
+
MergedSourcesDialog,
|
|
14778
|
+
{
|
|
14779
|
+
culture: mergedDialogCulture,
|
|
14780
|
+
label: cultureLabel(mergedDialogCulture),
|
|
14781
|
+
onClose: () => setMergedDialogCulture(null),
|
|
14782
|
+
onDownload: () => onDownloadMerged(mergedDialogCulture),
|
|
14783
|
+
isDownloading,
|
|
14784
|
+
ppp,
|
|
14785
|
+
t,
|
|
14786
|
+
styles
|
|
14787
|
+
}
|
|
14788
|
+
)
|
|
14789
|
+
] });
|
|
14617
14790
|
}
|
|
14618
14791
|
function ConfigRow({ styles, label, value }) {
|
|
14619
14792
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
@@ -14663,6 +14836,177 @@ function SourceRow({
|
|
|
14663
14836
|
)) }) })
|
|
14664
14837
|
] });
|
|
14665
14838
|
}
|
|
14839
|
+
var MERGED_PAGE_SIZE = 100;
|
|
14840
|
+
function MergedSourcesDialog({
|
|
14841
|
+
culture,
|
|
14842
|
+
label,
|
|
14843
|
+
onClose,
|
|
14844
|
+
onDownload,
|
|
14845
|
+
isDownloading,
|
|
14846
|
+
ppp,
|
|
14847
|
+
t,
|
|
14848
|
+
styles
|
|
14849
|
+
}) {
|
|
14850
|
+
const [entries, setEntries] = useState(null);
|
|
14851
|
+
const [loadError, setLoadError] = useState();
|
|
14852
|
+
const [filter, setFilter] = useState("");
|
|
14853
|
+
const [page, setPage] = useState(0);
|
|
14854
|
+
const [sortState, setSortState] = useState({
|
|
14855
|
+
sortColumn: "key",
|
|
14856
|
+
sortDirection: "ascending"
|
|
14857
|
+
});
|
|
14858
|
+
useEffect(() => {
|
|
14859
|
+
let cancelled = false;
|
|
14860
|
+
void (async () => {
|
|
14861
|
+
try {
|
|
14862
|
+
const value = await ppp.getMergedLocalizationEntriesAsync(culture);
|
|
14863
|
+
if (!cancelled) {
|
|
14864
|
+
setEntries(value);
|
|
14865
|
+
setLoadError(void 0);
|
|
14866
|
+
}
|
|
14867
|
+
} catch (reason) {
|
|
14868
|
+
if (!cancelled) {
|
|
14869
|
+
setEntries(null);
|
|
14870
|
+
setLoadError(reason instanceof Error ? reason.message : String(reason));
|
|
14871
|
+
}
|
|
14872
|
+
}
|
|
14873
|
+
})();
|
|
14874
|
+
return () => {
|
|
14875
|
+
cancelled = true;
|
|
14876
|
+
};
|
|
14877
|
+
}, [ppp, culture]);
|
|
14878
|
+
const columns = useMemo(
|
|
14879
|
+
() => [
|
|
14880
|
+
createTableColumn({
|
|
14881
|
+
columnId: "key",
|
|
14882
|
+
compare: (a, b) => a.key.localeCompare(b.key),
|
|
14883
|
+
renderHeaderCell: () => t("app.localization-admin.merged-column-key"),
|
|
14884
|
+
renderCell: (item) => item.key
|
|
14885
|
+
}),
|
|
14886
|
+
createTableColumn({
|
|
14887
|
+
columnId: "kind",
|
|
14888
|
+
compare: (a, b) => Number(a.sourceKind) - Number(b.sourceKind),
|
|
14889
|
+
renderHeaderCell: () => t("app.localization-admin.merged-column-kind"),
|
|
14890
|
+
renderCell: (item) => t(`app.localization-admin.kind-${kindKeyOf(item.sourceKind)}`)
|
|
14891
|
+
}),
|
|
14892
|
+
createTableColumn({
|
|
14893
|
+
columnId: "source",
|
|
14894
|
+
compare: (a, b) => a.sourceDisplayName.localeCompare(b.sourceDisplayName),
|
|
14895
|
+
renderHeaderCell: () => t("app.localization-admin.merged-column-source"),
|
|
14896
|
+
renderCell: (item) => item.sourceDisplayName
|
|
14897
|
+
}),
|
|
14898
|
+
createTableColumn({
|
|
14899
|
+
columnId: "value",
|
|
14900
|
+
compare: (a, b) => a.value.localeCompare(b.value),
|
|
14901
|
+
renderHeaderCell: () => t("app.localization-admin.merged-column-value"),
|
|
14902
|
+
renderCell: (item) => item.value
|
|
14903
|
+
})
|
|
14904
|
+
],
|
|
14905
|
+
[t]
|
|
14906
|
+
);
|
|
14907
|
+
const filtered = useMemo(() => {
|
|
14908
|
+
if (!entries) return [];
|
|
14909
|
+
const q = filter.trim().toLowerCase();
|
|
14910
|
+
const base = q ? entries.filter(
|
|
14911
|
+
(e) => e.key.toLowerCase().includes(q) || e.value.toLowerCase().includes(q) || e.sourceDisplayName.toLowerCase().includes(q)
|
|
14912
|
+
) : entries;
|
|
14913
|
+
return [...base];
|
|
14914
|
+
}, [entries, filter]);
|
|
14915
|
+
const sorted = useMemo(() => {
|
|
14916
|
+
const column = columns.find((c) => c.columnId === sortState.sortColumn);
|
|
14917
|
+
if (!column?.compare) return filtered;
|
|
14918
|
+
const sign = sortState.sortDirection === "ascending" ? 1 : -1;
|
|
14919
|
+
return [...filtered].sort((a, b) => sign * column.compare(a, b));
|
|
14920
|
+
}, [filtered, columns, sortState]);
|
|
14921
|
+
useEffect(() => {
|
|
14922
|
+
setPage(0);
|
|
14923
|
+
}, [filter, sortState]);
|
|
14924
|
+
const pageCount = Math.max(1, Math.ceil(sorted.length / MERGED_PAGE_SIZE));
|
|
14925
|
+
const currentPage = Math.min(page, pageCount - 1);
|
|
14926
|
+
const paged = sorted.slice(currentPage * MERGED_PAGE_SIZE, currentPage * MERGED_PAGE_SIZE + MERGED_PAGE_SIZE);
|
|
14927
|
+
const columnSizingOptions = useMemo(
|
|
14928
|
+
() => ({
|
|
14929
|
+
key: { minWidth: 200, defaultWidth: 320 },
|
|
14930
|
+
kind: { minWidth: 110, defaultWidth: 140 },
|
|
14931
|
+
source: { minWidth: 200, defaultWidth: 300 },
|
|
14932
|
+
value: { minWidth: 200, defaultWidth: 360 }
|
|
14933
|
+
}),
|
|
14934
|
+
[]
|
|
14935
|
+
);
|
|
14936
|
+
return /* @__PURE__ */ jsx(Dialog, { open: true, onOpenChange: (_event, data) => !data.open && onClose(), children: /* @__PURE__ */ jsx(DialogSurface, { className: styles.dialogSurface, children: /* @__PURE__ */ jsxs(DialogBody, { children: [
|
|
14937
|
+
/* @__PURE__ */ jsx(DialogTitle, { children: t("app.localization-admin.merged-dialog-title", [label]) }),
|
|
14938
|
+
/* @__PURE__ */ jsx(DialogContent, { children: loadError !== void 0 ? /* @__PURE__ */ jsx(MessageBar, { intent: "error", children: /* @__PURE__ */ jsx(MessageBarBody, { children: t("app.localization-admin.merged-load-failed", [loadError]) }) }) : entries === null ? /* @__PURE__ */ jsx(Spinner, {}) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
14939
|
+
/* @__PURE__ */ jsxs("div", { className: styles.dialogToolbar, children: [
|
|
14940
|
+
/* @__PURE__ */ jsx(
|
|
14941
|
+
Input,
|
|
14942
|
+
{
|
|
14943
|
+
className: styles.filterInput,
|
|
14944
|
+
value: filter,
|
|
14945
|
+
onChange: (_event, data) => setFilter(data.value),
|
|
14946
|
+
contentBefore: /* @__PURE__ */ jsx(SearchRegular, {}),
|
|
14947
|
+
placeholder: t("app.localization-admin.merged-filter-placeholder")
|
|
14948
|
+
}
|
|
14949
|
+
),
|
|
14950
|
+
/* @__PURE__ */ jsx("span", { className: styles.lastReloaded, children: t("app.localization-admin.merged-count", [sorted.length, entries.length]) }),
|
|
14951
|
+
/* @__PURE__ */ jsx("span", { className: styles.grow }),
|
|
14952
|
+
pageCount > 1 && /* @__PURE__ */ jsxs("span", { className: styles.pager, children: [
|
|
14953
|
+
/* @__PURE__ */ jsx(
|
|
14954
|
+
Button,
|
|
14955
|
+
{
|
|
14956
|
+
size: "small",
|
|
14957
|
+
appearance: "subtle",
|
|
14958
|
+
disabled: currentPage === 0,
|
|
14959
|
+
onClick: () => setPage(currentPage - 1),
|
|
14960
|
+
children: t("app.localization-admin.merged-prev")
|
|
14961
|
+
}
|
|
14962
|
+
),
|
|
14963
|
+
/* @__PURE__ */ jsx("span", { className: styles.lastReloaded, children: t("app.localization-admin.merged-page", [currentPage + 1, pageCount]) }),
|
|
14964
|
+
/* @__PURE__ */ jsx(
|
|
14965
|
+
Button,
|
|
14966
|
+
{
|
|
14967
|
+
size: "small",
|
|
14968
|
+
appearance: "subtle",
|
|
14969
|
+
disabled: currentPage >= pageCount - 1,
|
|
14970
|
+
onClick: () => setPage(currentPage + 1),
|
|
14971
|
+
children: t("app.localization-admin.merged-next")
|
|
14972
|
+
}
|
|
14973
|
+
)
|
|
14974
|
+
] })
|
|
14975
|
+
] }),
|
|
14976
|
+
sorted.length === 0 ? /* @__PURE__ */ jsx(MessageBar, { intent: "info", children: /* @__PURE__ */ jsx(MessageBarBody, { children: t("app.localization-admin.merged-empty") }) }) : /* @__PURE__ */ jsx("div", { className: styles.dialogGrid, children: /* @__PURE__ */ jsxs(
|
|
14977
|
+
DataGrid,
|
|
14978
|
+
{
|
|
14979
|
+
items: paged,
|
|
14980
|
+
columns,
|
|
14981
|
+
sortable: true,
|
|
14982
|
+
resizableColumns: true,
|
|
14983
|
+
sortState,
|
|
14984
|
+
onSortChange: (_event, next) => setSortState(next),
|
|
14985
|
+
columnSizingOptions,
|
|
14986
|
+
getRowId: (item) => item.key,
|
|
14987
|
+
size: "small",
|
|
14988
|
+
children: [
|
|
14989
|
+
/* @__PURE__ */ jsx(DataGridHeader, { children: /* @__PURE__ */ jsx(DataGridRow, { children: ({ renderHeaderCell }) => /* @__PURE__ */ jsx(DataGridHeaderCell, { children: renderHeaderCell() }) }) }),
|
|
14990
|
+
/* @__PURE__ */ jsx(DataGridBody, { children: ({ item, rowId }) => /* @__PURE__ */ jsx(DataGridRow, { children: ({ renderCell }) => /* @__PURE__ */ jsx(DataGridCell, { className: styles.mergedCell, children: renderCell(item) }) }, rowId) })
|
|
14991
|
+
]
|
|
14992
|
+
}
|
|
14993
|
+
) })
|
|
14994
|
+
] }) }),
|
|
14995
|
+
/* @__PURE__ */ jsxs(DialogActions, { children: [
|
|
14996
|
+
/* @__PURE__ */ jsx(
|
|
14997
|
+
Button,
|
|
14998
|
+
{
|
|
14999
|
+
appearance: "primary",
|
|
15000
|
+
icon: /* @__PURE__ */ jsx(ArrowDownloadRegular, {}),
|
|
15001
|
+
disabled: isDownloading,
|
|
15002
|
+
onClick: onDownload,
|
|
15003
|
+
children: t("app.localization-admin.merged-download-button")
|
|
15004
|
+
}
|
|
15005
|
+
),
|
|
15006
|
+
/* @__PURE__ */ jsx(Button, { appearance: "secondary", icon: /* @__PURE__ */ jsx(DismissRegular, {}), onClick: onClose, children: t("app.buttons.close.label") })
|
|
15007
|
+
] })
|
|
15008
|
+
] }) }) });
|
|
15009
|
+
}
|
|
14666
15010
|
var useStyles13 = makeStyles({
|
|
14667
15011
|
root: {
|
|
14668
15012
|
display: "flex",
|