chore: add resource worker
This commit is contained in:
@@ -27,6 +27,7 @@
|
|||||||
"dayjs": "^1.11.11",
|
"dayjs": "^1.11.11",
|
||||||
"echarts": "^5.5.1",
|
"echarts": "^5.5.1",
|
||||||
"has-ansi": "^5.0.1",
|
"has-ansi": "^5.0.1",
|
||||||
|
"highlight.js": "^11.10.0",
|
||||||
"jotai": "^2.8.4",
|
"jotai": "^2.8.4",
|
||||||
"localforage": "^1.10.0",
|
"localforage": "^1.10.0",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
|
|||||||
Generated
+36
-4
@@ -53,6 +53,9 @@ dependencies:
|
|||||||
has-ansi:
|
has-ansi:
|
||||||
specifier: ^5.0.1
|
specifier: ^5.0.1
|
||||||
version: 5.0.1
|
version: 5.0.1
|
||||||
|
highlight.js:
|
||||||
|
specifier: ^11.10.0
|
||||||
|
version: 11.10.0
|
||||||
jotai:
|
jotai:
|
||||||
specifier: ^2.8.4
|
specifier: ^2.8.4
|
||||||
version: 2.8.4(@types/react@18.3.1)(react@18.2.0)
|
version: 2.8.4(@types/react@18.3.1)(react@18.2.0)
|
||||||
@@ -4438,7 +4441,7 @@ packages:
|
|||||||
dependencies:
|
dependencies:
|
||||||
'@babel/core': 7.24.5
|
'@babel/core': 7.24.5
|
||||||
postcss: 7.0.39
|
postcss: 7.0.39
|
||||||
postcss-syntax: 0.36.2(postcss@8.4.38)
|
postcss-syntax: 0.36.2(postcss@7.0.39)
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
dev: false
|
dev: false
|
||||||
@@ -4479,7 +4482,7 @@ packages:
|
|||||||
postcss-syntax: '>=0.36.2'
|
postcss-syntax: '>=0.36.2'
|
||||||
dependencies:
|
dependencies:
|
||||||
postcss: 7.0.39
|
postcss: 7.0.39
|
||||||
postcss-syntax: 0.36.2(postcss@8.4.38)
|
postcss-syntax: 0.36.2(postcss@7.0.39)
|
||||||
remark: 13.0.0
|
remark: 13.0.0
|
||||||
unist-util-find-all-after: 3.0.2
|
unist-util-find-all-after: 3.0.2
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
@@ -10450,6 +10453,11 @@ packages:
|
|||||||
hasBin: true
|
hasBin: true
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/highlight.js@11.10.0:
|
||||||
|
resolution: {integrity: sha512-SYVnVFswQER+zu1laSya563s+F8VDGt7o35d4utbamowvUNLLMovFqwCLSocpZTz3MgaSRA1IbqRWZv97dtErQ==, tarball: https://registry.npmjs.org/highlight.js/-/highlight.js-11.10.0.tgz}
|
||||||
|
engines: {node: '>=12.0.0'}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/history@4.10.1:
|
/history@4.10.1:
|
||||||
resolution: {integrity: sha512-36nwAD620w12kuzPAsyINPWJqlNbij+hpK1k9XRloDtym8mxzGYl2c17LnV6IAGB2Dmg4tEa7G7DlawS0+qjew==, tarball: https://registry.npmjs.org/history/-/history-4.10.1.tgz}
|
resolution: {integrity: sha512-36nwAD620w12kuzPAsyINPWJqlNbij+hpK1k9XRloDtym8mxzGYl2c17LnV6IAGB2Dmg4tEa7G7DlawS0+qjew==, tarball: https://registry.npmjs.org/history/-/history-4.10.1.tgz}
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -13093,7 +13101,7 @@ packages:
|
|||||||
dependencies:
|
dependencies:
|
||||||
htmlparser2: 3.10.1
|
htmlparser2: 3.10.1
|
||||||
postcss: 7.0.39
|
postcss: 7.0.39
|
||||||
postcss-syntax: 0.36.2(postcss@8.4.38)
|
postcss-syntax: 0.36.2(postcss@7.0.39)
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/postcss-image-set-function@4.0.7(postcss@8.4.38):
|
/postcss-image-set-function@4.0.7(postcss@8.4.38):
|
||||||
@@ -13567,6 +13575,30 @@ packages:
|
|||||||
lodash: 4.17.21
|
lodash: 4.17.21
|
||||||
postcss: 8.4.38
|
postcss: 8.4.38
|
||||||
|
|
||||||
|
/postcss-syntax@0.36.2(postcss@7.0.39):
|
||||||
|
resolution: {integrity: sha512-nBRg/i7E3SOHWxF3PpF5WnJM/jQ1YpY9000OaVXlAQj6Zp/kIqJxEDWIZ67tAd7NLuk7zqN4yqe9nc0oNAOs1w==}
|
||||||
|
peerDependencies:
|
||||||
|
postcss: '>=5.0.0'
|
||||||
|
postcss-html: '*'
|
||||||
|
postcss-jsx: '*'
|
||||||
|
postcss-less: '*'
|
||||||
|
postcss-markdown: '*'
|
||||||
|
postcss-scss: '*'
|
||||||
|
peerDependenciesMeta:
|
||||||
|
postcss-html:
|
||||||
|
optional: true
|
||||||
|
postcss-jsx:
|
||||||
|
optional: true
|
||||||
|
postcss-less:
|
||||||
|
optional: true
|
||||||
|
postcss-markdown:
|
||||||
|
optional: true
|
||||||
|
postcss-scss:
|
||||||
|
optional: true
|
||||||
|
dependencies:
|
||||||
|
postcss: 7.0.39
|
||||||
|
dev: false
|
||||||
|
|
||||||
/postcss-syntax@0.36.2(postcss@8.4.38):
|
/postcss-syntax@0.36.2(postcss@8.4.38):
|
||||||
resolution: {integrity: sha512-nBRg/i7E3SOHWxF3PpF5WnJM/jQ1YpY9000OaVXlAQj6Zp/kIqJxEDWIZ67tAd7NLuk7zqN4yqe9nc0oNAOs1w==}
|
resolution: {integrity: sha512-nBRg/i7E3SOHWxF3PpF5WnJM/jQ1YpY9000OaVXlAQj6Zp/kIqJxEDWIZ67tAd7NLuk7zqN4yqe9nc0oNAOs1w==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
@@ -16724,7 +16756,7 @@ packages:
|
|||||||
postcss-sass: 0.4.4
|
postcss-sass: 0.4.4
|
||||||
postcss-scss: 2.1.1
|
postcss-scss: 2.1.1
|
||||||
postcss-selector-parser: 6.0.16
|
postcss-selector-parser: 6.0.16
|
||||||
postcss-syntax: 0.36.2(postcss@8.4.38)
|
postcss-syntax: 0.36.2(postcss@7.0.39)
|
||||||
postcss-value-parser: 4.2.0
|
postcss-value-parser: 4.2.0
|
||||||
resolve-from: 5.0.0
|
resolve-from: 5.0.0
|
||||||
slash: 3.0.0
|
slash: 3.0.0
|
||||||
|
|||||||
@@ -56,6 +56,7 @@ const CopyButton: React.FC<CopyButtonProps> = ({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Button
|
<Button
|
||||||
|
className="copy-button"
|
||||||
ref={buttonRef}
|
ref={buttonRef}
|
||||||
type={type}
|
type={type}
|
||||||
shape={shape}
|
shape={shape}
|
||||||
|
|||||||
@@ -0,0 +1,76 @@
|
|||||||
|
import hljs from 'highlight.js';
|
||||||
|
import 'highlight.js/styles/atom-one-dark.css';
|
||||||
|
import CopyButton from '../copy-button';
|
||||||
|
import { escapeHtml } from './utils';
|
||||||
|
|
||||||
|
interface CodeViewerProps {
|
||||||
|
code: string;
|
||||||
|
lang: string;
|
||||||
|
autodetect?: boolean;
|
||||||
|
ignoreIllegals?: boolean;
|
||||||
|
copyable?: boolean;
|
||||||
|
}
|
||||||
|
const CodeViewer: React.FC<CodeViewerProps> = (props) => {
|
||||||
|
const {
|
||||||
|
code,
|
||||||
|
lang,
|
||||||
|
autodetect = true,
|
||||||
|
ignoreIllegals = true,
|
||||||
|
copyable = true
|
||||||
|
} = props || {};
|
||||||
|
|
||||||
|
const renderCode = () => {
|
||||||
|
const autodetectLang = autodetect && !lang;
|
||||||
|
const cannotDetectLanguage = !autodetectLang && !hljs.getLanguage(lang);
|
||||||
|
let className = '';
|
||||||
|
|
||||||
|
if (!cannotDetectLanguage) {
|
||||||
|
className = `hljs ${lang}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
// No idea what language to use, return raw code
|
||||||
|
if (cannotDetectLanguage) {
|
||||||
|
console.warn(`The language "${lang}" you specified could not be found.`);
|
||||||
|
return {
|
||||||
|
value: escapeHtml(code),
|
||||||
|
className: className
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (autodetectLang) {
|
||||||
|
const result = hljs.highlightAuto(code);
|
||||||
|
return {
|
||||||
|
value: result.value,
|
||||||
|
className: className
|
||||||
|
};
|
||||||
|
}
|
||||||
|
const result = hljs.highlight(code, {
|
||||||
|
language: lang,
|
||||||
|
ignoreIllegals: ignoreIllegals
|
||||||
|
});
|
||||||
|
return {
|
||||||
|
value: result.value,
|
||||||
|
className: className
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const highlightedCode = renderCode();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<pre className="code-pre">
|
||||||
|
<code
|
||||||
|
className={highlightedCode.className}
|
||||||
|
dangerouslySetInnerHTML={{
|
||||||
|
__html: highlightedCode.value
|
||||||
|
}}
|
||||||
|
></code>
|
||||||
|
<CopyButton
|
||||||
|
text={highlightedCode.value}
|
||||||
|
size="small"
|
||||||
|
style={{ color: '#abb2bf' }}
|
||||||
|
></CopyButton>
|
||||||
|
</pre>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default CodeViewer;
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
import CodeViewer from './code-viewer';
|
||||||
|
import './style.less';
|
||||||
|
|
||||||
|
const HighlightCode: React.FC<{
|
||||||
|
code: string;
|
||||||
|
lang?: string;
|
||||||
|
}> = (props) => {
|
||||||
|
const { code, lang = 'bash' } = props;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="high-light-wrapper">
|
||||||
|
<CodeViewer lang={lang} code={code} />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default HighlightCode;
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
.high-light-wrapper {
|
||||||
|
text-align: left;
|
||||||
|
|
||||||
|
.hljs {
|
||||||
|
font-weight: var(--font-weight-normal);
|
||||||
|
padding-inline: 0;
|
||||||
|
padding-block: 1.2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.code-pre {
|
||||||
|
padding-inline: 12px 32px;
|
||||||
|
position: relative;
|
||||||
|
background-color: #282c34;
|
||||||
|
border-radius: var(--border-radius-mini);
|
||||||
|
|
||||||
|
.copy-button {
|
||||||
|
position: absolute;
|
||||||
|
top: 6px;
|
||||||
|
right: 6px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
export function escapeHtml(value: string): string {
|
||||||
|
return value
|
||||||
|
.replace(/&/g, '&')
|
||||||
|
.replace(/</g, '<')
|
||||||
|
.replace(/>/g, '>')
|
||||||
|
.replace(/"/g, '"')
|
||||||
|
.replace(/'/g, ''');
|
||||||
|
}
|
||||||
@@ -114,6 +114,7 @@ html {
|
|||||||
--ant-modal-header-margin-bottom: 20px;
|
--ant-modal-header-margin-bottom: 20px;
|
||||||
--ant-modal-footer-margin-top: 30px;
|
--ant-modal-footer-margin-top: 30px;
|
||||||
--ant-modal-content-padding: 20px 24px 24px;
|
--ant-modal-content-padding: 20px 24px 24px;
|
||||||
|
--ant-modal-title-color: var(--ant-color-text);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ export function useUpdateChunkedList(options: {
|
|||||||
clearTimeout(timerRef.current);
|
clearTimeout(timerRef.current);
|
||||||
timerRef.current = setTimeout(() => {
|
timerRef.current = setTimeout(() => {
|
||||||
options.setDataList?.([...cacheDataListRef.current]);
|
options.setDataList?.([...cacheDataListRef.current]);
|
||||||
}, 100);
|
}, 80);
|
||||||
};
|
};
|
||||||
const updateChunkedList = (
|
const updateChunkedList = (
|
||||||
data: ChunkedCollection,
|
data: ChunkedCollection,
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
export default {
|
export default {
|
||||||
'resources.title': 'Resources',
|
'resources.title': 'Resources',
|
||||||
'resources.nodes': 'Nodes',
|
'resources.nodes': 'Nodes',
|
||||||
|
'resources.button.create': 'Add Worker',
|
||||||
'resources.table.hostname': 'Hostname',
|
'resources.table.hostname': 'Hostname',
|
||||||
'resources.table.ip': 'IP',
|
'resources.table.ip': 'IP',
|
||||||
'resources.table.cpu': 'CPU',
|
'resources.table.cpu': 'CPU',
|
||||||
@@ -18,5 +19,9 @@ export default {
|
|||||||
'resources.table.total': 'Total',
|
'resources.table.total': 'Total',
|
||||||
'resources.table.used': 'Used',
|
'resources.table.used': 'Used',
|
||||||
'resources.table.wokers': 'workers',
|
'resources.table.wokers': 'workers',
|
||||||
'resources.table.unified': 'Unified Memory'
|
'resources.table.unified': 'Unified Memory',
|
||||||
|
'resources.worker.add.step1': 'Get Token',
|
||||||
|
'resources.worker.add.step2': 'Register Worker',
|
||||||
|
'resources.worker.add.step3':
|
||||||
|
'Refresh worker list, you can see the newly added worker'
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
export default {
|
export default {
|
||||||
'resources.title': '资源',
|
'resources.title': '资源',
|
||||||
|
'resources.button.create': '添加 Worker',
|
||||||
'resources.nodes': '节点',
|
'resources.nodes': '节点',
|
||||||
'resources.table.hostname': '主机名',
|
'resources.table.hostname': '主机名',
|
||||||
'resources.table.ip': 'IP',
|
'resources.table.ip': 'IP',
|
||||||
@@ -18,5 +19,8 @@ export default {
|
|||||||
'resources.table.total': '总量',
|
'resources.table.total': '总量',
|
||||||
'resources.table.used': '已用',
|
'resources.table.used': '已用',
|
||||||
'resources.table.wokers': 'workers',
|
'resources.table.wokers': 'workers',
|
||||||
'resources.table.unified': '统一内存'
|
'resources.table.unified': '统一内存',
|
||||||
|
'resources.worker.add.step1': '获取 Token',
|
||||||
|
'resources.worker.add.step2': '注册 Worker',
|
||||||
|
'resources.worker.add.step3': '刷新 worker 列表,可以看到新添加的 worker'
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -194,12 +194,20 @@ const LoginForm = () => {
|
|||||||
label={intl.formatMessage({ id: 'common.form.password' })}
|
label={intl.formatMessage({ id: 'common.form.password' })}
|
||||||
/>
|
/>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item name="autoLogin" valuePropName="checked">
|
<Form.Item noStyle name="autoLogin" valuePropName="checked">
|
||||||
<Checkbox style={{ marginLeft: 10 }}>
|
<Checkbox style={{ marginLeft: 5, marginBottom: 12 }}>
|
||||||
{intl.formatMessage({ id: 'common.login.rember' })}
|
<span style={{ color: 'var(--ant-color-text-secondary)' }}>
|
||||||
|
{' '}
|
||||||
|
{intl.formatMessage({ id: 'common.login.rember' })}
|
||||||
|
</span>
|
||||||
</Checkbox>
|
</Checkbox>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Button htmlType="submit" type="primary" block>
|
<Button
|
||||||
|
htmlType="submit"
|
||||||
|
type="primary"
|
||||||
|
block
|
||||||
|
style={{ height: '54px', fontSize: '16px' }}
|
||||||
|
>
|
||||||
{intl.formatMessage({ id: 'common.button.login' })}
|
{intl.formatMessage({ id: 'common.button.login' })}
|
||||||
</Button>
|
</Button>
|
||||||
</Form>
|
</Form>
|
||||||
|
|||||||
@@ -65,26 +65,6 @@ const PasswordForm: React.FC = () => {
|
|||||||
{intl.formatMessage({ id: 'users.password.modify.description' })}
|
{intl.formatMessage({ id: 'users.password.modify.description' })}
|
||||||
</span>
|
</span>
|
||||||
</h2>
|
</h2>
|
||||||
{/*
|
|
||||||
<Form.Item
|
|
||||||
name="current_password"
|
|
||||||
rules={[
|
|
||||||
{
|
|
||||||
required: true,
|
|
||||||
message: intl.formatMessage(
|
|
||||||
{ id: 'common.form.rule.input' },
|
|
||||||
{
|
|
||||||
name: intl.formatMessage({ id: 'users.form.currentpassword' })
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
]}
|
|
||||||
>
|
|
||||||
<SealInput.Password
|
|
||||||
prefix={<LockOutlined />}
|
|
||||||
label={intl.formatMessage({ id: 'users.form.currentpassword' })}
|
|
||||||
/>
|
|
||||||
</Form.Item> */}
|
|
||||||
<Form.Item
|
<Form.Item
|
||||||
name="new_password"
|
name="new_password"
|
||||||
rules={[
|
rules={[
|
||||||
@@ -136,7 +116,7 @@ const PasswordForm: React.FC = () => {
|
|||||||
htmlType="submit"
|
htmlType="submit"
|
||||||
type="primary"
|
type="primary"
|
||||||
block
|
block
|
||||||
style={{ marginTop: 20 }}
|
style={{ height: '54px', fontSize: '16px', marginTop: 10 }}
|
||||||
>
|
>
|
||||||
{intl.formatMessage({ id: 'common.button.submit' })}
|
{intl.formatMessage({ id: 'common.button.submit' })}
|
||||||
</Button>
|
</Button>
|
||||||
|
|||||||
@@ -0,0 +1,52 @@
|
|||||||
|
import HighlightCode from '@/components/highlight-code';
|
||||||
|
import { useIntl } from '@umijs/max';
|
||||||
|
import { Modal } from 'antd';
|
||||||
|
import React from 'react';
|
||||||
|
import { addWorkerGuide } from '../config';
|
||||||
|
|
||||||
|
type ViewModalProps = {
|
||||||
|
open: boolean;
|
||||||
|
onCancel: () => void;
|
||||||
|
};
|
||||||
|
|
||||||
|
const AddWorker: React.FC<ViewModalProps> = (props) => {
|
||||||
|
const { open, onCancel } = props || {};
|
||||||
|
const intl = useIntl();
|
||||||
|
|
||||||
|
const origin = window.location.origin;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Modal
|
||||||
|
title={intl.formatMessage({ id: 'resources.button.create' })}
|
||||||
|
open={open}
|
||||||
|
centered={true}
|
||||||
|
onCancel={onCancel}
|
||||||
|
destroyOnClose={true}
|
||||||
|
closeIcon={true}
|
||||||
|
maskClosable={false}
|
||||||
|
keyboard={false}
|
||||||
|
width={600}
|
||||||
|
footer={null}
|
||||||
|
>
|
||||||
|
<div>
|
||||||
|
<h3>1. {intl.formatMessage({ id: 'resources.worker.add.step1' })}</h3>
|
||||||
|
<h4>Linux Or MacOS </h4>
|
||||||
|
<HighlightCode code={addWorkerGuide.mac.getToken}></HighlightCode>
|
||||||
|
<h4>Windows </h4>
|
||||||
|
<HighlightCode code={addWorkerGuide.win.getToken}></HighlightCode>
|
||||||
|
<h3>2. {intl.formatMessage({ id: 'resources.worker.add.step2' })}</h3>
|
||||||
|
<h4>Linux Or MacOS </h4>
|
||||||
|
<HighlightCode
|
||||||
|
code={addWorkerGuide.mac.registerWorker(origin)}
|
||||||
|
></HighlightCode>
|
||||||
|
<h4>Windows </h4>
|
||||||
|
<HighlightCode
|
||||||
|
code={addWorkerGuide.win.registerWorker(origin)}
|
||||||
|
></HighlightCode>
|
||||||
|
<h3>3. {intl.formatMessage({ id: 'resources.worker.add.step3' })}</h3>
|
||||||
|
</div>
|
||||||
|
</Modal>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default React.memo(AddWorker);
|
||||||
@@ -8,6 +8,7 @@ import { convertFileSize, handleBatchRequest } from '@/utils';
|
|||||||
import {
|
import {
|
||||||
DeleteOutlined,
|
DeleteOutlined,
|
||||||
InfoCircleOutlined,
|
InfoCircleOutlined,
|
||||||
|
PlusOutlined,
|
||||||
SyncOutlined
|
SyncOutlined
|
||||||
} from '@ant-design/icons';
|
} from '@ant-design/icons';
|
||||||
import { useIntl } from '@umijs/max';
|
import { useIntl } from '@umijs/max';
|
||||||
@@ -17,6 +18,7 @@ import { memo, useEffect, useRef, useState } from 'react';
|
|||||||
import { deleteWorker, queryWorkersList } from '../apis';
|
import { deleteWorker, queryWorkersList } from '../apis';
|
||||||
import { WorkerStatusMapValue, status } from '../config';
|
import { WorkerStatusMapValue, status } from '../config';
|
||||||
import { Filesystem, GPUDeviceItem, ListItem } from '../config/types';
|
import { Filesystem, GPUDeviceItem, ListItem } from '../config/types';
|
||||||
|
import AddWorker from './add-worker';
|
||||||
const { Column } = Table;
|
const { Column } = Table;
|
||||||
|
|
||||||
const Resources: React.FC = () => {
|
const Resources: React.FC = () => {
|
||||||
@@ -30,6 +32,7 @@ const Resources: React.FC = () => {
|
|||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
const [total, setTotal] = useState(0);
|
const [total, setTotal] = useState(0);
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
|
const [open, setOpen] = useState(false);
|
||||||
const [dataSource, setDataSource] = useState<ListItem[]>([]);
|
const [dataSource, setDataSource] = useState<ListItem[]>([]);
|
||||||
const [queryParams, setQueryParams] = useState({
|
const [queryParams, setQueryParams] = useState({
|
||||||
page: 1,
|
page: 1,
|
||||||
@@ -94,6 +97,10 @@ const Resources: React.FC = () => {
|
|||||||
return mountRoot ? formateUtilazation(mountRoot.used, mountRoot.total) : 0;
|
return mountRoot ? formateUtilazation(mountRoot.used, mountRoot.total) : 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleAddWorker = () => {
|
||||||
|
setOpen(true);
|
||||||
|
};
|
||||||
|
|
||||||
const handleDelete = (row: ListItem) => {
|
const handleDelete = (row: ListItem) => {
|
||||||
modalRef.current.show({
|
modalRef.current.show({
|
||||||
content: 'worker',
|
content: 'worker',
|
||||||
@@ -166,14 +173,23 @@ const Resources: React.FC = () => {
|
|||||||
</Space>
|
</Space>
|
||||||
}
|
}
|
||||||
right={
|
right={
|
||||||
<Button
|
<Space size={20}>
|
||||||
icon={<DeleteOutlined />}
|
<Button
|
||||||
danger
|
icon={<PlusOutlined></PlusOutlined>}
|
||||||
onClick={handleDeleteBatch}
|
type="primary"
|
||||||
disabled={!rowSelection.selectedRowKeys.length}
|
onClick={handleAddWorker}
|
||||||
>
|
>
|
||||||
{intl.formatMessage({ id: 'common.button.delete' })}
|
{intl.formatMessage({ id: 'resources.button.create' })}
|
||||||
</Button>
|
</Button>
|
||||||
|
<Button
|
||||||
|
icon={<DeleteOutlined />}
|
||||||
|
danger
|
||||||
|
onClick={handleDeleteBatch}
|
||||||
|
disabled={!rowSelection.selectedRowKeys.length}
|
||||||
|
>
|
||||||
|
{intl.formatMessage({ id: 'common.button.delete' })}
|
||||||
|
</Button>
|
||||||
|
</Space>
|
||||||
}
|
}
|
||||||
></PageTools>
|
></PageTools>
|
||||||
<Table
|
<Table
|
||||||
@@ -371,6 +387,7 @@ const Resources: React.FC = () => {
|
|||||||
/>
|
/>
|
||||||
</Table>
|
</Table>
|
||||||
<DeleteModal ref={modalRef}></DeleteModal>
|
<DeleteModal ref={modalRef}></DeleteModal>
|
||||||
|
<AddWorker open={open} onCancel={() => setOpen(false)}></AddWorker>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -14,3 +14,19 @@ export const status: any = {
|
|||||||
[WorkerStatusMap.ready]: StatusMaps.success,
|
[WorkerStatusMap.ready]: StatusMaps.success,
|
||||||
[WorkerStatusMap.not_ready]: StatusMaps.error
|
[WorkerStatusMap.not_ready]: StatusMaps.error
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const addWorkerGuide = {
|
||||||
|
mac: {
|
||||||
|
getToken: 'cat /var/lib/gpustack/token',
|
||||||
|
registerWorker(server: string) {
|
||||||
|
return `curl -sfL https://get.gpustack.ai | sh -s - --server-url ${server} --token mytoken`;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
win: {
|
||||||
|
getToken:
|
||||||
|
'Get-Content -Path (Join-Path -Path $env:APPDATA -ChildPath "gpustack\\token") -Raw',
|
||||||
|
registerWorker(server: string) {
|
||||||
|
return `Invoke-Expression "& { $((Invoke-WebRequest -Uri "https://get.gpustack.ai" -UseBasicParsing).Content) } -ServerURL ${server} -Token mytoken"`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user