@postgres.ai/shared 4.0.1-pr-1053 → 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.
- package/components/ResetCloneModal/index.js +2 -6
- package/package.json +1 -1
- package/pages/Branches/components/BranchesTable/index.js +2 -7
- package/pages/Instance/Clones/ClonesList/index.js +2 -11
- package/pages/Instance/InactiveInstance/index.js +2 -7
- package/pages/Instance/Snapshots/components/SnapshotsList/index.js +3 -2
- package/pages/Instance/Snapshots/components/SnapshotsTable/index.js +2 -11
- package/pages/Instance/SnapshotsModal/index.js +2 -7
- package/utils/date.d.ts +2 -0
- package/utils/date.js +40 -2
|
@@ -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 {
|
|
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, " (",
|
|
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
|
@@ -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 {
|
|
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 }),
|
|
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 {
|
|
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 }) })) }),
|
|
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 {
|
|
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
|
|
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 =
|
|
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,
|
|
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
|
-
] }),
|
|
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
|
-
] }),
|
|
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
|
-
|
|
10
|
-
|
|
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
|
+
};
|