@postgres.ai/shared 4.0.0-pr-1051.1 → 4.0.1

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.
@@ -7,7 +7,6 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
7
7
  */
8
8
  import { useEffect, useState } from 'react';
9
9
  import { makeStyles } from '@material-ui/core';
10
- import { formatDistanceToNowStrict } from 'date-fns';
11
10
  import { Text } from '@postgres.ai/shared/components/Text';
12
11
  import { Modal } from '@postgres.ai/shared/components/Modal';
13
12
  import { Select } from '@postgres.ai/shared/components/Select';
@@ -15,7 +14,7 @@ import { ImportantText } from '@postgres.ai/shared/components/ImportantText';
15
14
  import { Spinner } from '@postgres.ai/shared/components/Spinner';
16
15
  import { SimpleModalControls } from '@postgres.ai/shared/components/SimpleModalControls';
17
16
  import { compareSnapshotsDesc } from '@postgres.ai/shared/utils/snapshot';
18
- import { isValidDate } from '@postgres.ai/shared/utils/date';
17
+ import { formatDateWithDistance } from '@postgres.ai/shared/utils/date';
19
18
  const useStyles = makeStyles({
20
19
  snapshots: {
21
20
  margin: '16px 0 0 0',
@@ -64,10 +63,7 @@ export const ResetCloneModal = (props) => {
64
63
  const isCurrent = snapshot.id === ((_a = clone.snapshot) === null || _a === void 0 ? void 0 : _a.id);
65
64
  return {
66
65
  value: snapshot.id,
67
- children: (_jsxs(_Fragment, { children: [snapshot.dataStateAt, " (", isValidDate(snapshot.dataStateAtDate) &&
68
- formatDistanceToNowStrict(snapshot.dataStateAtDate, {
69
- addSuffix: true,
70
- }), ")", isLatest && (_jsx("span", { className: classes.snapshotTag, children: "Latest" })), isCurrent && (_jsx("span", { className: classes.snapshotTag, children: "Current" }))] })),
66
+ children: (_jsxs(_Fragment, { children: [formatDateWithDistance(snapshot.dataStateAt, snapshot.dataStateAtDate), isLatest && (_jsx("span", { className: classes.snapshotTag, children: "Latest" })), isCurrent && (_jsx("span", { className: classes.snapshotTag, children: "Current" }))] })),
71
67
  };
72
68
  })) !== null && _a !== void 0 ? _a : [], onChange: (e) => setSelectedSnapshotId(e.target.value), fullWidth: true, className: classes.snapshots }), _jsx(SimpleModalControls, { items: [
73
69
  {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@postgres.ai/shared",
3
- "version": "4.0.0-pr-1051.1",
3
+ "version": "4.0.1",
4
4
  "main": "index.js",
5
5
  "types": "index.d.ts",
6
6
  "peerDependencies": {
@@ -10,8 +10,7 @@ import { useEffect, useState } from 'react';
10
10
  import copy from 'copy-to-clipboard';
11
11
  import { makeStyles } from '@material-ui/core';
12
12
  import { useHistory } from 'react-router-dom';
13
- import { formatDistanceToNowStrict } from 'date-fns';
14
- import { isValidDate } from '@postgres.ai/shared/utils/date';
13
+ import { formatDateWithDistance } from '@postgres.ai/shared/utils/date';
15
14
  import { ArrowDropDownIcon } from '@postgres.ai/shared/icons/ArrowDropDown';
16
15
  import { HorizontalScrollContainer } from '@postgres.ai/shared/components/HorizontalScrollContainer';
17
16
  import { useHost } from '@postgres.ai/shared/pages/Instance/context';
@@ -92,11 +91,7 @@ export const BranchesTable = ({ branches, emptyTableText, deleteBranch, branches
92
91
  setIsOpenDestroyModal(true);
93
92
  },
94
93
  },
95
- ] }), _jsx(TableBodyCell, { children: branch.name }), _jsx(TableBodyCell, { children: branch.parent }), _jsxs(TableBodyCell, { children: [branch.dataStateAt, " (", isValidDate(new Date(branch.dataStateAt))
96
- ? formatDistanceToNowStrict(new Date(branch.dataStateAt), {
97
- addSuffix: true,
98
- })
99
- : '-', ")"] }), _jsx(TableBodyCell, { children: branch.snapshotID }), _jsx(TableBodyCell, { children: branch.numSnapshots })] }, branch.name));
94
+ ] }), _jsx(TableBodyCell, { children: branch.name }), _jsx(TableBodyCell, { children: branch.parent }), _jsx(TableBodyCell, { children: formatDateWithDistance(branch.dataStateAt, new Date(branch.dataStateAt)) }), _jsx(TableBodyCell, { children: branch.snapshotID }), _jsx(TableBodyCell, { children: branch.numSnapshots })] }, branch.name));
100
95
  }) }), _jsx(DeleteBranchModal, { isOpen: isOpenDestroyModal, onClose: () => {
101
96
  setIsOpenDestroyModal(false);
102
97
  setBranchId('');
@@ -7,7 +7,6 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
7
7
  */
8
8
  import { useState } from 'react';
9
9
  import cn from 'classnames';
10
- import { formatDistanceToNowStrict } from 'date-fns';
11
10
  import { useHistory } from 'react-router-dom';
12
11
  import { Table, TableHead, TableRow, TableHeaderCell, TableBody, TableBodyCell, } from '@postgres.ai/shared/components/Table';
13
12
  import { ArrowDropDownIcon } from '@postgres.ai/shared/icons/ArrowDropDown';
@@ -20,7 +19,7 @@ import { Tooltip } from '@postgres.ai/shared/components/Tooltip';
20
19
  import { useHost } from '@postgres.ai/shared/pages/Instance/context';
21
20
  import { getCloneStatusType, getCloneStatusText, } from '@postgres.ai/shared/utils/clone';
22
21
  import { formatBytesIEC } from '@postgres.ai/shared/utils/units';
23
- import { isValidDate } from '@postgres.ai/shared/utils/date';
22
+ import { formatDateWithDistance } from '@postgres.ai/shared/utils/date';
24
23
  import { MenuCell } from './MenuCell';
25
24
  import { ConnectionModal } from './ConnectionModal';
26
25
  import styles from './styles.module.scss';
@@ -83,14 +82,6 @@ export const ClonesList = (props) => {
83
82
  const clonePagePath = host.routes.clone(clone.id);
84
83
  return (_jsxs(TableRow, { hover: !props.isDisabled, onClick: props.isDisabled
85
84
  ? undefined
86
- : () => history.push(clonePagePath), className: cn(!props.isDisabled && styles.interactiveRow), children: [_jsx(MenuCell, { clone: clone, onConnect: openConnectionModal, clonePagePath: clonePagePath }), _jsx(TableBodyCell, { children: _jsx(Tooltip, { content: clone.status.message, children: _jsx(Status, { type: getCloneStatusType(clone.status.code), children: getCloneStatusText(clone.status.code) }) }) }), _jsx(TableBodyCell, { children: clone.id }), !props.hideBranchingFeatures && _jsx(TableBodyCell, { children: clone.branch }), _jsx(TableBodyCell, { children: clone.protected ? (_jsx(Tooltip, { content: "Clone is protected from manual and automated deletion. Note that abandoned protected clones may lead to out-of-disk-space events because they hold old data, blocking cleanup and refresh processes.", children: _jsx(ShieldIcon, { className: styles.protectionIcon }) })) : (_jsx(Tooltip, { content: "Clone is not protected from deletion. To save disk space it will be automatically deleted if there is no activity for a long time.", children: _jsx(RenewableIcon, { className: styles.protectionIcon }) })) }), _jsxs(TableBodyCell, { children: [clone.createdAt, " (", isValidDate(clone.createdAtDate)
87
- ? formatDistanceToNowStrict(clone.createdAtDate, {
88
- addSuffix: true,
89
- })
90
- : '-', ")"] }), _jsx(TableBodyCell, { children: clone.db.port }), _jsx(TableBodyCell, { children: clone.db.username }), _jsx(TableBodyCell, { children: formatBytesIEC(clone.metadata.cloneDiffSize) }), _jsx(TableBodyCell, { children: (_b = (_a = clone.snapshot) === null || _a === void 0 ? void 0 : _a.pool) !== null && _b !== void 0 ? _b : '-' }), _jsx(TableBodyCell, { children: clone.snapshot ? (_jsxs(_Fragment, { children: [clone.snapshot.dataStateAt, " (", isValidDate(clone.snapshot.dataStateAtDate)
91
- ? formatDistanceToNowStrict(clone.snapshot.dataStateAtDate, {
92
- addSuffix: true,
93
- })
94
- : '-', ")"] })) : ('-') })] }, clone.id));
85
+ : () => history.push(clonePagePath), className: cn(!props.isDisabled && styles.interactiveRow), children: [_jsx(MenuCell, { clone: clone, onConnect: openConnectionModal, clonePagePath: clonePagePath }), _jsx(TableBodyCell, { children: _jsx(Tooltip, { content: clone.status.message, children: _jsx(Status, { type: getCloneStatusType(clone.status.code), children: getCloneStatusText(clone.status.code) }) }) }), _jsx(TableBodyCell, { children: clone.id }), !props.hideBranchingFeatures && _jsx(TableBodyCell, { children: clone.branch }), _jsx(TableBodyCell, { children: clone.protected ? (_jsx(Tooltip, { content: "Clone is protected from manual and automated deletion. Note that abandoned protected clones may lead to out-of-disk-space events because they hold old data, blocking cleanup and refresh processes.", children: _jsx(ShieldIcon, { className: styles.protectionIcon }) })) : (_jsx(Tooltip, { content: "Clone is not protected from deletion. To save disk space it will be automatically deleted if there is no activity for a long time.", children: _jsx(RenewableIcon, { className: styles.protectionIcon }) })) }), _jsx(TableBodyCell, { children: formatDateWithDistance(clone.createdAt, clone.createdAtDate) }), _jsx(TableBodyCell, { children: clone.db.port }), _jsx(TableBodyCell, { children: clone.db.username }), _jsx(TableBodyCell, { children: formatBytesIEC(clone.metadata.cloneDiffSize) }), _jsx(TableBodyCell, { children: (_b = (_a = clone.snapshot) === null || _a === void 0 ? void 0 : _a.pool) !== null && _b !== void 0 ? _b : '-' }), _jsx(TableBodyCell, { children: clone.snapshot ? formatDateWithDistance(clone.snapshot.dataStateAt, clone.snapshot.dataStateAtDate) : '-' })] }, clone.id));
95
86
  }) })] }) }), cloneIdForConnect && (_jsx(ConnectionModal, { cloneId: cloneIdForConnect, isOpen: isOpenConnectionModal, onClose: closeConnectionModal }))] }));
