feat: manually mirror opencoze's code from bytedance
Change-Id: I09a73aadda978ad9511264a756b2ce51f5761adf
This commit is contained in:
@@ -0,0 +1,55 @@
|
||||
.wrapper {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 16px;
|
||||
align-items: center;
|
||||
|
||||
width: 640px;
|
||||
min-width: 640px;
|
||||
max-width: 640px;
|
||||
min-height: 480px;
|
||||
padding: 16px 24px 24px;
|
||||
|
||||
background: var(--coz-bg-plus, #F9F9F9);
|
||||
border-radius: var(--default, 8px)
|
||||
}
|
||||
|
||||
.header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
|
||||
width: 100%;
|
||||
height: 32px;
|
||||
min-height: 32px;
|
||||
}
|
||||
|
||||
.body {
|
||||
display: flex;
|
||||
flex: 1 0 0;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.footer {
|
||||
@apply flex items-center justify-end w-full;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 20px;
|
||||
font-weight: 500;
|
||||
font-style: normal;
|
||||
line-height: 28px; /* 140% */
|
||||
color: var(--coz-fg-plus, rgba(6, 7, 9, 96%));
|
||||
}
|
||||
|
||||
.error-txt {
|
||||
margin-top: 16px;
|
||||
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
font-style: normal;
|
||||
line-height: normal;
|
||||
color: var(--Light-usage-text---color-text-1, rgba(28, 31, 35, 80%));
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* 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 { I18n } from '@coze-arch/i18n';
|
||||
import { IconCozCross } from '@coze-arch/coze-design/icons';
|
||||
import { Button } from '@coze-arch/coze-design';
|
||||
|
||||
import styles from '../index.module.less';
|
||||
import { ReactComponent as IconImageBroken } from '../../assets/coz_image_broken.svg';
|
||||
|
||||
interface LoadErrorProps {
|
||||
onClose?: VoidFunction;
|
||||
}
|
||||
|
||||
export const LoadError = ({ onClose }: LoadErrorProps) => (
|
||||
<div className={styles.wrapper}>
|
||||
<div className={styles.header}>
|
||||
<div className={styles.title}>
|
||||
{I18n.t('analytics_query_aigc_infopanel_title')}
|
||||
</div>
|
||||
<Button
|
||||
icon={<IconCozCross className="w-4 h-4" />}
|
||||
color="secondary"
|
||||
className="w-4 h-4"
|
||||
onClick={onClose}
|
||||
></Button>
|
||||
</div>
|
||||
<div className={styles.body}>
|
||||
<IconImageBroken className="w-[64px] h-[64px]" />
|
||||
<span className={styles['error-txt']}>
|
||||
{I18n.t('analytics_query_aigc_errorpanel_context')}
|
||||
</span>
|
||||
</div>
|
||||
<div className={styles.footer}>
|
||||
<Button type="primary" size="default" onClick={onClose}>
|
||||
{I18n.t('analytics_query_aigc_errorpanel_ok')}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* 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 { useState } from 'react';
|
||||
|
||||
import { logger } from '@coze-arch/logger';
|
||||
import { I18n } from '@coze-arch/i18n';
|
||||
import { IconCozCross } from '@coze-arch/coze-design/icons';
|
||||
import { Button } from '@coze-arch/coze-design';
|
||||
|
||||
import styles from '../index.module.less';
|
||||
import { fetchResource, downloadFile } from '../../utils/download';
|
||||
import { ReactComponent as IconImageBroken } from '../../assets/not-support.svg';
|
||||
|
||||
interface LoadErrorProps {
|
||||
onClose?: VoidFunction;
|
||||
url: string;
|
||||
filename?: string;
|
||||
}
|
||||
|
||||
export const NotSupport = ({ onClose, url, filename }: LoadErrorProps) => {
|
||||
const [loading, setLoading] = useState(false);
|
||||
|
||||
const handleDownload = async () => {
|
||||
try {
|
||||
setLoading(true);
|
||||
const blob = await fetchResource(url);
|
||||
downloadFile(blob, filename);
|
||||
setLoading(false);
|
||||
} catch (error) {
|
||||
logger.error({
|
||||
eventName: 'LoadError-page',
|
||||
error: error as Error,
|
||||
});
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
return (
|
||||
<div className={styles.wrapper}>
|
||||
<div className={styles.header}>
|
||||
<div className={styles.title}>
|
||||
{I18n.t('analytics_query_aigc_inforpanel_title_file')}
|
||||
</div>
|
||||
<Button
|
||||
icon={<IconCozCross className="w-4 h-4" />}
|
||||
color="secondary"
|
||||
className="w-4 h-4"
|
||||
onClick={onClose}
|
||||
></Button>
|
||||
</div>
|
||||
<div className={styles.body}>
|
||||
<IconImageBroken className="w-[200px] h-[200px]" />
|
||||
<span className={styles['error-txt']}>
|
||||
{I18n.t('analytics_query_aigc_infopanel_context')}
|
||||
</span>
|
||||
</div>
|
||||
<div className={styles.footer}>
|
||||
<Button
|
||||
type="primary"
|
||||
size="default"
|
||||
onClick={onClose}
|
||||
color="primary"
|
||||
className="mr-2"
|
||||
>
|
||||
{I18n.t('analytics_query_aigc_infopanel_cancel')}
|
||||
</Button>
|
||||
<Button
|
||||
type="primary"
|
||||
size="default"
|
||||
onClick={handleDownload}
|
||||
loading={loading}
|
||||
>
|
||||
{I18n.t('analytics_query_aigc_infopanel_download')}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* 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 ReactDOM from 'react-dom';
|
||||
import React from 'react';
|
||||
|
||||
import { IconCozCrossFill } from '@coze-arch/coze-design/icons';
|
||||
|
||||
let overlayContainer: HTMLDivElement | null = null;
|
||||
|
||||
interface OverlayProps {
|
||||
onClose?: VoidFunction;
|
||||
children?: React.ReactNode;
|
||||
withMask?: boolean;
|
||||
}
|
||||
|
||||
const Overlay = ({ onClose, children, withMask }: OverlayProps) => (
|
||||
<div
|
||||
className="p-5"
|
||||
style={
|
||||
withMask
|
||||
? {
|
||||
position: 'fixed',
|
||||
top: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
backgroundColor: 'rgba(0, 0, 0, 0.70)',
|
||||
zIndex: 1000,
|
||||
}
|
||||
: {}
|
||||
}
|
||||
>
|
||||
<div
|
||||
className="absolute top-5 right-5 rounded-[50%] w-[40px] h-[40px] p-[11px] flex items-center justify-center bg-[rgba(255,255,255,0.12)] backdrop-blur-md cursor-pointer"
|
||||
style={{
|
||||
zIndex: 10010,
|
||||
}}
|
||||
onClick={onClose}
|
||||
>
|
||||
<IconCozCrossFill className="w-[18px] h-[18px] text-white" />
|
||||
</div>
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
|
||||
const createOverlayContainer = () => {
|
||||
overlayContainer = document.createElement('div');
|
||||
document.body.appendChild(overlayContainer);
|
||||
};
|
||||
|
||||
const show = (params: {
|
||||
content: (onClose: VoidFunction) => React.ReactNode;
|
||||
withMask?: boolean;
|
||||
}) => {
|
||||
const { content, withMask = true } = params;
|
||||
if (!overlayContainer) {
|
||||
createOverlayContainer();
|
||||
}
|
||||
|
||||
const close = () => {
|
||||
overlayContainer && ReactDOM.unmountComponentAtNode(overlayContainer);
|
||||
};
|
||||
|
||||
ReactDOM.render(
|
||||
<Overlay onClose={close} children={content?.(close)} withMask={withMask} />,
|
||||
overlayContainer,
|
||||
);
|
||||
|
||||
return close;
|
||||
};
|
||||
|
||||
const OverlayAPI = {
|
||||
show,
|
||||
};
|
||||
|
||||
export default OverlayAPI;
|
||||
Reference in New Issue
Block a user