@powerportalspro/react-fluent 5.1.0 → 6.0.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 +313 -30
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +316 -33
- package/dist/index.js.map +1 -1
- package/package.json +7 -6
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';
|
|
@@ -9015,7 +9015,13 @@ function MainGridImpl({
|
|
|
9015
9015
|
(row) => row.properties?.[columnName],
|
|
9016
9016
|
{
|
|
9017
9017
|
id: columnName,
|
|
9018
|
-
|
|
9018
|
+
// Headers normally show the server-resolved Dataverse display name, which bypasses the
|
|
9019
|
+
// client `t()` — so the ?ppp-show-keys aid couldn't reach them. Consult key-mode here too:
|
|
9020
|
+
// when it's on, show the column's localization key (the one a consumer would override),
|
|
9021
|
+
// keyed by the column's OWN owning table (`resolvedColumn.tableName` — the related table
|
|
9022
|
+
// for a linked-entity column, not the grid's primary table). For linked columns the name
|
|
9023
|
+
// is a dotted alias path, so take the segment after the last dot as the real column name.
|
|
9024
|
+
header: () => isKeyModeEnabled() ? `tables.${resolvedColumn.tableName}.columns.${columnName.split(".").pop() ?? columnName}.label` : resolvedColumn.displayName,
|
|
9019
9025
|
cell: (cellCtx) => {
|
|
9020
9026
|
const rowRecord = cellCtx.row.original;
|
|
9021
9027
|
const rowId = rowRecord.id;
|
|
@@ -13558,27 +13564,57 @@ function NavMenu({ children, width, className, style }) {
|
|
|
13558
13564
|
useNavSelectedStyles();
|
|
13559
13565
|
const location = useLocation();
|
|
13560
13566
|
const navigate = useNavigate();
|
|
13561
|
-
const { allRoutes,
|
|
13567
|
+
const { allRoutes, groups, defaultOpenIndexes } = useMemo(
|
|
13562
13568
|
() => collectNavTree(children),
|
|
13563
13569
|
[children]
|
|
13564
13570
|
);
|
|
13565
|
-
const
|
|
13571
|
+
const selectedRoute = useMemo(
|
|
13566
13572
|
() => bestRouteMatch(allRoutes, location.pathname),
|
|
13567
13573
|
[allRoutes, location.pathname]
|
|
13568
13574
|
);
|
|
13575
|
+
const [openIndexes, setOpenIndexes] = useState(
|
|
13576
|
+
() => /* @__PURE__ */ new Set([
|
|
13577
|
+
...defaultOpenIndexes,
|
|
13578
|
+
// Seed the active route's group too, so it's open on first paint
|
|
13579
|
+
// (the effect below only fires after mount).
|
|
13580
|
+
...selectedRoute && selectedRoute.groupIndex >= 0 ? [selectedRoute.groupIndex] : []
|
|
13581
|
+
])
|
|
13582
|
+
);
|
|
13583
|
+
const selectedGroupIndex = selectedRoute?.groupIndex ?? -1;
|
|
13584
|
+
useEffect(() => {
|
|
13585
|
+
if (selectedGroupIndex < 0) return;
|
|
13586
|
+
setOpenIndexes(
|
|
13587
|
+
(prev) => prev.has(selectedGroupIndex) ? prev : new Set(prev).add(selectedGroupIndex)
|
|
13588
|
+
);
|
|
13589
|
+
}, [selectedGroupIndex]);
|
|
13590
|
+
const openCategories = useMemo(
|
|
13591
|
+
() => groups.filter((_, index) => openIndexes.has(index)),
|
|
13592
|
+
[groups, openIndexes]
|
|
13593
|
+
);
|
|
13569
13594
|
const handleSelect = (_, data) => {
|
|
13570
13595
|
const value = data.value;
|
|
13571
13596
|
if (typeof value === "string" && value.startsWith("/")) {
|
|
13572
13597
|
navigate(value);
|
|
13573
13598
|
}
|
|
13574
13599
|
};
|
|
13600
|
+
const handleCategoryToggle = (_, data) => {
|
|
13601
|
+
const index = groups.indexOf(data.value);
|
|
13602
|
+
if (index < 0) return;
|
|
13603
|
+
setOpenIndexes((prev) => {
|
|
13604
|
+
const next = new Set(prev);
|
|
13605
|
+
if (next.has(index)) next.delete(index);
|
|
13606
|
+
else next.add(index);
|
|
13607
|
+
return next;
|
|
13608
|
+
});
|
|
13609
|
+
};
|
|
13575
13610
|
const navStyle = width ? { ...style, minWidth: width, maxWidth: width } : style;
|
|
13576
13611
|
return /* @__PURE__ */ jsx(
|
|
13577
13612
|
Nav,
|
|
13578
13613
|
{
|
|
13579
|
-
selectedValue:
|
|
13614
|
+
selectedValue: selectedRoute?.to ?? "",
|
|
13580
13615
|
onNavItemSelect: handleSelect,
|
|
13581
|
-
|
|
13616
|
+
openCategories,
|
|
13617
|
+
onNavCategoryItemToggle: handleCategoryToggle,
|
|
13582
13618
|
className: mergeClasses("ppp-nav-menu", styles.nav, className),
|
|
13583
13619
|
style: navStyle,
|
|
13584
13620
|
children
|
|
@@ -13608,42 +13644,46 @@ function NavItem({ to, icon, children }) {
|
|
|
13608
13644
|
}
|
|
13609
13645
|
function collectNavTree(children) {
|
|
13610
13646
|
const allRoutes = [];
|
|
13611
|
-
const
|
|
13612
|
-
const
|
|
13647
|
+
const groups = [];
|
|
13648
|
+
const defaultOpenIndexes = [];
|
|
13649
|
+
const visit = (nodes, groupIndex) => {
|
|
13613
13650
|
Children.forEach(nodes, (child) => {
|
|
13614
13651
|
if (!isValidElement(child)) return;
|
|
13615
13652
|
if (child.type === NavGroup) {
|
|
13616
13653
|
const props = child.props;
|
|
13617
13654
|
const value = props.value ?? `group:${props.label}`;
|
|
13618
|
-
|
|
13619
|
-
|
|
13655
|
+
const index = groups.length;
|
|
13656
|
+
groups.push(value);
|
|
13657
|
+
if (props.defaultExpanded) defaultOpenIndexes.push(index);
|
|
13658
|
+
visit(props.children, index);
|
|
13620
13659
|
return;
|
|
13621
13660
|
}
|
|
13622
13661
|
if (child.type === NavItem) {
|
|
13623
13662
|
const props = child.props;
|
|
13624
13663
|
allRoutes.push({
|
|
13625
13664
|
to: props.to,
|
|
13626
|
-
match: props.match ?? (props.to === "/" ? "exact" : "prefix")
|
|
13665
|
+
match: props.match ?? (props.to === "/" ? "exact" : "prefix"),
|
|
13666
|
+
groupIndex
|
|
13627
13667
|
});
|
|
13628
13668
|
return;
|
|
13629
13669
|
}
|
|
13630
13670
|
const wrapperChildren = child.props.children;
|
|
13631
|
-
if (wrapperChildren !== void 0) visit(wrapperChildren);
|
|
13671
|
+
if (wrapperChildren !== void 0) visit(wrapperChildren, groupIndex);
|
|
13632
13672
|
});
|
|
13633
13673
|
};
|
|
13634
|
-
visit(children);
|
|
13635
|
-
return { allRoutes,
|
|
13674
|
+
visit(children, -1);
|
|
13675
|
+
return { allRoutes, groups, defaultOpenIndexes };
|
|
13636
13676
|
}
|
|
13637
13677
|
function bestRouteMatch(routes, pathname) {
|
|
13638
13678
|
const normalize = (p) => p.length > 1 && p.endsWith("/") ? p.slice(0, -1) : p;
|
|
13639
13679
|
const target = normalize(pathname);
|
|
13640
13680
|
let best;
|
|
13641
13681
|
let bestLen = -1;
|
|
13642
|
-
for (const
|
|
13643
|
-
const route = normalize(to);
|
|
13644
|
-
const matches = route === target || match === "prefix" && (route === "/" || target.startsWith(route + "/"));
|
|
13682
|
+
for (const candidate of routes) {
|
|
13683
|
+
const route = normalize(candidate.to);
|
|
13684
|
+
const matches = route === target || candidate.match === "prefix" && (route === "/" || target.startsWith(route + "/"));
|
|
13645
13685
|
if (matches && route.length > bestLen) {
|
|
13646
|
-
best =
|
|
13686
|
+
best = candidate;
|
|
13647
13687
|
bestLen = route.length;
|
|
13648
13688
|
}
|
|
13649
13689
|
}
|
|
@@ -14386,8 +14426,28 @@ var useStyles12 = makeStyles({
|
|
|
14386
14426
|
mergedButtons: {
|
|
14387
14427
|
display: "flex",
|
|
14388
14428
|
flexWrap: "wrap",
|
|
14389
|
-
gap: tokens.
|
|
14429
|
+
gap: tokens.spacingHorizontalL
|
|
14430
|
+
},
|
|
14431
|
+
// One culture group: language label + inspect button + download button, kept together.
|
|
14432
|
+
mergedCulture: {
|
|
14433
|
+
display: "flex",
|
|
14434
|
+
alignItems: "center",
|
|
14435
|
+
gap: tokens.spacingHorizontalXS
|
|
14390
14436
|
},
|
|
14437
|
+
mergedCultureLabel: { fontSize: tokens.fontSizeBase200 },
|
|
14438
|
+
dialogSurface: { maxWidth: "1100px", width: "90vw" },
|
|
14439
|
+
dialogToolbar: {
|
|
14440
|
+
display: "flex",
|
|
14441
|
+
alignItems: "center",
|
|
14442
|
+
gap: tokens.spacingHorizontalM,
|
|
14443
|
+
flexWrap: "wrap",
|
|
14444
|
+
marginBottom: tokens.spacingVerticalS
|
|
14445
|
+
},
|
|
14446
|
+
// Scroll viewport for the merged grid so a tall result set scrolls inside the dialog.
|
|
14447
|
+
dialogGrid: { maxHeight: "60vh", overflowY: "auto", overflowX: "auto" },
|
|
14448
|
+
filterInput: { minWidth: "260px" },
|
|
14449
|
+
pager: { display: "flex", alignItems: "center", gap: tokens.spacingHorizontalS },
|
|
14450
|
+
grow: { flex: 1 },
|
|
14391
14451
|
sectionBody: {
|
|
14392
14452
|
display: "flex",
|
|
14393
14453
|
flexDirection: "column",
|
|
@@ -14406,6 +14466,15 @@ function downloadBytes(fileName, data, contentType = "application/json") {
|
|
|
14406
14466
|
anchor.click();
|
|
14407
14467
|
URL.revokeObjectURL(url);
|
|
14408
14468
|
}
|
|
14469
|
+
var kindKeyOf = (kind) => KIND_KEY[Number(kind)] ?? "tablemetadata";
|
|
14470
|
+
function cultureLabel(culture) {
|
|
14471
|
+
try {
|
|
14472
|
+
const name = new Intl.DisplayNames(void 0, { type: "language" }).of(culture);
|
|
14473
|
+
return name && name.toLowerCase() !== culture.toLowerCase() ? `${name} (${culture})` : culture;
|
|
14474
|
+
} catch {
|
|
14475
|
+
return culture;
|
|
14476
|
+
}
|
|
14477
|
+
}
|
|
14409
14478
|
function LocalizationAdmin({ className }) {
|
|
14410
14479
|
const styles = useStyles12();
|
|
14411
14480
|
const t = useT();
|
|
@@ -14415,6 +14484,7 @@ function LocalizationAdmin({ className }) {
|
|
|
14415
14484
|
const [isReloading, setIsReloading] = useState(false);
|
|
14416
14485
|
const [isDownloading, setIsDownloading] = useState(false);
|
|
14417
14486
|
const [message, setMessage] = useState();
|
|
14487
|
+
const [mergedDialogCulture, setMergedDialogCulture] = useState(null);
|
|
14418
14488
|
const loadOverview = useCallback(async () => {
|
|
14419
14489
|
try {
|
|
14420
14490
|
const value = await ppp.getLocalizationOverviewAsync();
|
|
@@ -14572,17 +14642,44 @@ function LocalizationAdmin({ className }) {
|
|
|
14572
14642
|
/* @__PURE__ */ jsx(LocalizationTranslator, {}),
|
|
14573
14643
|
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
14644
|
/* @__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
|
-
|
|
14645
|
+
/* @__PURE__ */ jsx("div", { className: styles.mergedButtons, children: availableCultures.map((culture) => /* @__PURE__ */ jsxs("div", { className: styles.mergedCulture, children: [
|
|
14646
|
+
/* @__PURE__ */ jsx("span", { className: styles.mergedCultureLabel, children: cultureLabel(culture) }),
|
|
14647
|
+
/* @__PURE__ */ jsx(
|
|
14648
|
+
Tooltip,
|
|
14649
|
+
{
|
|
14650
|
+
content: t("app.localization-admin.view-merged-tooltip", [
|
|
14651
|
+
cultureLabel(culture)
|
|
14652
|
+
]),
|
|
14653
|
+
relationship: "label",
|
|
14654
|
+
children: /* @__PURE__ */ jsx(
|
|
14655
|
+
Button,
|
|
14656
|
+
{
|
|
14657
|
+
appearance: "outline",
|
|
14658
|
+
icon: /* @__PURE__ */ jsx(EyeRegular, {}),
|
|
14659
|
+
onClick: () => setMergedDialogCulture(culture)
|
|
14660
|
+
}
|
|
14661
|
+
)
|
|
14662
|
+
}
|
|
14663
|
+
),
|
|
14664
|
+
/* @__PURE__ */ jsx(
|
|
14665
|
+
Tooltip,
|
|
14666
|
+
{
|
|
14667
|
+
content: t("app.localization-admin.download-merged-tooltip", [
|
|
14668
|
+
cultureLabel(culture)
|
|
14669
|
+
]),
|
|
14670
|
+
relationship: "label",
|
|
14671
|
+
children: /* @__PURE__ */ jsx(
|
|
14672
|
+
Button,
|
|
14673
|
+
{
|
|
14674
|
+
appearance: "subtle",
|
|
14675
|
+
disabled: isDownloading,
|
|
14676
|
+
icon: /* @__PURE__ */ jsx(ArrowDownloadRegular, {}),
|
|
14677
|
+
onClick: () => onDownloadMerged(culture)
|
|
14678
|
+
}
|
|
14679
|
+
)
|
|
14680
|
+
}
|
|
14681
|
+
)
|
|
14682
|
+
] }, culture)) })
|
|
14586
14683
|
] }) }) }),
|
|
14587
14684
|
/* @__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
14685
|
/* @__PURE__ */ jsx(Text, { children: t("app.localization-admin.sources-description") }),
|
|
@@ -14613,7 +14710,22 @@ function LocalizationAdmin({ className }) {
|
|
|
14613
14710
|
] }) }) })
|
|
14614
14711
|
] });
|
|
14615
14712
|
}
|
|
14616
|
-
return /* @__PURE__ */
|
|
14713
|
+
return /* @__PURE__ */ jsxs("div", { className: mergeClasses("ppp-localization-admin", styles.root, className), children: [
|
|
14714
|
+
content,
|
|
14715
|
+
mergedDialogCulture !== null && /* @__PURE__ */ jsx(
|
|
14716
|
+
MergedSourcesDialog,
|
|
14717
|
+
{
|
|
14718
|
+
culture: mergedDialogCulture,
|
|
14719
|
+
label: cultureLabel(mergedDialogCulture),
|
|
14720
|
+
onClose: () => setMergedDialogCulture(null),
|
|
14721
|
+
onDownload: () => onDownloadMerged(mergedDialogCulture),
|
|
14722
|
+
isDownloading,
|
|
14723
|
+
ppp,
|
|
14724
|
+
t,
|
|
14725
|
+
styles
|
|
14726
|
+
}
|
|
14727
|
+
)
|
|
14728
|
+
] });
|
|
14617
14729
|
}
|
|
14618
14730
|
function ConfigRow({ styles, label, value }) {
|
|
14619
14731
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
@@ -14663,6 +14775,177 @@ function SourceRow({
|
|
|
14663
14775
|
)) }) })
|
|
14664
14776
|
] });
|
|
14665
14777
|
}
|
|
14778
|
+
var MERGED_PAGE_SIZE = 100;
|
|
14779
|
+
function MergedSourcesDialog({
|
|
14780
|
+
culture,
|
|
14781
|
+
label,
|
|
14782
|
+
onClose,
|
|
14783
|
+
onDownload,
|
|
14784
|
+
isDownloading,
|
|
14785
|
+
ppp,
|
|
14786
|
+
t,
|
|
14787
|
+
styles
|
|
14788
|
+
}) {
|
|
14789
|
+
const [entries, setEntries] = useState(null);
|
|
14790
|
+
const [loadError, setLoadError] = useState();
|
|
14791
|
+
const [filter, setFilter] = useState("");
|
|
14792
|
+
const [page, setPage] = useState(0);
|
|
14793
|
+
const [sortState, setSortState] = useState({
|
|
14794
|
+
sortColumn: "key",
|
|
14795
|
+
sortDirection: "ascending"
|
|
14796
|
+
});
|
|
14797
|
+
useEffect(() => {
|
|
14798
|
+
let cancelled = false;
|
|
14799
|
+
void (async () => {
|
|
14800
|
+
try {
|
|
14801
|
+
const value = await ppp.getMergedLocalizationEntriesAsync(culture);
|
|
14802
|
+
if (!cancelled) {
|
|
14803
|
+
setEntries(value);
|
|
14804
|
+
setLoadError(void 0);
|
|
14805
|
+
}
|
|
14806
|
+
} catch (reason) {
|
|
14807
|
+
if (!cancelled) {
|
|
14808
|
+
setEntries(null);
|
|
14809
|
+
setLoadError(reason instanceof Error ? reason.message : String(reason));
|
|
14810
|
+
}
|
|
14811
|
+
}
|
|
14812
|
+
})();
|
|
14813
|
+
return () => {
|
|
14814
|
+
cancelled = true;
|
|
14815
|
+
};
|
|
14816
|
+
}, [ppp, culture]);
|
|
14817
|
+
const columns = useMemo(
|
|
14818
|
+
() => [
|
|
14819
|
+
createTableColumn({
|
|
14820
|
+
columnId: "key",
|
|
14821
|
+
compare: (a, b) => a.key.localeCompare(b.key),
|
|
14822
|
+
renderHeaderCell: () => t("app.localization-admin.merged-column-key"),
|
|
14823
|
+
renderCell: (item) => item.key
|
|
14824
|
+
}),
|
|
14825
|
+
createTableColumn({
|
|
14826
|
+
columnId: "kind",
|
|
14827
|
+
compare: (a, b) => Number(a.sourceKind) - Number(b.sourceKind),
|
|
14828
|
+
renderHeaderCell: () => t("app.localization-admin.merged-column-kind"),
|
|
14829
|
+
renderCell: (item) => t(`app.localization-admin.kind-${kindKeyOf(item.sourceKind)}`)
|
|
14830
|
+
}),
|
|
14831
|
+
createTableColumn({
|
|
14832
|
+
columnId: "source",
|
|
14833
|
+
compare: (a, b) => a.sourceDisplayName.localeCompare(b.sourceDisplayName),
|
|
14834
|
+
renderHeaderCell: () => t("app.localization-admin.merged-column-source"),
|
|
14835
|
+
renderCell: (item) => item.sourceDisplayName
|
|
14836
|
+
}),
|
|
14837
|
+
createTableColumn({
|
|
14838
|
+
columnId: "value",
|
|
14839
|
+
compare: (a, b) => a.value.localeCompare(b.value),
|
|
14840
|
+
renderHeaderCell: () => t("app.localization-admin.merged-column-value"),
|
|
14841
|
+
renderCell: (item) => item.value
|
|
14842
|
+
})
|
|
14843
|
+
],
|
|
14844
|
+
[t]
|
|
14845
|
+
);
|
|
14846
|
+
const filtered = useMemo(() => {
|
|
14847
|
+
if (!entries) return [];
|
|
14848
|
+
const q = filter.trim().toLowerCase();
|
|
14849
|
+
const base = q ? entries.filter(
|
|
14850
|
+
(e) => e.key.toLowerCase().includes(q) || e.value.toLowerCase().includes(q) || e.sourceDisplayName.toLowerCase().includes(q)
|
|
14851
|
+
) : entries;
|
|
14852
|
+
return [...base];
|
|
14853
|
+
}, [entries, filter]);
|
|
14854
|
+
const sorted = useMemo(() => {
|
|
14855
|
+
const column = columns.find((c) => c.columnId === sortState.sortColumn);
|
|
14856
|
+
if (!column?.compare) return filtered;
|
|
14857
|
+
const sign = sortState.sortDirection === "ascending" ? 1 : -1;
|
|
14858
|
+
return [...filtered].sort((a, b) => sign * column.compare(a, b));
|
|
14859
|
+
}, [filtered, columns, sortState]);
|
|
14860
|
+
useEffect(() => {
|
|
14861
|
+
setPage(0);
|
|
14862
|
+
}, [filter, sortState]);
|
|
14863
|
+
const pageCount = Math.max(1, Math.ceil(sorted.length / MERGED_PAGE_SIZE));
|
|
14864
|
+
const currentPage = Math.min(page, pageCount - 1);
|
|
14865
|
+
const paged = sorted.slice(currentPage * MERGED_PAGE_SIZE, currentPage * MERGED_PAGE_SIZE + MERGED_PAGE_SIZE);
|
|
14866
|
+
const columnSizingOptions = useMemo(
|
|
14867
|
+
() => ({
|
|
14868
|
+
key: { minWidth: 200, defaultWidth: 320 },
|
|
14869
|
+
kind: { minWidth: 110, defaultWidth: 140 },
|
|
14870
|
+
source: { minWidth: 200, defaultWidth: 300 },
|
|
14871
|
+
value: { minWidth: 200, defaultWidth: 360 }
|
|
14872
|
+
}),
|
|
14873
|
+
[]
|
|
14874
|
+
);
|
|
14875
|
+
return /* @__PURE__ */ jsx(Dialog, { open: true, onOpenChange: (_event, data) => !data.open && onClose(), children: /* @__PURE__ */ jsx(DialogSurface, { className: styles.dialogSurface, children: /* @__PURE__ */ jsxs(DialogBody, { children: [
|
|
14876
|
+
/* @__PURE__ */ jsx(DialogTitle, { children: t("app.localization-admin.merged-dialog-title", [label]) }),
|
|
14877
|
+
/* @__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: [
|
|
14878
|
+
/* @__PURE__ */ jsxs("div", { className: styles.dialogToolbar, children: [
|
|
14879
|
+
/* @__PURE__ */ jsx(
|
|
14880
|
+
Input,
|
|
14881
|
+
{
|
|
14882
|
+
className: styles.filterInput,
|
|
14883
|
+
value: filter,
|
|
14884
|
+
onChange: (_event, data) => setFilter(data.value),
|
|
14885
|
+
contentBefore: /* @__PURE__ */ jsx(SearchRegular, {}),
|
|
14886
|
+
placeholder: t("app.localization-admin.merged-filter-placeholder")
|
|
14887
|
+
}
|
|
14888
|
+
),
|
|
14889
|
+
/* @__PURE__ */ jsx("span", { className: styles.lastReloaded, children: t("app.localization-admin.merged-count", [sorted.length, entries.length]) }),
|
|
14890
|
+
/* @__PURE__ */ jsx("span", { className: styles.grow }),
|
|
14891
|
+
pageCount > 1 && /* @__PURE__ */ jsxs("span", { className: styles.pager, children: [
|
|
14892
|
+
/* @__PURE__ */ jsx(
|
|
14893
|
+
Button,
|
|
14894
|
+
{
|
|
14895
|
+
size: "small",
|
|
14896
|
+
appearance: "subtle",
|
|
14897
|
+
disabled: currentPage === 0,
|
|
14898
|
+
onClick: () => setPage(currentPage - 1),
|
|
14899
|
+
children: t("app.localization-admin.merged-prev")
|
|
14900
|
+
}
|
|
14901
|
+
),
|
|
14902
|
+
/* @__PURE__ */ jsx("span", { className: styles.lastReloaded, children: t("app.localization-admin.merged-page", [currentPage + 1, pageCount]) }),
|
|
14903
|
+
/* @__PURE__ */ jsx(
|
|
14904
|
+
Button,
|
|
14905
|
+
{
|
|
14906
|
+
size: "small",
|
|
14907
|
+
appearance: "subtle",
|
|
14908
|
+
disabled: currentPage >= pageCount - 1,
|
|
14909
|
+
onClick: () => setPage(currentPage + 1),
|
|
14910
|
+
children: t("app.localization-admin.merged-next")
|
|
14911
|
+
}
|
|
14912
|
+
)
|
|
14913
|
+
] })
|
|
14914
|
+
] }),
|
|
14915
|
+
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(
|
|
14916
|
+
DataGrid,
|
|
14917
|
+
{
|
|
14918
|
+
items: paged,
|
|
14919
|
+
columns,
|
|
14920
|
+
sortable: true,
|
|
14921
|
+
resizableColumns: true,
|
|
14922
|
+
sortState,
|
|
14923
|
+
onSortChange: (_event, next) => setSortState(next),
|
|
14924
|
+
columnSizingOptions,
|
|
14925
|
+
getRowId: (item) => item.key,
|
|
14926
|
+
size: "small",
|
|
14927
|
+
children: [
|
|
14928
|
+
/* @__PURE__ */ jsx(DataGridHeader, { children: /* @__PURE__ */ jsx(DataGridRow, { children: ({ renderHeaderCell }) => /* @__PURE__ */ jsx(DataGridHeaderCell, { children: renderHeaderCell() }) }) }),
|
|
14929
|
+
/* @__PURE__ */ jsx(DataGridBody, { children: ({ item, rowId }) => /* @__PURE__ */ jsx(DataGridRow, { children: ({ renderCell }) => /* @__PURE__ */ jsx(DataGridCell, { children: renderCell(item) }) }, rowId) })
|
|
14930
|
+
]
|
|
14931
|
+
}
|
|
14932
|
+
) })
|
|
14933
|
+
] }) }),
|
|
14934
|
+
/* @__PURE__ */ jsxs(DialogActions, { children: [
|
|
14935
|
+
/* @__PURE__ */ jsx(
|
|
14936
|
+
Button,
|
|
14937
|
+
{
|
|
14938
|
+
appearance: "primary",
|
|
14939
|
+
icon: /* @__PURE__ */ jsx(ArrowDownloadRegular, {}),
|
|
14940
|
+
disabled: isDownloading,
|
|
14941
|
+
onClick: onDownload,
|
|
14942
|
+
children: t("app.localization-admin.merged-download-button")
|
|
14943
|
+
}
|
|
14944
|
+
),
|
|
14945
|
+
/* @__PURE__ */ jsx(Button, { appearance: "secondary", icon: /* @__PURE__ */ jsx(DismissRegular, {}), onClick: onClose, children: t("app.buttons.close.label") })
|
|
14946
|
+
] })
|
|
14947
|
+
] }) }) });
|
|
14948
|
+
}
|
|
14666
14949
|
var useStyles13 = makeStyles({
|
|
14667
14950
|
root: {
|
|
14668
14951
|
display: "flex",
|