@crowdin/app-project-module 3.0.1 → 3.2.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/out/middlewares/crowdin-client.d.ts +4 -2
- package/out/middlewares/crowdin-client.js +51 -14
- package/out/middlewares/integration-credentials.js +34 -12
- package/out/modules/integration/handlers/crowdin-files.js +34 -1
- package/out/modules/integration/handlers/user-error-detail.d.ts +2 -0
- package/out/modules/integration/handlers/user-error-detail.js +48 -0
- package/out/modules/integration/handlers/user-errors.d.ts +6 -0
- package/out/modules/integration/handlers/user-errors.js +39 -17
- package/out/modules/integration/index.js +8 -0
- package/out/modules/integration/types.d.ts +1 -0
- package/out/static/ui/main.bundle.js +116 -55
- package/out/static/ui/main.bundle.js.map +1 -1
- package/out/storage/drizzle/d1/index.js +2 -1
- package/out/storage/drizzle/d1/migrations/user-errors-indexes.d.ts +7 -0
- package/out/storage/drizzle/d1/migrations/user-errors-indexes.js +27 -0
- package/out/storage/drizzle/index.d.ts +8 -1
- package/out/storage/drizzle/index.js +75 -4
- package/out/storage/drizzle/postgresql/migrations/0003_user_errors_pagination_index.sql +5 -0
- package/out/storage/drizzle/postgresql/migrations/meta/0003_snapshot.json +646 -0
- package/out/storage/drizzle/postgresql/migrations/meta/_journal.json +7 -0
- package/out/storage/drizzle/sqlite/migrations/0002_user_errors_indexes.sql +4 -0
- package/out/storage/drizzle/sqlite/migrations/meta/0002_snapshot.json +687 -0
- package/out/storage/drizzle/sqlite/migrations/meta/_journal.json +7 -0
- package/out/storage/types.d.ts +30 -0
- package/out/types.d.ts +1 -0
- package/out/util/connection.d.ts +5 -0
- package/out/util/connection.js +7 -0
- package/package.json +1 -1
|
@@ -36821,54 +36821,21 @@ Defaulting to \`null\`.`;
|
|
|
36821
36821
|
}
|
|
36822
36822
|
|
|
36823
36823
|
const rowsPerPageOptions = [10, 25, 50];
|
|
36824
|
-
|
|
36825
|
-
const
|
|
36826
|
-
|
|
36827
|
-
|
|
36828
|
-
const UserErrorsTable = ({ errors, isLoading, onSelect }) => {
|
|
36829
|
-
const [search, setSearch] = reactExports.useState('');
|
|
36830
|
-
const [isAscending, setIsAscending] = reactExports.useState(false);
|
|
36831
|
-
const [page, setPage] = reactExports.useState(1);
|
|
36832
|
-
const [rowsPerPage, setRowsPerPage] = reactExports.useState(rowsPerPageOptions[0]);
|
|
36833
|
-
const filteredErrors = reactExports.useMemo(() => {
|
|
36834
|
-
const normalizedSearch = search.trim().toLocaleLowerCase();
|
|
36835
|
-
const matchingErrors = normalizedSearch
|
|
36836
|
-
? errors.filter((error) =>
|
|
36837
|
-
// Typed as string, but the payload is unvalidated API data - a row
|
|
36838
|
-
// with a missing field must not take the whole table down.
|
|
36839
|
-
[error.formattedDate, error.action, error.message].some((value) => String(value !== null && value !== void 0 ? value : '')
|
|
36840
|
-
.toLocaleLowerCase()
|
|
36841
|
-
.includes(normalizedSearch)))
|
|
36842
|
-
: errors;
|
|
36843
|
-
return [...matchingErrors].sort((first, second) => {
|
|
36844
|
-
const difference = getTimestamp(first.createdAt) - getTimestamp(second.createdAt);
|
|
36845
|
-
return isAscending ? difference : -difference;
|
|
36846
|
-
});
|
|
36847
|
-
}, [errors, isAscending, search]);
|
|
36848
|
-
const pageCount = Math.max(1, Math.ceil(filteredErrors.length / rowsPerPage));
|
|
36849
|
-
reactExports.useEffect(() => {
|
|
36850
|
-
setPage((currentPage) => Math.min(currentPage, pageCount));
|
|
36851
|
-
}, [pageCount]);
|
|
36852
|
-
const visibleErrors = filteredErrors.slice((page - 1) * rowsPerPage, page * rowsPerPage);
|
|
36853
|
-
const firstVisibleRow = filteredErrors.length === 0 ? 0 : (page - 1) * rowsPerPage + 1;
|
|
36854
|
-
const lastVisibleRow = Math.min(page * rowsPerPage, filteredErrors.length);
|
|
36824
|
+
const UserErrorsTable = ({ errors, isLoading, total, currentPage, rowsPerPage, searchText, isSortedAsc, onSelect, onOptionsChange, }) => {
|
|
36825
|
+
const pageCount = Math.max(1, Math.ceil(total / rowsPerPage));
|
|
36826
|
+
const firstVisibleRow = total === 0 ? 0 : (currentPage - 1) * rowsPerPage + 1;
|
|
36827
|
+
const lastVisibleRow = Math.min(currentPage * rowsPerPage, total);
|
|
36855
36828
|
const handleRowKeyDown = (event, error) => {
|
|
36856
36829
|
if (event.key === 'Enter' || event.key === ' ') {
|
|
36857
36830
|
event.preventDefault();
|
|
36858
36831
|
onSelect(error);
|
|
36859
36832
|
}
|
|
36860
36833
|
};
|
|
36861
|
-
return (jsxRuntimeExports.jsxs("div", { "data-slot": "user-errors-table", className: "overflow-hidden rounded-lg border bg-card text-card-foreground", children: [jsxRuntimeExports.jsx("div", { "data-slot": "table-toolbar", className: "border-b p-4", children: jsxRuntimeExports.jsxs("div", { className: "relative max-w-md", children: [jsxRuntimeExports.jsx(Search, { className: "pointer-events-none absolute top-1/2 left-3 size-4 -translate-y-1/2 text-muted-foreground" }), jsxRuntimeExports.jsx(Input, { value:
|
|
36862
|
-
setSearch(event.target.value);
|
|
36863
|
-
setPage(1);
|
|
36864
|
-
}, className: "h-9 pl-9", placeholder: "Search error logs", "aria-label": "Search error logs" })] }) }), jsxRuntimeExports.jsxs(Table, { children: [jsxRuntimeExports.jsx(TableHeader, { children: jsxRuntimeExports.jsxs(TableRow, { className: "hover:bg-transparent", children: [jsxRuntimeExports.jsx(TableHead, { className: "w-1/3 px-4", "aria-sort": isAscending ? 'ascending' : 'descending', children: jsxRuntimeExports.jsxs(Button, { type: "button", variant: "ghost", className: "-ml-2", onClick: () => setIsAscending((currentValue) => !currentValue), "aria-label": `Sort by date ${isAscending ? 'descending' : 'ascending'}`, children: ["Date", isAscending ? (jsxRuntimeExports.jsx(ArrowUp, { "aria-hidden": "true" })) : (jsxRuntimeExports.jsx(ArrowDown, { "aria-hidden": "true" }))] }) }), jsxRuntimeExports.jsx(TableHead, { className: "w-1/3 px-4", children: "Action" }), jsxRuntimeExports.jsx(TableHead, { className: "w-1/3 px-4", children: "Message" })] }) }), jsxRuntimeExports.jsx(TableBody, { "aria-busy": isLoading, children: isLoading ? (Array.from({ length: 3 }).map((_, index) => (jsxRuntimeExports.jsx(TableRow, { children: [0, 1, 2].map((cell) => (jsxRuntimeExports.jsxs(TableCell, { className: "h-12 px-4", children: [index === 0 && cell === 0 && (jsxRuntimeExports.jsx("span", { className: "sr-only", role: "status", children: "Loading error logs" })), jsxRuntimeExports.jsx("div", { className: "h-4 max-w-48 animate-pulse rounded bg-muted" })] }, cell))) }, index)))) : visibleErrors.length > 0 ? (visibleErrors.map((error) => (jsxRuntimeExports.jsxs(TableRow, { tabIndex: 0, className: "cursor-pointer focus-visible:bg-muted/50 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-inset", onClick: () => onSelect(error), onKeyDown: (event) => handleRowKeyDown(event, error), "aria-label": `Open error details for ${error.action} on ${error.formattedDate}`, children: [jsxRuntimeExports.jsx(TableCell, { className: "h-12 px-4 font-medium whitespace-normal", children: error.formattedDate }), jsxRuntimeExports.jsx(TableCell, { className: "h-12 px-4 whitespace-normal", children: error.action }), jsxRuntimeExports.jsx(TableCell, { className: "h-12 max-w-0 px-4 whitespace-normal", children: jsxRuntimeExports.jsx("span", { className: "line-clamp-2 break-words", children: error.message }) })] }, error.id)))) : (jsxRuntimeExports.jsx(TableRow, { className: "hover:bg-transparent", children: jsxRuntimeExports.jsx(TableCell, { colSpan: 3, className: "h-32 text-center text-muted-foreground", children: search ? 'No error logs match your search.' : 'No error logs found.' }) })) })] }), jsxRuntimeExports.jsxs("div", { "data-slot": "table-pagination", className: "flex flex-col gap-3 border-t px-4 py-2 sm:flex-row sm:items-center sm:justify-end", children: [jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2 text-sm", children: [jsxRuntimeExports.jsx("span", { className: "whitespace-nowrap text-muted-foreground", children: "Rows per page" }), jsxRuntimeExports.jsxs(Select, { value: String(rowsPerPage), onValueChange: (value) => {
|
|
36865
|
-
setRowsPerPage(Number(value));
|
|
36866
|
-
setPage(1);
|
|
36867
|
-
}, children: [jsxRuntimeExports.jsx(SelectTrigger, { className: "w-18", "aria-label": "Rows per page", children: jsxRuntimeExports.jsx(SelectValue, {}) }), jsxRuntimeExports.jsx(SelectContent, { align: "end", children: rowsPerPageOptions.map((option) => (jsxRuntimeExports.jsx(SelectItem, { value: String(option), children: option }, option))) })] })] }), jsxRuntimeExports.jsxs("p", { className: "m-0 min-w-24 text-sm text-muted-foreground", "aria-live": "polite", children: [firstVisibleRow, "-", lastVisibleRow, " of ", filteredErrors.length] }), jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-1", children: [jsxRuntimeExports.jsx(Button, { type: "button", variant: "ghost", size: "icon", onClick: () => setPage(1), disabled: page === 1, "aria-label": "Go to first page", children: jsxRuntimeExports.jsx(ChevronsLeft, {}) }), jsxRuntimeExports.jsx(Button, { type: "button", variant: "ghost", size: "icon", onClick: () => setPage((currentPage) => Math.max(1, currentPage - 1)), disabled: page === 1, "aria-label": "Go to previous page", children: jsxRuntimeExports.jsx(ChevronLeft, {}) }), jsxRuntimeExports.jsx(Button, { type: "button", variant: "ghost", size: "icon", onClick: () => setPage((currentPage) => Math.min(pageCount, currentPage + 1)), disabled: page === pageCount, "aria-label": "Go to next page", children: jsxRuntimeExports.jsx(ChevronRight, {}) }), jsxRuntimeExports.jsx(Button, { type: "button", variant: "ghost", size: "icon", onClick: () => setPage(pageCount), disabled: page === pageCount, "aria-label": "Go to last page", children: jsxRuntimeExports.jsx(ChevronsRight, {}) })] })] })] }));
|
|
36834
|
+
return (jsxRuntimeExports.jsxs("div", { "data-slot": "user-errors-table", className: "overflow-hidden rounded-lg border bg-card text-card-foreground", children: [jsxRuntimeExports.jsx("div", { "data-slot": "table-toolbar", className: "border-b p-4", children: jsxRuntimeExports.jsxs("div", { className: "relative max-w-md", children: [jsxRuntimeExports.jsx(Search, { className: "pointer-events-none absolute top-1/2 left-3 size-4 -translate-y-1/2 text-muted-foreground" }), jsxRuntimeExports.jsx(Input, { value: searchText, onChange: (event) => onOptionsChange({ searchText: event.target.value, currentPage: 1 }), className: "h-9 pl-9", placeholder: "Search by action or message", "aria-label": "Search error logs by action or message" })] }) }), jsxRuntimeExports.jsxs(Table, { children: [jsxRuntimeExports.jsx(TableHeader, { children: jsxRuntimeExports.jsxs(TableRow, { className: "hover:bg-transparent", children: [jsxRuntimeExports.jsx(TableHead, { className: "w-1/3 px-4", "aria-sort": isSortedAsc ? 'ascending' : 'descending', children: jsxRuntimeExports.jsxs(Button, { type: "button", variant: "ghost", className: "-ml-2", onClick: () => onOptionsChange({ isSortedAsc: !isSortedAsc, currentPage: 1 }), "aria-label": `Sort by date ${isSortedAsc ? 'descending' : 'ascending'}`, children: ["Date", isSortedAsc ? (jsxRuntimeExports.jsx(ArrowUp, { "aria-hidden": "true" })) : (jsxRuntimeExports.jsx(ArrowDown, { "aria-hidden": "true" }))] }) }), jsxRuntimeExports.jsx(TableHead, { className: "w-1/3 px-4", children: "Action" }), jsxRuntimeExports.jsx(TableHead, { className: "w-1/3 px-4", children: "Message" })] }) }), jsxRuntimeExports.jsx(TableBody, { "aria-busy": isLoading, children: isLoading ? (Array.from({ length: 3 }).map((_, index) => (jsxRuntimeExports.jsx(TableRow, { children: [0, 1, 2].map((cell) => (jsxRuntimeExports.jsxs(TableCell, { className: "h-12 px-4", children: [index === 0 && cell === 0 && (jsxRuntimeExports.jsx("span", { className: "sr-only", role: "status", children: "Loading error logs" })), jsxRuntimeExports.jsx("div", { className: "h-4 max-w-48 animate-pulse rounded bg-muted" })] }, cell))) }, index)))) : errors.length > 0 ? (errors.map((error) => (jsxRuntimeExports.jsxs(TableRow, { tabIndex: 0, className: "cursor-pointer focus-visible:bg-muted/50 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-inset", onClick: () => onSelect(error), onKeyDown: (event) => handleRowKeyDown(event, error), "aria-label": `Open error details for ${error.action} on ${error.formattedDate}`, children: [jsxRuntimeExports.jsx(TableCell, { className: "h-12 px-4 font-medium whitespace-normal", children: error.formattedDate }), jsxRuntimeExports.jsx(TableCell, { className: "h-12 px-4 whitespace-normal", children: error.action }), jsxRuntimeExports.jsx(TableCell, { className: "h-12 max-w-0 px-4 whitespace-normal", children: jsxRuntimeExports.jsx("span", { className: "line-clamp-2 break-words", children: error.message }) })] }, error.id)))) : (jsxRuntimeExports.jsx(TableRow, { className: "hover:bg-transparent", children: jsxRuntimeExports.jsx(TableCell, { colSpan: 3, className: "h-32 text-center text-muted-foreground", children: searchText ? 'No error logs match your search.' : 'No error logs found.' }) })) })] }), jsxRuntimeExports.jsxs("div", { "data-slot": "table-pagination", className: "flex flex-col gap-3 border-t px-4 py-2 sm:flex-row sm:items-center sm:justify-end", children: [jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2 text-sm", children: [jsxRuntimeExports.jsx("span", { className: "whitespace-nowrap text-muted-foreground", children: "Rows per page" }), jsxRuntimeExports.jsxs(Select, { value: String(rowsPerPage), onValueChange: (value) => onOptionsChange({ rowsPerPage: Number(value), currentPage: 1 }), children: [jsxRuntimeExports.jsx(SelectTrigger, { className: "w-18", "aria-label": "Rows per page", children: jsxRuntimeExports.jsx(SelectValue, {}) }), jsxRuntimeExports.jsx(SelectContent, { align: "end", children: rowsPerPageOptions.map((option) => (jsxRuntimeExports.jsx(SelectItem, { value: String(option), children: option }, option))) })] })] }), jsxRuntimeExports.jsxs("p", { className: "m-0 min-w-24 text-sm text-muted-foreground", "aria-live": "polite", children: [firstVisibleRow, "-", lastVisibleRow, " of ", total] }), jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-1", children: [jsxRuntimeExports.jsx(Button, { type: "button", variant: "ghost", size: "icon", onClick: () => onOptionsChange({ currentPage: 1 }), disabled: currentPage === 1, "aria-label": "Go to first page", children: jsxRuntimeExports.jsx(ChevronsLeft, {}) }), jsxRuntimeExports.jsx(Button, { type: "button", variant: "ghost", size: "icon", onClick: () => onOptionsChange({ currentPage: Math.max(1, currentPage - 1) }), disabled: currentPage === 1, "aria-label": "Go to previous page", children: jsxRuntimeExports.jsx(ChevronLeft, {}) }), jsxRuntimeExports.jsx(Button, { type: "button", variant: "ghost", size: "icon", onClick: () => onOptionsChange({ currentPage: Math.min(pageCount, currentPage + 1) }), disabled: currentPage === pageCount, "aria-label": "Go to next page", children: jsxRuntimeExports.jsx(ChevronRight, {}) }), jsxRuntimeExports.jsx(Button, { type: "button", variant: "ghost", size: "icon", onClick: () => onOptionsChange({ currentPage: pageCount }), disabled: currentPage === pageCount, "aria-label": "Go to last page", children: jsxRuntimeExports.jsx(ChevronsRight, {}) })] })] })] }));
|
|
36868
36835
|
};
|
|
36869
36836
|
|
|
36870
|
-
const IntegrationView = ({ appComponentRef, userErrors, isUserErrorsLoading, onSelectUserError, isErrorLogsVisible, ...integrationProps }) => {
|
|
36871
|
-
return (jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [jsxRuntimeExports.jsx("div", { style: { display: isErrorLogsVisible ? 'none' : undefined }, children: jsxRuntimeExports.jsx(SimpleIntegration, { ref: appComponentRef, ...integrationProps }) }), jsxRuntimeExports.jsxs("div", { id: "user-errors", style: { display: isErrorLogsVisible ? undefined : 'none' }, children: [jsxRuntimeExports.jsx(UserErrorsTable, { errors: userErrors, isLoading: isUserErrorsLoading, onSelect: onSelectUserError }), jsxRuntimeExports.jsx(AppAlert, { className: "mt-4", children: "This table displays the most recent error logs from the past month. Logs older than one month will be automatically deleted." })] })] }));
|
|
36837
|
+
const IntegrationView = ({ appComponentRef, userErrors, isUserErrorsLoading, userErrorsTotal, userErrorsCurrentPage, userErrorsRowsPerPage, userErrorsSearchText, userErrorsIsSortedAsc, onSelectUserError, onUserErrorsOptionsChange, isErrorLogsVisible, ...integrationProps }) => {
|
|
36838
|
+
return (jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [jsxRuntimeExports.jsx("div", { style: { display: isErrorLogsVisible ? 'none' : undefined }, children: jsxRuntimeExports.jsx(SimpleIntegration, { ref: appComponentRef, ...integrationProps }) }), jsxRuntimeExports.jsxs("div", { id: "user-errors", style: { display: isErrorLogsVisible ? undefined : 'none' }, children: [jsxRuntimeExports.jsx(UserErrorsTable, { errors: userErrors, isLoading: isUserErrorsLoading, total: userErrorsTotal, currentPage: userErrorsCurrentPage, rowsPerPage: userErrorsRowsPerPage, searchText: userErrorsSearchText, isSortedAsc: userErrorsIsSortedAsc, onSelect: onSelectUserError, onOptionsChange: onUserErrorsOptionsChange }), jsxRuntimeExports.jsx(AppAlert, { className: "mt-4", children: "This table displays the most recent error logs from the past month. Logs older than one month will be automatically deleted." })] })] }));
|
|
36872
36839
|
};
|
|
36873
36840
|
|
|
36874
36841
|
function Progress({ className, value, ...props }) {
|
|
@@ -49165,7 +49132,7 @@ Defaulting to \`null\`.`;
|
|
|
49165
49132
|
return reactExports.useRef(null);
|
|
49166
49133
|
}
|
|
49167
49134
|
|
|
49168
|
-
const AppDialog = reactExports.forwardRef(({ id, title, width = '70', showCloseButton = true, children, footer, className }, ref) => {
|
|
49135
|
+
const AppDialog = reactExports.forwardRef(({ id, title, width = '70', showCloseButton = true, children, footer, className, onClose }, ref) => {
|
|
49169
49136
|
const [isOpen, setIsOpen] = reactExports.useState(false);
|
|
49170
49137
|
const [portalContainer, setPortalContainer] = reactExports.useState(null);
|
|
49171
49138
|
const contentRef = reactExports.useRef(null);
|
|
@@ -49180,7 +49147,12 @@ Defaulting to \`null\`.`;
|
|
|
49180
49147
|
: width === '65'
|
|
49181
49148
|
? 'sm:max-w-4xl'
|
|
49182
49149
|
: 'sm:max-w-5xl';
|
|
49183
|
-
return (jsxRuntimeExports.jsx(Dialog, { open: isOpen, onOpenChange:
|
|
49150
|
+
return (jsxRuntimeExports.jsx(Dialog, { open: isOpen, onOpenChange: (open) => {
|
|
49151
|
+
setIsOpen(open);
|
|
49152
|
+
if (!open) {
|
|
49153
|
+
onClose === null || onClose === void 0 ? void 0 : onClose();
|
|
49154
|
+
}
|
|
49155
|
+
}, children: jsxRuntimeExports.jsx(DialogContent, { ref: contentRef, id: id, showCloseButton: showCloseButton, onOpenAutoFocus: (event) => {
|
|
49184
49156
|
var _a;
|
|
49185
49157
|
event.preventDefault();
|
|
49186
49158
|
(_a = contentRef.current) === null || _a === void 0 ? void 0 : _a.focus();
|
|
@@ -49504,7 +49476,8 @@ Defaulting to \`null\`.`;
|
|
|
49504
49476
|
}
|
|
49505
49477
|
}
|
|
49506
49478
|
function getUserErrorDetail(error) {
|
|
49507
|
-
|
|
49479
|
+
// `data` is loaded separately, right after the modal opens
|
|
49480
|
+
const data = error.data && isJSON(error.data) ? JSON.parse(error.data) : null;
|
|
49508
49481
|
const preClassName = 'm-0 max-w-full overflow-x-auto whitespace-pre-wrap break-words rounded-lg bg-muted p-3 text-xs leading-relaxed text-foreground ring-1 ring-border dark:bg-background';
|
|
49509
49482
|
const rows = [
|
|
49510
49483
|
{ label: 'Action', value: error.action },
|
|
@@ -49514,6 +49487,10 @@ Defaulting to \`null\`.`;
|
|
|
49514
49487
|
},
|
|
49515
49488
|
{ label: 'Date/time', value: error.formattedDate },
|
|
49516
49489
|
];
|
|
49490
|
+
if (!data) {
|
|
49491
|
+
rows.push({ label: 'Details', value: jsxRuntimeExports.jsx(Skeleton, { className: "h-8 w-full" }) });
|
|
49492
|
+
return renderUserErrorDetailRows(rows);
|
|
49493
|
+
}
|
|
49517
49494
|
if (data.requestParams) {
|
|
49518
49495
|
rows.push({ label: 'Method', value: data.requestParams.method });
|
|
49519
49496
|
}
|
|
@@ -49542,12 +49519,17 @@ Defaulting to \`null\`.`;
|
|
|
49542
49519
|
rows.push({ label: 'App Data', value: data.appData });
|
|
49543
49520
|
}
|
|
49544
49521
|
}
|
|
49522
|
+
return renderUserErrorDetailRows(rows);
|
|
49523
|
+
}
|
|
49524
|
+
function renderUserErrorDetailRows(rows) {
|
|
49545
49525
|
return (jsxRuntimeExports.jsx("div", { className: "min-w-0", children: jsxRuntimeExports.jsx("dl", { className: "grid gap-4", children: rows.map((row) => (jsxRuntimeExports.jsxs("div", { className: "grid gap-1 sm:grid-cols-[10rem_minmax(0,1fr)] sm:gap-6", children: [jsxRuntimeExports.jsx("dt", { className: "text-sm font-medium text-muted-foreground", children: row.label }), jsxRuntimeExports.jsx("dd", { className: "m-0 min-w-0 break-words text-sm text-foreground", children: row.value })] }, row.label))) }) }));
|
|
49546
49526
|
}
|
|
49547
|
-
const UserErrorDetailModal = ({ modalRef, selectedUserError }) => {
|
|
49548
|
-
return (jsxRuntimeExports.jsx(AppDialog, { ref: modalRef, id: "user-error-detail", width: "60", title: "Details", children: selectedUserError && getUserErrorDetail(selectedUserError) }));
|
|
49527
|
+
const UserErrorDetailModal = ({ modalRef, selectedUserError, onClose }) => {
|
|
49528
|
+
return (jsxRuntimeExports.jsx(AppDialog, { ref: modalRef, id: "user-error-detail", width: "60", title: "Details", onClose: onClose, children: selectedUserError && getUserErrorDetail(selectedUserError) }));
|
|
49549
49529
|
};
|
|
49550
49530
|
|
|
49531
|
+
const USER_ERRORS_PER_PAGE = 10;
|
|
49532
|
+
const USER_ERRORS_SEARCH_DEBOUNCE = 300;
|
|
49551
49533
|
const MainPage = (props) => {
|
|
49552
49534
|
const { name, userId, notice, checkSubscription, isManager, isOwner, infoModal, configurationFields, config: configString, syncNewElements, withCronSync, webhooks, integrationOneLevelFetching, integrationSearchListener, excludedTargetLanguages, filtering, hasOrganization, zenModeUrl, asyncProgress = { checkInterval: 3000 }, reloadOnConfigSave, progressiveCrowdinFilesLoading, integrationButtonMenuItems, crowdinButtonMenuItems, } = props;
|
|
49553
49535
|
const config = reactExports.useRef(configString ? JSON.parse(configString.replace(/\\n/g, '\\\\n')) : {});
|
|
@@ -49559,6 +49541,9 @@ Defaulting to \`null\`.`;
|
|
|
49559
49541
|
const scheduleModalRef = reactExports.useRef(null);
|
|
49560
49542
|
const permissionsModalRef = reactExports.useRef(null);
|
|
49561
49543
|
const userErrorDetailModalRef = reactExports.useRef(null);
|
|
49544
|
+
const userErrorsRequestId = reactExports.useRef(0);
|
|
49545
|
+
const userErrorDetailRequestId = reactExports.useRef(0);
|
|
49546
|
+
const userErrorsSearchTimer = reactExports.useRef(undefined);
|
|
49562
49547
|
const subscriptionLink = reactExports.useRef('');
|
|
49563
49548
|
const refreshDependencies = useFieldDependencies(configurationFields);
|
|
49564
49549
|
const [isNoticeVisible, setIsNoticeVisible] = reactExports.useState(false);
|
|
@@ -49566,6 +49551,11 @@ Defaulting to \`null\`.`;
|
|
|
49566
49551
|
const [isErrorLogsVisible, setIsErrorLogsVisible] = reactExports.useState(false);
|
|
49567
49552
|
const [userErrors, setUserErrors] = reactExports.useState([]);
|
|
49568
49553
|
const [isUserErrorsLoading, setIsUserErrorsLoading] = reactExports.useState(false);
|
|
49554
|
+
const [userErrorsTotal, setUserErrorsTotal] = reactExports.useState(0);
|
|
49555
|
+
const [userErrorsCurrentPage, setUserErrorsCurrentPage] = reactExports.useState(1);
|
|
49556
|
+
const [userErrorsRowsPerPage, setUserErrorsRowsPerPage] = reactExports.useState(USER_ERRORS_PER_PAGE);
|
|
49557
|
+
const [userErrorsSearchText, setUserErrorsSearchText] = reactExports.useState('');
|
|
49558
|
+
const [userErrorsIsSortedAsc, setUserErrorsIsSortedAsc] = reactExports.useState(false);
|
|
49569
49559
|
const [selectedUserError, setSelectedUserError] = reactExports.useState(null);
|
|
49570
49560
|
const syncOps = useSyncOperations({
|
|
49571
49561
|
appComponent,
|
|
@@ -49618,7 +49608,12 @@ Defaulting to \`null\`.`;
|
|
|
49618
49608
|
}
|
|
49619
49609
|
};
|
|
49620
49610
|
document.body.addEventListener('keydown', handleKeydown);
|
|
49621
|
-
return () =>
|
|
49611
|
+
return () => {
|
|
49612
|
+
document.body.removeEventListener('keydown', handleKeydown);
|
|
49613
|
+
if (userErrorsSearchTimer.current) {
|
|
49614
|
+
clearTimeout(userErrorsSearchTimer.current);
|
|
49615
|
+
}
|
|
49616
|
+
};
|
|
49622
49617
|
}, []);
|
|
49623
49618
|
// A 402 from any API call means the subscription lapsed: show the subscribe modal.
|
|
49624
49619
|
reactExports.useEffect(() => {
|
|
@@ -49659,24 +49654,90 @@ Defaulting to \`null\`.`;
|
|
|
49659
49654
|
setIsNoticeVisible(false);
|
|
49660
49655
|
localStorage.setItem(`revised_${suffix !== null && suffix !== void 0 ? suffix : name}`, '1');
|
|
49661
49656
|
}
|
|
49662
|
-
async function
|
|
49663
|
-
|
|
49657
|
+
async function loadUserErrors({ currentPage = 1, rowsPerPage = USER_ERRORS_PER_PAGE, searchText = '', isSortedAsc = false, } = {}) {
|
|
49658
|
+
var _a, _b;
|
|
49659
|
+
const requestId = ++userErrorsRequestId.current;
|
|
49664
49660
|
setIsUserErrorsLoading(true);
|
|
49665
49661
|
try {
|
|
49666
49662
|
const restParams = await checkOrigin();
|
|
49667
|
-
const
|
|
49668
|
-
|
|
49663
|
+
const query = `&limit=${rowsPerPage}&offset=${(currentPage - 1) * rowsPerPage}` +
|
|
49664
|
+
`&order=${isSortedAsc ? 'asc' : 'desc'}` +
|
|
49665
|
+
(searchText ? `&search=${encodeURIComponent(searchText)}` : '');
|
|
49666
|
+
const res = await checkResponse(await fetch('api/user-errors' + restParams + query));
|
|
49667
|
+
// a slow response must not overwrite a page requested later
|
|
49668
|
+
if (requestId !== userErrorsRequestId.current) {
|
|
49669
|
+
return;
|
|
49670
|
+
}
|
|
49671
|
+
setUserErrors((_a = res === null || res === void 0 ? void 0 : res.data) !== null && _a !== void 0 ? _a : []);
|
|
49672
|
+
setUserErrorsTotal((_b = res === null || res === void 0 ? void 0 : res.total) !== null && _b !== void 0 ? _b : 0);
|
|
49673
|
+
setUserErrorsCurrentPage(currentPage);
|
|
49674
|
+
setUserErrorsRowsPerPage(rowsPerPage);
|
|
49675
|
+
setUserErrorsIsSortedAsc(isSortedAsc);
|
|
49669
49676
|
}
|
|
49670
49677
|
catch (e) {
|
|
49671
|
-
|
|
49678
|
+
if (requestId === userErrorsRequestId.current) {
|
|
49679
|
+
catchRejection(e, "Can't fetch error logs");
|
|
49680
|
+
}
|
|
49672
49681
|
}
|
|
49673
49682
|
finally {
|
|
49674
|
-
|
|
49683
|
+
if (requestId === userErrorsRequestId.current) {
|
|
49684
|
+
setIsUserErrorsLoading(false);
|
|
49685
|
+
}
|
|
49675
49686
|
}
|
|
49676
49687
|
}
|
|
49677
|
-
function
|
|
49678
|
-
|
|
49688
|
+
function clearUserErrorsSearchTimer() {
|
|
49689
|
+
if (userErrorsSearchTimer.current) {
|
|
49690
|
+
clearTimeout(userErrorsSearchTimer.current);
|
|
49691
|
+
userErrorsSearchTimer.current = undefined;
|
|
49692
|
+
}
|
|
49693
|
+
}
|
|
49694
|
+
// Called by the table on paging, rows-per-page, sorting and search input.
|
|
49695
|
+
// The search field has no debounce of its own, so typing is debounced here.
|
|
49696
|
+
function onUserErrorsOptionsChange(options) {
|
|
49697
|
+
var _a, _b, _c, _d;
|
|
49698
|
+
const currentPage = (_a = options.currentPage) !== null && _a !== void 0 ? _a : userErrorsCurrentPage;
|
|
49699
|
+
const rowsPerPage = (_b = options.rowsPerPage) !== null && _b !== void 0 ? _b : userErrorsRowsPerPage;
|
|
49700
|
+
const isSortedAsc = (_c = options.isSortedAsc) !== null && _c !== void 0 ? _c : userErrorsIsSortedAsc;
|
|
49701
|
+
const searchText = (_d = options.searchText) !== null && _d !== void 0 ? _d : userErrorsSearchText;
|
|
49702
|
+
const isSearchChange = options.searchText !== undefined && options.searchText !== userErrorsSearchText;
|
|
49703
|
+
clearUserErrorsSearchTimer();
|
|
49704
|
+
if (isSearchChange) {
|
|
49705
|
+
// reflect the keystroke immediately, but debounce the actual request
|
|
49706
|
+
setUserErrorsSearchText(searchText);
|
|
49707
|
+
userErrorsSearchTimer.current = setTimeout(() => loadUserErrors({ currentPage, rowsPerPage, searchText, isSortedAsc }), USER_ERRORS_SEARCH_DEBOUNCE);
|
|
49708
|
+
return;
|
|
49709
|
+
}
|
|
49710
|
+
loadUserErrors({ currentPage, rowsPerPage, searchText, isSortedAsc });
|
|
49711
|
+
}
|
|
49712
|
+
async function openUserErrorDetail(item) {
|
|
49713
|
+
// the list response carries no `data` - the heavy payload is loaded for this record only
|
|
49714
|
+
const requestId = ++userErrorDetailRequestId.current;
|
|
49715
|
+
setSelectedUserError({ ...item, data: null });
|
|
49679
49716
|
openModal(userErrorDetailModalRef.current);
|
|
49717
|
+
try {
|
|
49718
|
+
const restParams = await checkOrigin();
|
|
49719
|
+
const res = await checkResponse(await fetch(`api/user-errors/${item.id}` + restParams));
|
|
49720
|
+
setSelectedUserError((current) => ((current === null || current === void 0 ? void 0 : current.id) === item.id ? { ...current, data: res.data } : current));
|
|
49721
|
+
}
|
|
49722
|
+
catch (e) {
|
|
49723
|
+
// dialog was closed or reopened
|
|
49724
|
+
if (requestId !== userErrorDetailRequestId.current) {
|
|
49725
|
+
return;
|
|
49726
|
+
}
|
|
49727
|
+
catchRejection(e, "Can't fetch error log details");
|
|
49728
|
+
closeModal(userErrorDetailModalRef.current);
|
|
49729
|
+
setSelectedUserError(null);
|
|
49730
|
+
}
|
|
49731
|
+
}
|
|
49732
|
+
function onUserErrorDetailClose() {
|
|
49733
|
+
userErrorDetailRequestId.current++;
|
|
49734
|
+
}
|
|
49735
|
+
async function showErrorLogs() {
|
|
49736
|
+
setIsErrorLogsVisible(true);
|
|
49737
|
+
// the table keeps its state while the view is hidden - start over on re-entry
|
|
49738
|
+
clearUserErrorsSearchTimer();
|
|
49739
|
+
setUserErrorsSearchText('');
|
|
49740
|
+
await loadUserErrors();
|
|
49680
49741
|
}
|
|
49681
49742
|
function showIntegration() {
|
|
49682
49743
|
setIsErrorLogsVisible(false);
|
|
@@ -49684,7 +49745,7 @@ Defaulting to \`null\`.`;
|
|
|
49684
49745
|
return (jsxRuntimeExports.jsxs("div", { children: [jsxRuntimeExports.jsxs("div", { className: "mx-auto max-w-[1420px] px-6 py-4", children: [jsxRuntimeExports.jsx(TopBar, { notice: notice, isNoticeVisible: isNoticeVisible, checkSubscription: checkSubscription, subscriptionInfo: subscriptionInfo, isErrorLogsVisible: isErrorLogsVisible, isManager: isManager, infoModal: infoModal, hasSettings: !!configurationFields, isOwner: isOwner, onCloseNotice: closeAlert, onShowIntegration: showIntegration, onShowErrorLogs: showErrorLogs, onShowPermissions: permissions.showPermissionsDialog, onOpenInfoModal: () => openModal(infoModalRef.current), onOpenSettings: () => {
|
|
49685
49746
|
openModal(settingsModalRef.current);
|
|
49686
49747
|
setTimeout(settings.fillSettingsForm, 0);
|
|
49687
|
-
}, onLogout: integrationLogout }), jsxRuntimeExports.jsx(IntegrationView, { appComponentRef: appComponent, userErrors: userErrors, isUserErrorsLoading: isUserErrorsLoading, onSelectUserError:
|
|
49748
|
+
}, onLogout: integrationLogout }), jsxRuntimeExports.jsx(IntegrationView, { appComponentRef: appComponent, userErrors: userErrors, isUserErrorsLoading: isUserErrorsLoading, userErrorsTotal: userErrorsTotal, userErrorsCurrentPage: userErrorsCurrentPage, userErrorsRowsPerPage: userErrorsRowsPerPage, userErrorsSearchText: userErrorsSearchText, userErrorsIsSortedAsc: userErrorsIsSortedAsc, onSelectUserError: openUserErrorDetail, onUserErrorsOptionsChange: onUserErrorsOptionsChange, name: name, isErrorLogsVisible: isErrorLogsVisible, syncNewElements: syncNewElements, withCronSync: withCronSync, webhooks: webhooks, integrationOneLevelFetching: integrationOneLevelFetching, integrationSearchListener: integrationSearchListener, filtering: filtering, integrationButtonMenuItems: integrationButtonMenuItems, crowdinButtonMenuItems: crowdinButtonMenuItems, onRefreshFilesList: syncOps.handleRefreshFilesList, onFolderToggle: syncOps.handleFolderToggle, onUploadFilesToCrowdin: (detail) => syncOps.uploadFilesToCrowdin({ detail }), onUploadFilesToIntegration: (detail) => syncOps.uploadFilesToIntegration({ detail }), onLoadMore: syncOps.handleLoadMore, onIntegrationFilterChange: syncOps.handleIntegrationFilterChange, onIntegrationScheduleSync: (detail) => schedule.setIntegrationScheduleSync({ detail }), onCrowdinScheduleSync: (detail) => schedule.setCrowdinScheduleSync({ detail }), onIntegrationDisableSync: (detail) => schedule.disableIntegrationSync({ detail }), onCrowdinDisableSync: (detail) => schedule.disableCrowdinSync({ detail }) })] }), jsxRuntimeExports.jsx(Toaster, {}), jsxRuntimeExports.jsx(AsyncProgress, { ref: asyncProgressRef, onCancelJob: syncOps.cancelJob }), jsxRuntimeExports.jsx(SubscriptionModal, { modalRef: subscriptionModal, subscriptionLink: subscriptionLink, name: name, onLogout: integrationLogout }), jsxRuntimeExports.jsx(PermissionsModal, { modalRef: permissionsModalRef, isLoading: permissions.isLoading, permissionUserOptions: permissions.permissionUserOptions, selectedUsers: permissions.permissionsSelectedUsers, isConfirmVisible: permissions.isPermissionsConfirmVisible, permissionsSummary: permissions.permissionsSummary, hasOrganization: hasOrganization, zenModeUrl: zenModeUrl, saveDisabled: !permissions.isPermissionsLoaded, onUsersChange: permissions.checkUsers, onSave: permissions.inviteUsers }), excludedTargetLanguages && (jsxRuntimeExports.jsx(ExcludedLanguagesModal, { modalRef: syncOps.languageModalRef, languageSelectRef: syncOps.languageSelectRef, languageModalState: syncOps.languageModalState, onUpdateTargetLanguages: syncOps.updateCrowdinFilesTargetLanguages, onSyncToCrowdin: syncOps.uploadFilesToCrowdinWithExcludedLanguages })), infoModal && jsxRuntimeExports.jsx(InfoModal, { modalRef: infoModalRef, infoModal: infoModal }), configurationFields && (jsxRuntimeExports.jsx(SettingsModal, { modalRef: settingsModalRef, isLoading: settings.isLoading, configurationFields: configurationFields, isSaveDisabled: settings.isSettingsSaveDisabled, settingsFieldChange: settings.settingsFieldChange, registerSettingsField: settings.registerSettingsField, fieldErrors: settings.fieldErrors, onSave: settings.saveSettings })), ((syncNewElements === null || syncNewElements === void 0 ? void 0 : syncNewElements.crowdin) || (syncNewElements === null || syncNewElements === void 0 ? void 0 : syncNewElements.integration)) && (jsxRuntimeExports.jsx(ScheduleModal, { modalRef: scheduleModalRef, selectedFilesCheckboxRef: schedule.selectedFilesCheckboxRef, allFolderFilesCheckboxRef: schedule.allFolderFilesCheckboxRef, newFilesCheckboxRef: schedule.newFilesCheckboxRef, scheduleModalState: schedule.scheduleModalState, isSaveDisabled: schedule.isScheduleSaveDisabled, onChangeOptions: schedule.onChangeAutoSynchronizationOptions, onSave: schedule.saveScheduleSync })), jsxRuntimeExports.jsx(UserErrorDetailModal, { modalRef: userErrorDetailModalRef, selectedUserError: selectedUserError, onClose: onUserErrorDetailClose })] }));
|
|
49688
49749
|
};
|
|
49689
49750
|
|
|
49690
49751
|
initializeCrowdinIframeContext();
|