@powerportalspro/react-fluent 5.0.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 +459 -58
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +462 -61
- 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,
|
|
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';
|
|
@@ -2468,6 +2468,7 @@ var ImageViewer = forwardRef(function ImageViewer2({
|
|
|
2468
2468
|
const selectionRef = useRef(selection);
|
|
2469
2469
|
selectionRef.current = selection;
|
|
2470
2470
|
const prevTransformRef = useRef({ angle, zoom, pan, flipH, flipV });
|
|
2471
|
+
const resizingRef = useRef(false);
|
|
2471
2472
|
const dragRef = useRef(null);
|
|
2472
2473
|
const [isDragging, setIsDragging] = useState(false);
|
|
2473
2474
|
const zoomRef = useRef(zoom);
|
|
@@ -2497,6 +2498,7 @@ var ImageViewer = forwardRef(function ImageViewer2({
|
|
|
2497
2498
|
const cur = { angle, zoom, pan, flipH, flipV };
|
|
2498
2499
|
const transformChanged = prev.angle !== cur.angle || prev.zoom !== cur.zoom || prev.pan.x !== cur.pan.x || prev.pan.y !== cur.pan.y || prev.flipH !== cur.flipH || prev.flipV !== cur.flipV;
|
|
2499
2500
|
if (transformChanged) {
|
|
2501
|
+
resizingRef.current = false;
|
|
2500
2502
|
const sel = selectionRef.current;
|
|
2501
2503
|
const imgEl = imgRef.current;
|
|
2502
2504
|
if (sel && imgEl) {
|
|
@@ -2527,6 +2529,51 @@ var ImageViewer = forwardRef(function ImageViewer2({
|
|
|
2527
2529
|
}
|
|
2528
2530
|
prevTransformRef.current = cur;
|
|
2529
2531
|
}, [angle, zoom, pan, flipH, flipV]);
|
|
2532
|
+
useEffect(() => {
|
|
2533
|
+
if (!toolbar) return;
|
|
2534
|
+
const container = imageContainerRef.current;
|
|
2535
|
+
if (!container) return;
|
|
2536
|
+
let prevMetrics = imgRef.current ? readImageLayoutMetrics(imgRef.current) : null;
|
|
2537
|
+
const observer = new ResizeObserver(() => {
|
|
2538
|
+
const imgEl = imgRef.current;
|
|
2539
|
+
if (!imgEl) return;
|
|
2540
|
+
const newMetrics = readImageLayoutMetrics(imgEl);
|
|
2541
|
+
if (!newMetrics) return;
|
|
2542
|
+
const sel = selectionRef.current;
|
|
2543
|
+
const layoutChanged = !prevMetrics || prevMetrics.layoutW !== newMetrics.layoutW || prevMetrics.layoutH !== newMetrics.layoutH || prevMetrics.offsetLeft !== newMetrics.offsetLeft || prevMetrics.offsetTop !== newMetrics.offsetTop;
|
|
2544
|
+
if (sel && prevMetrics && layoutChanged) {
|
|
2545
|
+
const natural = containerRectToImageNatural(
|
|
2546
|
+
sel,
|
|
2547
|
+
imgEl,
|
|
2548
|
+
angleRef.current,
|
|
2549
|
+
zoomRef.current,
|
|
2550
|
+
panRef.current,
|
|
2551
|
+
flipHRef.current,
|
|
2552
|
+
flipVRef.current,
|
|
2553
|
+
prevMetrics
|
|
2554
|
+
);
|
|
2555
|
+
if (natural) {
|
|
2556
|
+
const reprojected = imageNaturalRectToContainer(
|
|
2557
|
+
natural,
|
|
2558
|
+
imgEl,
|
|
2559
|
+
angleRef.current,
|
|
2560
|
+
zoomRef.current,
|
|
2561
|
+
panRef.current,
|
|
2562
|
+
flipHRef.current,
|
|
2563
|
+
flipVRef.current,
|
|
2564
|
+
newMetrics
|
|
2565
|
+
);
|
|
2566
|
+
if (reprojected) {
|
|
2567
|
+
resizingRef.current = true;
|
|
2568
|
+
setSelection(reprojected);
|
|
2569
|
+
}
|
|
2570
|
+
}
|
|
2571
|
+
}
|
|
2572
|
+
prevMetrics = newMetrics;
|
|
2573
|
+
});
|
|
2574
|
+
observer.observe(container);
|
|
2575
|
+
return () => observer.disconnect();
|
|
2576
|
+
}, [toolbar]);
|
|
2530
2577
|
const onDirtyChangedRef = useRef(onDirtyChanged);
|
|
2531
2578
|
onDirtyChangedRef.current = onDirtyChanged;
|
|
2532
2579
|
useEffect(() => {
|
|
@@ -3280,7 +3327,7 @@ var ImageViewer = forwardRef(function ImageViewer2({
|
|
|
3280
3327
|
// pointermove (which is what changes the selection during
|
|
3281
3328
|
// a drag) calls setSelection — that triggers a re-render
|
|
3282
3329
|
// which reads the current dragRef value.
|
|
3283
|
-
transition: dragRef.current ? "none" : "left 120ms ease-out, top 120ms ease-out, width 120ms ease-out, height 120ms ease-out"
|
|
3330
|
+
transition: dragRef.current || resizingRef.current ? "none" : "left 120ms ease-out, top 120ms ease-out, width 120ms ease-out, height 120ms ease-out"
|
|
3284
3331
|
},
|
|
3285
3332
|
children: [
|
|
3286
3333
|
showThirds && /* @__PURE__ */ jsxs("div", { className: styles.thirdsGuide, "aria-hidden": "true", children: [
|
|
@@ -3441,6 +3488,21 @@ function useImageSrc(source) {
|
|
|
3441
3488
|
return source.value ? `data:${resolveMimeType(source)};base64,${source.value}` : null;
|
|
3442
3489
|
return bytesUrlRef.current;
|
|
3443
3490
|
}
|
|
3491
|
+
function readImageLayoutMetrics(imageEl) {
|
|
3492
|
+
const layoutW = imageEl.offsetWidth;
|
|
3493
|
+
const layoutH = imageEl.offsetHeight;
|
|
3494
|
+
const naturalW = imageEl.naturalWidth;
|
|
3495
|
+
const naturalH = imageEl.naturalHeight;
|
|
3496
|
+
if (layoutW === 0 || layoutH === 0 || naturalW === 0 || naturalH === 0) return null;
|
|
3497
|
+
return {
|
|
3498
|
+
layoutW,
|
|
3499
|
+
layoutH,
|
|
3500
|
+
offsetLeft: imageEl.offsetLeft,
|
|
3501
|
+
offsetTop: imageEl.offsetTop,
|
|
3502
|
+
naturalW,
|
|
3503
|
+
naturalH
|
|
3504
|
+
};
|
|
3505
|
+
}
|
|
3444
3506
|
function getDisplayedImageBounds(imageEl, angle, zoom, pan, flipH, flipV) {
|
|
3445
3507
|
const layoutW = imageEl.offsetWidth;
|
|
3446
3508
|
const layoutH = imageEl.offsetHeight;
|
|
@@ -3483,15 +3545,13 @@ function getDisplayedImageBounds(imageEl, angle, zoom, pan, flipH, flipV) {
|
|
|
3483
3545
|
}
|
|
3484
3546
|
return { x: minX, y: minY, w: maxX - minX, h: maxY - minY };
|
|
3485
3547
|
}
|
|
3486
|
-
function containerRectToImageNatural(rect, imageEl, angle, zoom, pan, flipH, flipV) {
|
|
3487
|
-
const
|
|
3488
|
-
|
|
3489
|
-
const naturalW =
|
|
3490
|
-
const naturalH = imageEl.naturalHeight;
|
|
3491
|
-
if (layoutW === 0 || layoutH === 0 || naturalW === 0 || naturalH === 0) return null;
|
|
3548
|
+
function containerRectToImageNatural(rect, imageEl, angle, zoom, pan, flipH, flipV, metricsOverride) {
|
|
3549
|
+
const m = metricsOverride ?? readImageLayoutMetrics(imageEl);
|
|
3550
|
+
if (!m) return null;
|
|
3551
|
+
const { layoutW, layoutH, naturalW, naturalH } = m;
|
|
3492
3552
|
const containScale = Math.min(layoutW / naturalW, layoutH / naturalH);
|
|
3493
|
-
const imgCenterX =
|
|
3494
|
-
const imgCenterY =
|
|
3553
|
+
const imgCenterX = m.offsetLeft + layoutW / 2;
|
|
3554
|
+
const imgCenterY = m.offsetTop + layoutH / 2;
|
|
3495
3555
|
const sx = zoom * (flipH ? -1 : 1);
|
|
3496
3556
|
const sy = zoom * (flipV ? -1 : 1);
|
|
3497
3557
|
if (sx === 0 || sy === 0) return null;
|
|
@@ -3524,15 +3584,13 @@ function containerRectToImageNatural(rect, imageEl, angle, zoom, pan, flipH, fli
|
|
|
3524
3584
|
}
|
|
3525
3585
|
return { x: minX, y: minY, w: maxX - minX, h: maxY - minY };
|
|
3526
3586
|
}
|
|
3527
|
-
function imageNaturalRectToContainer(rect, imageEl, angle, zoom, pan, flipH, flipV) {
|
|
3528
|
-
const
|
|
3529
|
-
|
|
3530
|
-
const naturalW =
|
|
3531
|
-
const naturalH = imageEl.naturalHeight;
|
|
3532
|
-
if (layoutW === 0 || layoutH === 0 || naturalW === 0 || naturalH === 0) return null;
|
|
3587
|
+
function imageNaturalRectToContainer(rect, imageEl, angle, zoom, pan, flipH, flipV, metricsOverride) {
|
|
3588
|
+
const m = metricsOverride ?? readImageLayoutMetrics(imageEl);
|
|
3589
|
+
if (!m) return null;
|
|
3590
|
+
const { layoutW, layoutH, naturalW, naturalH } = m;
|
|
3533
3591
|
const containScale = Math.min(layoutW / naturalW, layoutH / naturalH);
|
|
3534
|
-
const imgCenterX =
|
|
3535
|
-
const imgCenterY =
|
|
3592
|
+
const imgCenterX = m.offsetLeft + layoutW / 2;
|
|
3593
|
+
const imgCenterY = m.offsetTop + layoutH / 2;
|
|
3536
3594
|
const sx = zoom * (flipH ? -1 : 1);
|
|
3537
3595
|
const sy = zoom * (flipV ? -1 : 1);
|
|
3538
3596
|
const rad = angle * Math.PI / 180;
|
|
@@ -4410,6 +4468,69 @@ function ZipViewer({
|
|
|
4410
4468
|
}
|
|
4411
4469
|
);
|
|
4412
4470
|
}
|
|
4471
|
+
function ZipEntryIcon({ fileName, className }) {
|
|
4472
|
+
switch (getFileExtension(fileName)) {
|
|
4473
|
+
case "pdf":
|
|
4474
|
+
return /* @__PURE__ */ jsx(DocumentPdf20Regular, { className });
|
|
4475
|
+
case "xls":
|
|
4476
|
+
case "xlsx":
|
|
4477
|
+
case "csv":
|
|
4478
|
+
case "ods":
|
|
4479
|
+
return /* @__PURE__ */ jsx(DocumentTable20Regular, { className });
|
|
4480
|
+
case "ppt":
|
|
4481
|
+
case "pptx":
|
|
4482
|
+
case "odp":
|
|
4483
|
+
return /* @__PURE__ */ jsx(SlideText20Regular, { className });
|
|
4484
|
+
case "png":
|
|
4485
|
+
case "jpg":
|
|
4486
|
+
case "jpeg":
|
|
4487
|
+
case "gif":
|
|
4488
|
+
case "bmp":
|
|
4489
|
+
case "webp":
|
|
4490
|
+
case "svg":
|
|
4491
|
+
case "ico":
|
|
4492
|
+
case "tif":
|
|
4493
|
+
case "tiff":
|
|
4494
|
+
return /* @__PURE__ */ jsx(Image20Regular, { className });
|
|
4495
|
+
case "mp4":
|
|
4496
|
+
case "mov":
|
|
4497
|
+
case "avi":
|
|
4498
|
+
case "mkv":
|
|
4499
|
+
case "webm":
|
|
4500
|
+
case "m4v":
|
|
4501
|
+
return /* @__PURE__ */ jsx(Video20Regular, { className });
|
|
4502
|
+
case "mp3":
|
|
4503
|
+
case "wav":
|
|
4504
|
+
case "ogg":
|
|
4505
|
+
case "flac":
|
|
4506
|
+
case "m4a":
|
|
4507
|
+
case "aac":
|
|
4508
|
+
return /* @__PURE__ */ jsx(MusicNote220Regular, { className });
|
|
4509
|
+
case "zip":
|
|
4510
|
+
case "7z":
|
|
4511
|
+
case "rar":
|
|
4512
|
+
case "tar":
|
|
4513
|
+
case "gz":
|
|
4514
|
+
return /* @__PURE__ */ jsx(FolderZip20Regular, { className });
|
|
4515
|
+
case "txt":
|
|
4516
|
+
case "md":
|
|
4517
|
+
case "markdown":
|
|
4518
|
+
case "log":
|
|
4519
|
+
case "json":
|
|
4520
|
+
case "xml":
|
|
4521
|
+
case "yaml":
|
|
4522
|
+
case "yml":
|
|
4523
|
+
case "html":
|
|
4524
|
+
case "htm":
|
|
4525
|
+
case "js":
|
|
4526
|
+
case "ts":
|
|
4527
|
+
case "cs":
|
|
4528
|
+
case "css":
|
|
4529
|
+
return /* @__PURE__ */ jsx(DocumentText20Regular, { className });
|
|
4530
|
+
default:
|
|
4531
|
+
return /* @__PURE__ */ jsx(Document20Regular, { className });
|
|
4532
|
+
}
|
|
4533
|
+
}
|
|
4413
4534
|
function ZipTreeNode({ node, depth, expanded, selected, onToggle, onSelect }) {
|
|
4414
4535
|
const styles = useFileViewerStyles();
|
|
4415
4536
|
const isExpanded = expanded.has(node.fullPath);
|
|
@@ -4468,7 +4589,7 @@ function ZipTreeNode({ node, depth, expanded, selected, onToggle, onSelect }) {
|
|
|
4468
4589
|
style: indent,
|
|
4469
4590
|
children: [
|
|
4470
4591
|
/* @__PURE__ */ jsx("span", { className: styles.zipChevronSpacer }),
|
|
4471
|
-
/* @__PURE__ */ jsx(
|
|
4592
|
+
/* @__PURE__ */ jsx(ZipEntryIcon, { fileName: node.name, className: styles.zipIcon }),
|
|
4472
4593
|
/* @__PURE__ */ jsx("span", { className: styles.zipName, children: node.name })
|
|
4473
4594
|
]
|
|
4474
4595
|
}
|
|
@@ -5113,11 +5234,13 @@ var useFileViewerStyles = makeStyles({
|
|
|
5113
5234
|
outlineOffset: "-1px"
|
|
5114
5235
|
}
|
|
5115
5236
|
},
|
|
5237
|
+
// Selection style ported from the Blazor zip viewer: a subtle accent tint over
|
|
5238
|
+
// the row (text stays its normal color), intensifying slightly on hover so the
|
|
5239
|
+
// neutral row-hover doesn't wash out the selection.
|
|
5116
5240
|
zipRowSelected: {
|
|
5117
|
-
backgroundColor: tokens.
|
|
5118
|
-
color: tokens.colorBrandForeground2,
|
|
5241
|
+
backgroundColor: `color-mix(in srgb, ${tokens.colorBrandBackground} 12%, transparent)`,
|
|
5119
5242
|
":hover": {
|
|
5120
|
-
backgroundColor: tokens.
|
|
5243
|
+
backgroundColor: `color-mix(in srgb, ${tokens.colorBrandBackground} 18%, transparent)`
|
|
5121
5244
|
}
|
|
5122
5245
|
},
|
|
5123
5246
|
zipChevron: {
|
|
@@ -8892,7 +9015,13 @@ function MainGridImpl({
|
|
|
8892
9015
|
(row) => row.properties?.[columnName],
|
|
8893
9016
|
{
|
|
8894
9017
|
id: columnName,
|
|
8895
|
-
|
|
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,
|
|
8896
9025
|
cell: (cellCtx) => {
|
|
8897
9026
|
const rowRecord = cellCtx.row.original;
|
|
8898
9027
|
const rowId = rowRecord.id;
|
|
@@ -11656,15 +11785,11 @@ function ManyToManyLookupEdit({
|
|
|
11656
11785
|
return relatedPrimaryName;
|
|
11657
11786
|
}, [resolvedColumns, relatedPrimaryName]);
|
|
11658
11787
|
const lastSeededRecordIdRef = useRef(void 0);
|
|
11659
|
-
const lastSeededViewIdRef = useRef(void 0);
|
|
11660
11788
|
useEffect(() => {
|
|
11661
11789
|
if (initialLoad.status !== QueryStatus.Success || !initialLoad.data) return;
|
|
11662
11790
|
if (!primaryNameColumn || !parentRecord) return;
|
|
11663
|
-
if (lastSeededRecordIdRef.current === parentRefId
|
|
11664
|
-
return;
|
|
11665
|
-
}
|
|
11791
|
+
if (lastSeededRecordIdRef.current === parentRefId) return;
|
|
11666
11792
|
lastSeededRecordIdRef.current = parentRefId;
|
|
11667
|
-
lastSeededViewIdRef.current = selectedViewId;
|
|
11668
11793
|
const seeded = initialLoad.data.tableRecords.map((r) => ({
|
|
11669
11794
|
id: r.id,
|
|
11670
11795
|
displayName: resolveDisplayName(r, primaryNameColumn) ?? "",
|
|
@@ -11673,7 +11798,7 @@ function ManyToManyLookupEdit({
|
|
|
11673
11798
|
setInitialSelection(seeded);
|
|
11674
11799
|
setPendingAdds([]);
|
|
11675
11800
|
setPendingRemoveIds([]);
|
|
11676
|
-
}, [initialLoad.status, initialLoad.data, parentRecord, primaryNameColumn,
|
|
11801
|
+
}, [initialLoad.status, initialLoad.data, parentRecord, primaryNameColumn, parentRefId]);
|
|
11677
11802
|
const [query, setQuery] = useState("");
|
|
11678
11803
|
const [debouncedQuery, setDebouncedQuery] = useState("");
|
|
11679
11804
|
const [searchResults, setSearchResults] = useState([]);
|
|
@@ -11785,7 +11910,6 @@ function ManyToManyLookupEdit({
|
|
|
11785
11910
|
setPendingAdds([]);
|
|
11786
11911
|
setPendingRemoveIds([]);
|
|
11787
11912
|
lastSeededRecordIdRef.current = void 0;
|
|
11788
|
-
lastSeededViewIdRef.current = void 0;
|
|
11789
11913
|
},
|
|
11790
11914
|
// Cancel/Discard: just drop the pending adds/removes; the
|
|
11791
11915
|
// seed-guard refs stay so the initial selection (already loaded
|
|
@@ -13440,27 +13564,57 @@ function NavMenu({ children, width, className, style }) {
|
|
|
13440
13564
|
useNavSelectedStyles();
|
|
13441
13565
|
const location = useLocation();
|
|
13442
13566
|
const navigate = useNavigate();
|
|
13443
|
-
const { allRoutes,
|
|
13567
|
+
const { allRoutes, groups, defaultOpenIndexes } = useMemo(
|
|
13444
13568
|
() => collectNavTree(children),
|
|
13445
13569
|
[children]
|
|
13446
13570
|
);
|
|
13447
|
-
const
|
|
13571
|
+
const selectedRoute = useMemo(
|
|
13448
13572
|
() => bestRouteMatch(allRoutes, location.pathname),
|
|
13449
13573
|
[allRoutes, location.pathname]
|
|
13450
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
|
+
);
|
|
13451
13594
|
const handleSelect = (_, data) => {
|
|
13452
13595
|
const value = data.value;
|
|
13453
13596
|
if (typeof value === "string" && value.startsWith("/")) {
|
|
13454
13597
|
navigate(value);
|
|
13455
13598
|
}
|
|
13456
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
|
+
};
|
|
13457
13610
|
const navStyle = width ? { ...style, minWidth: width, maxWidth: width } : style;
|
|
13458
13611
|
return /* @__PURE__ */ jsx(
|
|
13459
13612
|
Nav,
|
|
13460
13613
|
{
|
|
13461
|
-
selectedValue:
|
|
13614
|
+
selectedValue: selectedRoute?.to ?? "",
|
|
13462
13615
|
onNavItemSelect: handleSelect,
|
|
13463
|
-
|
|
13616
|
+
openCategories,
|
|
13617
|
+
onNavCategoryItemToggle: handleCategoryToggle,
|
|
13464
13618
|
className: mergeClasses("ppp-nav-menu", styles.nav, className),
|
|
13465
13619
|
style: navStyle,
|
|
13466
13620
|
children
|
|
@@ -13490,42 +13644,46 @@ function NavItem({ to, icon, children }) {
|
|
|
13490
13644
|
}
|
|
13491
13645
|
function collectNavTree(children) {
|
|
13492
13646
|
const allRoutes = [];
|
|
13493
|
-
const
|
|
13494
|
-
const
|
|
13647
|
+
const groups = [];
|
|
13648
|
+
const defaultOpenIndexes = [];
|
|
13649
|
+
const visit = (nodes, groupIndex) => {
|
|
13495
13650
|
Children.forEach(nodes, (child) => {
|
|
13496
13651
|
if (!isValidElement(child)) return;
|
|
13497
13652
|
if (child.type === NavGroup) {
|
|
13498
13653
|
const props = child.props;
|
|
13499
13654
|
const value = props.value ?? `group:${props.label}`;
|
|
13500
|
-
|
|
13501
|
-
|
|
13655
|
+
const index = groups.length;
|
|
13656
|
+
groups.push(value);
|
|
13657
|
+
if (props.defaultExpanded) defaultOpenIndexes.push(index);
|
|
13658
|
+
visit(props.children, index);
|
|
13502
13659
|
return;
|
|
13503
13660
|
}
|
|
13504
13661
|
if (child.type === NavItem) {
|
|
13505
13662
|
const props = child.props;
|
|
13506
13663
|
allRoutes.push({
|
|
13507
13664
|
to: props.to,
|
|
13508
|
-
match: props.match ?? (props.to === "/" ? "exact" : "prefix")
|
|
13665
|
+
match: props.match ?? (props.to === "/" ? "exact" : "prefix"),
|
|
13666
|
+
groupIndex
|
|
13509
13667
|
});
|
|
13510
13668
|
return;
|
|
13511
13669
|
}
|
|
13512
13670
|
const wrapperChildren = child.props.children;
|
|
13513
|
-
if (wrapperChildren !== void 0) visit(wrapperChildren);
|
|
13671
|
+
if (wrapperChildren !== void 0) visit(wrapperChildren, groupIndex);
|
|
13514
13672
|
});
|
|
13515
13673
|
};
|
|
13516
|
-
visit(children);
|
|
13517
|
-
return { allRoutes,
|
|
13674
|
+
visit(children, -1);
|
|
13675
|
+
return { allRoutes, groups, defaultOpenIndexes };
|
|
13518
13676
|
}
|
|
13519
13677
|
function bestRouteMatch(routes, pathname) {
|
|
13520
13678
|
const normalize = (p) => p.length > 1 && p.endsWith("/") ? p.slice(0, -1) : p;
|
|
13521
13679
|
const target = normalize(pathname);
|
|
13522
13680
|
let best;
|
|
13523
13681
|
let bestLen = -1;
|
|
13524
|
-
for (const
|
|
13525
|
-
const route = normalize(to);
|
|
13526
|
-
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 + "/"));
|
|
13527
13685
|
if (matches && route.length > bestLen) {
|
|
13528
|
-
best =
|
|
13686
|
+
best = candidate;
|
|
13529
13687
|
bestLen = route.length;
|
|
13530
13688
|
}
|
|
13531
13689
|
}
|
|
@@ -14268,8 +14426,28 @@ var useStyles12 = makeStyles({
|
|
|
14268
14426
|
mergedButtons: {
|
|
14269
14427
|
display: "flex",
|
|
14270
14428
|
flexWrap: "wrap",
|
|
14271
|
-
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
|
|
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
|
|
14272
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 },
|
|
14273
14451
|
sectionBody: {
|
|
14274
14452
|
display: "flex",
|
|
14275
14453
|
flexDirection: "column",
|
|
@@ -14288,6 +14466,15 @@ function downloadBytes(fileName, data, contentType = "application/json") {
|
|
|
14288
14466
|
anchor.click();
|
|
14289
14467
|
URL.revokeObjectURL(url);
|
|
14290
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
|
+
}
|
|
14291
14478
|
function LocalizationAdmin({ className }) {
|
|
14292
14479
|
const styles = useStyles12();
|
|
14293
14480
|
const t = useT();
|
|
@@ -14297,6 +14484,7 @@ function LocalizationAdmin({ className }) {
|
|
|
14297
14484
|
const [isReloading, setIsReloading] = useState(false);
|
|
14298
14485
|
const [isDownloading, setIsDownloading] = useState(false);
|
|
14299
14486
|
const [message, setMessage] = useState();
|
|
14487
|
+
const [mergedDialogCulture, setMergedDialogCulture] = useState(null);
|
|
14300
14488
|
const loadOverview = useCallback(async () => {
|
|
14301
14489
|
try {
|
|
14302
14490
|
const value = await ppp.getLocalizationOverviewAsync();
|
|
@@ -14454,17 +14642,44 @@ function LocalizationAdmin({ className }) {
|
|
|
14454
14642
|
/* @__PURE__ */ jsx(LocalizationTranslator, {}),
|
|
14455
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: [
|
|
14456
14644
|
/* @__PURE__ */ jsx(Text, { children: t("app.localization-admin.download-merged-description") }),
|
|
14457
|
-
/* @__PURE__ */ jsx("div", { className: styles.mergedButtons, children: availableCultures.map((culture) => /* @__PURE__ */
|
|
14458
|
-
|
|
14459
|
-
|
|
14460
|
-
|
|
14461
|
-
|
|
14462
|
-
|
|
14463
|
-
|
|
14464
|
-
|
|
14465
|
-
|
|
14466
|
-
|
|
14467
|
-
|
|
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)) })
|
|
14468
14683
|
] }) }) }),
|
|
14469
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: [
|
|
14470
14685
|
/* @__PURE__ */ jsx(Text, { children: t("app.localization-admin.sources-description") }),
|
|
@@ -14495,7 +14710,22 @@ function LocalizationAdmin({ className }) {
|
|
|
14495
14710
|
] }) }) })
|
|
14496
14711
|
] });
|
|
14497
14712
|
}
|
|
14498
|
-
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
|
+
] });
|
|
14499
14729
|
}
|
|
14500
14730
|
function ConfigRow({ styles, label, value }) {
|
|
14501
14731
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
@@ -14545,6 +14775,177 @@ function SourceRow({
|
|
|
14545
14775
|
)) }) })
|
|
14546
14776
|
] });
|
|
14547
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
|
+
}
|
|
14548
14949
|
var useStyles13 = makeStyles({
|
|
14549
14950
|
root: {
|
|
14550
14951
|
display: "flex",
|