@postgres.ai/shared 4.0.0-pr-1028.9 → 4.0.0-pr-1028.10
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/package.json +1 -1
- package/pages/Clone/index.js +2 -2
- package/pages/Instance/Clones/ClonesList/index.d.ts +1 -0
- package/pages/Instance/Clones/ClonesList/index.js +2 -2
- package/pages/Instance/Clones/index.d.ts +1 -0
- package/pages/Instance/Clones/index.js +1 -1
- package/pages/Instance/Info/Retrieval/ConfirmFullRefreshModal/index.d.ts +8 -0
- package/pages/Instance/Info/Retrieval/ConfirmFullRefreshModal/index.js +66 -0
- package/pages/Instance/Info/Retrieval/index.js +8 -2
- package/pages/Instance/stores/Main.d.ts +6 -0
- package/pages/Instance/stores/Main.js +18 -0
- package/types/api/endpoints/fullRefresh.d.ts +6 -0
- package/types/api/endpoints/fullRefresh.js +1 -0
package/package.json
CHANGED
package/pages/Clone/index.js
CHANGED
|
@@ -220,8 +220,8 @@ export const Clone = observer((props) => {
|
|
|
220
220
|
isReloading ||
|
|
221
221
|
isUpdatingClone ||
|
|
222
222
|
!isCloneStable;
|
|
223
|
-
return (_jsxs(_Fragment, { children: [headRendered, _jsxs("div", { className: classes.wrapper, children: [_jsxs("div", { className: classes.summary, children: [_jsxs("div", { className: classes.actions, children: [_jsxs(Button, { variant: "contained", color: "primary", onClick: requestResetClone, disabled: isDisabledControls, title: 'Reset clone', className: classes.actionButton, children: ["Reset clone", isResettingClone && (_jsx(Spinner, { size: "sm", className: classes.spinner }))] }), _jsxs(Button, { variant: "contained", color: "primary", onClick: requestDestroyClone, disabled: isDisabledControls, title: 'Delete this clone', className: classes.actionButton, children: ["Delete clone", isDestroyingClone && (_jsx(Spinner, { size: "sm", className: classes.spinner }))] }), _jsxs(Button, { variant: "contained", color: "primary", onClick: createSnapshot, disabled: isDisabledControls, title: '
|
|
224
|
-
(stores.main.resetCloneError && (_jsx(ErrorStub, { title: 'Resetting error', message: stores.main.resetCloneError, className: classes.errorStub }))), _jsxs("div", { children: [_jsx("p", { children: _jsx("strong", { children: "Branch" }) }), _jsx("p", { className: classes.text, children: clone.branch })] }), _jsxs("div", { className: classes.title, children: [_jsx("p", { children: _jsx("strong", { children: "Created" }) }), _jsx("p", { className: classes.text, children: clone.createdAt })] }), _jsx("br", {}), _jsxs("div", { children: [_jsxs("p", { children: [_jsx("strong", { children: "Data state at" }), "\u00A0", _jsx(Tooltip, { content: _jsxs(_Fragment, { children: [_jsx("strong", { children: "Data state time" }), " is a time at which data is\u00A0 recovered for this clone."] }), children: icons.infoIcon })] }), _jsx("p", { className: classes.text, children: (_e = clone.snapshot) === null || _e === void 0 ? void 0 : _e.dataStateAt })] }), _jsx("br", {}), _jsxs("div", { children: [_jsx("p", { children: _jsx("strong", { children: "Status" }) }), _jsx(Status, { rawClone: clone, className: classes.status })] }), _jsx("br", {}), _jsxs("div", { children: [_jsxs("p", { children: [_jsx("strong", { children: "Summary" }), "\u00A0", _jsx(Tooltip, { content: _jsxs(_Fragment, { children: [_jsx("strong", { children: "Logical data size" }), " is a logical size of files in PGDATA which is being thin-cloned.", _jsx("br", {}), _jsx("br", {}), _jsx("strong", { children: "Physical data diff size" }), " is an actual size of a\u00A0 thin clone. On creation there is no diff between clone\u2019s\u00A0 and initial data state, all data blocks match. During work\u00A0 with the clone data diverges and data diff size increases.", _jsx("br", {}), _jsx("br", {}), _jsx("strong", { children: "Clone creation time" }), " is time which was\u00A0 spent to provision the clone."] }), children: icons.infoIcon })] }), _jsxs("p", { className: classes.text, children: [_jsx("span", { className: classes.paramTitle, children: "Logical data size:" }), ((_f = instance.state) === null || _f === void 0 ? void 0 : _f.dataSize)
|
|
223
|
+
return (_jsxs(_Fragment, { children: [headRendered, _jsxs("div", { className: classes.wrapper, children: [_jsxs("div", { className: classes.summary, children: [_jsxs("div", { className: classes.actions, children: [_jsxs(Button, { variant: "contained", color: "primary", onClick: requestResetClone, disabled: isDisabledControls, title: 'Reset clone', className: classes.actionButton, children: ["Reset clone", isResettingClone && (_jsx(Spinner, { size: "sm", className: classes.spinner }))] }), _jsxs(Button, { variant: "contained", color: "primary", onClick: requestDestroyClone, disabled: isDisabledControls, title: 'Delete this clone', className: classes.actionButton, children: ["Delete clone", isDestroyingClone && (_jsx(Spinner, { size: "sm", className: classes.spinner }))] }), !props.hideBracnhingFeatures && _jsxs(Button, { variant: "contained", color: "primary", onClick: createSnapshot, disabled: isDisabledControls, title: 'Create snapshot', className: classes.actionButton, children: ["Create snapshot", snapshots.snapshotDataLoading && (_jsx(Spinner, { size: "sm", className: classes.spinner }))] }), _jsxs(Button, { variant: "outlined", color: "secondary", onClick: reloadClone, disabled: isDisabledControls, title: 'Refresh clone information', className: classes.actionButton, children: ["Reload info", isReloading && _jsx(Spinner, { size: "sm", className: classes.spinner })] })] }), stores.main.destroyCloneError ||
|
|
224
|
+
(stores.main.resetCloneError && (_jsx(ErrorStub, { title: 'Resetting error', message: stores.main.resetCloneError, className: classes.errorStub }))), !props.hideBracnhingFeatures && _jsxs("div", { children: [_jsx("p", { children: _jsx("strong", { children: "Branch" }) }), _jsx("p", { className: classes.text, children: clone.branch })] }), _jsxs("div", { className: classes.title, children: [_jsx("p", { children: _jsx("strong", { children: "Created" }) }), _jsx("p", { className: classes.text, children: clone.createdAt })] }), _jsx("br", {}), _jsxs("div", { children: [_jsxs("p", { children: [_jsx("strong", { children: "Data state at" }), "\u00A0", _jsx(Tooltip, { content: _jsxs(_Fragment, { children: [_jsx("strong", { children: "Data state time" }), " is a time at which data is\u00A0 recovered for this clone."] }), children: icons.infoIcon })] }), _jsx("p", { className: classes.text, children: (_e = clone.snapshot) === null || _e === void 0 ? void 0 : _e.dataStateAt })] }), _jsx("br", {}), _jsxs("div", { children: [_jsx("p", { children: _jsx("strong", { children: "Status" }) }), _jsx(Status, { rawClone: clone, className: classes.status })] }), _jsx("br", {}), _jsxs("div", { children: [_jsxs("p", { children: [_jsx("strong", { children: "Summary" }), "\u00A0", _jsx(Tooltip, { content: _jsxs(_Fragment, { children: [_jsx("strong", { children: "Logical data size" }), " is a logical size of files in PGDATA which is being thin-cloned.", _jsx("br", {}), _jsx("br", {}), _jsx("strong", { children: "Physical data diff size" }), " is an actual size of a\u00A0 thin clone. On creation there is no diff between clone\u2019s\u00A0 and initial data state, all data blocks match. During work\u00A0 with the clone data diverges and data diff size increases.", _jsx("br", {}), _jsx("br", {}), _jsx("strong", { children: "Clone creation time" }), " is time which was\u00A0 spent to provision the clone."] }), children: icons.infoIcon })] }), _jsxs("p", { className: classes.text, children: [_jsx("span", { className: classes.paramTitle, children: "Logical data size:" }), ((_f = instance.state) === null || _f === void 0 ? void 0 : _f.dataSize)
|
|
225
225
|
? formatBytesIEC(instance.state.dataSize)
|
|
226
226
|
: '-'] }), _jsxs("p", { className: classes.text, children: [_jsx("span", { className: classes.paramTitle, children: "Physical data diff size:" }), clone.metadata.cloneDiffSize
|
|
227
227
|
? formatBytesIEC(clone.metadata.cloneDiffSize)
|
|
@@ -78,12 +78,12 @@ export const ClonesList = (props) => {
|
|
|
78
78
|
};
|
|
79
79
|
if (!((_b = state.clones) === null || _b === void 0 ? void 0 : _b.length))
|
|
80
80
|
return _jsx("p", { className: styles.emptyStub, children: props.emptyStubText });
|
|
81
|
-
return (_jsxs(_Fragment, { children: [_jsx(HorizontalScrollContainer, { children: _jsxs(Table, { children: [_jsx(TableHead, { children: _jsxs(TableRow, { children: [_jsx(TableHeaderCell, {}), _jsx(TableHeaderCell, { children: "Status" }), _jsx(TableHeaderCell, { children: "ID" }), _jsx(TableHeaderCell, { children: _jsxs("div", { onClick: handleSortByBranch, className: cn(styles.interactiveRow, styles.verticalCentered), children: ["Branch", _jsx(ArrowDropDownIcon, { className: cn(state.sortByCreated === 'asc' && styles.hideSortIcon, state.sortByBranch === 'asc' && styles.sortIconUp, styles.sortIcon) })] }) }), _jsx(TableHeaderCell, { children: _jsx(Tooltip, { content: "When enabled, neither manual nor automated deletion of this clone is possible. Note that abandoned protected clones may lead to out-of-disk-space events because they hold old data, blocking cleanup and refresh processes.", children: _jsxs("div", { className: styles.verticalCentered, children: ["Protected", _jsx(InfoIcon, { className: styles.infoIcon })] }) }) }), _jsx(TableHeaderCell, { children: _jsxs("div", { onClick: handleSortByCreated, className: cn(styles.interactiveRow, styles.verticalCentered), children: ["Created", _jsx(ArrowDropDownIcon, { className: cn(state.sortByBranch === 'asc' && styles.hideSortIcon, state.sortByCreated === 'asc' && styles.sortIconUp, styles.sortIcon) })] }) }), _jsx(TableHeaderCell, { children: "Port" }), _jsx(TableHeaderCell, { children: "DB user" }), _jsx(TableHeaderCell, { children: _jsx(Tooltip, { content: "Clone's own size \u2013 how much data was added or modified.", children: _jsxs("div", { className: styles.verticalCentered, children: ["Diff size", _jsx(InfoIcon, { className: styles.infoIcon })] }) }) }), _jsx(TableHeaderCell, { children: "Disk" }), _jsx(TableHeaderCell, { children: "Data state time" })] }) }), _jsx(TableBody, { children: state.clones.map((clone) => {
|
|
81
|
+
return (_jsxs(_Fragment, { children: [_jsx(HorizontalScrollContainer, { children: _jsxs(Table, { children: [_jsx(TableHead, { children: _jsxs(TableRow, { children: [_jsx(TableHeaderCell, {}), _jsx(TableHeaderCell, { children: "Status" }), _jsx(TableHeaderCell, { children: "ID" }), !props.hideBracnhingFeatures && _jsx(TableHeaderCell, { children: _jsxs("div", { onClick: handleSortByBranch, className: cn(styles.interactiveRow, styles.verticalCentered), children: ["Branch", _jsx(ArrowDropDownIcon, { className: cn(state.sortByCreated === 'asc' && styles.hideSortIcon, state.sortByBranch === 'asc' && styles.sortIconUp, styles.sortIcon) })] }) }), _jsx(TableHeaderCell, { children: _jsx(Tooltip, { content: "When enabled, neither manual nor automated deletion of this clone is possible. Note that abandoned protected clones may lead to out-of-disk-space events because they hold old data, blocking cleanup and refresh processes.", children: _jsxs("div", { className: styles.verticalCentered, children: ["Protected", _jsx(InfoIcon, { className: styles.infoIcon })] }) }) }), _jsx(TableHeaderCell, { children: _jsxs("div", { onClick: handleSortByCreated, className: cn(styles.interactiveRow, styles.verticalCentered), children: ["Created", _jsx(ArrowDropDownIcon, { className: cn(state.sortByBranch === 'asc' && styles.hideSortIcon, state.sortByCreated === 'asc' && styles.sortIconUp, styles.sortIcon) })] }) }), _jsx(TableHeaderCell, { children: "Port" }), _jsx(TableHeaderCell, { children: "DB user" }), _jsx(TableHeaderCell, { children: _jsx(Tooltip, { content: "Clone's own size \u2013 how much data was added or modified.", children: _jsxs("div", { className: styles.verticalCentered, children: ["Diff size", _jsx(InfoIcon, { className: styles.infoIcon })] }) }) }), _jsx(TableHeaderCell, { children: "Disk" }), _jsx(TableHeaderCell, { children: "Data state time" })] }) }), _jsx(TableBody, { children: state.clones.map((clone) => {
|
|
82
82
|
var _a, _b;
|
|
83
83
|
const clonePagePath = host.routes.clone(clone.id);
|
|
84
84
|
return (_jsxs(TableRow, { hover: !props.isDisabled, onClick: props.isDisabled
|
|
85
85
|
? 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 }), _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)
|
|
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.hideBracnhingFeatures && _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
87
|
? formatDistanceToNowStrict(clone.createdAtDate, {
|
|
88
88
|
addSuffix: true,
|
|
89
89
|
})
|
|
@@ -60,5 +60,5 @@ export const Clones = observer((props) => {
|
|
|
60
60
|
const canCreateClone = hasSnapshots && !stores.main.isDisabledInstance;
|
|
61
61
|
return (_jsxs("div", { className: classes.root, children: [!onlyRenderList && (_jsxs(_Fragment, { children: [_jsx(SectionTitle, { level: 2, tag: "h2", text: "Cloning summary" }), _jsx(Header, { expectedCloningTimeS: round(instance.state.cloning.expectedCloningTime, 2), logicalSize: instance.state.dataSize, clonesCount: instance.state.cloning.clones.length })] })), _jsx(SectionTitle, { level: 2, tag: "h3", text: `Clones (${instance.state.cloning.clones.length})`, rightContent: _jsxs(_Fragment, { children: [_jsx(Button, { theme: "primary", onClick: goToCloneAddPage, isDisabled: !canCreateClone, isLoading: isLoadingSnapshots, children: "Create clone" }), !hasSnapshots && (_jsx(Tooltip, { content: "No snapshots", children: _jsx("div", { style: { display: 'flex' }, children: _jsx(InfoIcon, { className: classes.infoIcon }) }) }))] }) }), _jsx(ClonesList, { clones: isShortList
|
|
62
62
|
? instance.state.cloning.clones.slice(0, SHORT_LIST_SIZE)
|
|
63
|
-
: instance.state.cloning.clones, isDisabled: stores.main.isDisabledInstance, emptyStubText: "This instance has no active clones." }), showListSizeButton && !onlyRenderList && (_jsx(Button, { className: classes.listSizeButton, onClick: toggleListSize, children: isShortList ? 'Show more' : 'Show less' }))] }));
|
|
63
|
+
: instance.state.cloning.clones, isDisabled: stores.main.isDisabledInstance, emptyStubText: "This instance has no active clones.", hideBracnhingFeatures: props.hideBracnhingFeatures }), showListSizeButton && !onlyRenderList && (_jsx(Button, { className: classes.listSizeButton, onClick: toggleListSize, children: isShortList ? 'Show more' : 'Show less' }))] }));
|
|
64
64
|
});
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useState } from 'react';
|
|
3
|
+
import { makeStyles } from '@material-ui/core';
|
|
4
|
+
import { Modal } from '@postgres.ai/shared/components/Modal';
|
|
5
|
+
import { Text } from '@postgres.ai/shared/components/Text';
|
|
6
|
+
import { SimpleModalControls } from '@postgres.ai/shared/components/SimpleModalControls';
|
|
7
|
+
import { useStores } from '@postgres.ai/shared/pages/Instance/context';
|
|
8
|
+
const useStyles = makeStyles({
|
|
9
|
+
errorMessage: {
|
|
10
|
+
color: 'red',
|
|
11
|
+
marginTop: '10px',
|
|
12
|
+
wordBreak: 'break-all',
|
|
13
|
+
},
|
|
14
|
+
checkboxRoot: {
|
|
15
|
+
padding: '9px 10px',
|
|
16
|
+
},
|
|
17
|
+
grayText: {
|
|
18
|
+
color: '#8a8a8a',
|
|
19
|
+
fontSize: '12px',
|
|
20
|
+
wordBreak: 'break-word',
|
|
21
|
+
},
|
|
22
|
+
marginTop: {
|
|
23
|
+
marginTop: '6px',
|
|
24
|
+
},
|
|
25
|
+
}, { index: 1 });
|
|
26
|
+
export const ConfirmFullRefreshModal = ({ isOpen, onClose, instanceId, }) => {
|
|
27
|
+
var _a;
|
|
28
|
+
const classes = useStyles();
|
|
29
|
+
const stores = useStores();
|
|
30
|
+
const { fullRefresh } = stores.main;
|
|
31
|
+
const [fullRefreshError, setFullRefreshError] = useState(null);
|
|
32
|
+
const handleClose = () => {
|
|
33
|
+
onClose();
|
|
34
|
+
};
|
|
35
|
+
const handleConfirm = async () => {
|
|
36
|
+
const result = await fullRefresh(instanceId);
|
|
37
|
+
if (!result) {
|
|
38
|
+
setFullRefreshError({ error: { message: 'Unexpected error occurred.' } });
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
const { response, error } = result;
|
|
42
|
+
if (error) {
|
|
43
|
+
setFullRefreshError({
|
|
44
|
+
error: {
|
|
45
|
+
message: error.message,
|
|
46
|
+
},
|
|
47
|
+
});
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
if (response) {
|
|
51
|
+
onClose();
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
return (_jsxs(Modal, { title: 'Confirmation', onClose: handleClose, isOpen: isOpen, size: "sm", children: [_jsx(Text, { children: "Are you sure you want to perform a full refresh of the instance? This action cannot be undone." }), fullRefreshError && _jsx("p", { className: classes.errorMessage, children: (_a = fullRefreshError.error) === null || _a === void 0 ? void 0 : _a.message }), _jsx(SimpleModalControls, { items: [
|
|
55
|
+
{
|
|
56
|
+
text: 'Cancel',
|
|
57
|
+
onClick: handleClose,
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
text: 'Confirm',
|
|
61
|
+
variant: 'primary',
|
|
62
|
+
onClick: handleConfirm,
|
|
63
|
+
isDisabled: fullRefreshError !== null,
|
|
64
|
+
},
|
|
65
|
+
] })] }));
|
|
66
|
+
};
|
|
@@ -12,6 +12,7 @@ import { Property } from '../components/Property';
|
|
|
12
12
|
import { RefreshFailedAlert } from './RefreshFailedAlert';
|
|
13
13
|
import { getTypeByStatus, isRetrievalUnknown } from './utils';
|
|
14
14
|
import { RetrievalModal } from './RetrievalModal';
|
|
15
|
+
import { ConfirmFullRefreshModal } from './ConfirmFullRefreshModal';
|
|
15
16
|
const useStyles = makeStyles(() => ({
|
|
16
17
|
infoIcon: {
|
|
17
18
|
height: '12px',
|
|
@@ -21,6 +22,9 @@ const useStyles = makeStyles(() => ({
|
|
|
21
22
|
},
|
|
22
23
|
detailsButton: {
|
|
23
24
|
marginLeft: '8px',
|
|
25
|
+
'@media (max-width: 600px)': {
|
|
26
|
+
marginTop: '4px',
|
|
27
|
+
},
|
|
24
28
|
},
|
|
25
29
|
}), { index: 1 });
|
|
26
30
|
export const Retrieval = observer(() => {
|
|
@@ -28,6 +32,7 @@ export const Retrieval = observer(() => {
|
|
|
28
32
|
const stores = useStores();
|
|
29
33
|
const classes = useStyles();
|
|
30
34
|
const [isModalOpen, setIsModalOpen] = useState(false);
|
|
35
|
+
const [isFullRefreshModalOpen, setIsFullRefreshModalOpen] = useState(false);
|
|
31
36
|
const { instance, instanceRetrieval } = stores.main;
|
|
32
37
|
if (!instance)
|
|
33
38
|
return null;
|
|
@@ -39,9 +44,10 @@ export const Retrieval = observer(() => {
|
|
|
39
44
|
const { mode, status, activity } = instanceRetrieval;
|
|
40
45
|
const isVisible = mode !== 'physical' && !isRetrievalUnknown(mode);
|
|
41
46
|
const isActive = mode === 'logical' && status === 'refreshing';
|
|
42
|
-
|
|
47
|
+
const canCallFullRefresh = retrieving.status === 'finished' || retrieving.status === 'failed';
|
|
48
|
+
return (_jsxs(Section, { title: "Retrieval", children: [_jsx(Property, { name: "Status", children: _jsxs(Status, { type: getTypeByStatus(retrieving.status), children: [capitalize(retrieving.status), isVisible && (_jsx(_Fragment, { children: _jsx(Button, { theme: "primary", onClick: () => setIsModalOpen(true), isDisabled: !isActive, className: classes.detailsButton, children: "Show details" }) })), _jsx(Button, { theme: "secondary", onClick: () => setIsFullRefreshModalOpen(true), isDisabled: !canCallFullRefresh, className: classes.detailsButton, children: "Full refresh" })] }) }), _jsx(Property, { name: "Mode", children: retrieving.mode }), _jsx(Property, { name: "Last refresh", children: retrieving.lastRefresh
|
|
43
49
|
? formatDateStd(retrieving.lastRefresh, { withDistance: true })
|
|
44
50
|
: '-' }), _jsx(Property, { name: "Next refresh", children: retrieving.nextRefresh
|
|
45
51
|
? formatDateStd(retrieving.nextRefresh, { withDistance: true })
|
|
46
|
-
: 'Not scheduled' }), _jsx(RefreshFailedAlert, {}), _jsx(RetrievalModal, { data: activity, isOpen: isModalOpen, onClose: () => setIsModalOpen(false) })] }));
|
|
52
|
+
: 'Not scheduled' }), _jsx(RefreshFailedAlert, {}), _jsx(RetrievalModal, { data: activity, isOpen: isModalOpen, onClose: () => setIsModalOpen(false) }), _jsx(ConfirmFullRefreshModal, { isOpen: isFullRefreshModalOpen, onClose: () => setIsFullRefreshModalOpen(false), instanceId: instance.id })] }));
|
|
47
53
|
});
|
|
@@ -22,6 +22,7 @@ import { GetBranches } from '@postgres.ai/shared/types/api/endpoints/getBranches
|
|
|
22
22
|
import { DeleteBranch } from '@postgres.ai/shared/types/api/endpoints/deleteBranch';
|
|
23
23
|
import { GetSeImages } from '@postgres.ai/shared/types/api/endpoints/getSeImages';
|
|
24
24
|
import { DestroySnapshot } from '@postgres.ai/shared/types/api/endpoints/destroySnapshot';
|
|
25
|
+
import { FullRefresh } from "../../../types/api/endpoints/fullRefresh";
|
|
25
26
|
export declare type Api = {
|
|
26
27
|
getInstance: GetInstance;
|
|
27
28
|
getSnapshots?: GetSnapshots;
|
|
@@ -42,6 +43,7 @@ export declare type Api = {
|
|
|
42
43
|
getSnapshotList?: GetSnapshotList;
|
|
43
44
|
deleteBranch?: DeleteBranch;
|
|
44
45
|
destroySnapshot?: DestroySnapshot;
|
|
46
|
+
fullRefresh?: FullRefresh;
|
|
45
47
|
};
|
|
46
48
|
declare type Error = {
|
|
47
49
|
title?: string;
|
|
@@ -137,5 +139,9 @@ export declare class MainStore {
|
|
|
137
139
|
response: boolean | null;
|
|
138
140
|
error: any;
|
|
139
141
|
} | undefined>;
|
|
142
|
+
fullRefresh: (instanceId: string) => Promise<{
|
|
143
|
+
response: string | null;
|
|
144
|
+
error: Error | null;
|
|
145
|
+
} | undefined>;
|
|
140
146
|
}
|
|
141
147
|
export {};
|
|
@@ -289,6 +289,24 @@ export class MainStore {
|
|
|
289
289
|
error: error ? await error.json().then((err) => err) : null,
|
|
290
290
|
};
|
|
291
291
|
};
|
|
292
|
+
this.fullRefresh = async (instanceId) => {
|
|
293
|
+
var _a, _b;
|
|
294
|
+
if (!this.api.fullRefresh)
|
|
295
|
+
return;
|
|
296
|
+
const { response, error } = await this.api.fullRefresh({
|
|
297
|
+
instanceId,
|
|
298
|
+
});
|
|
299
|
+
if (error) {
|
|
300
|
+
const parsedError = await error.json().then((err) => ({
|
|
301
|
+
message: err.message || 'An unknown error occurred',
|
|
302
|
+
}));
|
|
303
|
+
return { response: null, error: parsedError };
|
|
304
|
+
}
|
|
305
|
+
else if ((_b = (_a = this.instance) === null || _a === void 0 ? void 0 : _a.state) === null || _b === void 0 ? void 0 : _b.retrieving) {
|
|
306
|
+
this.instance.state.retrieving.status = 'refreshing';
|
|
307
|
+
}
|
|
308
|
+
return { response: response ? String(response) : null, error: null };
|
|
309
|
+
};
|
|
292
310
|
makeAutoObservable(this);
|
|
293
311
|
this.api = api;
|
|
294
312
|
this.snapshots = new SnapshotsStore(api);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|