feat: manually mirror opencoze's code from bytedance
Change-Id: I09a73aadda978ad9511264a756b2ce51f5761adf
This commit is contained in:
@@ -0,0 +1,18 @@
|
||||
.card-button {
|
||||
cursor: pointer;
|
||||
|
||||
height: 32px;
|
||||
padding: 6px 16px;
|
||||
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
line-height: 20px;
|
||||
text-align: center;
|
||||
|
||||
border: 1px solid;
|
||||
border-radius: 8px;
|
||||
|
||||
@apply coz-stroke-primary;
|
||||
@apply coz-bg-primary;
|
||||
@apply coz-fg-primary;
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { type FC, type PropsWithChildren } from 'react';
|
||||
|
||||
import cls from 'classnames';
|
||||
|
||||
import styles from './index.module.less';
|
||||
|
||||
export const CardButton: FC<
|
||||
PropsWithChildren<{
|
||||
className?: string;
|
||||
onClick?: () => void;
|
||||
}>
|
||||
> = ({ className, onClick, children }) => (
|
||||
<button
|
||||
className={cls(styles['card-button'], className)}
|
||||
color="primary"
|
||||
onClick={onClick}
|
||||
>
|
||||
{children}
|
||||
</button>
|
||||
);
|
||||
@@ -0,0 +1,42 @@
|
||||
.container {
|
||||
cursor: pointer;
|
||||
|
||||
position: relative;
|
||||
|
||||
margin-bottom: 20px;
|
||||
padding: 16px;
|
||||
|
||||
border: 1px solid;
|
||||
border-radius: 8px;
|
||||
|
||||
@apply coz-stroke-primary;
|
||||
|
||||
|
||||
&:not(.skeleton):hover {
|
||||
@apply coz-bg-max;
|
||||
@apply coz-stroke-primary;
|
||||
|
||||
box-shadow: 0 6px 8px 0 rgba(28, 31, 35, 6%);
|
||||
|
||||
&.shadow-primary {
|
||||
box-shadow: 0 6px 8px 0 rgba(0, 8, 16, 12%);
|
||||
}
|
||||
}
|
||||
|
||||
&.skeleton {
|
||||
cursor: default;
|
||||
border-color: transparent;
|
||||
}
|
||||
|
||||
.check {
|
||||
position: absolute;
|
||||
z-index: 1;
|
||||
top: 16px;
|
||||
right: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
.width100 {
|
||||
overflow: hidden;
|
||||
width: 100%;
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import classNames from 'classnames';
|
||||
|
||||
import s from './index.module.less';
|
||||
|
||||
const Container = (props: {
|
||||
className?: string;
|
||||
children?: React.ReactNode;
|
||||
shadowMode?: 'default' | 'primary';
|
||||
onClick?: () => void;
|
||||
}) => {
|
||||
const { className, children, onClick, shadowMode } = props;
|
||||
|
||||
return (
|
||||
<div
|
||||
className={classNames(
|
||||
'coz-bg-max',
|
||||
s.container,
|
||||
s.width100,
|
||||
className,
|
||||
s[`shadow-${shadowMode}`],
|
||||
)}
|
||||
onClick={onClick}
|
||||
>
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const SkeletonContainer = (props: {
|
||||
children?: React.ReactNode;
|
||||
className?: string;
|
||||
}) => (
|
||||
<div
|
||||
className={classNames(
|
||||
'coz-mg-primary',
|
||||
s.container,
|
||||
s.width100,
|
||||
s.skeleton,
|
||||
props.className,
|
||||
)}
|
||||
>
|
||||
{props?.children}
|
||||
</div>
|
||||
);
|
||||
|
||||
export const CardContainer = Container;
|
||||
export const CardSkeletonContainer = SkeletonContainer;
|
||||
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { type FC } from 'react';
|
||||
|
||||
import cls from 'classnames';
|
||||
import { AvatarName } from '@coze-studio/components';
|
||||
import { type explore } from '@coze-studio/api-schema';
|
||||
import { type UserInfo as ProductUserInfo } from '@coze-arch/bot-api/product_api';
|
||||
import { Typography } from '@coze-arch/coze-design';
|
||||
|
||||
type UserInfo = explore.product_common.UserInfo | ProductUserInfo;
|
||||
interface TemplateCardBodyProps {
|
||||
title?: string;
|
||||
description?: string;
|
||||
userInfo?: UserInfo;
|
||||
descClassName?: string;
|
||||
renderCardTag?: () => React.ReactNode;
|
||||
renderDescBottomSlot?: () => React.ReactNode;
|
||||
}
|
||||
export const CardInfo: FC<TemplateCardBodyProps> = ({
|
||||
title,
|
||||
description,
|
||||
userInfo,
|
||||
renderCardTag,
|
||||
descClassName,
|
||||
renderDescBottomSlot,
|
||||
}) => (
|
||||
<div className={cls('mt-[8px] px-[4px] grow', 'flex flex-col')}>
|
||||
<div className="flex items-center gap-[8px] overflow-hidden">
|
||||
<Typography.Text
|
||||
className="!font-medium text-[16px] leading-[22px] coz-fg-primary !max-w-[180px]"
|
||||
ellipsis={{ showTooltip: true, rows: 1 }}
|
||||
>
|
||||
{title}
|
||||
</Typography.Text>
|
||||
{renderCardTag?.()}
|
||||
</div>
|
||||
|
||||
<AvatarName
|
||||
className="mt-[4px]"
|
||||
avatar={userInfo?.avatar_url}
|
||||
name={userInfo?.name}
|
||||
username={userInfo?.user_name}
|
||||
label={{
|
||||
name: userInfo?.user_label?.label_name,
|
||||
icon: userInfo?.user_label?.icon_url,
|
||||
href: userInfo?.user_label?.jump_link,
|
||||
}}
|
||||
/>
|
||||
|
||||
<div
|
||||
className={cls(
|
||||
'mt-[8px] flex flex-col justify-between grow',
|
||||
descClassName,
|
||||
)}
|
||||
>
|
||||
<Typography.Text
|
||||
className="min-h-[40px] leading-[20px] coz-fg-secondary"
|
||||
ellipsis={{ showTooltip: true, rows: 2 }}
|
||||
>
|
||||
{description}
|
||||
</Typography.Text>
|
||||
{renderDescBottomSlot?.()}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { type ReactNode } from 'react';
|
||||
|
||||
import { I18n, type I18nKeysNoOptionsType } from '@coze-arch/i18n';
|
||||
import {
|
||||
IconCozBot,
|
||||
IconCozWorkflow,
|
||||
IconCozWorkspace,
|
||||
} from '@coze-arch/coze-design/icons';
|
||||
import { Tag, type TagProps } from '@coze-arch/coze-design';
|
||||
import { ProductEntityType } from '@coze-arch/bot-api/product_api';
|
||||
|
||||
interface IProps {
|
||||
type: ProductEntityType;
|
||||
}
|
||||
|
||||
interface TagConfig {
|
||||
icon: ReactNode;
|
||||
i18nKey: I18nKeysNoOptionsType;
|
||||
}
|
||||
|
||||
const TYPE_ICON_MAP: Partial<Record<ProductEntityType, TagConfig>> = {
|
||||
[ProductEntityType.BotTemplate]: {
|
||||
icon: <IconCozBot />,
|
||||
i18nKey: 'template_agent',
|
||||
},
|
||||
[ProductEntityType.WorkflowTemplateV2]: {
|
||||
icon: <IconCozWorkflow />,
|
||||
i18nKey: 'template_workflow',
|
||||
},
|
||||
[ProductEntityType.ImageflowTemplateV2]: {
|
||||
icon: <IconCozWorkflow />,
|
||||
i18nKey: 'template_workflow',
|
||||
},
|
||||
[ProductEntityType.ProjectTemplate]: {
|
||||
icon: <IconCozWorkspace />,
|
||||
i18nKey: 'project_store_search',
|
||||
},
|
||||
};
|
||||
|
||||
const TYPE_COLOR_MAP: Partial<Record<ProductEntityType, TagProps['color']>> = {
|
||||
[ProductEntityType.BotTemplate]: 'primary',
|
||||
[ProductEntityType.WorkflowTemplateV2]: 'primary',
|
||||
[ProductEntityType.ImageflowTemplateV2]: 'primary',
|
||||
[ProductEntityType.ProjectTemplate]: 'brand',
|
||||
};
|
||||
|
||||
export const CardTag = ({ type }: IProps) => {
|
||||
const config = TYPE_ICON_MAP[type];
|
||||
if (!config) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<Tag
|
||||
color={TYPE_COLOR_MAP[type] ?? 'primary'}
|
||||
className="h-[20px] !px-[4px] !py-[2px] coz-fg-primary font-medium shrink-0"
|
||||
>
|
||||
{config.icon}
|
||||
<span className="ml-[2px]">{I18n.t(config.i18nKey)}</span>
|
||||
</Tag>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,79 @@
|
||||
.plugin {
|
||||
margin-bottom: 0;
|
||||
|
||||
.plugin-wrapper {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.btn-container {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
|
||||
display: none;
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
|
||||
width: 100%;
|
||||
|
||||
&.one-column-grid {
|
||||
grid-template-columns: repeat(1, minmax(0, 1fr));
|
||||
}
|
||||
}
|
||||
|
||||
&:hover {
|
||||
.btn-container {
|
||||
display: grid;
|
||||
}
|
||||
|
||||
.description {
|
||||
visibility: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
.card-avatar {
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
border-radius: 6px;
|
||||
|
||||
/*
|
||||
* 如此写边框和设置背景色的原因
|
||||
* 1、边框是内边框,处于图片的边缘上,因此需要用after来写
|
||||
* 2、背景色用before实体来写,是由于 border和背景色都是透明色,重叠会导致颜色加重,出现边框
|
||||
*/
|
||||
&::after {
|
||||
content: '';
|
||||
|
||||
position: absolute;
|
||||
z-index: 2;
|
||||
|
||||
width: calc(100% - 2px);
|
||||
height: calc(100% - 2px);
|
||||
|
||||
border-style: solid;
|
||||
border-width: 1px;
|
||||
border-radius: 6px;
|
||||
|
||||
@apply coz-stroke-primary;
|
||||
}
|
||||
|
||||
&::before {
|
||||
content: '';
|
||||
|
||||
position: absolute;
|
||||
z-index: 1;
|
||||
top: 1px;
|
||||
left: 1px;
|
||||
|
||||
width: calc(100% - 2px);
|
||||
height: calc(100% - 2px);
|
||||
|
||||
@apply bg-stroke-5;
|
||||
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
& > img {
|
||||
z-index: 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
137
frontend/packages/community/component/src/card/plugin/index.tsx
Normal file
137
frontend/packages/community/component/src/card/plugin/index.tsx
Normal file
@@ -0,0 +1,137 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { type FC } from 'react';
|
||||
|
||||
import cls from 'classnames';
|
||||
import { type explore } from '@coze-studio/api-schema';
|
||||
import { I18n } from '@coze-arch/i18n';
|
||||
import { Avatar, Space, Tag, Toast, Tooltip } from '@coze-arch/coze-design';
|
||||
|
||||
import { cozeBaseUrl } from '@/const/url';
|
||||
|
||||
import { PluginAuthMode, type AuthMode } from '../type';
|
||||
import { CardInfo } from '../components/info';
|
||||
import { CardContainer, CardSkeletonContainer } from '../components/container';
|
||||
import { CardButton } from '../components/button';
|
||||
|
||||
import styles from './index.module.less';
|
||||
|
||||
interface ProductInfo extends explore.ProductInfo {
|
||||
plugin_extra: explore.ProductInfo['plugin_extra'] & AuthMode;
|
||||
}
|
||||
|
||||
export type PluginCardProps = ProductInfo & {
|
||||
isInstalled?: boolean;
|
||||
isShowInstallButton?: boolean;
|
||||
};
|
||||
|
||||
export const PluginCard: FC<PluginCardProps> = props => (
|
||||
<CardContainer
|
||||
className={styles.plugin}
|
||||
shadowMode="default"
|
||||
onClick={() => {
|
||||
console.log('CardContainer...');
|
||||
}}
|
||||
>
|
||||
<div className={styles['plugin-wrapper']}>
|
||||
<PluginCardBody {...props} />
|
||||
|
||||
<Space
|
||||
className={cls(styles['btn-container'], {
|
||||
[styles['one-column-grid']]:
|
||||
props.isInstalled || !props.isShowInstallButton,
|
||||
})}
|
||||
>
|
||||
{!props.isInstalled && props.isShowInstallButton ? (
|
||||
<CardButton
|
||||
onClick={() => {
|
||||
Toast.success(I18n.t('plugin_install_success'));
|
||||
}}
|
||||
>
|
||||
{I18n.t('plugin_store_install')}
|
||||
</CardButton>
|
||||
) : null}
|
||||
<CardButton
|
||||
onClick={() => {
|
||||
window.open(
|
||||
`${cozeBaseUrl}/store/plugin/${props.meta_info?.id}?from=plugin_card`,
|
||||
);
|
||||
}}
|
||||
>
|
||||
{I18n.t('plugin_usage_limits_modal_view_details')}
|
||||
</CardButton>
|
||||
</Space>
|
||||
</div>
|
||||
</CardContainer>
|
||||
);
|
||||
|
||||
export const PluginCardSkeleton = () => (
|
||||
<CardSkeletonContainer className={cls('h-[186px]', styles.plugin)} />
|
||||
);
|
||||
|
||||
const PluginCardBody: FC<PluginCardProps> = props => {
|
||||
const renderCardTag = () => {
|
||||
if (
|
||||
props.plugin_extra.auth_mode === PluginAuthMode.Required ||
|
||||
props.plugin_extra.auth_mode === PluginAuthMode.Supported
|
||||
) {
|
||||
return (
|
||||
<Tag
|
||||
color={'yellow'}
|
||||
className="h-[20px] !px-[4px] !py-[2px] coz-fg-primary font-medium shrink-0"
|
||||
>
|
||||
<span className="ml-[2px]">
|
||||
{I18n.t('plugin_store_unauthorized')}
|
||||
</span>
|
||||
</Tag>
|
||||
);
|
||||
} else if (props.plugin_extra.auth_mode === PluginAuthMode.Configured) {
|
||||
return (
|
||||
<Tooltip content={I18n.t('plugin_store_contact_deployer')}>
|
||||
<Tag
|
||||
color={'brand'}
|
||||
className="h-[20px] !px-[4px] !py-[2px] coz-fg-primary font-medium shrink-0"
|
||||
>
|
||||
<span className="ml-[2px]">
|
||||
{I18n.t('plugin_store_authorized')}
|
||||
</span>
|
||||
</Tag>
|
||||
</Tooltip>
|
||||
);
|
||||
}
|
||||
return null;
|
||||
};
|
||||
return (
|
||||
<div>
|
||||
<Avatar
|
||||
className={styles['card-avatar']}
|
||||
src={props.meta_info?.icon_url}
|
||||
shape="square"
|
||||
/>
|
||||
<CardInfo
|
||||
{...{
|
||||
title: props.meta_info?.name,
|
||||
description: props.meta_info?.description,
|
||||
userInfo: props.meta_info?.user_info,
|
||||
authMode: props.plugin_extra.auth_mode,
|
||||
renderCardTag,
|
||||
descClassName: styles.description,
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,28 @@
|
||||
.template {
|
||||
margin-bottom: 0;
|
||||
|
||||
.template-wrapper {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.btn-container {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
|
||||
display: none;
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
.btn-container {
|
||||
display: grid;
|
||||
}
|
||||
|
||||
.description {
|
||||
visibility: hidden;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,201 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { type FC, useState } from 'react';
|
||||
|
||||
import cls from 'classnames';
|
||||
import { explore } from '@coze-studio/api-schema';
|
||||
import { useSpaceList } from '@coze-foundation/space-store';
|
||||
import { I18n } from '@coze-arch/i18n';
|
||||
import { Image, Input, Modal, Space, Toast } from '@coze-arch/coze-design';
|
||||
import { ProductEntityType } from '@coze-arch/bot-api/product_api';
|
||||
|
||||
import { cozeBaseUrl } from '@/const/url';
|
||||
|
||||
import { type CardInfoProps } from '../type';
|
||||
import { CardTag } from '../components/tag';
|
||||
import { CardInfo } from '../components/info';
|
||||
import { CardContainer, CardSkeletonContainer } from '../components/container';
|
||||
import { CardButton } from '../components/button';
|
||||
|
||||
type ProductInfo = explore.ProductInfo;
|
||||
import styles from './index.module.less';
|
||||
|
||||
export type TemplateCardProps = ProductInfo;
|
||||
|
||||
const PATH_MAP: Partial<
|
||||
Record<explore.product_common.ProductEntityType, string>
|
||||
> = {
|
||||
[ProductEntityType.BotTemplate]: 'agent',
|
||||
[ProductEntityType.WorkflowTemplateV2]: 'workflow',
|
||||
[ProductEntityType.ImageflowTemplateV2]: 'workflow',
|
||||
[ProductEntityType.ProjectTemplate]: 'project',
|
||||
};
|
||||
|
||||
export const TemplateCard: FC<TemplateCardProps> = props => {
|
||||
const [visible, setVisible] = useState(false);
|
||||
return (
|
||||
<CardContainer
|
||||
className={styles.template}
|
||||
shadowMode="default"
|
||||
onClick={() => {
|
||||
console.log('Template Click Card');
|
||||
}}
|
||||
>
|
||||
<div className={styles['template-wrapper']}>
|
||||
<TempCardBody
|
||||
{...{
|
||||
title: props.meta_info?.name,
|
||||
description: props.meta_info?.description,
|
||||
userInfo: props.meta_info?.user_info,
|
||||
entityType: props.meta_info.entity_type,
|
||||
imgSrc: props.meta_info.covers?.[0].url,
|
||||
}}
|
||||
/>
|
||||
<Space className={styles['btn-container']}>
|
||||
<CardButton
|
||||
onClick={() => {
|
||||
setVisible(true);
|
||||
}}
|
||||
>
|
||||
{I18n.t('copy')}
|
||||
</CardButton>
|
||||
<CardButton
|
||||
onClick={() => {
|
||||
const pathPrefix = PATH_MAP[props.meta_info.entity_type] || '';
|
||||
const pathSuffix = [
|
||||
ProductEntityType.WorkflowTemplateV2,
|
||||
ProductEntityType.ImageflowTemplateV2,
|
||||
].includes(props.meta_info.entity_type)
|
||||
? `?entity_type=${props.meta_info.entity_type}`
|
||||
: '';
|
||||
window.open(
|
||||
`${cozeBaseUrl}/template/${pathPrefix}/${props.meta_info.id}${pathSuffix}`,
|
||||
);
|
||||
}}
|
||||
>
|
||||
{I18n.t('plugin_usage_limits_modal_view_details')}
|
||||
</CardButton>
|
||||
</Space>
|
||||
</div>
|
||||
{visible ? (
|
||||
<DuplicateModal
|
||||
productId={props.meta_info.id}
|
||||
entityType={props.meta_info.entity_type}
|
||||
defaultTitle={`${props.meta_info?.name}(${I18n.t('duplicate_rename_copy')})`}
|
||||
hide={() => setVisible(false)}
|
||||
/>
|
||||
) : null}
|
||||
</CardContainer>
|
||||
);
|
||||
};
|
||||
|
||||
const DuplicateModal: FC<{
|
||||
defaultTitle: string;
|
||||
productId: string;
|
||||
entityType: explore.product_common.ProductEntityType;
|
||||
hide: () => void;
|
||||
}> = ({ defaultTitle, hide, productId, entityType }) => {
|
||||
const [title, setTitle] = useState(defaultTitle);
|
||||
const { spaces } = useSpaceList();
|
||||
const spaceId = spaces?.[0]?.id;
|
||||
console.log('title', title, spaces);
|
||||
return (
|
||||
<Modal
|
||||
type="modal"
|
||||
title={I18n.t('creat_project_use_template')}
|
||||
visible={true}
|
||||
onOk={async () => {
|
||||
try {
|
||||
await explore.PublicDuplicateProduct({
|
||||
product_id: productId,
|
||||
entity_type: entityType,
|
||||
space_id: spaceId,
|
||||
name: title,
|
||||
});
|
||||
Toast.success(I18n.t('copy_success'));
|
||||
hide();
|
||||
} catch (err) {
|
||||
console.error('PublicDuplicateProduct', err);
|
||||
Toast.error(I18n.t('copy_failed'));
|
||||
}
|
||||
}}
|
||||
onCancel={hide}
|
||||
cancelText={I18n.t('Cancel')}
|
||||
okText={I18n.t('Confirm')}
|
||||
>
|
||||
<Space vertical spacing={4} className="w-full">
|
||||
<Space className="w-full">
|
||||
<span className="coz-fg-primary font-medium leading-[20px]">
|
||||
{I18n.t('creat_project_project_name')}
|
||||
</span>
|
||||
<span className="coz-fg-hglt-red">*</span>
|
||||
</Space>
|
||||
<Input
|
||||
className="w-full"
|
||||
placeholder=""
|
||||
defaultValue={defaultTitle}
|
||||
onChange={value => {
|
||||
setTitle(value);
|
||||
}}
|
||||
/>
|
||||
</Space>
|
||||
</Modal>
|
||||
);
|
||||
};
|
||||
|
||||
export const TemplateCardSkeleton = () => (
|
||||
<CardSkeletonContainer className={cls('h-[278px]', styles.template)} />
|
||||
);
|
||||
|
||||
export const TempCardBody: FC<
|
||||
CardInfoProps & {
|
||||
entityType?: explore.product_common.ProductEntityType | ProductEntityType;
|
||||
renderImageBottomSlot?: () => React.ReactNode;
|
||||
renderDescBottomSlot?: () => React.ReactNode;
|
||||
}
|
||||
> = ({
|
||||
title,
|
||||
imgSrc,
|
||||
description,
|
||||
entityType,
|
||||
userInfo,
|
||||
renderImageBottomSlot,
|
||||
renderDescBottomSlot,
|
||||
}) => (
|
||||
<div>
|
||||
<div className="relative w-full h-[140px] rounded-[8px] overflow-hidden">
|
||||
<Image
|
||||
preview={false}
|
||||
src={imgSrc}
|
||||
className="w-full h-full"
|
||||
imgCls="w-full h-full object-cover object-center"
|
||||
/>
|
||||
{renderImageBottomSlot?.()}
|
||||
</div>
|
||||
<CardInfo
|
||||
{...{
|
||||
title,
|
||||
description,
|
||||
userInfo,
|
||||
renderCardTag: () =>
|
||||
entityType ? <CardTag type={entityType} /> : null,
|
||||
descClassName: styles.description,
|
||||
renderDescBottomSlot,
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
43
frontend/packages/community/component/src/card/type.ts
Normal file
43
frontend/packages/community/component/src/card/type.ts
Normal file
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { type explore } from '@coze-studio/api-schema';
|
||||
import { type UserInfo as ProductUserInfo } from '@coze-arch/bot-api/product_api';
|
||||
type UserInfo = explore.product_common.UserInfo;
|
||||
|
||||
export interface CardInfoProps {
|
||||
title?: string;
|
||||
imgSrc?: string;
|
||||
description?: string;
|
||||
userInfo?: UserInfo | ProductUserInfo;
|
||||
}
|
||||
|
||||
/** for open coze */
|
||||
export enum PluginAuthMode {
|
||||
/** No authorization required */
|
||||
NoAuth = 0,
|
||||
/** Authorization is required, but not configured */
|
||||
Required = 1,
|
||||
/** Authorization is required and has been configured */
|
||||
Configured = 2,
|
||||
/** Authorization is required, but the configuration can be empty */
|
||||
Supported = 3,
|
||||
}
|
||||
|
||||
export interface AuthMode {
|
||||
/** for open coze */
|
||||
auth_mode?: PluginAuthMode;
|
||||
}
|
||||
Reference in New Issue
Block a user