feat: manually mirror opencoze's code from bytedance
Change-Id: I09a73aadda978ad9511264a756b2ce51f5761adf
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
const { defineConfig } = require('@coze-arch/stylelint-config');
|
||||
|
||||
module.exports = defineConfig({
|
||||
extends: [],
|
||||
});
|
||||
15
frontend/packages/studio/open-platform/open-auth/README.md
Normal file
15
frontend/packages/studio/open-platform/open-auth/README.md
Normal file
@@ -0,0 +1,15 @@
|
||||
# @coze-studio/open-auth
|
||||
|
||||
|
||||
## Features
|
||||
|
||||
- [x] eslint & ts
|
||||
- [x] esm bundle
|
||||
- [x] umd bundle
|
||||
- [x] storybook
|
||||
|
||||
## Commands
|
||||
|
||||
- init: `rush update`
|
||||
- dev: `npm run dev`
|
||||
- build: `npm run build`
|
||||
@@ -0,0 +1,357 @@
|
||||
/*
|
||||
* 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 { renderHook, act } from '@testing-library/react-hooks';
|
||||
|
||||
import {
|
||||
useGetPATList,
|
||||
useCreatePAT,
|
||||
useUpdatePAT,
|
||||
useDeletePAT,
|
||||
usePATPermission,
|
||||
} from '@/hooks/pat/use-token';
|
||||
|
||||
vi.mock('@coze-arch/bot-api', () => ({
|
||||
patPermissionApi: {
|
||||
ListPersonalAccessTokensByCreator: vi
|
||||
.fn()
|
||||
.mockRejectedValueOnce('error')
|
||||
.mockResolvedValue({
|
||||
code: 0,
|
||||
msg: '',
|
||||
data: {
|
||||
personal_access_tokens: [
|
||||
{
|
||||
id: 'id',
|
||||
name: 'name',
|
||||
created_at: 0,
|
||||
updated_at: 0,
|
||||
last_used_at: 0,
|
||||
expire_at: 0,
|
||||
},
|
||||
],
|
||||
},
|
||||
}),
|
||||
ListPersonalAccessTokens: vi
|
||||
.fn()
|
||||
.mockRejectedValueOnce('error')
|
||||
.mockRejectedValueOnce('error')
|
||||
.mockResolvedValue({
|
||||
code: 0,
|
||||
data: {
|
||||
personal_access_tokens: [
|
||||
{
|
||||
id: '2124658667281',
|
||||
name: 'Secret token--480-c',
|
||||
created_at: 1711697638,
|
||||
updated_at: 1711697638,
|
||||
last_used_at: -1,
|
||||
expire_at: 1711699200,
|
||||
},
|
||||
],
|
||||
},
|
||||
msg: '',
|
||||
}),
|
||||
CreatePersonalAccessTokenAndPermission: vi
|
||||
.fn()
|
||||
.mockRejectedValueOnce('error')
|
||||
.mockResolvedValue({
|
||||
code: 0,
|
||||
data: {
|
||||
token: 'pat',
|
||||
personal_access_token: {
|
||||
id: '2106243199900',
|
||||
name: 'Secret token',
|
||||
created_at: 1712668504,
|
||||
updated_at: 1712668504,
|
||||
last_used_at: -1,
|
||||
expire_at: 1712754904,
|
||||
},
|
||||
},
|
||||
msg: '',
|
||||
}),
|
||||
UpdatePersonalAccessTokenAndPermission: vi
|
||||
.fn()
|
||||
.mockRejectedValueOnce('error')
|
||||
.mockResolvedValue({
|
||||
code: 0,
|
||||
data: {},
|
||||
msg: '',
|
||||
}),
|
||||
DeletePersonalAccessTokenAndPermission: vi
|
||||
.fn()
|
||||
.mockRejectedValueOnce('error')
|
||||
.mockResolvedValue({
|
||||
code: 0,
|
||||
data: {},
|
||||
msg: '',
|
||||
}),
|
||||
GetPersonalAccessTokenAndPermission: vi
|
||||
.fn()
|
||||
.mockRejectedValueOnce('error')
|
||||
.mockResolvedValue({
|
||||
code: 0,
|
||||
data: {
|
||||
personal_access_token: {
|
||||
id: '2196515701286',
|
||||
name: 'Secret token',
|
||||
created_at: 1711946476,
|
||||
updated_at: 1711946476,
|
||||
last_used_at: -1,
|
||||
expire_at: -1,
|
||||
},
|
||||
workspace_permission: {
|
||||
option: 2,
|
||||
permission_list: [
|
||||
{
|
||||
resource_type: 'Bot',
|
||||
actions: ['chat'],
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
msg: '',
|
||||
}),
|
||||
ListPersonalAccessTokenSupportPermissions: vi
|
||||
.fn()
|
||||
.mockRejectedValueOnce('error')
|
||||
.mockResolvedValue({
|
||||
code: 0,
|
||||
data: {
|
||||
permission_list: [
|
||||
{
|
||||
resource_type: 'Bot',
|
||||
actions: ['chat'],
|
||||
},
|
||||
],
|
||||
},
|
||||
msg: '',
|
||||
}),
|
||||
},
|
||||
PlaygroundApi: {
|
||||
GetSpaceListV2: vi
|
||||
.fn()
|
||||
.mockRejectedValueOnce('error')
|
||||
.mockResolvedValue({
|
||||
code: 0,
|
||||
data: {
|
||||
bot_space_list: [
|
||||
{
|
||||
description: 'Personal Space',
|
||||
hide_operation: false,
|
||||
icon_url:
|
||||
'https://placehold.co/460x460?text=placeholder-1',
|
||||
id: '7304535597841317932',
|
||||
name: 'Personal',
|
||||
role_type: 1,
|
||||
space_type: 1,
|
||||
},
|
||||
{
|
||||
description: 'Public',
|
||||
hide_operation: true,
|
||||
icon_url:
|
||||
'https://placehold.co/460x460?text=placeholder-1',
|
||||
id: '7293504662404071468',
|
||||
name: 'Public',
|
||||
role_type: 3,
|
||||
space_type: 2,
|
||||
},
|
||||
],
|
||||
},
|
||||
msg: '',
|
||||
}),
|
||||
},
|
||||
developerBackendApi: {
|
||||
GetPermissionList: vi
|
||||
.fn()
|
||||
.mockRejectedValueOnce('error')
|
||||
.mockResolvedValue({
|
||||
code: 0,
|
||||
data: {
|
||||
data: [
|
||||
{
|
||||
childrens: [
|
||||
{
|
||||
childrens: [],
|
||||
create_time: '2024-05-06 12:03:11',
|
||||
description: 'Bot相关聊天',
|
||||
display_name: '',
|
||||
key: 'chat',
|
||||
parent_id: '7365730459227013164',
|
||||
permission_id: '7365731956782284844',
|
||||
update_time: '2024-05-06 12:03:11',
|
||||
},
|
||||
],
|
||||
create_time: '2024-05-06 11:57:38',
|
||||
description: 'Bot相关',
|
||||
display_name: '',
|
||||
key: 'Bot',
|
||||
parent_id: '0',
|
||||
permission_id: '7365730459227013164',
|
||||
update_time: '2024-05-06 14:08:16',
|
||||
},
|
||||
],
|
||||
},
|
||||
msg: '',
|
||||
}),
|
||||
},
|
||||
}));
|
||||
|
||||
vi.mock('@coze-arch/bot-flags', () => ({
|
||||
getFlags: vi.fn(),
|
||||
}));
|
||||
vi.mock('../../src/utils/time.ts', () => ({
|
||||
getExpireAt: vi.fn(() => '-'),
|
||||
}));
|
||||
vi.mock('@coze-arch/coze-design', () => ({}));
|
||||
vi.mock('@coze-studio/bot-detail-store', () => ({
|
||||
initBotDetailStore: vi.fn(),
|
||||
useBotDetailStoreSet: {
|
||||
clear: vi.fn(),
|
||||
},
|
||||
}));
|
||||
vi.mock('@flow-foundation/enterprise', () => ({
|
||||
useEnterpriseStore: () => ({
|
||||
isCurrentEnterpriseInit: true,
|
||||
}),
|
||||
useCurrentEnterpriseInfo: vi.fn(),
|
||||
useEnterpriseList: vi.fn(),
|
||||
}));
|
||||
|
||||
describe('useGetPATList', () => {
|
||||
it('get pat list error', () => {
|
||||
const { result } = renderHook(() => useGetPATList({}));
|
||||
expect(result.current.loading).toEqual(false);
|
||||
act(() => result.current.fetchData());
|
||||
expect(result.current.loading).toEqual(true);
|
||||
});
|
||||
|
||||
it('get pat list success', () => {
|
||||
const { result } = renderHook(() => useGetPATList({}));
|
||||
expect(result.current.loading).toEqual(false);
|
||||
act(() => result.current.fetchData());
|
||||
expect(result.current.dataSource).toEqual([]);
|
||||
expect(result.current.loading).toEqual(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('useCreatePAT', () => {
|
||||
const createValue = {
|
||||
name: 'Secret token',
|
||||
duration_day: '1',
|
||||
workspace_permission: {
|
||||
option: 2,
|
||||
permission_list: [{ resource_type: 'Bot', actions: ['chat'] }],
|
||||
},
|
||||
};
|
||||
it('create error', async () => {
|
||||
const { result, waitForNextUpdate } = renderHook(() => useCreatePAT());
|
||||
expect(result.current.loading).toEqual(false);
|
||||
act(() => result.current.runCreate(createValue));
|
||||
await waitForNextUpdate();
|
||||
expect(result.current.loading).toEqual(false);
|
||||
});
|
||||
|
||||
it('create success', async () => {
|
||||
const { result, waitForValueToChange } = renderHook(() => useCreatePAT());
|
||||
expect(result.current.loading).toEqual(false);
|
||||
act(() => result.current.runCreate(createValue));
|
||||
await waitForValueToChange(() => result.current.successData);
|
||||
expect(result.current.successData?.token).toEqual('pat');
|
||||
expect(result.current.loading).toEqual(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('useUpdatePAT', () => {
|
||||
const updateValue = {
|
||||
id: 'id',
|
||||
name: 'Secret token',
|
||||
workspace_permission: {
|
||||
option: 2,
|
||||
permission_list: [{ resource_type: 'Bot', actions: ['chat'] }],
|
||||
},
|
||||
};
|
||||
|
||||
const successHandle = vi.fn();
|
||||
it('update error', async () => {
|
||||
const { result, waitForNextUpdate } = renderHook(() =>
|
||||
useUpdatePAT({ successHandle }),
|
||||
);
|
||||
expect(result.current.loading).toEqual(false);
|
||||
act(() => result.current.runUpdate(updateValue));
|
||||
await waitForNextUpdate();
|
||||
expect(result.current.loading).toEqual(false);
|
||||
});
|
||||
|
||||
it('update success', async () => {
|
||||
const { result, waitForValueToChange } = renderHook(() =>
|
||||
useUpdatePAT({ successHandle }),
|
||||
);
|
||||
expect(result.current.loading).toEqual(false);
|
||||
act(() => result.current.runUpdate(updateValue));
|
||||
await waitForValueToChange(() => result.current.loading);
|
||||
expect(result.current.loading).toEqual(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('useDeletePAT', () => {
|
||||
const successHandle = vi.fn();
|
||||
it('delete error', async () => {
|
||||
const { result, waitForNextUpdate } = renderHook(() =>
|
||||
useDeletePAT({ successHandle }),
|
||||
);
|
||||
expect(result.current.loading).toEqual(false);
|
||||
act(() => result.current.runDelete('id'));
|
||||
await waitForNextUpdate();
|
||||
expect(result.current.loading).toEqual(false);
|
||||
});
|
||||
|
||||
it('delete success', async () => {
|
||||
const { result, waitForValueToChange } = renderHook(() =>
|
||||
useDeletePAT({ successHandle }),
|
||||
);
|
||||
expect(result.current.loading).toEqual(false);
|
||||
act(() => result.current.runDelete('id'));
|
||||
await waitForValueToChange(() => result.current.loading);
|
||||
expect(result.current.loading).toEqual(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('usePATPermission', () => {
|
||||
let id = '1';
|
||||
it('get user pat permission error', async () => {
|
||||
const { result, waitForNextUpdate } = renderHook(() =>
|
||||
usePATPermission({ patId: id }),
|
||||
);
|
||||
await waitForNextUpdate();
|
||||
expect(result.current.patPermission).toEqual(undefined);
|
||||
});
|
||||
|
||||
it('get user pat permission success', async () => {
|
||||
const { result, rerender, waitForValueToChange } = renderHook(() =>
|
||||
usePATPermission({ patId: id }),
|
||||
);
|
||||
|
||||
rerender({ patId: '2' });
|
||||
await waitForValueToChange(() => result.current.patPermission);
|
||||
expect(result.current.patPermission?.personal_access_token?.name).toEqual(
|
||||
'Secret token',
|
||||
);
|
||||
id = '';
|
||||
rerender({ patId: '' });
|
||||
expect(result.current.patPermission).toEqual(undefined);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"operationSettings": [
|
||||
{
|
||||
"operationName": "test:cov",
|
||||
"outputFolderNames": ["coverage"]
|
||||
},
|
||||
{
|
||||
"operationName": "ts-check",
|
||||
"outputFolderNames": ["./dist"]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
const { defineConfig } = require('@coze-arch/eslint-config');
|
||||
|
||||
module.exports = defineConfig({
|
||||
packageRoot: __dirname,
|
||||
preset: 'web',
|
||||
rules: {},
|
||||
});
|
||||
@@ -0,0 +1,72 @@
|
||||
{
|
||||
"name": "@coze-studio/open-auth",
|
||||
"version": "0.0.1",
|
||||
"description": "bot open platform",
|
||||
"license": "Apache-2.0",
|
||||
"author": "gaoding.devingao@bytedance.com",
|
||||
"maintainers": [],
|
||||
"exports": {
|
||||
".": "./src/index.tsx"
|
||||
},
|
||||
"main": "src/index.tsx",
|
||||
"scripts": {
|
||||
"build": "exit 0",
|
||||
"lint": "eslint ./ --cache",
|
||||
"test": "vitest --run --passWithNoTests",
|
||||
"test:cov": "npm run test -- --coverage"
|
||||
},
|
||||
"dependencies": {
|
||||
"@coze-arch/bot-api": "workspace:*",
|
||||
"@coze-arch/bot-semi": "workspace:*",
|
||||
"@coze-arch/coze-design": "0.0.6-alpha.346d77",
|
||||
"@coze-arch/i18n": "workspace:*",
|
||||
"@coze-arch/logger": "workspace:*",
|
||||
"@coze-arch/report-events": "workspace:*",
|
||||
"ahooks": "^3.7.8",
|
||||
"classnames": "^2.3.2",
|
||||
"copy-to-clipboard": "^3.3.3",
|
||||
"dayjs": "^1.11.7",
|
||||
"lodash-es": "^4.17.21"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@coze-arch/bot-typings": "workspace:*",
|
||||
"@coze-arch/eslint-config": "workspace:*",
|
||||
"@coze-arch/stylelint-config": "workspace:*",
|
||||
"@coze-arch/ts-config": "workspace:*",
|
||||
"@coze-arch/vitest-config": "workspace:*",
|
||||
"@rsbuild/core": "1.1.13",
|
||||
"@testing-library/jest-dom": "^6.1.5",
|
||||
"@testing-library/react": "^14.1.2",
|
||||
"@testing-library/react-hooks": "^8.0.1",
|
||||
"@types/lodash-es": "^4.17.10",
|
||||
"@types/node": "18.18.9",
|
||||
"@types/react": "18.2.37",
|
||||
"@types/react-dom": "18.2.15",
|
||||
"@types/react-helmet": "^6.1.11",
|
||||
"@vitest/coverage-v8": "~3.0.5",
|
||||
"axios": "^1.7.1",
|
||||
"core-js": "^3.37.1",
|
||||
"eventemitter3": "^5.0.1",
|
||||
"less": "^3.13.1",
|
||||
"less-loader": "^7.1.0",
|
||||
"less-plugin-autoprefix": "^2.0.0",
|
||||
"react": "~18.2.0",
|
||||
"react-dom": "~18.2.0",
|
||||
"react-helmet": "^6.1.0",
|
||||
"react-is": ">= 16.8.0",
|
||||
"react-router-dom": "^6.22.0",
|
||||
"scheduler": ">=0.19.0",
|
||||
"styled-components": ">= 2",
|
||||
"stylelint": "^15.11.0",
|
||||
"typescript": "5.7.2",
|
||||
"utility-types": "^3.10.0",
|
||||
"vitest": "~3.0.5",
|
||||
"webpack": "~5.91.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": ">=18.2.0",
|
||||
"react-dom": ">=18.2.0"
|
||||
},
|
||||
"// deps": "immer@^10.0.3 为脚本自动补齐,请勿改动"
|
||||
}
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* 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 { vi } from 'vitest';
|
||||
|
||||
vi.mock('@coze-arch/i18n', () => ({
|
||||
I18n: {
|
||||
t: vi.fn(),
|
||||
},
|
||||
}));
|
||||
vi.mock('@coze-arch/logger', () => ({
|
||||
logger: {
|
||||
info: vi.fn(),
|
||||
createLoggerWith: vi.fn(() => ({
|
||||
info: vi.fn(),
|
||||
persist: {
|
||||
error: vi.fn(),
|
||||
},
|
||||
})),
|
||||
},
|
||||
reporter: {
|
||||
errorEvent: vi.fn(),
|
||||
info: vi.fn(),
|
||||
},
|
||||
}));
|
||||
|
||||
vi.stubGlobal('IS_OVERSEA', false);
|
||||
vi.stubGlobal('IS_DEV_MODE', true);
|
||||
vi.stubGlobal('IS_BOE', true);
|
||||
@@ -0,0 +1,137 @@
|
||||
/* stylelint-disable declaration-no-important */
|
||||
/* stylelint-disable no-descending-specificity */
|
||||
/* stylelint-disable max-nesting-depth */
|
||||
// 历史问题
|
||||
.table-wrap {
|
||||
flex: 1;
|
||||
min-height: 0;
|
||||
margin-right: -11px;
|
||||
padding-right: 11px;
|
||||
}
|
||||
|
||||
.table-content {
|
||||
width: 100%;
|
||||
|
||||
:global {
|
||||
.semi-table-tbody > .semi-table-row,
|
||||
.semi-table-thead > .semi-table-row > .semi-table-row-head,
|
||||
.semi-table-tbody > .semi-table-row:hover > .semi-table-row-cell {
|
||||
background-color: transparent !important;
|
||||
background-image: none !important;
|
||||
}
|
||||
|
||||
.semi-table-tbody > .semi-table-row > .semi-table-row-cell {
|
||||
height: 60px !important;
|
||||
padding: 0 16px !important;
|
||||
font-weight: 400 !important;
|
||||
color: var(--coz-fg-primary) !important;
|
||||
}
|
||||
|
||||
.semi-table-header::-webkit-scrollbar {
|
||||
width: 4px;
|
||||
background-color: transparent;
|
||||
border-bottom-width: 0;
|
||||
}
|
||||
|
||||
.semi-table-body {
|
||||
padding-top: 0 !important;
|
||||
|
||||
.scroll-wrap;
|
||||
}
|
||||
|
||||
.semi-table-tbody
|
||||
> .semi-table-row
|
||||
> .semi-table-row-cell:last-child::after,
|
||||
.semi-table-tbody
|
||||
> .semi-table-row
|
||||
> .semi-table-row-cell:first-child::after {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.semi-table-fixed-header table {
|
||||
height: 48px !important;
|
||||
}
|
||||
|
||||
.semi-table-thead > .semi-table-row > .semi-table-row-head {
|
||||
padding: 0 16px !important;
|
||||
color: var(--coz-fg-plus, rgba(6, 7, 9, 96%)) !important;
|
||||
}
|
||||
|
||||
.semi-table-tbody > .semi-table-row {
|
||||
cursor: default !important;
|
||||
font-size: 14px !important;
|
||||
}
|
||||
|
||||
.semi-switch:not(.semi-switch-checked) {
|
||||
background-color: var(--semi-color-fill-0);
|
||||
}
|
||||
|
||||
.semi-switch:not(.semi-switch-checked):hover {
|
||||
background-color: var(--semi-color-fill-1);
|
||||
}
|
||||
}
|
||||
|
||||
&.small {
|
||||
:global {
|
||||
.semi-table-tbody > .semi-table-row > .semi-table-row-cell {
|
||||
height: 56px !important;
|
||||
padding: 0 8px !important;
|
||||
}
|
||||
|
||||
.semi-table-fixed-header table {
|
||||
height: 28px !important;
|
||||
}
|
||||
|
||||
.semi-table-thead > .semi-table-row > .semi-table-row-head {
|
||||
padding: 0 8px !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.primary {
|
||||
:global {
|
||||
.semi-table-tbody > .semi-table-row > .semi-table-row-cell {
|
||||
color: var(--coz-fg-primary, rgba(6, 7, 9, 80%)) !important;
|
||||
}
|
||||
|
||||
.semi-table-fixed-header table {
|
||||
height: 28px !important;
|
||||
}
|
||||
|
||||
.semi-table-thead > .semi-table-row > .semi-table-row-head {
|
||||
padding: 0 8px !important;
|
||||
color: var(--coz-fg-secondary, rgba(32, 41, 69, 62%)) !important;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.scroll-wrap {
|
||||
&::-webkit-scrollbar-thumb {
|
||||
background: var(--coz-fg-dim, rgba(6, 7, 9, 30%));
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar {
|
||||
display: block !important;
|
||||
width: 4px;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar:hover {
|
||||
width: 4px;
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar-button {
|
||||
display: none;
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar-track {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar-corner {
|
||||
background-color: transparent;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* 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 TableProps, Table } from '@coze-arch/coze-design';
|
||||
|
||||
import styles from './index.module.less';
|
||||
|
||||
export const AuthTable: FC<
|
||||
TableProps & {
|
||||
size?: 'small' | 'default';
|
||||
type?: 'primary' | 'default';
|
||||
}
|
||||
> = ({
|
||||
wrapperClassName,
|
||||
tableProps,
|
||||
size = 'default',
|
||||
type = 'default',
|
||||
...rest
|
||||
}) => (
|
||||
<Table
|
||||
{...rest}
|
||||
wrapperClassName={cls(styles['table-wrap'], wrapperClassName)}
|
||||
tableProps={{
|
||||
...tableProps,
|
||||
className: cls(
|
||||
styles['table-content'],
|
||||
tableProps?.className,
|
||||
styles[size],
|
||||
styles[type],
|
||||
),
|
||||
}}
|
||||
/>
|
||||
);
|
||||
@@ -0,0 +1,15 @@
|
||||
|
||||
.message-frame {
|
||||
margin-bottom: 24px;
|
||||
padding: 12px 16px;
|
||||
|
||||
font-size: 12px;
|
||||
font-weight: 400;
|
||||
font-style: normal;
|
||||
line-height: 16px;
|
||||
color: var(--coz-fg-primary);
|
||||
|
||||
background: var(--coz-mg-hglt, rgba(186, 192, 255, 20%));
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* 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, type FC } from 'react';
|
||||
|
||||
import classNames from 'classnames';
|
||||
import { I18n } from '@coze-arch/i18n';
|
||||
import { IconCozInfoCircle } from '@coze-arch/coze-design/icons';
|
||||
import { Tooltip, Typography, Space } from '@coze-arch/coze-design';
|
||||
|
||||
import styles from './index.module.less';
|
||||
export const LinkDocs: FC<{ text?: string; onClick?: () => void }> = ({
|
||||
text,
|
||||
onClick,
|
||||
}) => (
|
||||
<Typography.Text
|
||||
className="text-[12px] !font-normal"
|
||||
link
|
||||
onClick={() => {
|
||||
onClick?.();
|
||||
}}
|
||||
>
|
||||
{text ? text : I18n.t('coze_api_instru')}
|
||||
</Typography.Text>
|
||||
);
|
||||
|
||||
export const PATInstructionWrap: FC<{
|
||||
onClick?: () => void;
|
||||
}> = ({ onClick }) => (
|
||||
<div className={styles['message-frame']}>
|
||||
<Space spacing={0}>
|
||||
<p>{I18n.t('pat_reminder_1')}</p>
|
||||
<LinkDocs onClick={onClick} />
|
||||
</Space>
|
||||
<p>{I18n.t('pat_reminder_2')}</p>
|
||||
{IS_OVERSEA ? <p>{I18n.t('api_token_reminder_1')}</p> : null}
|
||||
</div>
|
||||
);
|
||||
|
||||
export const Tips: FC<{ tips: string | ReactNode; className?: string }> = ({
|
||||
tips,
|
||||
className,
|
||||
}) => (
|
||||
<Tooltip theme="dark" trigger="hover" content={tips}>
|
||||
<div
|
||||
className={classNames(
|
||||
'flex items-center justify-center hover:coz-mg-secondary-hovered w-[16px] h-[16px] rounded-[4px] mr-[4px] ml-[2px] text-[12px]',
|
||||
className,
|
||||
)}
|
||||
>
|
||||
<IconCozInfoCircle className="coz-fg-secondary" />
|
||||
</div>
|
||||
</Tooltip>
|
||||
);
|
||||
@@ -0,0 +1,32 @@
|
||||
/* stylelint-disable declaration-no-important */
|
||||
.table-container {
|
||||
overflow: auto;
|
||||
overflow-x: hidden;
|
||||
|
||||
&::-webkit-scrollbar-thumb {
|
||||
background: var(--coz-fg-dim, rgba(6, 7, 9, 30%));
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar {
|
||||
display: block !important;
|
||||
width: 4px;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar:hover {
|
||||
width: 4px;
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar-button {
|
||||
display: none;
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar-track {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar-corner {
|
||||
background-color: transparent;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
* 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 { useRef } from 'react';
|
||||
|
||||
import cls from 'classnames';
|
||||
import { I18n } from '@coze-arch/i18n';
|
||||
import { type ColumnProps } from '@coze-arch/coze-design';
|
||||
import { UIEmpty } from '@coze-arch/bot-semi';
|
||||
import { type PersonalAccessToken } from '@coze-arch/bot-api/pat_permission_api';
|
||||
|
||||
import { useTableHeight } from '@/hooks/use-table-height';
|
||||
import { AuthTable } from '@/components/auth-table';
|
||||
|
||||
import { getTableColumnConf } from './table-column';
|
||||
|
||||
import styles from './index.module.less';
|
||||
export type GetCustomDataConfig = (options: {
|
||||
onEdit: (v: PersonalAccessToken) => void;
|
||||
onDelete: (id: string) => void;
|
||||
}) => ColumnProps<PersonalAccessToken>[];
|
||||
|
||||
interface DataTableProps {
|
||||
loading: boolean;
|
||||
size?: 'small' | 'default';
|
||||
type?: 'primary' | 'default';
|
||||
dataSource: PersonalAccessToken[];
|
||||
onEdit: (v: PersonalAccessToken) => void;
|
||||
onDelete: (id: string) => void;
|
||||
onAddClick: () => void;
|
||||
renderDataEmptySlot?: () => React.ReactElement | null;
|
||||
getCustomDataConfig?: GetCustomDataConfig;
|
||||
}
|
||||
|
||||
export const DataTable = ({
|
||||
loading,
|
||||
dataSource,
|
||||
onEdit,
|
||||
onDelete,
|
||||
onAddClick,
|
||||
renderDataEmptySlot,
|
||||
getCustomDataConfig = getTableColumnConf,
|
||||
size,
|
||||
type,
|
||||
}: DataTableProps) => {
|
||||
const tableRef = useRef<HTMLDivElement>(null);
|
||||
const tableHeight = useTableHeight(tableRef);
|
||||
|
||||
const columns: ColumnProps<PersonalAccessToken>[] = getCustomDataConfig?.({
|
||||
onEdit,
|
||||
onDelete,
|
||||
}).filter(item => !item.hidden);
|
||||
|
||||
return (
|
||||
<div className={cls('flex-1', styles['table-container'])} ref={tableRef}>
|
||||
<AuthTable
|
||||
useHoverStyle={false}
|
||||
size={size}
|
||||
type={type}
|
||||
tableProps={{
|
||||
rowKey: 'id',
|
||||
loading,
|
||||
dataSource,
|
||||
columns,
|
||||
scroll: { y: tableHeight },
|
||||
}}
|
||||
empty={
|
||||
renderDataEmptySlot?.() || (
|
||||
<UIEmpty
|
||||
empty={{
|
||||
title: I18n.t('no_api_token_1'),
|
||||
description: I18n.t('add_api_token_1'),
|
||||
btnText: I18n.t('add_new_token_button_1'),
|
||||
btnOnClick: onAddClick,
|
||||
}}
|
||||
/>
|
||||
)
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* 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 { type ColumnProps } from '@coze-arch/coze-design';
|
||||
import { type PersonalAccessToken } from '@coze-arch/bot-api/pat_permission_api';
|
||||
|
||||
import { getDetailTime } from '@/utils/time';
|
||||
|
||||
export const columnCreateAtConf: () => ColumnProps<PersonalAccessToken> =
|
||||
() => ({
|
||||
title: I18n.t('coze_api_list3'),
|
||||
dataIndex: 'created_at',
|
||||
render: (createTime: number) => getDetailTime(createTime),
|
||||
});
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* 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 { type ColumnProps } from '@coze-arch/coze-design';
|
||||
import { type PersonalAccessToken } from '@coze-arch/bot-api/pat_permission_api';
|
||||
|
||||
import { getExpirationTime } from '@/utils/time';
|
||||
|
||||
export const columnExpireAtConf: () => ColumnProps<PersonalAccessToken> =
|
||||
() => ({
|
||||
title: I18n.t('expire_time_1'), // 状态
|
||||
dataIndex: 'expire_at',
|
||||
render: (expireTime: number) => getExpirationTime(expireTime),
|
||||
});
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* 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 { type ColumnProps } from '@coze-arch/coze-design';
|
||||
import { type PersonalAccessToken } from '@coze-arch/bot-api/pat_permission_api';
|
||||
|
||||
import { getDetailTime } from '@/utils/time';
|
||||
|
||||
export const columnLastUseAtConf: () => ColumnProps<PersonalAccessToken> =
|
||||
() => ({
|
||||
title: I18n.t('coze_api_list4'),
|
||||
dataIndex: 'last_used_at',
|
||||
render: (lastUseTime: number) => getDetailTime(lastUseTime),
|
||||
});
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* 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 { type ColumnProps } from '@coze-arch/coze-design';
|
||||
import { type PersonalAccessToken } from '@coze-arch/bot-api/pat_permission_api';
|
||||
export const columnNameConf: () => ColumnProps<PersonalAccessToken> = () => ({
|
||||
title: I18n.t('coze_api_list1'),
|
||||
dataIndex: 'name',
|
||||
width: 120,
|
||||
render: (name: string) => <p>{name}</p>,
|
||||
});
|
||||
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
* 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 classNames from 'classnames';
|
||||
import { I18n } from '@coze-arch/i18n';
|
||||
import { IconCozMinusCircle, IconCozEdit } from '@coze-arch/coze-design/icons';
|
||||
import { type ColumnProps, Tooltip, Space } from '@coze-arch/coze-design';
|
||||
import { UIButton, Popconfirm } from '@coze-arch/bot-semi';
|
||||
import { type PersonalAccessToken } from '@coze-arch/bot-api/pat_permission_api';
|
||||
|
||||
import { getStatus } from '@/utils/time';
|
||||
|
||||
import styles from './index.module.less';
|
||||
export const ColumnOpBody: FC<{
|
||||
record: PersonalAccessToken;
|
||||
isCurrentUser?: boolean;
|
||||
onEdit: (v: PersonalAccessToken) => void;
|
||||
onDelete: (id: string) => void;
|
||||
afterConfirmDelete?: () => void;
|
||||
afterCancelDelete?: () => void;
|
||||
}> = ({
|
||||
record,
|
||||
isCurrentUser,
|
||||
onEdit,
|
||||
onDelete,
|
||||
afterConfirmDelete,
|
||||
afterCancelDelete,
|
||||
}) => {
|
||||
const isActive = getStatus(record?.expire_at as number);
|
||||
|
||||
return (
|
||||
<Space align="center" spacing={17}>
|
||||
<Tooltip
|
||||
content={
|
||||
isCurrentUser
|
||||
? I18n.t(isActive ? 'Edit' : 'not_support_edit_1')
|
||||
: I18n.t('org_api_pat_edit_reminder')
|
||||
}
|
||||
>
|
||||
<UIButton
|
||||
onClick={() => onEdit(record)}
|
||||
className={classNames(styles['btn-frame'], {
|
||||
[styles['btn-frame-disabled']]: !isActive,
|
||||
})}
|
||||
theme="borderless"
|
||||
icon={<IconCozEdit className={styles.icon} />}
|
||||
disabled={!isActive || !isCurrentUser}
|
||||
></UIButton>
|
||||
</Tooltip>
|
||||
<Popconfirm
|
||||
style={{ width: 400 }}
|
||||
okType="danger"
|
||||
trigger="click"
|
||||
onConfirm={() => {
|
||||
onDelete(`${record?.id}`);
|
||||
afterConfirmDelete?.();
|
||||
}}
|
||||
onCancel={() => {
|
||||
afterCancelDelete?.();
|
||||
}}
|
||||
content={I18n.t('remove_token_1')}
|
||||
title={I18n.t('remove_token_reminder_1')}
|
||||
>
|
||||
<div>
|
||||
<Tooltip content={I18n.t('Remove')}>
|
||||
<UIButton
|
||||
className={styles['btn-frame']}
|
||||
theme="borderless"
|
||||
icon={<IconCozMinusCircle className={styles.icon} />}
|
||||
></UIButton>
|
||||
</Tooltip>
|
||||
</div>
|
||||
</Popconfirm>
|
||||
</Space>
|
||||
);
|
||||
};
|
||||
|
||||
export const columnOpConf: () => ColumnProps<PersonalAccessToken> = () => ({
|
||||
title: I18n.t('coze_api_list5'),
|
||||
width: 120,
|
||||
render: (_: string, _record: unknown) => null,
|
||||
});
|
||||
@@ -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 { I18n } from '@coze-arch/i18n';
|
||||
import { Tag } from '@coze-arch/coze-design';
|
||||
import { type ColumnProps } from '@coze-arch/coze-design';
|
||||
import { type PersonalAccessToken } from '@coze-arch/bot-api/pat_permission_api';
|
||||
|
||||
import { getStatus } from '@/utils/time';
|
||||
|
||||
export const columnStatusConf: () => ColumnProps<PersonalAccessToken> = () => ({
|
||||
title: I18n.t('api_status_1'),
|
||||
dataIndex: 'id',
|
||||
width: 80,
|
||||
render: (_: string, record: PersonalAccessToken) => {
|
||||
const isActive = getStatus(record?.expire_at as number);
|
||||
return (
|
||||
<Tag size="small" color={isActive ? 'primary' : 'grey'}>
|
||||
{I18n.t(isActive ? 'api_status_active_1' : 'api_status_expired_1')}
|
||||
</Tag>
|
||||
);
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,14 @@
|
||||
.btn-frame {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
|
||||
.icon {
|
||||
color: #6b6b75;
|
||||
}
|
||||
|
||||
&.btn-frame-disabled {
|
||||
.icon {
|
||||
color: rgba(29, 28, 35, 20%);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* 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 ColumnProps } from '@coze-arch/coze-design';
|
||||
import { type PersonalAccessToken } from '@coze-arch/bot-api/pat_permission_api';
|
||||
|
||||
import { columnStatusConf } from './column-status';
|
||||
import { ColumnOpBody, columnOpConf } from './column-op';
|
||||
import { columnNameConf } from './column-name';
|
||||
import { columnLastUseAtConf } from './column-last-use-at';
|
||||
import { columnExpireAtConf } from './column-expire-at';
|
||||
import { columnCreateAtConf } from './column-create-at';
|
||||
export const getTableColumnConf = ({
|
||||
onEdit,
|
||||
onDelete,
|
||||
}: {
|
||||
onEdit: (v: PersonalAccessToken) => void;
|
||||
onDelete: (id: string) => void;
|
||||
}): ColumnProps<PersonalAccessToken>[] => [
|
||||
columnNameConf(),
|
||||
columnCreateAtConf(),
|
||||
columnLastUseAtConf(),
|
||||
columnExpireAtConf(),
|
||||
columnStatusConf(),
|
||||
{
|
||||
...columnOpConf(),
|
||||
render: (_, record) => (
|
||||
<ColumnOpBody {...{ record, isCurrentUser: true, onEdit, onDelete }} />
|
||||
),
|
||||
},
|
||||
];
|
||||
|
||||
export const patColumn = {
|
||||
columnNameConf,
|
||||
columnCreateAtConf,
|
||||
columnLastUseAtConf,
|
||||
columnExpireAtConf,
|
||||
columnStatusConf,
|
||||
ColumnOpBody,
|
||||
columnOpConf,
|
||||
};
|
||||
@@ -0,0 +1,104 @@
|
||||
/*
|
||||
* 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 { useEffect } from 'react';
|
||||
|
||||
import { type FetchCustomPatList } from '@/hooks/pat/use-token';
|
||||
import { usePatOperation } from '@/hooks/pat/action/use-pat-operation';
|
||||
|
||||
import { TopBody } from './top-body';
|
||||
import { ResultModal } from './result-modal';
|
||||
import { PermissionModal, type PermissionModalProps } from './permission-modal';
|
||||
import { DataTable, type GetCustomDataConfig } from './data-table';
|
||||
export interface PATProps {
|
||||
size?: 'small' | 'default';
|
||||
type?: 'primary' | 'default';
|
||||
renderTopBodySlot?: (options: {
|
||||
openAddModal: () => void;
|
||||
}) => React.ReactNode;
|
||||
renderDataEmptySlot?: () => React.ReactElement | null;
|
||||
getCustomDataConfig?: GetCustomDataConfig;
|
||||
fetchCustomPatList?: FetchCustomPatList;
|
||||
renderPermissionModal?: (options: PermissionModalProps) => void;
|
||||
afterCancelPermissionModal?: (isCreate: boolean) => void;
|
||||
}
|
||||
export const PatBody: React.FC<PATProps> = ({
|
||||
size,
|
||||
type,
|
||||
renderTopBodySlot,
|
||||
renderDataEmptySlot,
|
||||
getCustomDataConfig,
|
||||
fetchCustomPatList,
|
||||
renderPermissionModal,
|
||||
afterCancelPermissionModal,
|
||||
}) => {
|
||||
const {
|
||||
onAddClick,
|
||||
loading,
|
||||
dataSource,
|
||||
editHandle,
|
||||
runDelete,
|
||||
refreshHandle,
|
||||
showDataForm,
|
||||
isCreate,
|
||||
createSuccessHandle,
|
||||
onCancel,
|
||||
successData,
|
||||
showResult,
|
||||
setShowResult,
|
||||
editInfo,
|
||||
fetchData,
|
||||
} = usePatOperation({ fetchCustomPatList, afterCancelPermissionModal });
|
||||
|
||||
useEffect(() => {
|
||||
fetchData();
|
||||
}, []);
|
||||
const permissionModalOptions = {
|
||||
isCreate,
|
||||
onRefresh: refreshHandle,
|
||||
editInfo,
|
||||
onCreateSuccess: createSuccessHandle,
|
||||
onCancel,
|
||||
};
|
||||
return (
|
||||
<div className="w-full h-full flex flex-col">
|
||||
{renderTopBodySlot?.({ openAddModal: onAddClick }) || (
|
||||
<TopBody openAddModal={onAddClick} />
|
||||
)}
|
||||
<DataTable
|
||||
size={size}
|
||||
type={type}
|
||||
loading={loading}
|
||||
dataSource={dataSource}
|
||||
onEdit={editHandle}
|
||||
onDelete={runDelete}
|
||||
onAddClick={onAddClick}
|
||||
renderDataEmptySlot={renderDataEmptySlot}
|
||||
getCustomDataConfig={getCustomDataConfig}
|
||||
/>
|
||||
{showDataForm
|
||||
? renderPermissionModal?.(permissionModalOptions) || (
|
||||
<PermissionModal {...permissionModalOptions} />
|
||||
)
|
||||
: null}
|
||||
<ResultModal
|
||||
data={successData}
|
||||
visible={showResult}
|
||||
onOk={() => setShowResult(false)}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,11 @@
|
||||
.expiration-select {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
|
||||
:global {
|
||||
.semi-form-field {
|
||||
width: 100%;
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
/*
|
||||
* 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 { I18n } from '@coze-arch/i18n';
|
||||
import { Form, Input } from '@coze-arch/coze-design';
|
||||
import { type GetPersonalAccessTokenAndPermissionResponseData } from '@coze-arch/bot-api/pat_permission_api';
|
||||
|
||||
import {
|
||||
ExpirationDate,
|
||||
disabledDate,
|
||||
getExpirationOptions,
|
||||
getExpirationTime,
|
||||
} from '@/utils/time';
|
||||
import { Tips } from '@/components/instructions-wrap';
|
||||
|
||||
import styles from './index.module.less';
|
||||
|
||||
export const CommonFormParams: FC<{
|
||||
isCreate?: boolean;
|
||||
patPermission?: GetPersonalAccessTokenAndPermissionResponseData;
|
||||
}> = ({ isCreate, patPermission }) => {
|
||||
const [durationDay, setDurationDay] = useState<ExpirationDate>();
|
||||
const dataOptionsList = getExpirationOptions();
|
||||
|
||||
return (
|
||||
<>
|
||||
<Form.Input
|
||||
trigger={['blur', 'change']}
|
||||
field="name"
|
||||
label={{
|
||||
text: I18n.t('coze_api_list1'),
|
||||
required: true,
|
||||
}}
|
||||
placeholder={''}
|
||||
maxLength={20}
|
||||
rules={[{ required: true, message: '' }]}
|
||||
/>
|
||||
<Form.Slot
|
||||
label={{
|
||||
text: I18n.t('expire_time_1'),
|
||||
required: true,
|
||||
extra: <Tips tips={I18n.t('expired_time_forbidden_1')} />,
|
||||
}}
|
||||
>
|
||||
{isCreate ? (
|
||||
<>
|
||||
<div className={styles['expiration-select']}>
|
||||
<Form.Select
|
||||
noLabel={true}
|
||||
field="duration_day"
|
||||
style={{ width: '100%' }}
|
||||
disabled={!isCreate}
|
||||
optionList={dataOptionsList}
|
||||
onChange={v => setDurationDay(v as ExpirationDate)}
|
||||
rules={[{ required: true, message: '' }]}
|
||||
placeholder={I18n.t('select_expired_time_1')}
|
||||
/>
|
||||
|
||||
{durationDay === ExpirationDate.CUSTOMIZE && (
|
||||
<Form.DatePicker
|
||||
noLabel={true}
|
||||
field="expire_at"
|
||||
style={{ width: '100%' }}
|
||||
disabled={!isCreate}
|
||||
disabledDate={disabledDate}
|
||||
position="bottomRight"
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</>
|
||||
) : (
|
||||
<Input
|
||||
disabled
|
||||
value={
|
||||
patPermission?.personal_access_token?.expire_at
|
||||
? getExpirationTime(
|
||||
patPermission?.personal_access_token?.expire_at as number,
|
||||
)
|
||||
: ''
|
||||
}
|
||||
/>
|
||||
)}
|
||||
</Form.Slot>
|
||||
</>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,72 @@
|
||||
.permission-form-content {
|
||||
overflow-y: auto;
|
||||
|
||||
width: 417px;
|
||||
max-height: 522px;
|
||||
margin-top: 16px;
|
||||
margin-right: -11px;
|
||||
padding-right: 8px;
|
||||
.scroll-wrap;
|
||||
|
||||
:global {
|
||||
/* stylelint-disable-next-line no-descending-specificity */
|
||||
.semi-form-field {
|
||||
padding: 0;
|
||||
padding-bottom: 16px;
|
||||
}
|
||||
|
||||
.semi-form-field-label {
|
||||
margin-bottom: 6px;
|
||||
padding: 0 8px;
|
||||
|
||||
font-size: 12px;
|
||||
font-weight: 500;
|
||||
font-style: normal;
|
||||
line-height: 16px;
|
||||
color: var(--coz-fg-primary);
|
||||
}
|
||||
|
||||
.semi-form-field-error-message {
|
||||
padding-left: 8px;
|
||||
}
|
||||
|
||||
.semi-form-field-main {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.semi-form-field-label-required .semi-form-field-label-text::after,
|
||||
.semi-form-field-label-with-extra .semi-form-field-label-extra {
|
||||
margin-left: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.scroll-wrap {
|
||||
&::-webkit-scrollbar-thumb {
|
||||
background: var(--coz-fg-dim, rgba(6, 7, 9, 30%));
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar {
|
||||
// stylelint-disable-next-line declaration-no-important
|
||||
display: block !important;
|
||||
width: 4px;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar:hover {
|
||||
width: 4px;
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar-button {
|
||||
display: none;
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar-track {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar-corner {
|
||||
background-color: transparent;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,174 @@
|
||||
/*
|
||||
* 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 {
|
||||
forwardRef,
|
||||
type PropsWithChildren,
|
||||
useEffect,
|
||||
useImperativeHandle,
|
||||
useRef,
|
||||
} from 'react';
|
||||
|
||||
import { I18n } from '@coze-arch/i18n';
|
||||
import {
|
||||
type PersonalAccessToken,
|
||||
type CreatePersonalAccessTokenAndPermissionResponseData,
|
||||
type GetPersonalAccessTokenAndPermissionResponseData,
|
||||
} from '@coze-arch/bot-api/pat_permission_api';
|
||||
import { Form, type FormApi, Modal, Spin, Toast } from '@coze-arch/coze-design';
|
||||
|
||||
import { usePatForm, type FormApiInfo } from '@/hooks/pat/action/use-pat-form';
|
||||
|
||||
import { CommonFormParams } from './common-form-params';
|
||||
|
||||
import styles from './index.module.less';
|
||||
|
||||
export interface PermissionModalProps {
|
||||
editInfo?: PersonalAccessToken;
|
||||
isCreate: boolean;
|
||||
isReady?: boolean;
|
||||
onRefresh: () => void;
|
||||
onCreateSuccess: (
|
||||
v: CreatePersonalAccessTokenAndPermissionResponseData,
|
||||
) => void;
|
||||
onCancel: () => void;
|
||||
onPatPermissionChange?: (
|
||||
data?: GetPersonalAccessTokenAndPermissionResponseData,
|
||||
) => void;
|
||||
onCustomFormValueChange?: (values: unknown, changedValue: unknown) => void;
|
||||
validateCustomParams?: () => boolean;
|
||||
getCustomParams?: () => Record<string, unknown>;
|
||||
afterSubmit?: (params: Record<string, unknown>) => void;
|
||||
isShowAuthMigrateNotice?: boolean;
|
||||
}
|
||||
|
||||
export interface PermissionModalRef {
|
||||
setFormValue: (key: string, value: unknown) => void;
|
||||
validateParams: () => void;
|
||||
getFormValues: () => Record<string, unknown>;
|
||||
}
|
||||
|
||||
export const PermissionModal = forwardRef(function PermissionModal(
|
||||
{
|
||||
editInfo,
|
||||
isCreate,
|
||||
onRefresh,
|
||||
onCreateSuccess,
|
||||
onCancel,
|
||||
children,
|
||||
onPatPermissionChange,
|
||||
onCustomFormValueChange,
|
||||
validateCustomParams,
|
||||
getCustomParams,
|
||||
afterSubmit,
|
||||
isReady = true,
|
||||
isShowAuthMigrateNotice = false,
|
||||
}: PropsWithChildren<PermissionModalProps>,
|
||||
ref,
|
||||
) {
|
||||
const formApi = useRef<FormApi<FormApiInfo>>();
|
||||
const {
|
||||
isFailToValid,
|
||||
ready,
|
||||
loading,
|
||||
onSubmit,
|
||||
onFormValueChange,
|
||||
patPermission,
|
||||
successData,
|
||||
updateSuccessData,
|
||||
validateParams,
|
||||
} = usePatForm({
|
||||
editInfo,
|
||||
isCreate,
|
||||
formApi,
|
||||
validateCustomParams,
|
||||
getCustomParams,
|
||||
afterSubmit,
|
||||
isShowAuthMigrateNotice,
|
||||
});
|
||||
const modalReady = isReady && ready;
|
||||
|
||||
useEffect(() => {
|
||||
if (successData) {
|
||||
Toast.success({ content: I18n.t('Create_success'), showClose: false });
|
||||
onCreateSuccess(successData);
|
||||
onRefresh();
|
||||
}
|
||||
}, [successData]);
|
||||
|
||||
useEffect(() => {
|
||||
if (updateSuccessData) {
|
||||
Toast.success({ content: I18n.t('Edit_success'), showClose: false });
|
||||
onRefresh();
|
||||
}
|
||||
}, [updateSuccessData]);
|
||||
|
||||
useImperativeHandle(
|
||||
ref,
|
||||
() => ({
|
||||
setFormValue: (key: string, value: unknown) => {
|
||||
formApi.current?.setValue(key as keyof FormApiInfo, value);
|
||||
},
|
||||
getFormValues: () => formApi.current?.getValues(),
|
||||
validateParams,
|
||||
}),
|
||||
[validateParams],
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
onPatPermissionChange?.(patPermission);
|
||||
}, [patPermission]);
|
||||
|
||||
return (
|
||||
<Modal
|
||||
title={isCreate ? I18n.t('add_new_pat_1') : I18n.t('edit_pat_1')}
|
||||
visible={true}
|
||||
width={480}
|
||||
centered
|
||||
maskClosable={false}
|
||||
onCancel={onCancel}
|
||||
onOk={onSubmit}
|
||||
okButtonProps={{
|
||||
disabled: isFailToValid || !modalReady,
|
||||
loading,
|
||||
}}
|
||||
cancelText={I18n.t('cancel')}
|
||||
okText={I18n.t('confirm')}
|
||||
>
|
||||
<Spin spinning={!modalReady}>
|
||||
<div className={styles['permission-form-content']}>
|
||||
<Form<FormApiInfo>
|
||||
showValidateIcon={false}
|
||||
getFormApi={api => (formApi.current = api)}
|
||||
onValueChange={(values, changedValue) => {
|
||||
if (onCustomFormValueChange) {
|
||||
onCustomFormValueChange(values, changedValue);
|
||||
} else {
|
||||
onFormValueChange(values, changedValue as FormApiInfo);
|
||||
}
|
||||
}}
|
||||
>
|
||||
<CommonFormParams
|
||||
isCreate={isCreate}
|
||||
patPermission={patPermission}
|
||||
/>
|
||||
{children}
|
||||
</Form>
|
||||
</div>
|
||||
</Spin>
|
||||
</Modal>
|
||||
);
|
||||
});
|
||||
@@ -0,0 +1,66 @@
|
||||
.result-frame {
|
||||
:global {
|
||||
.semi-modal-body {
|
||||
// stylelint-disable-next-line declaration-no-important
|
||||
padding: 0 !important;
|
||||
}
|
||||
}
|
||||
|
||||
.warn-text {
|
||||
margin-bottom: 32px;
|
||||
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
line-height: 22px;
|
||||
color: var(--Light-usage-text---color-text-0, #1d1c23);
|
||||
}
|
||||
|
||||
.title-text {
|
||||
margin-bottom: 8px;
|
||||
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
line-height: 22px;
|
||||
color: var(--Light-usage-text---color-text-0, #1d1c23);
|
||||
}
|
||||
|
||||
.para {
|
||||
overflow: hidden;
|
||||
|
||||
max-width: 90%;
|
||||
margin-bottom: 36px;
|
||||
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
line-height: 22px;
|
||||
color: var(--Light-usage-text---color-text-0, #1d1c23);
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.key-text {
|
||||
overflow: hidden;
|
||||
|
||||
max-width: 487px;
|
||||
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
line-height: 22px;
|
||||
color: var(--Light-usage-text---color-text-0, #1d1c23);
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.sp {
|
||||
width: 100%;
|
||||
margin-bottom: 44px;
|
||||
|
||||
.icon {
|
||||
cursor: pointer;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
|
||||
svg {
|
||||
color: rgba(77, 83, 232, 100%);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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 copy from 'copy-to-clipboard';
|
||||
import { useMemoizedFn } from 'ahooks';
|
||||
import { I18n } from '@coze-arch/i18n';
|
||||
import { IconCozCopy } from '@coze-arch/coze-design/icons';
|
||||
import {
|
||||
UIModal,
|
||||
Typography,
|
||||
Toast,
|
||||
Space,
|
||||
Tooltip,
|
||||
} from '@coze-arch/bot-semi';
|
||||
import { type CreatePersonalAccessTokenAndPermissionResponseData } from '@coze-arch/bot-api/pat_permission_api';
|
||||
|
||||
import { getExpirationTime } from '@/utils/time';
|
||||
|
||||
import s from './index.module.less';
|
||||
|
||||
interface ResultProps {
|
||||
data?: CreatePersonalAccessTokenAndPermissionResponseData;
|
||||
visible: boolean;
|
||||
onOk: () => void;
|
||||
}
|
||||
|
||||
// 新建编辑 PAT
|
||||
export const ResultModal = ({ visible, onOk, data }: ResultProps) => {
|
||||
const doCopyAsync = useMemoizedFn(() => {
|
||||
const targetKey = data?.token;
|
||||
if (targetKey) {
|
||||
doCopy(targetKey);
|
||||
}
|
||||
});
|
||||
|
||||
const doCopy = useMemoizedFn(targetText => {
|
||||
const res = copy(targetText);
|
||||
if (!res) {
|
||||
throw new Error('custom error');
|
||||
}
|
||||
Toast.success({
|
||||
content: I18n.t('token_copied_1'),
|
||||
showClose: false,
|
||||
});
|
||||
});
|
||||
return (
|
||||
<UIModal
|
||||
className={s['result-frame']}
|
||||
title={I18n.t('new_pat_1')}
|
||||
visible={visible}
|
||||
width={560}
|
||||
centered
|
||||
onOk={onOk}
|
||||
onCancel={onOk}
|
||||
okText={I18n.t('confirm')}
|
||||
footer={null}
|
||||
>
|
||||
<p className={s['warn-text']}>{I18n.t('new_pat_reminder_1')}</p>
|
||||
<p className={s['title-text']}>{I18n.t('coze_api_list1')}</p>
|
||||
<Typography.Paragraph className={s.para} ellipsis={{ rows: 1 }}>
|
||||
{data?.personal_access_token?.name ?? '-'}
|
||||
</Typography.Paragraph>
|
||||
<p className={s['title-text']}>{I18n.t('expire_time_1')}</p>
|
||||
<Typography.Paragraph className={s.para} ellipsis={{ rows: 1 }}>
|
||||
{getExpirationTime(data?.personal_access_token.expire_at as number)}
|
||||
</Typography.Paragraph>
|
||||
<p className={s['title-text']}>{I18n.t('token_key_1')}</p>
|
||||
<Space spacing={4} className={s.sp}>
|
||||
<Typography.Paragraph className={s['key-text']} ellipsis={{ rows: 1 }}>
|
||||
{data?.token}
|
||||
</Typography.Paragraph>
|
||||
<Tooltip content={I18n.t('Copy')}>
|
||||
<IconCozCopy className={s.icon} onClick={doCopyAsync} />
|
||||
</Tooltip>
|
||||
</Space>
|
||||
</UIModal>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* 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 { I18n } from '@coze-arch/i18n';
|
||||
import { Button, Space } from '@coze-arch/coze-design';
|
||||
|
||||
import { PATInstructionWrap } from '@/components/instructions-wrap';
|
||||
|
||||
export const TopBody: FC<{
|
||||
openAddModal: () => void;
|
||||
}> = ({ openAddModal }) => (
|
||||
<Space vertical spacing={20}>
|
||||
<Space className="w-full">
|
||||
<h3 className="flex-1 m-0">{I18n.t('auth_tab_pat')}</h3>
|
||||
<Button onClick={openAddModal} theme="solid" type="primary">
|
||||
{I18n.t('add_new_token_button_1')}
|
||||
</Button>
|
||||
</Space>
|
||||
<div className="w-full">
|
||||
<PATInstructionWrap
|
||||
onClick={() => {
|
||||
window.open(
|
||||
IS_OVERSEA
|
||||
? // cp-disable-next-line
|
||||
'https://www.coze.com/open/docs/developer_guides/coze_api_overview'
|
||||
: // cp-disable-next-line
|
||||
'https://www.coze.cn/open/docs/developer_guides/coze_api_overview',
|
||||
);
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</Space>
|
||||
);
|
||||
@@ -0,0 +1,177 @@
|
||||
/*
|
||||
* 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 { useEffect, useState } from 'react';
|
||||
|
||||
import { I18n } from '@coze-arch/i18n';
|
||||
import { type PersonalAccessToken } from '@coze-arch/bot-api/pat_permission_api';
|
||||
import { Modal, type FormApi } from '@coze-arch/coze-design';
|
||||
|
||||
import { ExpirationDate, getExpireAt } from '@/utils/time';
|
||||
import {
|
||||
usePATPermission,
|
||||
useCreatePAT,
|
||||
useUpdatePAT,
|
||||
} from '@/hooks/pat/use-token';
|
||||
|
||||
export interface FormApiInfo {
|
||||
name: string;
|
||||
duration_day: ExpirationDate;
|
||||
|
||||
expire_at: Date;
|
||||
}
|
||||
|
||||
interface PatFormProps {
|
||||
editInfo?: PersonalAccessToken;
|
||||
isCreate: boolean;
|
||||
isShowAuthMigrateNotice?: boolean;
|
||||
formApi: React.MutableRefObject<FormApi<FormApiInfo> | undefined>;
|
||||
validateCustomParams?: () => boolean;
|
||||
getCustomParams?: () => Record<string, unknown>;
|
||||
afterSubmit?: (params: Record<string, unknown>) => void;
|
||||
}
|
||||
|
||||
const getDurationData = (durationDay: ExpirationDate, expireAt: Date) => ({
|
||||
duration_day: durationDay,
|
||||
...(durationDay === ExpirationDate.CUSTOMIZE
|
||||
? { expire_at: getExpireAt(expireAt as Date) }
|
||||
: {}),
|
||||
});
|
||||
|
||||
const validateName = (name?: string) => Boolean(name);
|
||||
const validateDuration = (durationDay?: ExpirationDate, expireAt?: Date) => {
|
||||
if (!durationDay) {
|
||||
return false;
|
||||
}
|
||||
if (durationDay === ExpirationDate.CUSTOMIZE && !expireAt) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
const authMigrateNoticeLSKey = 'auth_migrate_notice_do_not_show_again';
|
||||
|
||||
const useAuthMigrateNotice = (isShowAuthMigrateNotice?: boolean) => {
|
||||
useEffect(() => {
|
||||
if (!isShowAuthMigrateNotice) {
|
||||
return;
|
||||
}
|
||||
if (!localStorage.getItem(authMigrateNoticeLSKey)) {
|
||||
Modal.info({
|
||||
title: I18n.t('api_permissionkey_notification_title'),
|
||||
content: I18n.t('api_permissionkey_notification_content'),
|
||||
okText: I18n.t('got_it'),
|
||||
onOk: () => {
|
||||
localStorage.setItem(authMigrateNoticeLSKey, 'true');
|
||||
},
|
||||
showCancelButton: false,
|
||||
closable: false,
|
||||
maskClosable: false,
|
||||
});
|
||||
}
|
||||
}, []);
|
||||
};
|
||||
|
||||
export const usePatForm = ({
|
||||
editInfo,
|
||||
isCreate,
|
||||
formApi,
|
||||
getCustomParams,
|
||||
validateCustomParams,
|
||||
afterSubmit,
|
||||
isShowAuthMigrateNotice,
|
||||
}: PatFormProps) => {
|
||||
const { patPermission } = usePATPermission({
|
||||
patId: editInfo?.id,
|
||||
});
|
||||
|
||||
const { loading: createLoading, runCreate, successData } = useCreatePAT();
|
||||
const {
|
||||
loading: updateLoading,
|
||||
runUpdate,
|
||||
updateSuccessData,
|
||||
} = useUpdatePAT();
|
||||
|
||||
const [isFailToValid, setIsFailToValid] = useState(true);
|
||||
|
||||
const onSubmit = () => {
|
||||
const {
|
||||
name = '',
|
||||
duration_day,
|
||||
expire_at,
|
||||
} = formApi.current?.getValues() || {};
|
||||
|
||||
const params = {
|
||||
name,
|
||||
...(getCustomParams?.() || {}),
|
||||
};
|
||||
if (isCreate) {
|
||||
runCreate({
|
||||
...params,
|
||||
...getDurationData(duration_day as ExpirationDate, expire_at as Date),
|
||||
});
|
||||
} else {
|
||||
runUpdate({ ...params, id: editInfo?.id ?? '' });
|
||||
}
|
||||
afterSubmit?.({ ...params, duration_day, expire_at });
|
||||
};
|
||||
|
||||
const validateParams = () => {
|
||||
const { name, duration_day, expire_at } =
|
||||
formApi.current?.getValues() || {};
|
||||
|
||||
const nameValid = validateName(name);
|
||||
const isCustomParamsValid = validateCustomParams?.() !== false;
|
||||
const durationValid = isCreate
|
||||
? validateDuration(duration_day, expire_at)
|
||||
: true;
|
||||
setIsFailToValid(!(nameValid && isCustomParamsValid && durationValid));
|
||||
};
|
||||
|
||||
const onFormValueChange = (
|
||||
_values: FormApiInfo,
|
||||
_changedValue: FormApiInfo,
|
||||
) => {
|
||||
validateParams();
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (isCreate) {
|
||||
formApi.current?.setValue('name', 'Secret token');
|
||||
} else if (patPermission && patPermission?.personal_access_token?.name) {
|
||||
formApi.current?.setValue(
|
||||
'name',
|
||||
patPermission?.personal_access_token?.name,
|
||||
);
|
||||
}
|
||||
}, [patPermission]);
|
||||
|
||||
const ready = isCreate ? true : !!patPermission;
|
||||
|
||||
useAuthMigrateNotice(isShowAuthMigrateNotice);
|
||||
|
||||
return {
|
||||
isFailToValid,
|
||||
ready,
|
||||
loading: updateLoading || createLoading,
|
||||
onSubmit,
|
||||
onFormValueChange,
|
||||
patPermission,
|
||||
validateParams,
|
||||
successData,
|
||||
updateSuccessData,
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
* 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 { I18n } from '@coze-arch/i18n';
|
||||
import { Toast } from '@coze-arch/coze-design';
|
||||
import {
|
||||
type CreatePersonalAccessTokenAndPermissionResponseData,
|
||||
type PersonalAccessToken,
|
||||
} from '@coze-arch/bot-api/pat_permission_api';
|
||||
|
||||
import {
|
||||
useDeletePAT,
|
||||
useGetPATList,
|
||||
type FetchCustomPatList,
|
||||
} from '../use-token';
|
||||
export const usePatOperation = ({
|
||||
fetchCustomPatList,
|
||||
afterCancelPermissionModal,
|
||||
}: {
|
||||
fetchCustomPatList?: FetchCustomPatList;
|
||||
afterCancelPermissionModal?: (isCreate: boolean) => void;
|
||||
}) => {
|
||||
const { loading, dataSource, fetchData } = useGetPATList({
|
||||
fetchCustomPatList,
|
||||
});
|
||||
const { runDelete } = useDeletePAT({
|
||||
successHandle: () => {
|
||||
Toast.success({ content: I18n.t('Delete_success'), showClose: false });
|
||||
fetchData();
|
||||
},
|
||||
});
|
||||
const [showDataForm, setShowDataForm] = useState(false);
|
||||
const [showResult, setShowResult] = useState(false);
|
||||
const [isCreate, setIsCreate] = useState(true);
|
||||
const [editInfo, setEditInfo] = useState<PersonalAccessToken>();
|
||||
const [successData, setSuccessData] =
|
||||
useState<CreatePersonalAccessTokenAndPermissionResponseData>();
|
||||
const onAddClick = () => {
|
||||
setIsCreate(true);
|
||||
setShowDataForm(true);
|
||||
};
|
||||
const editHandle = (v: PersonalAccessToken) => {
|
||||
setEditInfo(v);
|
||||
setIsCreate(false);
|
||||
setShowDataForm(true);
|
||||
};
|
||||
const onCancel = () => {
|
||||
setShowDataForm(false);
|
||||
setEditInfo(undefined);
|
||||
afterCancelPermissionModal?.(isCreate);
|
||||
};
|
||||
|
||||
const createSuccessHandle = (
|
||||
data: CreatePersonalAccessTokenAndPermissionResponseData,
|
||||
) => {
|
||||
setSuccessData(data);
|
||||
setEditInfo(undefined);
|
||||
setShowResult(true);
|
||||
};
|
||||
const refreshHandle = () => {
|
||||
fetchData();
|
||||
setShowDataForm(false);
|
||||
setEditInfo(undefined);
|
||||
};
|
||||
return {
|
||||
dataSource,
|
||||
loading,
|
||||
showDataForm,
|
||||
setShowDataForm,
|
||||
isCreate,
|
||||
editInfo,
|
||||
successData,
|
||||
onAddClick,
|
||||
createSuccessHandle,
|
||||
refreshHandle,
|
||||
editHandle,
|
||||
runDelete,
|
||||
onCancel,
|
||||
setIsCreate,
|
||||
showResult,
|
||||
setShowResult,
|
||||
fetchData,
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,236 @@
|
||||
/*
|
||||
* 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 { useEffect, useState } from 'react';
|
||||
|
||||
import { useMemoizedFn, useRequest } from 'ahooks';
|
||||
import { REPORT_EVENTS } from '@coze-arch/report-events';
|
||||
import { reporter } from '@coze-arch/logger';
|
||||
import {
|
||||
type PersonalAccessToken,
|
||||
type CreatePersonalAccessTokenAndPermissionRequest,
|
||||
type UpdatePersonalAccessTokenAndPermissionRequest,
|
||||
type CreatePersonalAccessTokenAndPermissionResponseData,
|
||||
type GetPersonalAccessTokenAndPermissionResponseData,
|
||||
type ListPersonalAccessTokensResponse2,
|
||||
} from '@coze-arch/bot-api/pat_permission_api';
|
||||
import { patPermissionApi } from '@coze-arch/bot-api';
|
||||
|
||||
export type FetchCustomPatList =
|
||||
() => Promise<ListPersonalAccessTokensResponse2>;
|
||||
export const useGetPATList = ({
|
||||
fetchCustomPatList,
|
||||
}: {
|
||||
fetchCustomPatList?: FetchCustomPatList;
|
||||
}) => {
|
||||
const [dataSource, setDataSource] = useState<PersonalAccessToken[]>([]);
|
||||
const fetchPatList = useMemoizedFn(() => {
|
||||
if (fetchCustomPatList) {
|
||||
return fetchCustomPatList();
|
||||
}
|
||||
return patPermissionApi.ListPersonalAccessTokens({});
|
||||
});
|
||||
const { loading, run: fetchData } = useRequest(fetchPatList, {
|
||||
manual: true,
|
||||
onSuccess: dataSourceData => {
|
||||
setDataSource(dataSourceData?.data?.personal_access_tokens);
|
||||
reporter.event({
|
||||
eventName: REPORT_EVENTS.openGetPatList,
|
||||
meta: {
|
||||
level: 'success',
|
||||
action: 'ListPersonalAccessTokens',
|
||||
},
|
||||
});
|
||||
},
|
||||
onError: error => {
|
||||
reporter.errorEvent({
|
||||
eventName: REPORT_EVENTS.openGetPatList,
|
||||
error,
|
||||
meta: {
|
||||
action: 'ListPersonalAccessTokens',
|
||||
},
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
return {
|
||||
dataSource,
|
||||
loading,
|
||||
fetchData,
|
||||
};
|
||||
};
|
||||
|
||||
export const useCreatePAT = () => {
|
||||
const [successData, setSuccessData] =
|
||||
useState<CreatePersonalAccessTokenAndPermissionResponseData>();
|
||||
const { loading, run: runCreate } = useRequest(
|
||||
(info: CreatePersonalAccessTokenAndPermissionRequest) =>
|
||||
patPermissionApi.CreatePersonalAccessTokenAndPermission(info),
|
||||
{
|
||||
manual: true,
|
||||
onSuccess: dataSourceData => {
|
||||
setSuccessData(dataSourceData?.data);
|
||||
reporter.event({
|
||||
eventName: REPORT_EVENTS.openPatAction,
|
||||
meta: {
|
||||
level: 'success',
|
||||
action: 'CreatePersonalAccessTokenAndPermission',
|
||||
},
|
||||
});
|
||||
},
|
||||
onError: error => {
|
||||
reporter.errorEvent({
|
||||
eventName: REPORT_EVENTS.openPatAction,
|
||||
error,
|
||||
meta: {
|
||||
action: 'CreatePersonalAccessTokenAndPermission',
|
||||
},
|
||||
});
|
||||
},
|
||||
},
|
||||
);
|
||||
return {
|
||||
runCreate,
|
||||
loading,
|
||||
successData,
|
||||
};
|
||||
};
|
||||
|
||||
export const useUpdatePAT = (
|
||||
handle: {
|
||||
successHandle?: () => void;
|
||||
} = {},
|
||||
) => {
|
||||
const {
|
||||
loading,
|
||||
run: runUpdate,
|
||||
data: updateSuccessData,
|
||||
} = useRequest(
|
||||
(info: UpdatePersonalAccessTokenAndPermissionRequest) =>
|
||||
patPermissionApi.UpdatePersonalAccessTokenAndPermission(info),
|
||||
{
|
||||
manual: true,
|
||||
onSuccess: () => {
|
||||
handle?.successHandle?.();
|
||||
reporter.event({
|
||||
eventName: REPORT_EVENTS.openPatAction,
|
||||
meta: {
|
||||
level: 'success',
|
||||
action: 'UpdatePersonalAccessTokenAndPermission',
|
||||
},
|
||||
});
|
||||
},
|
||||
onError: error => {
|
||||
reporter.errorEvent({
|
||||
eventName: REPORT_EVENTS.openPatAction,
|
||||
error,
|
||||
meta: {
|
||||
action: 'UpdatePersonalAccessTokenAndPermission',
|
||||
},
|
||||
});
|
||||
},
|
||||
},
|
||||
);
|
||||
return {
|
||||
runUpdate,
|
||||
loading,
|
||||
updateSuccessData,
|
||||
};
|
||||
};
|
||||
|
||||
export const useDeletePAT = ({
|
||||
successHandle,
|
||||
}: {
|
||||
successHandle: () => void;
|
||||
}) => {
|
||||
const { loading, runAsync } = useRequest(
|
||||
(id: string) =>
|
||||
patPermissionApi.DeletePersonalAccessTokenAndPermission({ id }),
|
||||
{
|
||||
manual: true,
|
||||
},
|
||||
);
|
||||
const runDelete = async (id: string) => {
|
||||
try {
|
||||
await runAsync(id);
|
||||
successHandle();
|
||||
reporter.event({
|
||||
eventName: REPORT_EVENTS.openPatAction,
|
||||
meta: {
|
||||
level: 'success',
|
||||
action: 'DeletePersonalAccessTokenAndPermission',
|
||||
},
|
||||
});
|
||||
} catch (error) {
|
||||
reporter.errorEvent({
|
||||
eventName: REPORT_EVENTS.openPatAction,
|
||||
error: error as Error,
|
||||
meta: {
|
||||
action: 'DeletePersonalAccessTokenAndPermission',
|
||||
},
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
runDelete,
|
||||
loading,
|
||||
};
|
||||
};
|
||||
export const usePATPermission = ({ patId }: { patId?: string }) => {
|
||||
const [patPermission, setPatPermission] =
|
||||
useState<GetPersonalAccessTokenAndPermissionResponseData>();
|
||||
|
||||
const { error: detailError, run } = useRequest(
|
||||
(id: string) =>
|
||||
patPermissionApi.GetPersonalAccessTokenAndPermission({ id }),
|
||||
{
|
||||
manual: true,
|
||||
onSuccess: dataSourceData => {
|
||||
setPatPermission(dataSourceData.data);
|
||||
|
||||
reporter.event({
|
||||
eventName: REPORT_EVENTS.openGetPatList,
|
||||
meta: {
|
||||
level: 'success',
|
||||
action: 'GetPersonalAccessTokenAndPermission',
|
||||
},
|
||||
});
|
||||
},
|
||||
onError: error => {
|
||||
reporter.errorEvent({
|
||||
eventName: REPORT_EVENTS.openGetPatList,
|
||||
error,
|
||||
meta: {
|
||||
action: 'GetPersonalAccessTokenAndPermission',
|
||||
},
|
||||
});
|
||||
},
|
||||
},
|
||||
);
|
||||
useEffect(() => {
|
||||
if (patId) {
|
||||
run(patId);
|
||||
} else {
|
||||
setPatPermission(undefined);
|
||||
}
|
||||
}, [patId]);
|
||||
|
||||
return {
|
||||
patPermission,
|
||||
detailError,
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* 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, useEffect } from 'react';
|
||||
|
||||
export const useTableHeight = (tableRef: React.RefObject<HTMLDivElement>) => {
|
||||
const [tableHeight, setTableHeight] = useState<string>('calc(100vh - 360px)');
|
||||
|
||||
useEffect(() => {
|
||||
if (!tableRef.current) {
|
||||
return;
|
||||
}
|
||||
const calculateHeight = () => {
|
||||
if (tableRef.current) {
|
||||
const topPosition = tableRef.current.getBoundingClientRect().top;
|
||||
setTableHeight(`calc(100vh - ${topPosition + 80}px)`);
|
||||
}
|
||||
};
|
||||
|
||||
calculateHeight();
|
||||
window.addEventListener('resize', calculateHeight);
|
||||
|
||||
return () => {
|
||||
window.removeEventListener('resize', calculateHeight);
|
||||
};
|
||||
}, [tableRef.current]);
|
||||
|
||||
return tableHeight;
|
||||
};
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
export { type PATProps, PatBody } from './components/pat';
|
||||
export {
|
||||
disabledDate,
|
||||
ExpirationDate,
|
||||
getExpirationOptions,
|
||||
getExpireAt,
|
||||
getDetailTime,
|
||||
getExpirationTime,
|
||||
getStatus,
|
||||
} from './utils/time';
|
||||
export {
|
||||
LinkDocs,
|
||||
PATInstructionWrap,
|
||||
Tips,
|
||||
} from './components/instructions-wrap';
|
||||
export { useTableHeight } from './hooks/use-table-height';
|
||||
export { patColumn } from './components/pat/data-table/table-column';
|
||||
export { AuthTable } from './components/auth-table';
|
||||
export {
|
||||
PermissionModal,
|
||||
type PermissionModalProps,
|
||||
type PermissionModalRef,
|
||||
} from './components/pat/permission-modal';
|
||||
17
frontend/packages/studio/open-platform/open-auth/src/typings.d.ts
vendored
Normal file
17
frontend/packages/studio/open-platform/open-auth/src/typings.d.ts
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/// <reference types='@coze-arch/bot-typings' />
|
||||
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
* 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 dayjs from 'dayjs';
|
||||
import { I18n, type I18nKeysNoOptionsType } from '@coze-arch/i18n';
|
||||
|
||||
const MAX_EXPIRATION_DAYS = 30;
|
||||
// 1-30天有效期
|
||||
export const disabledDate = (date?: Date) => {
|
||||
const today = dayjs().startOf('day'); // 当天的开始时间
|
||||
const thirtyDaysLater = today.add(MAX_EXPIRATION_DAYS, 'day'); // 30天后的日期
|
||||
|
||||
return (
|
||||
dayjs(date).isBefore(today, 'day') ||
|
||||
dayjs(date).isSame(today, 'day') ||
|
||||
dayjs(date).isAfter(thirtyDaysLater, 'day')
|
||||
);
|
||||
};
|
||||
|
||||
export enum ExpirationDate {
|
||||
ONE = '1',
|
||||
THIRTY = '30',
|
||||
CUSTOMIZE = 'customize',
|
||||
}
|
||||
enum ServerTimeValue {
|
||||
PERMANENT = -1,
|
||||
NOT_USE = -1,
|
||||
}
|
||||
|
||||
export const getExpirationOptions = () => {
|
||||
const dataOptionsList = [
|
||||
{
|
||||
label: '1天',
|
||||
value: ExpirationDate.ONE,
|
||||
},
|
||||
{
|
||||
label: '30天',
|
||||
value: ExpirationDate.THIRTY,
|
||||
},
|
||||
{
|
||||
label: I18n.t('customize_key_1'),
|
||||
value: ExpirationDate.CUSTOMIZE,
|
||||
},
|
||||
];
|
||||
const newOptions = dataOptionsList.map(item => {
|
||||
const { value } = item;
|
||||
if (value === ExpirationDate.CUSTOMIZE) {
|
||||
return item;
|
||||
}
|
||||
const currentDate = dayjs();
|
||||
const futureDate = currentDate.add(Number(value), 'day');
|
||||
const date = futureDate.format('YYYY-MM-DD');
|
||||
return {
|
||||
label: I18n.t('expired_time_days_1' as I18nKeysNoOptionsType, {
|
||||
num: Number(value),
|
||||
date,
|
||||
}),
|
||||
value,
|
||||
};
|
||||
});
|
||||
return newOptions;
|
||||
};
|
||||
|
||||
export const getExpireAt = (d: Date) => {
|
||||
const h = 23;
|
||||
const m = 59;
|
||||
const s = 59;
|
||||
const intDate = dayjs(d)
|
||||
.add(h, 'hour')
|
||||
.add(m, 'minute')
|
||||
.add(s, 'second')
|
||||
.unix();
|
||||
return intDate;
|
||||
};
|
||||
|
||||
export const getDetailTime = (d: number) => {
|
||||
if (d === ServerTimeValue.NOT_USE) {
|
||||
return '-';
|
||||
}
|
||||
const showDate = dayjs.unix(d).format('YYYY-MM-DD HH:mm:ss');
|
||||
return showDate;
|
||||
};
|
||||
|
||||
export const getExpirationTime = (d: number) => {
|
||||
if (d === ServerTimeValue.PERMANENT) {
|
||||
return I18n.t('api_status_permanent_1');
|
||||
}
|
||||
const showDate = dayjs.unix(d).format('YYYY-MM-DD');
|
||||
return showDate;
|
||||
};
|
||||
|
||||
export const getStatus = (d: number) => {
|
||||
if (d === ServerTimeValue.PERMANENT) {
|
||||
return true;
|
||||
}
|
||||
const current = dayjs().unix();
|
||||
return d >= current;
|
||||
};
|
||||
@@ -0,0 +1,48 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/tsconfig",
|
||||
"extends": "@coze-arch/ts-config/tsconfig.web.json",
|
||||
"compilerOptions": {
|
||||
"paths": {
|
||||
"@/*": ["./src/*"]
|
||||
},
|
||||
"types": [],
|
||||
"strictNullChecks": true,
|
||||
"noImplicitAny": true,
|
||||
"rootDir": "./src",
|
||||
"outDir": "./dist",
|
||||
"tsBuildInfoFile": "dist/tsconfig.build.tsbuildinfo"
|
||||
},
|
||||
"include": ["src"],
|
||||
"references": [
|
||||
{
|
||||
"path": "../../../arch/bot-api/tsconfig.build.json"
|
||||
},
|
||||
{
|
||||
"path": "../../../arch/bot-typings/tsconfig.build.json"
|
||||
},
|
||||
{
|
||||
"path": "../../../arch/i18n/tsconfig.build.json"
|
||||
},
|
||||
{
|
||||
"path": "../../../arch/logger/tsconfig.build.json"
|
||||
},
|
||||
{
|
||||
"path": "../../../arch/report-events/tsconfig.build.json"
|
||||
},
|
||||
{
|
||||
"path": "../../../components/bot-semi/tsconfig.build.json"
|
||||
},
|
||||
{
|
||||
"path": "../../../../config/eslint-config/tsconfig.build.json"
|
||||
},
|
||||
{
|
||||
"path": "../../../../config/stylelint-config/tsconfig.build.json"
|
||||
},
|
||||
{
|
||||
"path": "../../../../config/ts-config/tsconfig.build.json"
|
||||
},
|
||||
{
|
||||
"path": "../../../../config/vitest-config/tsconfig.build.json"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/tsconfig",
|
||||
"compilerOptions": {
|
||||
"composite": true,
|
||||
"paths": {
|
||||
"@/*": ["./src/*"]
|
||||
}
|
||||
},
|
||||
"references": [
|
||||
{
|
||||
"path": "./tsconfig.build.json"
|
||||
},
|
||||
{
|
||||
"path": "./tsconfig.misc.json"
|
||||
}
|
||||
],
|
||||
"exclude": ["**/*"]
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
{
|
||||
"extends": "@coze-arch/ts-config/tsconfig.web.json",
|
||||
"$schema": "https://json.schemastore.org/tsconfig",
|
||||
"include": [
|
||||
"__tests__",
|
||||
"stories",
|
||||
"vitest.config.ts",
|
||||
"tailwind.config.ts",
|
||||
"setup"
|
||||
],
|
||||
"exclude": ["./dist"],
|
||||
"references": [
|
||||
{
|
||||
"path": "./tsconfig.build.json"
|
||||
}
|
||||
],
|
||||
"compilerOptions": {
|
||||
"rootDir": "./",
|
||||
"outDir": "./dist",
|
||||
"paths": {
|
||||
"@/*": ["./src/*"]
|
||||
},
|
||||
"types": ["vitest/globals"],
|
||||
"strictNullChecks": true,
|
||||
"noImplicitAny": true
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* 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 { defineConfig } from '@coze-arch/vitest-config';
|
||||
|
||||
export default defineConfig(
|
||||
{
|
||||
dirname: __dirname,
|
||||
preset: 'web',
|
||||
plugins: [
|
||||
{
|
||||
name: 'edenx-virtual-modules',
|
||||
enforce: 'pre',
|
||||
},
|
||||
],
|
||||
test: {
|
||||
setupFiles: ['./setup'],
|
||||
includeSource: ['./src'],
|
||||
coverage: {
|
||||
all: true,
|
||||
include: ['src'],
|
||||
exclude: [
|
||||
'src/**/*.tsx',
|
||||
'src/index.tsx',
|
||||
'src/global.d.ts',
|
||||
'src/typings.d.ts',
|
||||
'src/components/**',
|
||||
'src/pages/**',
|
||||
'src/constants/**',
|
||||
'src/utils/public-private-keys.ts', // window 提供的 api
|
||||
'src/utils/docs.ts', // 线上未使用 仅 boe使用 即将删除
|
||||
'src/utils/time.ts', // dayjs api 的调用
|
||||
'src/utils//analytics/index.ts',
|
||||
'src/utils//analytics/chart.ts', // 有图表 dom 相关内容
|
||||
'src/hooks/pat/action/**', // 操作类 hook
|
||||
'src/hooks/oauth-app/action/**', // 操作类 hook
|
||||
'src/hooks/use-arcosite.ts', // 线上未使用 仅 boe使用
|
||||
'src/hooks/use-show-mask.ts', // 主要为获取 dom 的 scrollTop
|
||||
'src/hooks/use-docs-path.ts', // useNavigate 相关内容
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
fixSemi: true,
|
||||
},
|
||||
);
|
||||
@@ -0,0 +1,8 @@
|
||||
const { defineConfig } = require('@coze-arch/stylelint-config');
|
||||
|
||||
module.exports = defineConfig({
|
||||
extends: [],
|
||||
rules: {
|
||||
'order/properties-order': null,
|
||||
},
|
||||
});
|
||||
69
frontend/packages/studio/open-platform/open-chat/README.md
Normal file
69
frontend/packages/studio/open-platform/open-chat/README.md
Normal file
@@ -0,0 +1,69 @@
|
||||
# @coze-studio/open-chat
|
||||
|
||||
Coze Web ChatApp SDK
|
||||
|
||||
## Overview
|
||||
|
||||
This package is part of the Coze Studio monorepo and provides chat & communication functionality. It includes component.
|
||||
|
||||
## Getting Started
|
||||
|
||||
### Installation
|
||||
|
||||
Add this package to your `package.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"dependencies": {
|
||||
"@coze-studio/open-chat": "workspace:*"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Then run:
|
||||
|
||||
```bash
|
||||
rush update
|
||||
```
|
||||
|
||||
### Usage
|
||||
|
||||
```typescript
|
||||
import { /* exported functions/components */ } from '@coze-studio/open-chat';
|
||||
|
||||
// Example usage
|
||||
// TODO: Add specific usage examples
|
||||
```
|
||||
|
||||
## Features
|
||||
|
||||
- Component
|
||||
|
||||
## API Reference
|
||||
|
||||
### Exports
|
||||
|
||||
- `BuilderChat,
|
||||
ChatType,
|
||||
RawMessageType,`
|
||||
- `Layout`
|
||||
|
||||
|
||||
For detailed API documentation, please refer to the TypeScript definitions.
|
||||
|
||||
## Development
|
||||
|
||||
This package is built with:
|
||||
|
||||
- TypeScript
|
||||
- React
|
||||
- Vitest for testing
|
||||
- ESLint for code quality
|
||||
|
||||
## Contributing
|
||||
|
||||
This package is part of the Coze Studio monorepo. Please follow the monorepo contribution guidelines.
|
||||
|
||||
## License
|
||||
|
||||
Apache-2.0
|
||||
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
vi.stubGlobal('IS_DEV_MODE', false);
|
||||
vi.stubGlobal('IS_BOE', false);
|
||||
vi.stubGlobal('IS_RELEASE_VERSION', true);
|
||||
vi.stubGlobal('REGION', 'cn');
|
||||
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"operationSettings": [
|
||||
{
|
||||
"operationName": "test:cov",
|
||||
"outputFolderNames": ["coverage"]
|
||||
},
|
||||
{
|
||||
"operationName": "ts-check",
|
||||
"outputFolderNames": ["./dist"]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
const { defineConfig } = require('@coze-arch/eslint-config');
|
||||
|
||||
module.exports = defineConfig({
|
||||
packageRoot: __dirname,
|
||||
preset: 'web',
|
||||
rules: {
|
||||
'@coze-arch/max-line-per-function': [
|
||||
'error',
|
||||
{
|
||||
max: 300,
|
||||
},
|
||||
],
|
||||
'no-restricted-imports': 'off',
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,62 @@
|
||||
{
|
||||
"name": "@coze-studio/open-chat",
|
||||
"version": "0.0.1",
|
||||
"description": "Coze Web ChatApp SDK ",
|
||||
"license": "Apache-2.0",
|
||||
"author": "gaoding.devingao@bytedance.com",
|
||||
"maintainers": [
|
||||
"gaoding.devingao@bytedance.com"
|
||||
],
|
||||
"sideEffects": false,
|
||||
"exports": {
|
||||
".": "./src/index.ts"
|
||||
},
|
||||
"main": "src/index.ts",
|
||||
"types": "./src/index.ts",
|
||||
"scripts": {
|
||||
"build": "exit 0",
|
||||
"lint": "eslint ./ --cache",
|
||||
"test": "vitest --run --passWithNoTests",
|
||||
"test:cov": "npm run test -- --coverage"
|
||||
},
|
||||
"dependencies": {
|
||||
"@coze-arch/i18n": "workspace:*",
|
||||
"@coze/chat-sdk": "0.1.11-beta.17",
|
||||
"react": "~18.2.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@coze-arch/bot-env": "workspace:*",
|
||||
"@coze-arch/bot-typings": "workspace:*",
|
||||
"@coze-arch/eslint-config": "workspace:*",
|
||||
"@coze-arch/pkg-root-webpack-plugin": "workspace:*",
|
||||
"@coze-arch/postcss-config": "workspace:*",
|
||||
"@coze-arch/stylelint-config": "workspace:*",
|
||||
"@coze-arch/tailwind-config": "workspace:*",
|
||||
"@coze-arch/ts-config": "workspace:*",
|
||||
"@coze-arch/vitest-config": "workspace:*",
|
||||
"@coze-studio/open-env-adapter": "workspace:*",
|
||||
"@rspack/plugin-react-refresh": "0.6.0",
|
||||
"@testing-library/jest-dom": "^6.1.5",
|
||||
"@testing-library/react": "^14.1.2",
|
||||
"@testing-library/react-hooks": "^8.0.1",
|
||||
"@types/lodash-es": "^4.17.10",
|
||||
"@types/node": "^18",
|
||||
"@types/react": "18.2.37",
|
||||
"@types/react-dom": "18.2.15",
|
||||
"@vitest/coverage-v8": "~3.0.5",
|
||||
"concurrently": "~8.2.2",
|
||||
"css-loader": "^6.10.0",
|
||||
"debug": "^4.3.4",
|
||||
"style-loader": "^3.3.4",
|
||||
"tailwindcss": "~3.3.3",
|
||||
"ts-node": "^10.9.1",
|
||||
"typescript": "~5.8.2",
|
||||
"vitest": "~3.0.5",
|
||||
"webpack": "~5.91.0"
|
||||
},
|
||||
"// deps": "debug@^4.3.4 为脚本自动补齐,请勿改动",
|
||||
"botPublishConfig": {
|
||||
"main": "dist/index.js"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,170 @@
|
||||
/*
|
||||
* 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 '@coze/chat-sdk/webCss';
|
||||
import { forwardRef, useMemo, type Ref, useImperativeHandle } from 'react';
|
||||
|
||||
import {
|
||||
openApiHostByRegionWithToken,
|
||||
openApiCdnUrlByRegion,
|
||||
} from '@coze-studio/open-env-adapter';
|
||||
import { I18n } from '@coze-arch/i18n';
|
||||
import ChatSdk from '@coze/chat-sdk/webJs';
|
||||
import {
|
||||
type RawMessage,
|
||||
type IChatFlowProps,
|
||||
type Language,
|
||||
} from '@coze/chat-sdk';
|
||||
|
||||
import { type IBuilderChatProps, type BuilderChatRef } from '@/types';
|
||||
|
||||
const {
|
||||
ChatFlowFramework,
|
||||
ChatSlot,
|
||||
useSendMessage,
|
||||
ChatType,
|
||||
RawMessageType,
|
||||
} = ChatSdk;
|
||||
|
||||
export { ChatType, RawMessageType };
|
||||
export const ChatContent = forwardRef(
|
||||
(_props: {}, ref: Ref<BuilderChatRef>) => {
|
||||
const { sendMessage } = useSendMessage();
|
||||
useImperativeHandle(
|
||||
ref,
|
||||
() => ({
|
||||
sendMessage: (message: RawMessage) => {
|
||||
sendMessage(message);
|
||||
},
|
||||
}),
|
||||
[sendMessage],
|
||||
);
|
||||
return <ChatSlot />;
|
||||
},
|
||||
);
|
||||
|
||||
export const BuilderChat = forwardRef(
|
||||
(props: IBuilderChatProps, ref: Ref<BuilderChatRef>) => {
|
||||
const { workflow } = props;
|
||||
const eventCallbacks: IChatFlowProps['eventCallbacks'] = useMemo(
|
||||
() => ({
|
||||
onImageClick: props.eventCallbacks?.onImageClick,
|
||||
onGetChatFlowExecuteId: props.eventCallbacks?.onGetChatFlowExecuteId,
|
||||
onThemeChange: props.eventCallbacks?.onThemeChange,
|
||||
onInitSuccess: props.eventCallbacks?.onInitSuccess,
|
||||
message: {
|
||||
afterMessageReceivedFinish:
|
||||
props.eventCallbacks?.afterMessageReceivedFinish,
|
||||
},
|
||||
}),
|
||||
[props.eventCallbacks],
|
||||
);
|
||||
const { userInfo } = props;
|
||||
const { auth } = props;
|
||||
const areaUi: IChatFlowProps['areaUi'] = useMemo(
|
||||
// eslint-disable-next-line complexity
|
||||
() => ({
|
||||
layout: props.project?.layout,
|
||||
isDisabled: props.areaUi?.isDisabled,
|
||||
input: {
|
||||
isNeed: props.areaUi?.input?.isShow,
|
||||
isNeedAudio: props.areaUi?.input?.isNeedAudio ?? !IS_OVERSEA,
|
||||
placholder: props.areaUi?.input?.placeholder,
|
||||
isNeedTaskMessage: props.areaUi?.input?.isNeedTaskMessage,
|
||||
defaultText: props.areaUi?.input?.defaultText,
|
||||
renderChatInputTopSlot: props.areaUi?.input?.renderChatInputTopSlot,
|
||||
},
|
||||
clearContext:
|
||||
props.project?.mode === 'websdk'
|
||||
? {
|
||||
isNeed: true,
|
||||
position: 'inputLeft',
|
||||
}
|
||||
: {
|
||||
isNeed: false,
|
||||
},
|
||||
clearMessage:
|
||||
props.project?.mode === 'websdk'
|
||||
? {
|
||||
isNeed: true,
|
||||
position: 'headerRight',
|
||||
}
|
||||
: {
|
||||
isNeed:
|
||||
props.areaUi?.isNeedClearMessage !== undefined
|
||||
? props.areaUi?.isNeedClearMessage
|
||||
: true,
|
||||
position: 'inputLeft',
|
||||
},
|
||||
uploadBtn: {
|
||||
isNeed: props.areaUi?.uploadable,
|
||||
},
|
||||
uiTheme: props.areaUi?.uiTheme,
|
||||
renderLoading: props.areaUi?.renderLoading,
|
||||
header: {
|
||||
isNeed: props.areaUi?.header?.isShow || false,
|
||||
icon: props.project?.iconUrl,
|
||||
title: props.project?.name,
|
||||
renderRightSlot: () => <>{props.areaUi?.header?.extra || null}</>,
|
||||
},
|
||||
footer: props.areaUi?.footer,
|
||||
}),
|
||||
[props.areaUi, props.project],
|
||||
);
|
||||
const setting: IChatFlowProps['setting'] = useMemo(
|
||||
() => ({
|
||||
apiBaseUrl: openApiHostByRegionWithToken,
|
||||
cdnBaseUrlPath: openApiCdnUrlByRegion,
|
||||
language: I18n.language as Language,
|
||||
logLevel: IS_BOE ? 'debug' : 'release',
|
||||
...(props.setting || {}),
|
||||
}),
|
||||
[],
|
||||
);
|
||||
const project: IChatFlowProps['project'] = useMemo(
|
||||
() => ({
|
||||
id: props.project?.id || '',
|
||||
type: props.project?.type,
|
||||
mode: props.project?.mode as 'release',
|
||||
caller: props.project?.caller,
|
||||
defaultName: props.project?.defaultName,
|
||||
defaultIconUrl: props.project?.defaultIconUrl,
|
||||
connectorId: props.project?.connectorId,
|
||||
conversationName: props.project?.conversationName,
|
||||
name: props.project?.name,
|
||||
iconUrl: props.project?.iconUrl,
|
||||
OnBoarding: props.project?.onBoarding,
|
||||
}),
|
||||
[props.project],
|
||||
);
|
||||
return (
|
||||
<>
|
||||
<ChatFlowFramework
|
||||
workflow={workflow}
|
||||
project={project}
|
||||
userInfo={userInfo}
|
||||
eventCallbacks={eventCallbacks}
|
||||
auth={auth}
|
||||
style={props.style}
|
||||
areaUi={areaUi}
|
||||
setting={setting}
|
||||
>
|
||||
<ChatContent ref={ref} />
|
||||
</ChatFlowFramework>
|
||||
</>
|
||||
);
|
||||
},
|
||||
);
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
export {
|
||||
BuilderChat,
|
||||
ChatType,
|
||||
RawMessageType,
|
||||
} from './components/builder-chat';
|
||||
|
||||
export { Layout } from './types';
|
||||
export type {
|
||||
IWorkflow,
|
||||
IProject,
|
||||
IEventCallbacks,
|
||||
IBuilderChatProps,
|
||||
BuilderChatRef,
|
||||
DebugProps,
|
||||
HeaderConfig,
|
||||
} from './types';
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* 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';
|
||||
|
||||
export enum Layout {
|
||||
PC = 'pc',
|
||||
MOBILE = 'mobile',
|
||||
}
|
||||
|
||||
export interface HeaderConfig {
|
||||
isShow?: boolean; //是否显示header, 默认是true
|
||||
isNeedClose?: boolean; //是否需要关闭按钮, 默认是true
|
||||
extra?: ReactNode | false; // 用于站位的,默认无
|
||||
}
|
||||
|
||||
export interface DebugProps {
|
||||
cozeApiRequestHeader?: Record<string, string>;
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
* 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 React from 'react';
|
||||
|
||||
import {
|
||||
type ChatFrameworkProps,
|
||||
type IMessageCallback,
|
||||
type RawMessage,
|
||||
type IChatFlowProps,
|
||||
type FooterConfig,
|
||||
type IOnImageClickEvent,
|
||||
} from '@coze/chat-sdk';
|
||||
|
||||
import { type Layout, type DebugProps, type HeaderConfig } from './base';
|
||||
export interface IWorkflow {
|
||||
id?: string;
|
||||
parameters?: Record<string, unknown>;
|
||||
header?: Record<string, string>;
|
||||
}
|
||||
export interface IProject {
|
||||
id: string;
|
||||
type: 'app' | 'bot';
|
||||
mode: 'draft' | 'release' | 'websdk' | 'audit'; // 草稿模式 | 发布模式 | webSdk发布
|
||||
caller?: 'UI_BUILDER' | 'CANVAS';
|
||||
connectorId?: string;
|
||||
conversationName?: string; // project的话,必须填写
|
||||
conversationId?: string; // type 为bot的话,必须填写
|
||||
sectionId?: string; // type 为bot的话,必须填写
|
||||
name?: string;
|
||||
defaultName?: string;
|
||||
defaultIconUrl?: string;
|
||||
iconUrl?: string;
|
||||
layout?: Layout;
|
||||
version?: string;
|
||||
onBoarding?: {
|
||||
prologue: string;
|
||||
suggestions: string[];
|
||||
};
|
||||
}
|
||||
export interface IEventCallbacks {
|
||||
onMessageChanged?: () => void;
|
||||
onMessageSended?: () => void;
|
||||
onMessageReceivedStart?: () => void;
|
||||
onMessageRecievedFinish?: () => void;
|
||||
onImageClick?: IOnImageClickEvent;
|
||||
onGetChatFlowExecuteId?: (id: string) => void;
|
||||
onThemeChange?: (theme: 'bg-theme' | 'light') => void;
|
||||
afterMessageReceivedFinish?: IMessageCallback['afterMessageReceivedFinish'];
|
||||
onInitSuccess?: () => void;
|
||||
}
|
||||
export interface IBuilderChatProps {
|
||||
workflow: IWorkflow;
|
||||
project: IProject;
|
||||
eventCallbacks?: IEventCallbacks;
|
||||
userInfo: IChatFlowProps['userInfo'];
|
||||
areaUi: {
|
||||
isDisabled?: boolean; // 默认 false
|
||||
uploadable?: boolean; // 默认 true
|
||||
isNeedClearContext?: boolean; // 是否显示 clearContext按钮
|
||||
isNeedClearMessage?: boolean; // 是否显示 clearMessage按钮
|
||||
|
||||
//isShowHeader?: boolean; // 默认 false
|
||||
//isShowFooter?: boolean; // 默认 false
|
||||
input?: {
|
||||
placeholder?: string;
|
||||
renderChatInputTopSlot?: (isChatError?: boolean) => React.ReactNode;
|
||||
isShow?: boolean; //默认 true
|
||||
defaultText?: string;
|
||||
isNeedAudio?: boolean; // 是否需要语音输入,默认是false
|
||||
isNeedTaskMessage?: boolean;
|
||||
};
|
||||
header?: HeaderConfig; // 默认是
|
||||
footer?: FooterConfig;
|
||||
uiTheme?: 'uiBuilder' | 'chatFlow'; // uiBuilder 的主题
|
||||
renderLoading?: () => React.ReactNode;
|
||||
};
|
||||
auth?: {
|
||||
type: 'external' | 'internal'; // 内部: cookie换token, 外部: internal
|
||||
token?: string;
|
||||
refreshToken?: () => Promise<string> | string;
|
||||
};
|
||||
style?: React.CSSProperties;
|
||||
debug?: DebugProps;
|
||||
setting?: Partial<ChatFrameworkProps['setting']>;
|
||||
}
|
||||
|
||||
export interface BuilderChatRef {
|
||||
sendMessage: (message: RawMessage) => void;
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
export { Layout, type HeaderConfig, type DebugProps } from './base';
|
||||
export type {
|
||||
IWorkflow,
|
||||
IProject,
|
||||
IEventCallbacks,
|
||||
IBuilderChatProps,
|
||||
BuilderChatRef,
|
||||
} from './builder-chat';
|
||||
17
frontend/packages/studio/open-platform/open-chat/src/typings.d.ts
vendored
Normal file
17
frontend/packages/studio/open-platform/open-chat/src/typings.d.ts
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/// <reference types='@coze-arch/bot-typings' />
|
||||
@@ -0,0 +1,54 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/tsconfig",
|
||||
"extends": "@coze-arch/ts-config/tsconfig.web.json",
|
||||
"compilerOptions": {
|
||||
"types": [],
|
||||
"paths": {
|
||||
"@/*": ["./src/*"]
|
||||
},
|
||||
"esModuleInterop": true,
|
||||
"resolveJsonModule": true,
|
||||
"rootDir": "./src",
|
||||
"preserveSymlinks": false,
|
||||
"skipLibCheck": true,
|
||||
"outDir": "./dist",
|
||||
"tsBuildInfoFile": "dist/tsconfig.build.tsbuildinfo"
|
||||
},
|
||||
"include": ["src", "src/**/*.json"],
|
||||
"exclude": ["./src/**/*.test.ts", "src/**/__tests__/**", "src/test/setup.ts"],
|
||||
"references": [
|
||||
{
|
||||
"path": "../../../arch/bot-env/tsconfig.build.json"
|
||||
},
|
||||
{
|
||||
"path": "../../../arch/bot-typings/tsconfig.build.json"
|
||||
},
|
||||
{
|
||||
"path": "../../../arch/i18n/tsconfig.build.json"
|
||||
},
|
||||
{
|
||||
"path": "../../../../config/eslint-config/tsconfig.build.json"
|
||||
},
|
||||
{
|
||||
"path": "../../../../config/postcss-config/tsconfig.build.json"
|
||||
},
|
||||
{
|
||||
"path": "../../../../config/stylelint-config/tsconfig.build.json"
|
||||
},
|
||||
{
|
||||
"path": "../../../../config/tailwind-config/tsconfig.build.json"
|
||||
},
|
||||
{
|
||||
"path": "../../../../config/ts-config/tsconfig.build.json"
|
||||
},
|
||||
{
|
||||
"path": "../../../../config/vitest-config/tsconfig.build.json"
|
||||
},
|
||||
{
|
||||
"path": "../../../../infra/plugins/pkg-root-webpack-plugin/tsconfig.build.json"
|
||||
},
|
||||
{
|
||||
"path": "../open-env-adapter/tsconfig.build.json"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/tsconfig",
|
||||
"compilerOptions": {
|
||||
"composite": true
|
||||
},
|
||||
"references": [
|
||||
{
|
||||
"path": "./tsconfig.build.json"
|
||||
},
|
||||
{
|
||||
"path": "./tsconfig.misc.json"
|
||||
}
|
||||
],
|
||||
"exclude": ["**/*"]
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
{
|
||||
"extends": "@coze-arch/ts-config/tsconfig.web.json",
|
||||
"$schema": "https://json.schemastore.org/tsconfig",
|
||||
"include": [
|
||||
"stories",
|
||||
"vitest.config.ts",
|
||||
"tailwind.config.ts",
|
||||
"rspack.config.ts",
|
||||
"rspack-config/**/*.ts",
|
||||
"./src/**/*.test.ts",
|
||||
"**/__tests__",
|
||||
"src/test/setup.ts"
|
||||
],
|
||||
"exclude": ["node_modules", "./dist"],
|
||||
|
||||
"references": [
|
||||
{
|
||||
"path": "./tsconfig.build.json"
|
||||
}
|
||||
],
|
||||
"compilerOptions": {
|
||||
"rootDir": "./",
|
||||
"types": ["vitest/globals", "node"],
|
||||
"paths": {
|
||||
"@/*": ["./src/*"]
|
||||
},
|
||||
"esModuleInterop": true,
|
||||
"resolveJsonModule": true,
|
||||
"outDir": "./dist"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* 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 { defineConfig } from '@coze-arch/vitest-config';
|
||||
|
||||
export default defineConfig({
|
||||
dirname: __dirname,
|
||||
preset: 'web',
|
||||
test: {
|
||||
setupFiles: ['__tests__/setup.ts'],
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,8 @@
|
||||
const { defineConfig } = require('@coze-arch/stylelint-config');
|
||||
|
||||
module.exports = defineConfig({
|
||||
extends: [],
|
||||
rules: {
|
||||
'order/properties-order': null,
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,75 @@
|
||||
# @coze-studio/open-env-adapter
|
||||
|
||||
Coze Web ChatApp SDK
|
||||
|
||||
## Overview
|
||||
|
||||
This package is part of the Coze Studio monorepo and provides library functionality. It includes api, sdk.
|
||||
|
||||
## Getting Started
|
||||
|
||||
### Installation
|
||||
|
||||
Add this package to your `package.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"dependencies": {
|
||||
"@coze-studio/open-env-adapter": "workspace:*"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Then run:
|
||||
|
||||
```bash
|
||||
rush update
|
||||
```
|
||||
|
||||
### Usage
|
||||
|
||||
```typescript
|
||||
import { /* exported functions/components */ } from '@coze-studio/open-env-adapter';
|
||||
|
||||
// Example usage
|
||||
// TODO: Add specific usage examples
|
||||
```
|
||||
|
||||
## Features
|
||||
|
||||
- Api
|
||||
- Sdk
|
||||
|
||||
## API Reference
|
||||
|
||||
### Exports
|
||||
|
||||
- `iframeAppHost,
|
||||
cozeOfficialHost,
|
||||
openApiCdnUrlByRegion,
|
||||
openApiHostByRegion,
|
||||
openApiHostByRegionWithToken,
|
||||
openSdkPrefix,
|
||||
getOpenSDKUrl,
|
||||
getOpenSDKPath,
|
||||
eventMeta,`
|
||||
|
||||
|
||||
For detailed API documentation, please refer to the TypeScript definitions.
|
||||
|
||||
## Development
|
||||
|
||||
This package is built with:
|
||||
|
||||
- TypeScript
|
||||
- Modern JavaScript
|
||||
- Vitest for testing
|
||||
- ESLint for code quality
|
||||
|
||||
## Contributing
|
||||
|
||||
This package is part of the Coze Studio monorepo. Please follow the monorepo contribution guidelines.
|
||||
|
||||
## License
|
||||
|
||||
Apache-2.0
|
||||
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* 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 { getOpenSDKPath } from '@/chat';
|
||||
describe('chat-env', () => {
|
||||
it('getOpenSDKUrl', () => {
|
||||
const sdkPath = getOpenSDKPath('1.0.0');
|
||||
expect(sdkPath).toBe('');
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
vi.stubGlobal('IS_OVERSEA', false);
|
||||
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"operationSettings": [
|
||||
{
|
||||
"operationName": "test:cov",
|
||||
"outputFolderNames": ["coverage"]
|
||||
},
|
||||
{
|
||||
"operationName": "ts-check",
|
||||
"outputFolderNames": ["./dist"]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
const { defineConfig } = require('@coze-arch/eslint-config');
|
||||
|
||||
module.exports = defineConfig({
|
||||
packageRoot: __dirname,
|
||||
preset: 'web',
|
||||
rules: {
|
||||
'@coze-arch/max-line-per-function': [
|
||||
'error',
|
||||
{
|
||||
max: 300,
|
||||
},
|
||||
],
|
||||
'no-restricted-imports': 'off',
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,64 @@
|
||||
{
|
||||
"name": "@coze-studio/open-env-adapter",
|
||||
"version": "0.0.1",
|
||||
"description": "Coze Web ChatApp SDK ",
|
||||
"license": "Apache-2.0",
|
||||
"author": "gaoding.devingao@bytedance.com",
|
||||
"maintainers": [
|
||||
"gaoding.devingao@bytedance.com"
|
||||
],
|
||||
"sideEffects": false,
|
||||
"exports": {
|
||||
".": "./src/index.ts",
|
||||
"./chat": "./src/chat/index.ts"
|
||||
},
|
||||
"main": "src/index.ts",
|
||||
"types": "./src/index.ts",
|
||||
"typesVersions": {
|
||||
"*": {
|
||||
"chat": [
|
||||
"./src/chat/index.ts"
|
||||
]
|
||||
}
|
||||
},
|
||||
"scripts": {
|
||||
"build": "exit 0",
|
||||
"lint": "eslint ./ --cache",
|
||||
"test": "vitest --run --passWithNoTests",
|
||||
"test:cov": "vitest run --coverage"
|
||||
},
|
||||
"dependencies": {},
|
||||
"devDependencies": {
|
||||
"@coze-arch/bot-env": "workspace:*",
|
||||
"@coze-arch/bot-typings": "workspace:*",
|
||||
"@coze-arch/eslint-config": "workspace:*",
|
||||
"@coze-arch/pkg-root-webpack-plugin": "workspace:*",
|
||||
"@coze-arch/postcss-config": "workspace:*",
|
||||
"@coze-arch/stylelint-config": "workspace:*",
|
||||
"@coze-arch/tailwind-config": "workspace:*",
|
||||
"@coze-arch/ts-config": "workspace:*",
|
||||
"@coze-arch/vitest-config": "workspace:*",
|
||||
"@rspack/plugin-react-refresh": "0.6.0",
|
||||
"@testing-library/jest-dom": "^6.1.5",
|
||||
"@testing-library/react": "^14.1.2",
|
||||
"@testing-library/react-hooks": "^8.0.1",
|
||||
"@types/lodash-es": "^4.17.10",
|
||||
"@types/node": "^18",
|
||||
"@types/react": "18.2.37",
|
||||
"@types/react-dom": "18.2.15",
|
||||
"@vitest/coverage-v8": "~3.0.5",
|
||||
"concurrently": "~8.2.2",
|
||||
"css-loader": "^6.10.0",
|
||||
"debug": "^4.3.4",
|
||||
"style-loader": "^3.3.4",
|
||||
"tailwindcss": "~3.3.3",
|
||||
"ts-node": "^10.9.1",
|
||||
"typescript": "~5.8.2",
|
||||
"vitest": "~3.0.5",
|
||||
"webpack": "~5.91.0"
|
||||
},
|
||||
"// deps": "debug@^4.3.4 为脚本自动补齐,请勿改动",
|
||||
"botPublishConfig": {
|
||||
"main": "dist/index.js"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* 依赖 treeShaking 去除无关配置(Argus)
|
||||
*/
|
||||
const sdkRegion = 'cn';
|
||||
export const iframeAppHost = '';
|
||||
|
||||
export const cozeOfficialHost = '';
|
||||
|
||||
export const openApiCdnUrlByRegion = IS_OVERSEA
|
||||
? // cp-disable-next-line
|
||||
'https://sf16-sg.tiktokcdn.com/obj/eden-sg/rkzild_lgvj/ljhwZthlaukjlkulzlp/'
|
||||
: // cp-disable-next-line
|
||||
'https://lf3-static.bytednsdoc.com/obj/eden-cn/rkzild_lgvj/ljhwZthlaukjlkulzlp/';
|
||||
|
||||
// 用户需要修改此处baseurl,用于开放平台接口的域名配置
|
||||
export const openApiHostByRegion =
|
||||
typeof location !== 'undefined' ? location.origin : 'https://api.xxx.com';
|
||||
export const openApiHostByRegionWithToken = openApiHostByRegion;
|
||||
|
||||
export const openSdkPrefix = '';
|
||||
export const getOpenSDKUrl = (_version: string) => '';
|
||||
|
||||
export const getOpenSDKPath = (_version: string) => '';
|
||||
|
||||
export const eventMeta = {
|
||||
region: sdkRegion,
|
||||
is_release: false,
|
||||
dev: false,
|
||||
};
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
export {
|
||||
iframeAppHost,
|
||||
cozeOfficialHost,
|
||||
openApiCdnUrlByRegion,
|
||||
openApiHostByRegion,
|
||||
openApiHostByRegionWithToken,
|
||||
openSdkPrefix,
|
||||
getOpenSDKUrl,
|
||||
getOpenSDKPath,
|
||||
eventMeta,
|
||||
} from './chat';
|
||||
17
frontend/packages/studio/open-platform/open-env-adapter/src/typings.d.ts
vendored
Normal file
17
frontend/packages/studio/open-platform/open-env-adapter/src/typings.d.ts
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/// <reference types='@coze-arch/bot-typings' />
|
||||
@@ -0,0 +1,48 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/tsconfig",
|
||||
"extends": "@coze-arch/ts-config/tsconfig.web.json",
|
||||
"compilerOptions": {
|
||||
"types": [],
|
||||
"paths": {
|
||||
"@/*": ["./src/*"]
|
||||
},
|
||||
"esModuleInterop": true,
|
||||
"resolveJsonModule": true,
|
||||
"rootDir": "./src",
|
||||
"preserveSymlinks": false,
|
||||
"skipLibCheck": true,
|
||||
"outDir": "./dist",
|
||||
"tsBuildInfoFile": "dist/tsconfig.build.tsbuildinfo"
|
||||
},
|
||||
"include": ["src", "src/**/*.json"],
|
||||
"exclude": ["./src/**/*.test.ts", "src/**/__tests__/**", "src/test/setup.ts"],
|
||||
"references": [
|
||||
{
|
||||
"path": "../../../arch/bot-env/tsconfig.build.json"
|
||||
},
|
||||
{
|
||||
"path": "../../../arch/bot-typings/tsconfig.build.json"
|
||||
},
|
||||
{
|
||||
"path": "../../../../config/eslint-config/tsconfig.build.json"
|
||||
},
|
||||
{
|
||||
"path": "../../../../config/postcss-config/tsconfig.build.json"
|
||||
},
|
||||
{
|
||||
"path": "../../../../config/stylelint-config/tsconfig.build.json"
|
||||
},
|
||||
{
|
||||
"path": "../../../../config/tailwind-config/tsconfig.build.json"
|
||||
},
|
||||
{
|
||||
"path": "../../../../config/ts-config/tsconfig.build.json"
|
||||
},
|
||||
{
|
||||
"path": "../../../../config/vitest-config/tsconfig.build.json"
|
||||
},
|
||||
{
|
||||
"path": "../../../../infra/plugins/pkg-root-webpack-plugin/tsconfig.build.json"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/tsconfig",
|
||||
"compilerOptions": {
|
||||
"composite": true
|
||||
},
|
||||
"references": [
|
||||
{
|
||||
"path": "./tsconfig.build.json"
|
||||
},
|
||||
{
|
||||
"path": "./tsconfig.misc.json"
|
||||
}
|
||||
],
|
||||
"exclude": ["**/*"]
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
{
|
||||
"extends": "@coze-arch/ts-config/tsconfig.web.json",
|
||||
"$schema": "https://json.schemastore.org/tsconfig",
|
||||
"include": [
|
||||
"stories",
|
||||
"vitest.config.ts",
|
||||
"tailwind.config.ts",
|
||||
"rspack.config.ts",
|
||||
"rspack-config/**/*.ts",
|
||||
"./src/**/*.test.ts",
|
||||
"**/__tests__",
|
||||
"src/test/setup.ts"
|
||||
],
|
||||
"exclude": ["node_modules", "./dist"],
|
||||
|
||||
"references": [
|
||||
{
|
||||
"path": "./tsconfig.build.json"
|
||||
}
|
||||
],
|
||||
"compilerOptions": {
|
||||
"rootDir": "./",
|
||||
"types": ["vitest/globals", "node"],
|
||||
"paths": {
|
||||
"@/*": ["./src/*"]
|
||||
},
|
||||
"esModuleInterop": true,
|
||||
"resolveJsonModule": true,
|
||||
"outDir": "./dist"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* 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 { defineConfig } from '@coze-arch/vitest-config';
|
||||
|
||||
export default defineConfig({
|
||||
dirname: __dirname,
|
||||
preset: 'web',
|
||||
test: {
|
||||
setupFiles: ['__tests__/setup.ts'],
|
||||
},
|
||||
});
|
||||
Reference in New Issue
Block a user