96
87
  };
@@ -1,7 +1,7 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { Tooltip } from '@material-ui/core';
3
3
  import { makeStyles } from '@material-ui/core';
4
- import { formatDistanceToNowStrict } from 'date-fns';
4
+ import { formatDistanceSafe } from '@postgres.ai/shared/utils/date';
5
5
  import { Link } from '@postgres.ai/shared/components/Link2';
6
6
  import { formatTimestampUtc } from './utils';
7
7
  const useStyles = makeStyles({
@@ -54,12 +54,7 @@ export const InactiveInstance = ({ org, instance, }) => {
54
54
  }
55
55
  return '';
56
56
  };
57
- return (_jsxs("div", { className: classes.container, children: [_jsxs("div", { className: classes.flexContainer, children: [_jsx("span", { children: "Plan" }), _jsx("span", { children: (instance === null || instance === void 0 ? void 0 : instance.dto.plan) || '---' })] }), _jsxs("div", { className: classes.flexContainer, children: [_jsx("span", { children: "Version" }), _jsx("span", { children: getVersionDigits((instance === null || instance === void 0 ? void 0 : instance.state) && ((_b = (_a = instance === null || instance === void 0 ? void 0 : instance.state) === null || _a === void 0 ? void 0 : _a.engine) === null || _b === void 0 ? void 0 : _b.version)) })] }), _jsxs("div", { className: classes.flexContainer, children: [_jsx("span", { children: "Registered" }), _jsx("span", { className: classes.timeLabel, children: _jsx(Tooltip, { title: (_c = formatTimestampUtc(instance === null || instance === void 0 ? void 0 : instance.createdAt)) !== null && _c !== void 0 ? _c : '', classes: { tooltip: classes.toolTip }, children: _jsx("span", { children: (instance === null || instance === void 0 ? void 0 : instance.createdAt) &&
58
- formatDistanceToNowStrict(new Date(instance === null || instance === void 0 ? void 0 : instance.createdAt), {
59
- addSuffix: true,
60
- }) }) }) })] }), (instance === null || instance === void 0 ? void 0 : instance.telemetryLastReportedAt) && (_jsxs("div", { className: classes.flexContainer, children: [_jsx("span", { children: "Telemetry last reported" }), _jsx("span", { className: classes.timeLabel, children: _jsx(Tooltip, { title: (_d = formatTimestampUtc(instance === null || instance === void 0 ? void 0 : instance.telemetryLastReportedAt)) !== null && _d !== void 0 ? _d : '', classes: { tooltip: classes.toolTip }, children: _jsx("span", { children: formatDistanceToNowStrict(new Date(instance === null || instance === void 0 ? void 0 : instance.telemetryLastReportedAt), {
61
- addSuffix: true,
62
- }) }) }) })] })), _jsxs("div", { className: classes.flexContainer, children: [_jsx("span", { children: "Instance ID" }), _jsx("span", { children: _jsxs("span", { style: {
57
+ return (_jsxs("div", { className: classes.container, children: [_jsxs("div", { className: classes.flexContainer, children: [_jsx("span", { children: "Plan" }), _jsx("span", { children: (instance === null || instance === void 0 ? void 0 : instance.dto.plan) || '---' })] }), _jsxs("div", { className: classes.flexContainer, children: [_jsx("span", { children: "Version" }), _jsx("span", { children: getVersionDigits((instance === null || instance === void 0 ? void 0 : instance.state) && ((_b = (_a = instance === null || instance === void 0 ? void 0 : instance.state) === null || _a === void 0 ? void 0 : _a.engine) === null || _b === void 0 ? void 0 : _b.version)) })] }), _jsxs("div", { className: classes.flexContainer, children: [_jsx("span", { children: "Registered" }), _jsx("span", { className: classes.timeLabel, children: _jsx(Tooltip, { title: (_c = formatTimestampUtc(instance === null || instance === void 0 ? void 0 : instance.createdAt)) !== null && _c !== void 0 ? _c : '', classes: { tooltip: classes.toolTip }, children: _jsx("span", { children: (instance === null || instance === void 0 ? void 0 : instance.createdAt) ? formatDistanceSafe(new Date(instance === null || instance === void 0 ? void 0 : instance.createdAt)) : '-' }) }) })] }), (instance === null || instance === void 0 ? void 0 : instance.telemetryLastReportedAt) && (_jsxs("div", { className: classes.flexContainer, children: [_jsx("span", { children: "Telemetry last reported" }), _jsx("span", { className: classes.timeLabel, children: _jsx(Tooltip, { title: (_d = formatTimestampUtc(instance === null || instance === void 0 ? void 0 : instance.telemetryLastReportedAt)) !== null && _d !== void 0 ? _d : '', classes: { tooltip: classes.toolTip }, children: _jsx("span", { children: (instance === null || instance === void 0 ? void 0 : instance.telemetryLastReportedAt) ? formatDistanceSafe(new Date(instance === null || instance === void 0 ? void 0 : instance.telemetryLastReportedAt)) : '-' }) }) })] })), _jsxs("div", { className: classes.flexContainer, children: [_jsx("span", { children: "Instance ID" }), _jsx("span", { children: _jsxs("span", { style: {
63
58
  fontWeight: 'normal',
64
59
  }, children: [_jsx(Link, { to: `/${org}/instances/${instance === null || instance === void 0 ? void 0 : instance.id}`, children: instance === null || instance === void 0 ? void 0 : instance.id }), "\u00A0 (self-assigned:", ' ', ((_e = instance === null || instance === void 0 ? void 0 : instance.dto) === null || _e === void 0 ? void 0 : _e.selfassigned_instance_id) || 'N/A', ")"] }) })] }), (instance === null || instance === void 0 ? void 0 : instance.dto.plan) !== 'CE' && (_jsxs("div", { className: classes.flexContainer, children: [_jsx("span", { children: "Billing data" }), _jsx("span", { children: _jsx(Link, { to: `/${org}/billing`, children: "Billing data" }) })] })), _jsxs("p", { className: classes.content, children: ["To work with this instance, access its UI or API directly. Full integration of UI to the Platform is currently available only to the EE users. If you have any questions, reach out to", ' ', _jsx("a", { href: "https://postgres.ai/contact", target: "_blank", rel: "noopener noreferrer", children: "the Postgres.ai team" }), "."] })] }));
65
60
  };
@@ -10,7 +10,8 @@ import { IconButton } from '@mui/material';
10
10
  import { icons } from '@postgres.ai/shared/styles/icons';
11
11
  import { RowMenu } from '@postgres.ai/shared/components/Table/RowMenu';
12
12
  import { generateSnapshotPageId, groupSnapshotsByCreatedAtDate, } from '@postgres.ai/shared/pages/Instance/Snapshots/utils';
13
- import { format, formatDistanceToNowStrict } from 'date-fns';
13
+ import { format } from 'date-fns';
14
+ import { formatDistanceSafe } from '@postgres.ai/shared/utils/date';
14
15
  import { formatBytesIEC } from '@postgres.ai/shared/utils/units';
15
16
  import { useHistory } from 'react-router';
16
17
  const useStyles = makeStyles({
@@ -109,7 +110,7 @@ const useStyles = makeStyles({
109
110
  const SnapshotListItem = ({ snapshot, setSnapshotModal, openClonesModal, }) => {
110
111
  var _a, _b;
111
112
  const classes = useStyles();
112
- const timeAgo = formatDistanceToNowStrict(snapshot.createdAtDate);
113
+ const timeAgo = formatDistanceSafe(snapshot.createdAtDate);
113
114
  const history = useHistory();
114
115
  const host = useHost();
115
116
  return (_jsx("div", { className: classes.commitItem, children: _jsxs("div", { className: classes.gridContainer, children: [_jsxs("div", { className: classes.infoBlock, children: [_jsx("div", { className: classes.header, children: snapshot.message || '-' }), _jsxs("div", { className: classes.infoContent, title: snapshot.dataStateAt, children: [timeAgo, " ago"] })] }), _jsxs("div", { className: classes.infoBlock, children: [_jsx("div", { className: classes.header, children: "Pool" }), _jsx("div", { className: classes.infoContent, children: (_a = snapshot.pool) !== null && _a !== void 0 ? _a : '-' })] }), _jsxs("div", { className: classes.infoBlock, children: [_jsx("div", { className: classes.header, children: "Number of clones" }), _jsx("div", { className: classes.infoContent, children: (_b = snapshot.numClones) !== null && _b !== void 0 ? _b : '-' })] }), _jsxs("div", { className: classes.infoBlock, children: [_jsx("div", { className: classes.header, children: "Logical Size" }), _jsx("div", { className: classes.infoContent, children: snapshot.logicalSize ? formatBytesIEC(snapshot.logicalSize) : '-' })] }), _jsxs("div", { className: classes.infoBlock, children: [_jsx("div", { className: classes.header, children: "Physical Size" }), _jsx("div", { className: classes.infoContent, children: snapshot.physicalSize
@@ -9,7 +9,6 @@ import React from 'react';
9
9
  import cn from 'classnames';
10
10
  import { observer } from 'mobx-react-lite';
11
11
  import { makeStyles } from '@material-ui/core';
12
- import { formatDistanceToNowStrict } from 'date-fns';
13
12
  import copy from 'copy-to-clipboard';
14
13
  import { useHistory } from 'react-router-dom';
15
14
  import { HorizontalScrollContainer } from '@postgres.ai/shared/components/HorizontalScrollContainer';
@@ -18,7 +17,7 @@ import { DestroySnapshotModal } from '@postgres.ai/shared/pages/Snapshots/Snapsh
18
17
  import { useStores } from '@postgres.ai/shared/pages/Instance/context';
19
18
  import { ArrowDropDownIcon } from '@postgres.ai/shared/icons/ArrowDropDown';
20
19
  import { formatBytesIEC } from '@postgres.ai/shared/utils/units';
21
- import { isSameDayUTC, isValidDate } from '@postgres.ai/shared/utils/date';
20
+ import { isSameDayUTC, formatDateWithDistance } from '@postgres.ai/shared/utils/date';
22
21
  import { Table, TableHead, TableRow, TableBody, TableHeaderCell, TableBodyCell, TableBodyCellMenu, } from '@postgres.ai/shared/components/Table';
23
22
  const useStyles = makeStyles({
24
23
  cellContentCentered: {
@@ -108,15 +107,7 @@ export const SnapshotsTable = observer(({ instanceId }) => {
108
107
  snapshotId: snapshot.id,
109
108
  }),
110
109
  },
111
- ] }), _jsxs(TableBodyCell, { children: [snapshot.dataStateAt, " (", isValidDate(snapshot.dataStateAtDate)
112
- ? formatDistanceToNowStrict(snapshot.dataStateAtDate, {
113
- addSuffix: true,
114
- })
115
- : '-', ")"] }), _jsxs(TableBodyCell, { children: [snapshot.createdAt, " (", isValidDate(snapshot.createdAtDate)
116
- ? formatDistanceToNowStrict(snapshot.createdAtDate, {
117
- addSuffix: true,
118
- })
119
- : '-', ")"] }), _jsx(TableBodyCell, { children: (_a = snapshot.pool) !== null && _a !== void 0 ? _a : '-' }), _jsx(TableBodyCell, { children: (_b = snapshot.numClones) !== null && _b !== void 0 ? _b : '-' }), _jsx(TableBodyCell, { children: snapshot.logicalSize
110
+ ] }), _jsx(TableBodyCell, { children: formatDateWithDistance(snapshot.dataStateAt, snapshot.dataStateAtDate) }), _jsx(TableBodyCell, { children: formatDateWithDistance(snapshot.createdAt, snapshot.createdAtDate) }), _jsx(TableBodyCell, { children: (_a = snapshot.pool) !== null && _a !== void 0 ? _a : '-' }), _jsx(TableBodyCell, { children: (_b = snapshot.numClones) !== null && _b !== void 0 ? _b : '-' }), _jsx(TableBodyCell, { children: snapshot.logicalSize
120
111
  ? formatBytesIEC(snapshot.logicalSize)
121
112
  : '-' }), _jsx(TableBodyCell, { children: snapshot.physicalSize
122
113
  ? formatBytesIEC(snapshot.physicalSize)
@@ -7,7 +7,6 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
7
7
  */
8
8
  import { observer } from 'mobx-react-lite';
9
9
  import { makeStyles } from '@material-ui/core';
10
- import { formatDistanceToNowStrict } from 'date-fns';
11
10
  import copy from 'copy-to-clipboard';
12
11
  import { useStores } from '@postgres.ai/shared/pages/Instance/context';
13
12
  import { ArrowDropDownIcon } from '@postgres.ai/shared/icons/ArrowDropDown';
@@ -15,7 +14,7 @@ import { Modal as ModalBase } from '@postgres.ai/shared/components/Modal';
15
14
  import { HorizontalScrollContainer } from '@postgres.ai/shared/components/HorizontalScrollContainer';
16
15
  import { Table, TableHead, TableRow, TableBody, TableHeaderCell, TableBodyCell, TableBodyCellMenu, } from '@postgres.ai/shared/components/Table';
17
16
  import { formatBytesIEC } from '@postgres.ai/shared/utils/units';
18
- import { isSameDayUTC } from '@postgres.ai/shared/utils/date';
17
+ import { isSameDayUTC, formatDateWithDistance } from '@postgres.ai/shared/utils/date';
19
18
  import { Tags } from '@postgres.ai/shared/pages/Instance/components/Tags';
20
19
  import { ModalReloadButton } from '@postgres.ai/shared/pages/Instance/components/ModalReloadButton';
21
20
  import { getTags } from '../Snapshots/components/SnapshotsModal/utils';
@@ -70,11 +69,7 @@ export const SnapshotsModal = observer(() => {
70
69
  snapshotId: snapshot.id,
71
70
  }),
72
71
  },
73
- ] }), _jsxs(TableBodyCell, { children: [snapshot.dataStateAt, " (", formatDistanceToNowStrict(snapshot.dataStateAtDate, {
74
- addSuffix: true,
75
- }), ")"] }), _jsxs(TableBodyCell, { children: [snapshot.createdAt, " (", formatDistanceToNowStrict(snapshot.createdAtDate, {
76
- addSuffix: true,
77
- }), ")"] }), _jsx(TableBodyCell, { children: (_a = snapshot.pool) !== null && _a !== void 0 ? _a : '-' }), _jsx(TableBodyCell, { children: snapshot.physicalSize
72
+ ] }), _jsx(TableBodyCell, { children: formatDateWithDistance(snapshot.dataStateAt, snapshot.dataStateAtDate) }), _jsx(TableBodyCell, { children: formatDateWithDistance(snapshot.createdAt, snapshot.createdAtDate) }), _jsx(TableBodyCell, { children: (_a = snapshot.pool) !== null && _a !== void 0 ? _a : '-' }), _jsx(TableBodyCell, { children: snapshot.physicalSize
78
73
  ? formatBytesIEC(snapshot.physicalSize)
79
74
  : '-' })] }, snapshot.id));
80
75
  }) })] }) }))] }));
package/utils/date.d.ts CHANGED
@@ -16,3 +16,5 @@ export declare const formatDateStd: (date: Date, options?: {
16
16
  withDistance?: boolean;
17
17
  }) => string;
18
18
  export declare const isValidDate: (dateObject: Date) => boolean;
19
+ export declare const formatDateWithDistance: (dateString: string, dateObject: Date) => string;
20
+ export declare const formatDistanceSafe: (dateObject: Date) => string;
package/utils/date.js CHANGED
@@ -6,8 +6,22 @@
6
6
  */
7
7
  import { parse, startOfDay, isSameDay, startOfMonth, startOfWeek, endOfMonth, endOfWeek, differenceInDays, addDays, addMonths, isSameMonth, format, formatDistanceToNowStrict, } from 'date-fns';
8
8
  export const formatDateToISO = (dateString) => {
9
- const parsedDate = parse(dateString, 'yyyyMMddHHmmss', new Date());
10
- return format(parsedDate, "yyyy-MM-dd'T'HH:mm:ssXXX");
9
+ // Handle empty or invalid date strings
10
+ if (!dateString || dateString.trim() === '') {
11
+ return '';
12
+ }
13
+ try {
14
+ const parsedDate = parse(dateString, 'yyyyMMddHHmmss', new Date());
15
+ // Additional validation of parsed date
16
+ if (!isValidDate(parsedDate) || isNaN(parsedDate.getTime())) {
17
+ return '';
18
+ }
19
+ return format(parsedDate, "yyyy-MM-dd'T'HH:mm:ssXXX");
20
+ }
21
+ catch (error) {
22
+ // Return empty string for invalid date formats
23
+ return '';
24
+ }
11
25
  };
12
26
  // parseDate parses date of both format: '2006-01-02 15:04:05 UTC' and `2006-01-02T15:04:05Z` (RFC3339).
13
27
  export const parseDate = (dateStr) => parse(dateStr.replace(' UTC', 'Z').replace('T', ' '), 'yyyy-MM-dd HH:mm:ssX', new Date());
@@ -38,3 +52,27 @@ export const formatDateStd = (date, options) => `${formatUTC(date, 'yyyy-MM-dd H
38
52
  export const isValidDate = (dateObject) => {
39
53
  return new Date(dateObject).toString() !== 'Invalid Date';
40
54
  };
55
+ // Safe date formatting with distance
56
+ export const formatDateWithDistance = (dateString, dateObject) => {
57
+ if (!dateString || !isValidDate(dateObject))
58
+ return '-';
59
+ try {
60
+ return `${dateString} (${formatDistanceToNowStrict(dateObject, { addSuffix: true })})`;
61
+ }
62
+ catch (error) {
63
+ console.warn('Error formatting date distance:', error, 'date:', dateObject);
64
+ return '-';
65
+ }
66
+ };
67
+ // Safe distance formatting only
68
+ export const formatDistanceSafe = (dateObject) => {
69
+ if (!isValidDate(dateObject))
70
+ return '-';
71
+ try {
72
+ return formatDistanceToNowStrict(dateObject, { addSuffix: true });
73
+ }
74
+ catch (error) {
75
+ console.warn('Error formatting distance:', error, 'date:', dateObject);
76
+ return '-';
77
+ }
78
+ };