feat: manually mirror opencoze's code from bytedance
Change-Id: I09a73aadda978ad9511264a756b2ce51f5761adf
This commit is contained in:
@@ -0,0 +1,206 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* eslint-disable @coze-arch/max-line-per-function */
|
||||
import { useNavigate, useParams } from 'react-router-dom';
|
||||
import { Helmet } from 'react-helmet';
|
||||
import { useState } from 'react';
|
||||
|
||||
import { useShallow } from 'zustand/react/shallow';
|
||||
import { useRequest } from 'ahooks';
|
||||
import {
|
||||
ConnectorClassification,
|
||||
type ConnectorPublishConfig,
|
||||
type GetPublishRecordDetailRequest,
|
||||
} from '@coze-arch/idl/intelligence_api';
|
||||
import { I18n } from '@coze-arch/i18n';
|
||||
import { IconCozArrowLeft } from '@coze-arch/coze-design/icons';
|
||||
import {
|
||||
Banner,
|
||||
Button,
|
||||
IconButton,
|
||||
Toast,
|
||||
useFormApi,
|
||||
} from '@coze-arch/coze-design';
|
||||
import { type DynamicParams } from '@coze-arch/bot-typings/teamspace';
|
||||
import { intelligenceApi } from '@coze-arch/bot-api';
|
||||
|
||||
import { isPublishFinish } from '../utils/is-publish-finish';
|
||||
import { MIN_PUBLISH_HEADER_HEIGHT } from '../utils/constants';
|
||||
import { useProjectPublishStore } from '../store';
|
||||
import { usePublishContainer } from '../context/publish-container-context';
|
||||
|
||||
export function PublishTitleBar() {
|
||||
const navigate = useNavigate();
|
||||
const formApi = useFormApi();
|
||||
const { space_id = '', project_id = '' } = useParams<DynamicParams>();
|
||||
const goBack = () => navigate(`/space/${space_id}/project-ide/${project_id}`);
|
||||
const {
|
||||
connectorList,
|
||||
showPublishResult,
|
||||
setShowPublishResult,
|
||||
versionDescription,
|
||||
versionNumber,
|
||||
connectors,
|
||||
unions,
|
||||
connectorPublishConfig,
|
||||
socialPlatformChatflow,
|
||||
selectedConnectorIds,
|
||||
setPublishRecordDetail,
|
||||
} = useProjectPublishStore(
|
||||
useShallow(s => ({
|
||||
connectorList: s.connectorList,
|
||||
showPublishResult: s.showPublishResult,
|
||||
setShowPublishResult: s.setShowPublishResult,
|
||||
versionNumber: s.versionNumber,
|
||||
versionDescription: s.versionDescription,
|
||||
connectors: s.connectors,
|
||||
unions: s.unions,
|
||||
connectorPublishConfig: s.connectorPublishConfig,
|
||||
socialPlatformChatflow: s.socialPlatformChatflow,
|
||||
selectedConnectorIds: s.selectedConnectorIds,
|
||||
setPublishRecordDetail: s.setPublishRecordDetail,
|
||||
})),
|
||||
);
|
||||
const [publishing, setPublishing] = useState(false);
|
||||
const { publishHeaderHeight, setPublishHeaderHeight } = usePublishContainer();
|
||||
// 发布结果轮询
|
||||
const { run: getPublishRecordDetail, cancel } = useRequest(
|
||||
async (params: GetPublishRecordDetailRequest) =>
|
||||
await intelligenceApi.GetPublishRecordDetail(params),
|
||||
{
|
||||
pollingInterval: 3000,
|
||||
pollingWhenHidden: false,
|
||||
pollingErrorRetryCount: 3,
|
||||
manual: true,
|
||||
onSuccess: res => {
|
||||
if (res?.data) {
|
||||
setPublishRecordDetail(res.data);
|
||||
|
||||
if (isPublishFinish(res.data)) {
|
||||
cancel();
|
||||
}
|
||||
if (!showPublishResult) {
|
||||
setShowPublishResult(true);
|
||||
}
|
||||
} else {
|
||||
cancel();
|
||||
}
|
||||
},
|
||||
onError: () => {
|
||||
cancel();
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
const handlePublishProject = async () => {
|
||||
if (showPublishResult) {
|
||||
goBack();
|
||||
} else {
|
||||
try {
|
||||
setPublishing(true);
|
||||
await formApi.validate();
|
||||
if (!selectedConnectorIds.length) {
|
||||
Toast.error(I18n.t('publish_tooltip_select_platform'));
|
||||
return;
|
||||
}
|
||||
const publishConnectors: Record<string, Record<string, string>> = {};
|
||||
const publishConnectorConfigs: Record<string, ConnectorPublishConfig> =
|
||||
{};
|
||||
selectedConnectorIds.forEach(id => {
|
||||
const connectorId = unions[id] ?? id;
|
||||
publishConnectors[connectorId] = connectors[connectorId] ?? {};
|
||||
// 社交平台的 chatflow 选项统一
|
||||
if (
|
||||
connectorList.find(c => c.id === connectorId)
|
||||
?.connector_classification ===
|
||||
ConnectorClassification.SocialPlatform
|
||||
) {
|
||||
publishConnectorConfigs[connectorId] = socialPlatformChatflow;
|
||||
} else if (connectorPublishConfig[connectorId]) {
|
||||
publishConnectorConfigs[connectorId] =
|
||||
connectorPublishConfig[connectorId];
|
||||
}
|
||||
});
|
||||
|
||||
const { data } = await intelligenceApi.PublishProject({
|
||||
project_id,
|
||||
version_number: versionNumber,
|
||||
description: versionDescription,
|
||||
connectors: publishConnectors,
|
||||
connector_publish_config: publishConnectorConfigs,
|
||||
});
|
||||
|
||||
setPublishRecordDetail({
|
||||
publish_monetization_result: data?.publish_monetization_result,
|
||||
});
|
||||
if (data?.publish_record_id) {
|
||||
getPublishRecordDetail({
|
||||
publish_record_id: data.publish_record_id,
|
||||
project_id,
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
// 校验的错误还需要Toast提示出来
|
||||
if (typeof Object.values(error as Error)[0] === 'string') {
|
||||
Toast.error(Object.values(error as Error)[0]);
|
||||
}
|
||||
} finally {
|
||||
setPublishing(false);
|
||||
}
|
||||
}
|
||||
};
|
||||
return (
|
||||
<div
|
||||
className="sticky top-0 z-[100] coz-bg-primary overflow-y-hidden"
|
||||
style={{ height: publishHeaderHeight }}
|
||||
>
|
||||
<Helmet>
|
||||
<title>{I18n.t('Publish')}</title>
|
||||
</Helmet>
|
||||
<div className="flex p-[16px] justify-between items-center coz-stroke-primary border-b border-x-0 border-t-0 border-solid pl-2">
|
||||
<div className="flex items-center">
|
||||
<IconButton
|
||||
icon={<IconCozArrowLeft className="h-[18px] w-[18px]" />}
|
||||
color="secondary"
|
||||
iconSize="large"
|
||||
onClick={goBack}
|
||||
/>
|
||||
<span className="ml-[8px] font-medium text-[20px]">
|
||||
{I18n.t('Publish')}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<Button
|
||||
onClick={handlePublishProject}
|
||||
loading={publishing}
|
||||
data-testid="project.publish"
|
||||
>
|
||||
{showPublishResult
|
||||
? I18n.t('bot_publish_success_back')
|
||||
: I18n.t('Publish')}
|
||||
</Button>
|
||||
</div>
|
||||
<Banner
|
||||
type="info"
|
||||
description={I18n.t('project_release_notify')}
|
||||
onClose={() => {
|
||||
setPublishHeaderHeight(MIN_PUBLISH_HEADER_HEIGHT);
|
||||
}}
|
||||
></Banner>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user