|
@@ -1,7 +1,7 @@
|
|
|
-import { useCallback, useEffect, useMemo, useState } from 'react';
|
|
|
|
|
|
|
+import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
|
import { useTranslation } from 'react-i18next';
|
|
import { useTranslation } from 'react-i18next';
|
|
|
import { useQuery } from '@tanstack/react-query';
|
|
import { useQuery } from '@tanstack/react-query';
|
|
|
-import { Button, Card, Col, ConfigProvider, Input, Layout, Modal, Result, Row, Spin, Statistic, Typography, message } from 'antd';
|
|
|
|
|
|
|
+import { Alert, Button, Card, Checkbox, Col, ConfigProvider, Input, Layout, Modal, Result, Row, Spin, Statistic, Typography, message } from 'antd';
|
|
|
import {
|
|
import {
|
|
|
CheckCircleOutlined,
|
|
CheckCircleOutlined,
|
|
|
CloseCircleOutlined,
|
|
CloseCircleOutlined,
|
|
@@ -21,6 +21,33 @@ import { setMessageInstance } from '@/utils/messageBus';
|
|
|
import { HttpUtil } from '@/utils';
|
|
import { HttpUtil } from '@/utils';
|
|
|
import type { PanelUpdateInfo } from '../index/PanelUpdateModal';
|
|
import type { PanelUpdateInfo } from '../index/PanelUpdateModal';
|
|
|
|
|
|
|
|
|
|
+// Confirm-dialog body that lets the operator pick the stable or dev channel for
|
|
|
|
|
+// a node panel update. Reports changes via onChange so the imperative
|
|
|
|
|
+// modal.confirm onOk can read the latest choice through a ref.
|
|
|
|
|
+function UpdateChannelChoice({ onChange }: { onChange: (dev: boolean) => void }) {
|
|
|
|
|
+ const { t } = useTranslation();
|
|
|
|
|
+ const [dev, setDev] = useState(false);
|
|
|
|
|
+ return (
|
|
|
|
|
+ <div>
|
|
|
|
|
+ <p>{t('pages.nodes.updateConfirmContent')}</p>
|
|
|
|
|
+ <Checkbox
|
|
|
|
|
+ checked={dev}
|
|
|
|
|
+ onChange={(e) => { setDev(e.target.checked); onChange(e.target.checked); }}
|
|
|
|
|
+ >
|
|
|
|
|
+ {t('pages.nodes.updateDevChannel')}
|
|
|
|
|
+ </Checkbox>
|
|
|
|
|
+ {dev && (
|
|
|
|
|
+ <Alert
|
|
|
|
|
+ type="info"
|
|
|
|
|
+ showIcon
|
|
|
|
|
+ style={{ marginTop: 8 }}
|
|
|
|
|
+ message={t('pages.index.devChannelWarning')}
|
|
|
|
|
+ />
|
|
|
|
|
+ )}
|
|
|
|
|
+ </div>
|
|
|
|
|
+ );
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
export default function NodesPage() {
|
|
export default function NodesPage() {
|
|
|
const { t } = useTranslation();
|
|
const { t } = useTranslation();
|
|
|
const { isDark, isUltra, antdThemeConfig } = useTheme();
|
|
const { isDark, isUltra, antdThemeConfig } = useTheme();
|
|
@@ -136,8 +163,10 @@ export default function NodesPage() {
|
|
|
await setEnable(node.id, next);
|
|
await setEnable(node.id, next);
|
|
|
}, [setEnable]);
|
|
}, [setEnable]);
|
|
|
|
|
|
|
|
- const runUpdate = useCallback(async (ids: number[]) => {
|
|
|
|
|
- const msg = await updatePanels(ids);
|
|
|
|
|
|
|
+ const devRef = useRef(false);
|
|
|
|
|
+
|
|
|
|
|
+ const runUpdate = useCallback(async (ids: number[], dev: boolean) => {
|
|
|
|
|
+ const msg = await updatePanels(ids, dev);
|
|
|
if (!msg?.success) {
|
|
if (!msg?.success) {
|
|
|
messageApi.error(msg?.msg || t('somethingWentWrong'));
|
|
messageApi.error(msg?.msg || t('somethingWentWrong'));
|
|
|
return;
|
|
return;
|
|
@@ -156,12 +185,13 @@ export default function NodesPage() {
|
|
|
}, [updatePanels, messageApi, t]);
|
|
}, [updatePanels, messageApi, t]);
|
|
|
|
|
|
|
|
const onUpdateNode = useCallback((node: NodeRecord) => {
|
|
const onUpdateNode = useCallback((node: NodeRecord) => {
|
|
|
|
|
+ devRef.current = false;
|
|
|
modal.confirm({
|
|
modal.confirm({
|
|
|
title: t('pages.nodes.updateConfirmTitle', { count: 1 }),
|
|
title: t('pages.nodes.updateConfirmTitle', { count: 1 }),
|
|
|
- content: t('pages.nodes.updateConfirmContent'),
|
|
|
|
|
|
|
+ content: <UpdateChannelChoice onChange={(v) => { devRef.current = v; }} />,
|
|
|
okText: t('update'),
|
|
okText: t('update'),
|
|
|
cancelText: t('cancel'),
|
|
cancelText: t('cancel'),
|
|
|
- onOk: () => runUpdate([node.id]),
|
|
|
|
|
|
|
+ onOk: () => runUpdate([node.id], devRef.current),
|
|
|
});
|
|
});
|
|
|
}, [modal, t, runUpdate]);
|
|
}, [modal, t, runUpdate]);
|
|
|
|
|
|
|
@@ -173,12 +203,13 @@ export default function NodesPage() {
|
|
|
messageApi.warning(t('pages.nodes.toasts.updateNoneEligible'));
|
|
messageApi.warning(t('pages.nodes.toasts.updateNoneEligible'));
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
|
|
+ devRef.current = false;
|
|
|
modal.confirm({
|
|
modal.confirm({
|
|
|
title: t('pages.nodes.updateConfirmTitle', { count: eligible.length }),
|
|
title: t('pages.nodes.updateConfirmTitle', { count: eligible.length }),
|
|
|
- content: t('pages.nodes.updateConfirmContent'),
|
|
|
|
|
|
|
+ content: <UpdateChannelChoice onChange={(v) => { devRef.current = v; }} />,
|
|
|
okText: t('update'),
|
|
okText: t('update'),
|
|
|
cancelText: t('cancel'),
|
|
cancelText: t('cancel'),
|
|
|
- onOk: () => runUpdate(eligible),
|
|
|
|
|
|
|
+ onOk: () => runUpdate(eligible, devRef.current),
|
|
|
});
|
|
});
|
|
|
}, [modal, t, nodes, selectedIds, runUpdate, messageApi]);
|
|
}, [modal, t, nodes, selectedIds, runUpdate, messageApi]);
|
|
|
|
|
|