280 lines
7.4 KiB
TypeScript
280 lines
7.4 KiB
TypeScript
/*
|
|
* 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 { useParams } from 'react-router-dom';
|
|
import { useEffect, useRef, useState } from 'react';
|
|
|
|
import { I18n } from '@coze-arch/i18n';
|
|
import { type DynamicParams } from '@coze-arch/bot-typings/teamspace';
|
|
import {
|
|
type PluginMockSetCommonParams,
|
|
type PluginMockDataGenerateMode,
|
|
} from '@coze-arch/bot-tea';
|
|
import { useSpaceStore } from '@coze-arch/bot-studio-store';
|
|
import {
|
|
Space,
|
|
Toast,
|
|
UIButton,
|
|
UIModal,
|
|
Typography,
|
|
Divider,
|
|
} from '@coze-arch/bot-semi';
|
|
import { SpaceType } from '@coze-arch/bot-api/playground_api';
|
|
import { type mockset, type infra } from '@coze-arch/bot-api/debugger_api';
|
|
import {
|
|
calcStringSize,
|
|
type MockDataInfo,
|
|
MAX_SUBMIT_LENGTH,
|
|
getEnvironment,
|
|
} from '@coze-studio/mockset-shared';
|
|
import {
|
|
MocksetEditor,
|
|
type EditorAreaActions,
|
|
} from '@coze-studio/mockset-editor-adapter';
|
|
|
|
import {
|
|
PRE_DEFINED_NO_EMPTY_KEY,
|
|
useTransSchema,
|
|
} from '../hook/use-trans-schema';
|
|
import { useSaveMockData } from '../hook/use-save-mock-data';
|
|
|
|
import s from './index.module.less';
|
|
|
|
export enum CreationMode {
|
|
/** pop-up window */
|
|
MODAL = 'modal',
|
|
/** embed page */
|
|
CARD = 'card',
|
|
}
|
|
|
|
interface MockDataCreateCardProps {
|
|
mode: CreationMode;
|
|
mockInfo?: MockDataInfo;
|
|
// Effective when modal mode
|
|
visible?: boolean;
|
|
// Effective when modal mode
|
|
onCancel?: () => void;
|
|
onSuccess: (data?: mockset.MockRule[]) => void;
|
|
bizCtx: infra.BizCtx;
|
|
forceGenerate?: {
|
|
mode: PluginMockDataGenerateMode;
|
|
count: number;
|
|
};
|
|
}
|
|
|
|
/** Create or edit mock data - */
|
|
export function MockDataCreateCard({
|
|
mode,
|
|
mockInfo,
|
|
visible,
|
|
onCancel,
|
|
onSuccess,
|
|
bizCtx,
|
|
forceGenerate,
|
|
}: MockDataCreateCardProps) {
|
|
const { schema } = mockInfo || {};
|
|
const editorsRef = useRef<EditorAreaActions>(null);
|
|
const [disableSubmit, setDisableSubmit] = useState(false);
|
|
const [disableSubmitWhenGenerating, setDisableSubmitWhenGenerating] =
|
|
useState(false);
|
|
|
|
const { testValueValid, formattedResultExample: initialExample } =
|
|
useTransSchema(schema);
|
|
const { mock_set_id, tool_id } = useParams<DynamicParams>();
|
|
|
|
// Space information
|
|
const spaceType = useSpaceStore(store => store.space.space_type);
|
|
const isPersonal = spaceType === SpaceType.Personal;
|
|
|
|
const basicParams: PluginMockSetCommonParams = {
|
|
environment: getEnvironment(),
|
|
workspace_id: bizCtx.bizSpaceID || '',
|
|
workspace_type: isPersonal ? 'personal_workspace' : 'team_workspace',
|
|
tool_id: tool_id || '',
|
|
mock_set_id: mock_set_id || '',
|
|
};
|
|
|
|
const { save, loading } = useSaveMockData({
|
|
mockSetId: mock_set_id,
|
|
basicParams,
|
|
bizCtx,
|
|
onSuccess,
|
|
});
|
|
|
|
const confirmHandler = () => {
|
|
const values = editorsRef.current?.getValue();
|
|
if (!values) {
|
|
return;
|
|
}
|
|
|
|
for (const value of values) {
|
|
if (!value) {
|
|
Toast.error('no data');
|
|
return;
|
|
}
|
|
|
|
if (calcStringSize(value) > MAX_SUBMIT_LENGTH) {
|
|
Toast.error({
|
|
content: I18n.t('mockset_toast_data_size_limit'),
|
|
showClose: false,
|
|
});
|
|
return;
|
|
}
|
|
|
|
if (!testValueValid(value)) {
|
|
Toast.error({
|
|
content: I18n.t('mockdata_field_empty', {
|
|
fieldName: PRE_DEFINED_NO_EMPTY_KEY,
|
|
}),
|
|
showClose: false,
|
|
});
|
|
return;
|
|
}
|
|
}
|
|
|
|
const mockDataId = String(mockInfo?.mock?.id || 0);
|
|
|
|
save(values, mockDataId);
|
|
};
|
|
|
|
const validateHandler = (isValid: boolean[]) => {
|
|
setDisableSubmit(isValid.some(v => !v));
|
|
};
|
|
|
|
useEffect(() => {
|
|
// @ts-expect-error -- linter-disable-autofix
|
|
const unloadHandler = e => {
|
|
const info = I18n.t('mockset_tip_data_will_lose');
|
|
e.preventDefault();
|
|
e.returnValue = info;
|
|
return info;
|
|
};
|
|
|
|
if (
|
|
(mode === CreationMode.MODAL && visible) ||
|
|
mode === CreationMode.CARD
|
|
) {
|
|
window.addEventListener('beforeunload', unloadHandler);
|
|
}
|
|
|
|
return () => {
|
|
window.removeEventListener('beforeunload', unloadHandler);
|
|
};
|
|
}, [mode, visible]);
|
|
|
|
useEffect(() => {
|
|
if (forceGenerate) {
|
|
editorsRef.current?.forceStartGenerate?.(
|
|
forceGenerate.mode,
|
|
forceGenerate.count,
|
|
);
|
|
}
|
|
}, []);
|
|
|
|
return mode === CreationMode.MODAL ? (
|
|
<UIModal
|
|
visible={visible}
|
|
title={
|
|
mockInfo?.mock ? I18n.t('edit_mock_data') : I18n.t('add_mock_data')
|
|
}
|
|
className={s['mock-creation-modal']}
|
|
keepDOM={false}
|
|
footer={
|
|
<>
|
|
<span className="mr-[8px]">{I18n.t('mockset_save_description')}</span>
|
|
<Divider layout="vertical" margin="0px" />
|
|
<UIButton type={'tertiary'} key="Cancel" onClick={onCancel}>
|
|
{I18n.t('cancel')}
|
|
</UIButton>
|
|
<UIButton
|
|
type={'primary'}
|
|
theme={'solid'}
|
|
key="Confirm"
|
|
onClick={confirmHandler}
|
|
loading={loading}
|
|
disabled={disableSubmit || disableSubmitWhenGenerating}
|
|
>
|
|
{I18n.t('confirm')}
|
|
</UIButton>
|
|
</>
|
|
}
|
|
width={1000}
|
|
maskClosable={false}
|
|
onCancel={onCancel}
|
|
>
|
|
<MocksetEditor
|
|
className={s['mock-creation-modal-editor']}
|
|
mockInfo={{
|
|
mergedResultExample: initialExample,
|
|
...mockInfo,
|
|
}}
|
|
readOnly={false}
|
|
ref={editorsRef}
|
|
onValidate={validateHandler}
|
|
environment={{
|
|
spaceId: bizCtx.bizSpaceID,
|
|
mockSetId: mock_set_id,
|
|
basicParams,
|
|
}}
|
|
isCreateScene={!mockInfo?.mock}
|
|
onGenerationStatusChange={isGenerating =>
|
|
setDisableSubmitWhenGenerating(isGenerating)
|
|
}
|
|
/>
|
|
</UIModal>
|
|
) : (
|
|
<div className={s['mock-creation-card']}>
|
|
<div className={s['mock-creation-card-editor']}>
|
|
<MocksetEditor
|
|
mockInfo={{
|
|
mergedResultExample: initialExample,
|
|
...mockInfo,
|
|
}}
|
|
ref={editorsRef}
|
|
onValidate={validateHandler}
|
|
environment={{
|
|
spaceId: bizCtx.bizSpaceID,
|
|
mockSetId: mock_set_id,
|
|
basicParams,
|
|
}}
|
|
isCreateScene={!mockInfo?.mock}
|
|
onGenerationStatusChange={isGenerating =>
|
|
setDisableSubmitWhenGenerating(isGenerating)
|
|
}
|
|
/>
|
|
</div>
|
|
<div className={s['mock-creation-card-operation']}>
|
|
<Space>
|
|
<Typography.Text>
|
|
{I18n.t('mockset_save_description')}
|
|
</Typography.Text>
|
|
<Divider layout="vertical" margin="0px" />
|
|
<UIButton
|
|
type={'primary'}
|
|
theme={'solid'}
|
|
onClick={confirmHandler}
|
|
loading={loading}
|
|
disabled={disableSubmit || disableSubmitWhenGenerating}
|
|
>
|
|
{I18n.t('mockset_save')}
|
|
</UIButton>
|
|
</Space>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|