feat: community backends marketplace

This commit is contained in:
jialin
2026-01-30 20:48:55 +08:00
committed by Lawrence Li
parent b6bd9cd7dd
commit 0d5cd28d38
8 changed files with 41 additions and 27 deletions
+1 -1
View File
@@ -44,5 +44,5 @@ export default {
'backend.filter.source': 'Filter by source', 'backend.filter.source': 'Filter by source',
'backend.add.custom': 'Custom', 'backend.add.custom': 'Custom',
'backend.add.community': 'Community Repository', 'backend.add.community': 'Community Repository',
'backend.community.title': 'Community Backends' 'backend.community.title': 'Community Backends Marketplace'
}; };
+1 -1
View File
@@ -44,5 +44,5 @@ export default {
'backend.filter.source': 'Filter by source', 'backend.filter.source': 'Filter by source',
'backend.add.custom': 'Custom', 'backend.add.custom': 'Custom',
'backend.add.community': 'Community Repository', 'backend.add.community': 'Community Repository',
'backend.community.title': 'Community Backends' 'backend.community.title': 'Community Backends Marketplace'
}; };
+2 -2
View File
@@ -44,7 +44,7 @@ export default {
'backend.filter.source': 'Filter by source', 'backend.filter.source': 'Filter by source',
'backend.add.custom': 'Custom', 'backend.add.custom': 'Custom',
'backend.add.community': 'Community Repository', 'backend.add.community': 'Community Repository',
'backend.community.title': 'Community Backends' 'backend.community.title': 'Community Backends Marketplace'
}; };
// ========== To-Do: Translate Keys (Remove After Translation) ========== // ========== To-Do: Translate Keys (Remove After Translation) ==========
@@ -53,5 +53,5 @@ export default {
// 3. 'backend.filter.source': 'Filter by source', // 3. 'backend.filter.source': 'Filter by source',
// 4. 'backend.add.custom': 'Custom', // 4. 'backend.add.custom': 'Custom',
// 5. 'backend.add.community': 'Community Repository', // 5. 'backend.add.community': 'Community Repository',
// 6. 'backend.community.title': 'Community Backends' // 6. 'backend.community.title': 'Community Backends Marketplace'
// ========== End of To-Do List ========== // ========== End of To-Do List ==========
+1 -1
View File
@@ -41,5 +41,5 @@ export default {
'backend.filter.source': '按来源过滤', 'backend.filter.source': '按来源过滤',
'backend.add.custom': '自定义', 'backend.add.custom': '自定义',
'backend.add.community': '社区仓库', 'backend.add.community': '社区仓库',
'backend.community.title': '社区后端' 'backend.community.title': '社区后端市场'
}; };
@@ -83,7 +83,7 @@ const AddCommunityModal: React.FC<{
> >
<BackendDetail <BackendDetail
onEnable={handleOnEnable} onEnable={handleOnEnable}
currentData={currentData} data={currentData}
></BackendDetail> ></BackendDetail>
</ColumnWrapper> </ColumnWrapper>
</Container> </Container>
@@ -3,7 +3,7 @@ import { BulbOutlined } from '@ant-design/icons';
import { useIntl } from '@umijs/max'; import { useIntl } from '@umijs/max';
import { Button, Tag, Typography } from 'antd'; import { Button, Tag, Typography } from 'antd';
import _ from 'lodash'; import _ from 'lodash';
import React from 'react'; import React, { useEffect } from 'react';
import styled from 'styled-components'; import styled from 'styled-components';
import { generateIcon } from '../components/backend-card'; import { generateIcon } from '../components/backend-card';
@@ -62,9 +62,22 @@ const UL = styled.ul`
const BackendDetail: React.FC<{ const BackendDetail: React.FC<{
onEnable: (checked: boolean, data: any) => void; onEnable: (checked: boolean, data: any) => void;
onDisable?: () => void; onDisable?: () => void;
currentData?: any; data?: any;
}> = ({ onEnable, onDisable, currentData }) => { }> = ({ onEnable, onDisable, data }) => {
const intl = useIntl(); const intl = useIntl();
const [currentData, setCurrentData] = React.useState<any>(data);
useEffect(() => {
setCurrentData(data);
}, [data]);
const handleOnEnable = async (checked: boolean) => {
await onEnable(true, currentData);
setCurrentData({
...currentData,
enabled: checked
});
};
const renderSupportedFrameworks = () => { const renderSupportedFrameworks = () => {
const frameworks = currentData?.framework_index_map || {}; const frameworks = currentData?.framework_index_map || {};
@@ -109,7 +122,7 @@ const BackendDetail: React.FC<{
<Button <Button
type="primary" type="primary"
size="middle" size="middle"
onClick={() => onEnable(true, currentData)} onClick={() => handleOnEnable(true)}
> >
{intl.formatMessage({ id: 'common.button.enable' })} {intl.formatMessage({ id: 'common.button.enable' })}
</Button> </Button>
@@ -3,7 +3,7 @@ import ThemeTag from '@/components/tags-wrapper/theme-tag';
import useTableFetch from '@/hooks/use-table-fetch'; import useTableFetch from '@/hooks/use-table-fetch';
import { SearchOutlined } from '@ant-design/icons'; import { SearchOutlined } from '@ant-design/icons';
import { useIntl } from '@umijs/max'; import { useIntl } from '@umijs/max';
import { Input, Switch, Tooltip } from 'antd'; import { Input, Tooltip } from 'antd';
import _ from 'lodash'; import _ from 'lodash';
import React, { useEffect } from 'react'; import React, { useEffect } from 'react';
import styled from 'styled-components'; import styled from 'styled-components';
@@ -68,17 +68,10 @@ const CommunityBackends: React.FC<{
} }
> >
<> <>
{data.enabled ? ( {data.enabled && (
<ThemeTag style={{ margin: 0 }} color="geekblue" variant="filled"> <ThemeTag style={{ margin: 0 }} color="geekblue" variant="filled">
{intl.formatMessage({ id: 'common.status.enabled' })} {intl.formatMessage({ id: 'common.status.enabled' })}
</ThemeTag> </ThemeTag>
) : (
<span onClick={(e) => e.stopPropagation()}>
<Switch
onChange={(checked) => handleOnEnable(checked, data)}
size="small"
></Switch>
</span>
)} )}
</> </>
</Tooltip> </Tooltip>
+16 -8
View File
@@ -49,13 +49,14 @@ const SourceWrapper = styled.div`
} }
`; `;
const TagInner = styled(Tag)` // add height props
const TagInner = styled(Tag)<{ height?: number }>`
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
font-size: 18px; font-size: 18px;
height: 28px; height: ${({ height }) => (height ? `${height}px` : '28px')};
width: 28px; width: ${({ height }) => (height ? `${height}px` : '28px')};
border-radius: 6px; border-radius: 6px;
font-weight: 400; font-weight: 400;
`; `;
@@ -146,18 +147,21 @@ interface BackendCardProps {
active?: boolean; active?: boolean;
} }
export const generateIcon = (data: ListItem, height = 20) => { export const generateIcon = (data: ListItem, height?: number) => {
const innHeight = height || 20;
if (builtInBackendLogos[data.backend_name]) { if (builtInBackendLogos[data.backend_name]) {
return <img src={builtInBackendLogos[data.backend_name]} height={height} />; return (
<img src={builtInBackendLogos[data.backend_name]} height={innHeight} />
);
} }
if (data.icon) { if (data.icon) {
return <img src={data.icon} height={height} />; return <img src={data.icon} height={innHeight} />;
} }
const color = customColors[data.id % customColors.length]; const color = customColors[data.id % customColors.length];
const icon = customIcons[data.id % customIcons.length]; const icon = customIcons[data.id % customIcons.length];
return ( return (
<TagInner color={color} variant="filled"> <TagInner color={color} variant="filled" height={height || 28}>
{icon} {icon}
</TagInner> </TagInner>
); );
@@ -387,7 +391,11 @@ const BackendCard: React.FC<BackendCardProps> = ({
> >
<Content> <Content>
<CardName> <CardName>
<span>{data.backend_name}</span> <span>
{data.backend_source === BackendSourceValueMap.CUSTOM
? data.backend_name.replace(/-custom$/g, '')
: data.backend_name}
</span>
{renderSource()} {renderSource()}
</CardName> </CardName>
{/* <SourceWrapper> {/* <SourceWrapper>