chore: pluggable locale config

This commit is contained in:
jialin
2025-10-13 14:40:26 +08:00
parent caabeb065a
commit b5fa40047a
30 changed files with 731 additions and 575 deletions
+4 -5
View File
@@ -67,7 +67,6 @@ const AddModal: React.FC<AddModalProps> = (props) => {
};
const onFinish = (values: FormData) => {
console.log('Form values:', values);
const versionConfigs = values.version_configs?.reduce(
(acc: Record<string, any>, curr) => {
if (curr.version_no) {
@@ -176,12 +175,12 @@ const AddModal: React.FC<AddModalProps> = (props) => {
onChange={(value) => setActiveKey(value as string)}
options={[
{
label: 'Form',
label: intl.formatMessage({ id: 'backend.mode.form' }),
value: 'form',
icon: <IconFont type="icon-edit-content" />
},
{
label: 'YAML',
label: intl.formatMessage({ id: 'backend.mode.yaml' }),
value: 'yaml',
icon: <IconFont type="icon-code_block" />
}
@@ -207,7 +206,7 @@ const AddModal: React.FC<AddModalProps> = (props) => {
items={[
{
key: 'form',
label: 'Form',
label: intl.formatMessage({ id: 'backend.mode.form' }),
children: (
<BackendForm
onFinish={onFinish}
@@ -219,7 +218,7 @@ const AddModal: React.FC<AddModalProps> = (props) => {
},
{
key: 'yaml',
label: 'YAML',
label: intl.formatMessage({ id: 'backend.mode.yaml' }),
children: (
<ImportYAML
actionStatus={{
+51 -55
View File
@@ -3,7 +3,7 @@ import DropDownActions from '@/components/drop-down-actions';
import IconFont from '@/components/icon-font';
import ThemeTag from '@/components/tags-wrapper/theme-tag';
import Card from '@/components/templates/card';
import { DockerOutlined, InfoCircleOutlined } from '@ant-design/icons';
import { useIntl } from '@umijs/max';
import { Button, Tag } from 'antd';
import _ from 'lodash';
import { useMemo } from 'react';
@@ -87,6 +87,22 @@ const Content = styled.div`
}
`;
const InfoItem = styled.div`
display: grid;
grid-template-columns: max-content 1fr;
align-items: center;
gap: 8px;
color: var(--ant-color-text-tertiary);
.icon {
color: var(--ant-color-text-tertiary);
}
.label {
display: flex;
align-items: center;
gap: 4px;
}
`;
const BackendBox = styled.div`
display: flex;
align-items: center;
@@ -100,12 +116,14 @@ interface BackendCardProps {
}
const BackendCard: React.FC<BackendCardProps> = ({ data, onSelect }) => {
const intl = useIntl();
const handleOnSelect = (item: any) => {
onSelect?.({ action: item.key, data: data });
};
const handleClick = () => {
onSelect?.({ action: 'edit', data: data });
onSelect?.({ action: 'view_versions', data: data });
};
const renderIcon = () => {
@@ -133,28 +151,30 @@ const BackendCard: React.FC<BackendCardProps> = ({ data, onSelect }) => {
e.stopPropagation();
};
const renderDrivers = () => {
if (data.is_build_in) {
const backendList = _.get(
data,
[
'build_in_version_configs',
data.default_version,
'build_in_frameworks'
],
[]
);
const renderFrameworks = () => {
const frameworks = _.keys(data.framework_index_map || {});
return (
<>
<span className="label">
<IconFont className="icon" type="icon-gpu1" />
<span>Supported Frameworks: </span>
return (
<InfoItem>
<span className="label">
<IconFont className="icon" type="icon-gpu1" />
<span>
{intl.formatMessage({ id: 'backend.availableFrameworks' })}:{' '}
</span>
<AutoTooltip ghost maxWidth={'100%'}>
<BackendBox>
{_.take(backendList, 3).map((item: string) => {
return (
</span>
<BackendBox>
{_.take(frameworks, 3).map((item: string) => {
return (
<div key={item}>
<AutoTooltip
ghost
minWidth={20}
showTitle
title={
_.join(data.framework_index_map?.[item], ', ') || false
}
>
<ThemeTag
key={item}
style={{ marginRight: 0 }}
@@ -162,29 +182,12 @@ const BackendCard: React.FC<BackendCardProps> = ({ data, onSelect }) => {
>
{item}
</ThemeTag>
);
})}
</BackendBox>
</AutoTooltip>
</>
);
}
return (
<>
<span className="label">
<DockerOutlined className="icon" />
<span>Default Image: </span>
</span>
<span className="text">
<AutoTooltip ghost maxWidth={'100%'}>
{_.get(data, [
'version_configs',
data.default_version,
'image_name'
])}
</AutoTooltip>
</span>
</>
</AutoTooltip>
</div>
);
})}
</BackendBox>
</InfoItem>
);
};
@@ -194,7 +197,7 @@ const BackendCard: React.FC<BackendCardProps> = ({ data, onSelect }) => {
clickable={true}
hoverable={true}
disabled={false}
height={160}
height={140}
ghost
header={
<Header>
@@ -226,18 +229,11 @@ const BackendCard: React.FC<BackendCardProps> = ({ data, onSelect }) => {
bordered={false}
style={{ borderRadius: 'var(--ant-border-radius)' }}
>
Built-in
{intl.formatMessage({ id: 'backend.builtin' })}
</Tag>
)}
</CardName>
<div className="info">
<span className="label">
<InfoCircleOutlined className="icon" />
<span>Default Version: </span>
</span>
<span className="text">{data.default_version}</span>
{renderDrivers()}
</div>
{renderFrameworks()}
</Content>
</Card>
);
@@ -0,0 +1,89 @@
import ScrollerModal from '@/components/scroller-modal';
import { useIntl } from '@umijs/max';
import { useEffect, useState } from 'react';
import { VersionListItem } from '../config/types';
import VersionInfo from '../forms/version-info';
interface VersionInfoModalProps {
open?: boolean;
currentData?: any;
onClose?: () => void;
}
const VersionInfoModal: React.FC<VersionInfoModalProps> = ({
open,
currentData,
onClose
}) => {
const intl = useIntl();
const [versionConfigs, setVersionConfigs] = useState<VersionListItem[]>([]);
useEffect(() => {
if (open && currentData) {
// add is_built_in field to build_in_version_configs
const builtInVersions = currentData.build_in_version_configs || {};
for (const key in builtInVersions) {
if (builtInVersions?.hasOwnProperty(key)) {
builtInVersions[key].is_built_in = true;
}
}
const versions = {
...builtInVersions,
...currentData.version_configs
};
const versionList: VersionListItem[] = Object.entries(versions).map(
([key, value]: [string, any]) => ({
version_no: key,
image_name: value.image_name,
run_command: value.run_command,
is_default: key === currentData.default_version,
availableFrameworks: [
...(value.build_in_frameworks || []),
...(value.custom_framework ? [value.custom_framework] : [])
],
is_built_in: value.is_built_in || false
})
);
setVersionConfigs(versionList);
}
}, [open, currentData]);
return (
<ScrollerModal
open={open}
title={intl.formatMessage({ id: 'backend.versions' })}
width={600}
centered
destroyOnHidden
closable={true}
maskClosable={false}
onOk={onClose}
onCancel={onClose}
styles={{
content: {
padding: '0 0 16px 0'
},
header: {
padding: 'var(--ant-modal-content-padding)',
paddingBottom: '0'
},
body: {
padding: '16px 24px 32px'
},
footer: {
padding: '16px 24px',
margin: '0'
}
}}
footer={null}
>
<VersionInfo versionConfigs={versionConfigs} />
</ScrollerModal>
);
};
export default VersionInfoModal;
@@ -1,76 +0,0 @@
import ScrollerModal from '@/components/scroller-modal';
import { Form } from 'antd';
import { useEffect } from 'react';
import BuiltinVersions from '../forms/built-in-versions';
interface ViewBuiltinVersionsModalProps {
open?: boolean;
currentData?: any;
onClose?: () => void;
}
const ViewBuiltinVersionsModal: React.FC<ViewBuiltinVersionsModalProps> = ({
open,
currentData,
onClose
}) => {
const [form] = Form.useForm();
useEffect(() => {
if (open && currentData) {
const builtInVersions = Object.keys(
currentData.build_in_version_configs || {}
).map((key) => ({
version_no: key,
image_name: currentData.build_in_version_configs[key].image_name,
run_command: currentData.build_in_version_configs[key].run_command,
is_default: key === currentData.default_version,
build_in_frameworks:
currentData.build_in_version_configs[key].build_in_frameworks || [],
is_built_in: true
}));
form.setFieldsValue({
build_in_version_configs: builtInVersions
});
}
}, [open, currentData, form]);
return (
<ScrollerModal
open={open}
style={{
top: '20%'
}}
title="View Built-in Versions"
width={550}
destroyOnHidden
closable={true}
maskClosable={false}
onOk={onClose}
onCancel={onClose}
styles={{
content: {
padding: '0 0 16px 0'
},
header: {
padding: 'var(--ant-modal-content-padding)',
paddingBottom: '0'
},
body: {
padding: '16px 24px 32px'
},
footer: {
padding: '16px 24px',
margin: '0'
}
}}
footer={null}
>
<Form form={form}>
<BuiltinVersions />
</Form>
</ScrollerModal>
);
};
export default ViewBuiltinVersionsModal;
@@ -74,29 +74,6 @@ const ViewerEditor: React.FC<ViewerProps> = forwardRef((props, ref) => {
editorRef.current = editor;
monacoRef.current = monaco;
const uri = monaco.Uri.parse(path);
// monaco.editor.onDidChangeMarkers((uris: string[]) => {
// if (!uris.some((u) => u.toString() === uri.toString())) return;
// const model = monaco.editor.getModel(uri);
// if (!model) return;
// console.log('Markers changed:', uris);
// const markers = monaco.editor.getModelMarkers({ resource: uri });
// const adjusted = markers.map((m: any) => {
// if (m._adjusted) return m;
// return {
// ...m,
// _adjusted: true,
// severity: monaco.MarkerSeverity.ErrorText
// };
// });
// monaco.editor.setModelMarkers(
// monaco.editor.getModel(uri),
// 'yaml',
// adjusted
// );
// });
};
const formatCode = () => {