feat: manually mirror opencoze's code from bytedance
Change-Id: I09a73aadda978ad9511264a756b2ce51f5761adf
This commit is contained in:
72
frontend/packages/project-ide/base-adapter/README.md
Normal file
72
frontend/packages/project-ide/base-adapter/README.md
Normal file
@@ -0,0 +1,72 @@
|
||||
# @coze-project-ide/base-adapter
|
||||
|
||||
Adapter of coze ProjectIDE
|
||||
|
||||
## Overview
|
||||
|
||||
This package is part of the Coze Studio monorepo and provides ide features functionality. It includes hook, store, service.
|
||||
|
||||
## Getting Started
|
||||
|
||||
### Installation
|
||||
|
||||
Add this package to your `package.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"dependencies": {
|
||||
"@coze-project-ide/base-adapter": "workspace:*"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Then run:
|
||||
|
||||
```bash
|
||||
rush update
|
||||
```
|
||||
|
||||
### Usage
|
||||
|
||||
```typescript
|
||||
import { /* exported functions/components */ } from '@coze-project-ide/base-adapter';
|
||||
|
||||
// Example usage
|
||||
// TODO: Add specific usage examples
|
||||
```
|
||||
|
||||
## Features
|
||||
|
||||
- Hook
|
||||
- Store
|
||||
- Service
|
||||
|
||||
## API Reference
|
||||
|
||||
### Exports
|
||||
|
||||
- `useCommitVersion`
|
||||
- `IDEGlobalProvider,
|
||||
useIDEGlobalContext,
|
||||
useIDEGlobalStore,`
|
||||
- `OptionsService, WsService`
|
||||
|
||||
|
||||
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,12 @@
|
||||
{
|
||||
"operationSettings": [
|
||||
{
|
||||
"operationName": "test:cov",
|
||||
"outputFolderNames": ["coverage"]
|
||||
},
|
||||
{
|
||||
"operationName": "ts-check",
|
||||
"outputFolderNames": ["dist"]
|
||||
}
|
||||
]
|
||||
}
|
||||
15
frontend/packages/project-ide/base-adapter/eslint.config.js
Normal file
15
frontend/packages/project-ide/base-adapter/eslint.config.js
Normal file
@@ -0,0 +1,15 @@
|
||||
const { defineConfig } = require('@coze-arch/eslint-config');
|
||||
|
||||
module.exports = defineConfig({
|
||||
packageRoot: __dirname,
|
||||
preset: 'node',
|
||||
rules: {
|
||||
'@typescript-eslint/no-explicit-any': 'off',
|
||||
'@typescript-eslint/naming-convention': 'off',
|
||||
'@typescript-eslint/method-signature-style': 'off',
|
||||
'@stylistic/ts/comma-dangle': 'off',
|
||||
'@typescript-eslint/adjacent-overload-signatures': 'off',
|
||||
'@typescript-eslint/unified-signatures': 'off',
|
||||
'eslint-comments/require-description': 'off',
|
||||
},
|
||||
});
|
||||
33
frontend/packages/project-ide/base-adapter/package.json
Normal file
33
frontend/packages/project-ide/base-adapter/package.json
Normal file
@@ -0,0 +1,33 @@
|
||||
{
|
||||
"name": "@coze-project-ide/base-adapter",
|
||||
"version": "0.0.1",
|
||||
"description": "Adapter of coze ProjectIDE",
|
||||
"license": "Apache-2.0",
|
||||
"author": "chenjiawei.inizio@bytedance.com",
|
||||
"maintainers": [],
|
||||
"main": "src/index.ts",
|
||||
"scripts": {
|
||||
"build": "exit 0",
|
||||
"lint": "eslint ./ --cache",
|
||||
"test": "vitest --run --passWithNoTests",
|
||||
"test:cov": "npm run test -- --coverage"
|
||||
},
|
||||
"dependencies": {
|
||||
"@coze-project-ide/base-interface": "workspace:*",
|
||||
"@coze-project-ide/client": "workspace:*",
|
||||
"@coze-arch/bot-typings": "workspace:*",
|
||||
"inversify": "^6.0.1",
|
||||
"react-router-dom": "^6.22.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@coze-arch/eslint-config": "workspace:*",
|
||||
"@coze-arch/ts-config": "workspace:*",
|
||||
"@coze-arch/vitest-config": "workspace:*",
|
||||
"@types/node": "^18",
|
||||
"@types/react": "18.2.37",
|
||||
"@vitest/coverage-v8": "~3.0.5",
|
||||
"sucrase": "^3.32.0",
|
||||
"vitest": "~3.0.5"
|
||||
}
|
||||
}
|
||||
|
||||
17
frontend/packages/project-ide/base-adapter/src/global.d.ts
vendored
Normal file
17
frontend/packages/project-ide/base-adapter/src/global.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,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.
|
||||
*/
|
||||
|
||||
export { useCommitVersion } from './use-commit-version';
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
export const useCommitVersion = () => ({
|
||||
version: '',
|
||||
patch: () => null,
|
||||
});
|
||||
23
frontend/packages/project-ide/base-adapter/src/index.ts
Normal file
23
frontend/packages/project-ide/base-adapter/src/index.ts
Normal file
@@ -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.
|
||||
*/
|
||||
|
||||
export { useCommitVersion } from './hooks';
|
||||
export {
|
||||
IDEGlobalProvider,
|
||||
useIDEGlobalContext,
|
||||
useIDEGlobalStore,
|
||||
} from '@coze-project-ide/base-interface';
|
||||
export { OptionsService, WsService } from './services';
|
||||
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
* 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 { OptionsService } from './options-service';
|
||||
export { WsService } from './ws-service';
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* 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 NavigateFunction } from 'react-router-dom';
|
||||
|
||||
export const OptionsService = Symbol('OptionsService');
|
||||
|
||||
export interface OptionsService {
|
||||
spaceId: string;
|
||||
projectId: string;
|
||||
version: string;
|
||||
navigate: NavigateFunction;
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* 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 { inject, injectable } from 'inversify';
|
||||
import { Emitter } from '@coze-project-ide/client';
|
||||
import { type WsMessageProps } from '@coze-project-ide/base-interface';
|
||||
|
||||
import { OptionsService } from './options-service';
|
||||
|
||||
export const safeParseEvent = (payload: string) => {
|
||||
try {
|
||||
return JSON.parse(payload);
|
||||
} catch (e) {
|
||||
console.warn('parse app cmd payload error', e);
|
||||
return undefined;
|
||||
}
|
||||
};
|
||||
|
||||
@injectable()
|
||||
export class WsService {
|
||||
@inject(OptionsService) options: OptionsService;
|
||||
|
||||
protected onMessageSendEmitter = new Emitter<WsMessageProps>();
|
||||
onMessageSend = this.onMessageSendEmitter.event;
|
||||
|
||||
send(data: any) {
|
||||
return;
|
||||
}
|
||||
|
||||
init() {
|
||||
return;
|
||||
}
|
||||
|
||||
onDispose() {
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/tsconfig",
|
||||
"extends": "@coze-arch/ts-config/tsconfig.web.json",
|
||||
"compilerOptions": {
|
||||
"baseUrl": "./",
|
||||
"types": ["react"],
|
||||
"jsx": "react",
|
||||
"isolatedModules": true,
|
||||
"strictNullChecks": true,
|
||||
"strictPropertyInitialization": false,
|
||||
"rootDir": "./src",
|
||||
"outDir": "./lib-ts",
|
||||
"tsBuildInfoFile": "./lib-ts/tsconfig.build.tsbuildinfo"
|
||||
},
|
||||
"include": ["./src", "./src/**/*.json"],
|
||||
"exclude": ["node_modules", "dist"],
|
||||
"references": [
|
||||
{
|
||||
"path": "../../arch/bot-typings/tsconfig.build.json"
|
||||
},
|
||||
{
|
||||
"path": "../base-interface/tsconfig.build.json"
|
||||
},
|
||||
{
|
||||
"path": "../client/tsconfig.build.json"
|
||||
},
|
||||
{
|
||||
"path": "../../../config/eslint-config/tsconfig.build.json"
|
||||
},
|
||||
{
|
||||
"path": "../../../config/ts-config/tsconfig.build.json"
|
||||
},
|
||||
{
|
||||
"path": "../../../config/vitest-config/tsconfig.build.json"
|
||||
}
|
||||
]
|
||||
}
|
||||
15
frontend/packages/project-ide/base-adapter/tsconfig.json
Normal file
15
frontend/packages/project-ide/base-adapter/tsconfig.json
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/tsconfig",
|
||||
"exclude": ["**/*"],
|
||||
"compilerOptions": {
|
||||
"composite": true
|
||||
},
|
||||
"references": [
|
||||
{
|
||||
"path": "./tsconfig.build.json"
|
||||
},
|
||||
{
|
||||
"path": "./tsconfig.misc.json"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"extends": "@coze-arch/ts-config/tsconfig.node.json",
|
||||
"$schema": "https://json.schemastore.org/tsconfig",
|
||||
"compilerOptions": {
|
||||
"rootDir": "./",
|
||||
"outDir": "./dist",
|
||||
"module": "CommonJS",
|
||||
"target": "ES2020",
|
||||
"moduleResolution": "node"
|
||||
},
|
||||
"include": ["__tests__", "vitest.config.ts"],
|
||||
"exclude": ["./dist"],
|
||||
"references": [
|
||||
{
|
||||
"path": "./tsconfig.build.json"
|
||||
}
|
||||
]
|
||||
}
|
||||
22
frontend/packages/project-ide/base-adapter/vitest.config.ts
Normal file
22
frontend/packages/project-ide/base-adapter/vitest.config.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* 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: 'node',
|
||||
});
|
||||
69
frontend/packages/project-ide/base-interface/README.md
Normal file
69
frontend/packages/project-ide/base-interface/README.md
Normal file
@@ -0,0 +1,69 @@
|
||||
# @coze-project-ide/base-interface
|
||||
|
||||
Adapter of coze ProjectIDE
|
||||
|
||||
## Overview
|
||||
|
||||
This package is part of the Coze Studio monorepo and provides ide features functionality. It includes store.
|
||||
|
||||
## Getting Started
|
||||
|
||||
### Installation
|
||||
|
||||
Add this package to your `package.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"dependencies": {
|
||||
"@coze-project-ide/base-interface": "workspace:*"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Then run:
|
||||
|
||||
```bash
|
||||
rush update
|
||||
```
|
||||
|
||||
### Usage
|
||||
|
||||
```typescript
|
||||
import { /* exported functions/components */ } from '@coze-project-ide/base-interface';
|
||||
|
||||
// Example usage
|
||||
// TODO: Add specific usage examples
|
||||
```
|
||||
|
||||
## Features
|
||||
|
||||
- Store
|
||||
|
||||
## API Reference
|
||||
|
||||
### Exports
|
||||
|
||||
- `IDEGlobalProvider,
|
||||
useIDEGlobalContext,
|
||||
useIDEGlobalStore,`
|
||||
- `type WsMessageProps`
|
||||
|
||||
|
||||
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,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: 'node',
|
||||
rules: {
|
||||
'@typescript-eslint/no-explicit-any': 'off',
|
||||
'@typescript-eslint/naming-convention': 'off',
|
||||
'@typescript-eslint/method-signature-style': 'off',
|
||||
'@stylistic/ts/comma-dangle': 'off',
|
||||
'@typescript-eslint/adjacent-overload-signatures': 'off',
|
||||
'@typescript-eslint/unified-signatures': 'off',
|
||||
'eslint-comments/require-description': 'off',
|
||||
},
|
||||
});
|
||||
31
frontend/packages/project-ide/base-interface/package.json
Normal file
31
frontend/packages/project-ide/base-interface/package.json
Normal file
@@ -0,0 +1,31 @@
|
||||
{
|
||||
"name": "@coze-project-ide/base-interface",
|
||||
"version": "0.0.1",
|
||||
"description": "Adapter of coze ProjectIDE",
|
||||
"license": "Apache-2.0",
|
||||
"author": "chenjiawei.inizio@bytedance.com",
|
||||
"maintainers": [],
|
||||
"main": "src/index.ts",
|
||||
"scripts": {
|
||||
"build": "exit 0",
|
||||
"lint": "eslint ./ --cache",
|
||||
"test": "vitest --run --passWithNoTests",
|
||||
"test:cov": "npm run test -- --coverage"
|
||||
},
|
||||
"dependencies": {
|
||||
"@coze-arch/bot-api": "workspace:*",
|
||||
"react": "~18.2.0",
|
||||
"zustand": "^4.4.7"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@coze-arch/eslint-config": "workspace:*",
|
||||
"@coze-arch/ts-config": "workspace:*",
|
||||
"@coze-arch/vitest-config": "workspace:*",
|
||||
"@types/node": "^18",
|
||||
"@types/react": "18.2.37",
|
||||
"@vitest/coverage-v8": "~3.0.5",
|
||||
"sucrase": "^3.32.0",
|
||||
"vitest": "~3.0.5"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* 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 { createWithEqualityFn } from 'zustand/traditional';
|
||||
import { shallow } from 'zustand/shallow';
|
||||
import { type UseBoundStore, type StoreApi } from 'zustand';
|
||||
import {
|
||||
type User,
|
||||
type IntelligenceBasicInfo,
|
||||
type IntelligencePublishInfo,
|
||||
} from '@coze-arch/bot-api/intelligence_api';
|
||||
|
||||
interface CreateStoreOptions {
|
||||
spaceId: string;
|
||||
projectId: string;
|
||||
version: string;
|
||||
}
|
||||
|
||||
export interface IDEGlobalState {
|
||||
/**
|
||||
* 项目 id
|
||||
*/
|
||||
projectId: string;
|
||||
/**
|
||||
* 空间 id
|
||||
*/
|
||||
spaceId: string;
|
||||
|
||||
version: string;
|
||||
|
||||
/**
|
||||
* get_draft_intelligence_info 接口返回内容
|
||||
*/
|
||||
projectInfo?: {
|
||||
ownerInfo?: User;
|
||||
projectInfo?: IntelligenceBasicInfo;
|
||||
publishInfo?: IntelligencePublishInfo;
|
||||
};
|
||||
}
|
||||
|
||||
export interface IDEGlobalAction {
|
||||
patch: (next: Partial<IDEGlobalState>) => void;
|
||||
}
|
||||
|
||||
export type StoreContext = UseBoundStore<
|
||||
StoreApi<IDEGlobalState & IDEGlobalAction>
|
||||
>;
|
||||
|
||||
export const createStore = (options: CreateStoreOptions) =>
|
||||
createWithEqualityFn<IDEGlobalState & IDEGlobalAction>(
|
||||
set => ({
|
||||
spaceId: options.spaceId,
|
||||
projectId: options.projectId,
|
||||
version: options.version,
|
||||
patch: next => set(() => next),
|
||||
}),
|
||||
shallow,
|
||||
);
|
||||
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* 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 {
|
||||
IDEGlobalProvider,
|
||||
useIDEGlobalContext,
|
||||
useIDEGlobalStore,
|
||||
} from './provider';
|
||||
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import React, { createContext, useContext, useMemo } from 'react';
|
||||
|
||||
import {
|
||||
createStore,
|
||||
type StoreContext,
|
||||
type IDEGlobalState,
|
||||
type IDEGlobalAction,
|
||||
} from './create-store';
|
||||
|
||||
const IDEGlobalContext = createContext<StoreContext>(null as any);
|
||||
|
||||
type IDEGlobalProviderProps = React.PropsWithChildren<{
|
||||
spaceId: string;
|
||||
projectId: string;
|
||||
version: string;
|
||||
}>;
|
||||
|
||||
export const IDEGlobalProvider: React.FC<IDEGlobalProviderProps> = ({
|
||||
spaceId,
|
||||
projectId,
|
||||
version,
|
||||
children,
|
||||
}) => {
|
||||
const store = useMemo(
|
||||
() => createStore({ spaceId, projectId, version }),
|
||||
[spaceId, projectId, version],
|
||||
);
|
||||
|
||||
return (
|
||||
<IDEGlobalContext.Provider value={store}>
|
||||
{children}
|
||||
</IDEGlobalContext.Provider>
|
||||
);
|
||||
};
|
||||
|
||||
export const useIDEGlobalContext = () => useContext(IDEGlobalContext);
|
||||
|
||||
export const useIDEGlobalStore = <T,>(
|
||||
selector: (s: IDEGlobalState & IDEGlobalAction) => T,
|
||||
) => {
|
||||
const store = useIDEGlobalContext();
|
||||
|
||||
if (!store) {
|
||||
throw new Error('cant not found IDEGlobalContext');
|
||||
}
|
||||
|
||||
return store(selector);
|
||||
};
|
||||
17
frontend/packages/project-ide/base-interface/src/global.d.ts
vendored
Normal file
17
frontend/packages/project-ide/base-interface/src/global.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' />
|
||||
22
frontend/packages/project-ide/base-interface/src/index.ts
Normal file
22
frontend/packages/project-ide/base-interface/src/index.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* 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 {
|
||||
IDEGlobalProvider,
|
||||
useIDEGlobalContext,
|
||||
useIDEGlobalStore,
|
||||
} from './context';
|
||||
export { type WsMessageProps } from './types';
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* 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 {
|
||||
MessageOperateType,
|
||||
MessageBizType,
|
||||
} from '@coze-arch/bot-api/workflow_api';
|
||||
|
||||
export interface WsMessageProps {
|
||||
resId: string;
|
||||
extra: any;
|
||||
/**
|
||||
* 其他窗口执行保存传入的版本号
|
||||
*/
|
||||
saveVersion?: string;
|
||||
operateType: MessageOperateType;
|
||||
bizType: MessageBizType;
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/tsconfig",
|
||||
"extends": "@coze-arch/ts-config/tsconfig.web.json",
|
||||
"compilerOptions": {
|
||||
"baseUrl": "./",
|
||||
"types": ["react"],
|
||||
"jsx": "react",
|
||||
"isolatedModules": true,
|
||||
"strictNullChecks": true,
|
||||
"strictPropertyInitialization": false,
|
||||
"paths": {
|
||||
"@/*": ["./src/*"]
|
||||
},
|
||||
"rootDir": "./src",
|
||||
"outDir": "./lib-ts",
|
||||
"tsBuildInfoFile": "./lib-ts/tsconfig.build.tsbuildinfo"
|
||||
},
|
||||
"include": ["./src", "./src/**/*.json"],
|
||||
"exclude": ["node_modules", "dist"],
|
||||
"references": [
|
||||
{
|
||||
"path": "../../arch/bot-api/tsconfig.build.json"
|
||||
},
|
||||
{
|
||||
"path": "../../../config/eslint-config/tsconfig.build.json"
|
||||
},
|
||||
{
|
||||
"path": "../../../config/ts-config/tsconfig.build.json"
|
||||
},
|
||||
{
|
||||
"path": "../../../config/vitest-config/tsconfig.build.json"
|
||||
}
|
||||
]
|
||||
}
|
||||
15
frontend/packages/project-ide/base-interface/tsconfig.json
Normal file
15
frontend/packages/project-ide/base-interface/tsconfig.json
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/tsconfig",
|
||||
"exclude": ["**/*"],
|
||||
"compilerOptions": {
|
||||
"composite": true
|
||||
},
|
||||
"references": [
|
||||
{
|
||||
"path": "./tsconfig.build.json"
|
||||
},
|
||||
{
|
||||
"path": "./tsconfig.misc.json"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"extends": "@coze-arch/ts-config/tsconfig.node.json",
|
||||
"$schema": "https://json.schemastore.org/tsconfig",
|
||||
"compilerOptions": {
|
||||
"rootDir": "./",
|
||||
"outDir": "./dist",
|
||||
"module": "CommonJS",
|
||||
"target": "ES2020",
|
||||
"moduleResolution": "node"
|
||||
},
|
||||
"include": ["__tests__", "vitest.config.ts"],
|
||||
"exclude": ["./dist"],
|
||||
"references": [
|
||||
{
|
||||
"path": "./tsconfig.build.json"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* 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: 'node',
|
||||
});
|
||||
@@ -0,0 +1,31 @@
|
||||
import { mergeConfig } from 'vite';
|
||||
import svgr from 'vite-plugin-svgr';
|
||||
|
||||
/** @type { import('@storybook/react-vite').StorybookConfig } */
|
||||
const config = {
|
||||
stories: ['../stories/**/*.mdx', '../stories/**/*.stories.tsx'],
|
||||
addons: [
|
||||
'@storybook/addon-links',
|
||||
'@storybook/addon-essentials',
|
||||
'@storybook/addon-onboarding',
|
||||
'@storybook/addon-interactions',
|
||||
],
|
||||
framework: {
|
||||
name: '@storybook/react-vite',
|
||||
options: {},
|
||||
},
|
||||
docs: {
|
||||
autodocs: 'tag',
|
||||
},
|
||||
viteFinal: config =>
|
||||
mergeConfig(config, {
|
||||
plugins: [
|
||||
svgr({
|
||||
svgrOptions: {
|
||||
native: false,
|
||||
},
|
||||
}),
|
||||
],
|
||||
}),
|
||||
};
|
||||
export default config;
|
||||
@@ -0,0 +1,14 @@
|
||||
/** @type { import('@storybook/react').Preview } */
|
||||
const preview = {
|
||||
parameters: {
|
||||
actions: { argTypesRegex: "^on[A-Z].*" },
|
||||
controls: {
|
||||
matchers: {
|
||||
color: /(background|color)$/i,
|
||||
date: /Date$/i,
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export default preview;
|
||||
@@ -0,0 +1,5 @@
|
||||
const { defineConfig } = require('@coze-arch/stylelint-config');
|
||||
|
||||
module.exports = defineConfig({
|
||||
extends: [],
|
||||
});
|
||||
16
frontend/packages/project-ide/biz-components/README.md
Normal file
16
frontend/packages/project-ide/biz-components/README.md
Normal file
@@ -0,0 +1,16 @@
|
||||
# @coze-project-ide/biz-components
|
||||
|
||||
> Project template for react component with storybook.
|
||||
|
||||
## 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,12 @@
|
||||
{
|
||||
"operationSettings": [
|
||||
{
|
||||
"operationName": "test:cov",
|
||||
"outputFolderNames": ["coverage"]
|
||||
},
|
||||
{
|
||||
"operationName": "ts-check",
|
||||
"outputFolderNames": ["./dist"]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
const { defineConfig } = require('@coze-arch/eslint-config');
|
||||
|
||||
module.exports = defineConfig({
|
||||
packageRoot: __dirname,
|
||||
preset: 'web',
|
||||
rules: {
|
||||
'no-restricted-syntax': 'off',
|
||||
'@typescript-eslint/naming-convention': 'off',
|
||||
'@typescript-eslint/no-magic-numbers': 'off',
|
||||
'@coze-arch/no-batch-import-or-export': 'off',
|
||||
'@typescript-eslint/no-non-null-assertion': 'off',
|
||||
'@typescript-eslint/no-explicit-any': 'warn',
|
||||
},
|
||||
});
|
||||
55
frontend/packages/project-ide/biz-components/package.json
Normal file
55
frontend/packages/project-ide/biz-components/package.json
Normal file
@@ -0,0 +1,55 @@
|
||||
{
|
||||
"name": "@coze-project-ide/biz-components",
|
||||
"version": "0.0.1",
|
||||
"description": "project ide business components",
|
||||
"license": "Apache-2.0",
|
||||
"author": "zhangchaoyang.805@bytedance.com",
|
||||
"maintainers": [],
|
||||
"main": "src/index.ts",
|
||||
"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-flags": "workspace:*",
|
||||
"@coze-arch/bot-icons": "workspace:*",
|
||||
"@coze-arch/coze-design": "0.0.6-alpha.346d77",
|
||||
"@coze-arch/i18n": "workspace:*",
|
||||
"@coze-project-ide/framework": "workspace:*",
|
||||
"@coze-studio/user-store": "workspace:*",
|
||||
"@coze-workflow/base": "workspace:*",
|
||||
"classnames": "^2.3.2",
|
||||
"inversify": "^6.0.1",
|
||||
"lodash-es": "^4.17.21",
|
||||
"zustand": "^4.4.7"
|
||||
},
|
||||
"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:*",
|
||||
"@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/react": "18.2.37",
|
||||
"@types/react-dom": "18.2.15",
|
||||
"@vitest/coverage-v8": "~3.0.5",
|
||||
"react": "~18.2.0",
|
||||
"react-dom": "~18.2.0",
|
||||
"react-router-dom": "^6.22.0",
|
||||
"stylelint": "^15.11.0",
|
||||
"typescript": "~5.8.2",
|
||||
"vite-plugin-svgr": "~3.3.0",
|
||||
"vitest": "~3.0.5"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": ">=18.2.0",
|
||||
"react-dom": ">=18.2.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* 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 { useResourceList } from './use-resource-list';
|
||||
export { useOpenResource } from './use-open-resource';
|
||||
export { useResourceCopyDispatch } from './use-resource-copy-dispatch';
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* 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 { useIDENavigate } from '@coze-project-ide/framework';
|
||||
|
||||
import { type BizResourceTypeEnum } from '@/resource-folder-coze/type';
|
||||
|
||||
export const useOpenResource = () => {
|
||||
const navigate = useIDENavigate();
|
||||
return ({
|
||||
resourceId,
|
||||
resourceType,
|
||||
}: {
|
||||
resourceType?: BizResourceTypeEnum;
|
||||
resourceId?: string;
|
||||
}) => navigate(`/${resourceType}/${resourceId}`);
|
||||
};
|
||||
@@ -0,0 +1,172 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import { I18n } from '@coze-arch/i18n';
|
||||
import { Button, Space, Toast, Typography } from '@coze-arch/coze-design';
|
||||
import {
|
||||
type ResourceCopyDispatchRequest,
|
||||
ResourceCopyScene,
|
||||
type ResourceCopyTaskDetail,
|
||||
} from '@coze-arch/bot-api/plugin_develop';
|
||||
import {
|
||||
DisposableCollection,
|
||||
getURIByResource,
|
||||
ModalService,
|
||||
useIDEService,
|
||||
useProjectIDEServices,
|
||||
useSpaceId,
|
||||
} from '@coze-project-ide/framework';
|
||||
|
||||
import { resTypeDTOToVO } from '@/utils';
|
||||
import { usePrimarySidebarStore } from '@/stores';
|
||||
import { BizResourceTypeEnum } from '@/resource-folder-coze';
|
||||
|
||||
import { useOpenResource } from './use-open-resource';
|
||||
|
||||
export const useResourceCopyDispatch = () => {
|
||||
const modalService = useIDEService<ModalService>(ModalService);
|
||||
const refetch = usePrimarySidebarStore(state => state.refetch);
|
||||
const projectIDEServices = useProjectIDEServices();
|
||||
const openResource = useOpenResource();
|
||||
const spaceId = useSpaceId();
|
||||
const viewResource = ({
|
||||
scene,
|
||||
taskInfo,
|
||||
}: {
|
||||
scene?: ResourceCopyScene;
|
||||
taskInfo?: ResourceCopyTaskDetail;
|
||||
}) => {
|
||||
if (!taskInfo?.res_type || !taskInfo?.res_id || !scene) {
|
||||
return;
|
||||
}
|
||||
const openInIDE =
|
||||
scene &&
|
||||
[
|
||||
ResourceCopyScene.CopyProjectResource,
|
||||
ResourceCopyScene.CopyResourceFromLibrary,
|
||||
].includes(scene);
|
||||
|
||||
const resourceType = resTypeDTOToVO(taskInfo.res_type);
|
||||
const resId = taskInfo.res_id;
|
||||
|
||||
if (openInIDE) {
|
||||
openResource({
|
||||
resourceType: resTypeDTOToVO(taskInfo.res_type),
|
||||
resourceId: taskInfo.res_id,
|
||||
});
|
||||
} else {
|
||||
if (resourceType === BizResourceTypeEnum.Workflow) {
|
||||
window.open(`/work_flow?space_id=${spaceId}&workflow_id=${resId}`);
|
||||
} else {
|
||||
window.open(
|
||||
`/space/${spaceId}/${resourceType}/${resId}?from=project`,
|
||||
'_blank',
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
const showToast = ({
|
||||
scene,
|
||||
taskInfo,
|
||||
hideViewBtn,
|
||||
}: {
|
||||
scene?: ResourceCopyScene;
|
||||
taskInfo?: ResourceCopyTaskDetail;
|
||||
hideViewBtn?: boolean;
|
||||
}) => {
|
||||
let message = '';
|
||||
|
||||
switch (scene) {
|
||||
case ResourceCopyScene.CopyProjectResource:
|
||||
message = I18n.t('project_toast_copy_successful');
|
||||
break;
|
||||
case ResourceCopyScene.CopyResourceToLibrary:
|
||||
message = I18n.t('resource_toast_copy_to_library_success');
|
||||
break;
|
||||
case ResourceCopyScene.MoveResourceToLibrary:
|
||||
message = I18n.t('resource_toast_move_to_library_success');
|
||||
break;
|
||||
case ResourceCopyScene.CopyResourceFromLibrary:
|
||||
message = I18n.t('project_toast_successfully_imported_from_library');
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
Toast.success({
|
||||
content: (
|
||||
<Space spacing={6}>
|
||||
<Typography.Text>{message}</Typography.Text>
|
||||
{hideViewBtn ? null : (
|
||||
<Button
|
||||
color="primary"
|
||||
size="small"
|
||||
onClick={() => viewResource({ scene, taskInfo })}
|
||||
>
|
||||
{I18n.t('resource_toast_view_resource')}
|
||||
</Button>
|
||||
)}
|
||||
</Space>
|
||||
),
|
||||
});
|
||||
};
|
||||
return async (
|
||||
props: ResourceCopyDispatchRequest,
|
||||
): Promise<ResourceCopyTaskDetail | undefined> => {
|
||||
const disposables = new DisposableCollection();
|
||||
try {
|
||||
const taskInfo = await new Promise<ResourceCopyTaskDetail | undefined>(
|
||||
(resolve, reject) => {
|
||||
modalService.startPolling(props);
|
||||
disposables.pushAll([
|
||||
modalService.onSuccess(_taskInfo => {
|
||||
disposables.dispose();
|
||||
refetch();
|
||||
resolve(_taskInfo);
|
||||
}),
|
||||
modalService.onError(err => {
|
||||
disposables.dispose();
|
||||
reject(err);
|
||||
}),
|
||||
modalService.onCancel(() => {
|
||||
disposables.dispose();
|
||||
reject(new Error('cancelled'));
|
||||
}),
|
||||
]);
|
||||
},
|
||||
);
|
||||
|
||||
const hideViewBtn =
|
||||
props.scene === ResourceCopyScene.CopyResourceFromLibrary;
|
||||
showToast({ scene: props.scene, taskInfo, hideViewBtn });
|
||||
if (hideViewBtn) {
|
||||
viewResource({ scene: props.scene, taskInfo });
|
||||
}
|
||||
if (props.scene === ResourceCopyScene.MoveResourceToLibrary) {
|
||||
const uri = getURIByResource(
|
||||
resTypeDTOToVO(props.res_type) ?? '',
|
||||
props.res_id ?? '',
|
||||
);
|
||||
projectIDEServices.view.closeWidgetByUri(uri);
|
||||
}
|
||||
return taskInfo;
|
||||
} catch (err) {
|
||||
console.error('error dispatch resource', err);
|
||||
}
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* 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 { useMemo } from 'react';
|
||||
|
||||
import { ProjectResourceGroupType } from '@coze-arch/bot-api/plugin_develop';
|
||||
|
||||
import { usePrimarySidebarStore } from '@/stores';
|
||||
import { type BizResourceType } from '@/resource-folder-coze';
|
||||
|
||||
export const useResourceList = (): {
|
||||
workflowResource: BizResourceType[];
|
||||
pluginResource: BizResourceType[];
|
||||
dataResource: BizResourceType[];
|
||||
initLoaded?: boolean;
|
||||
isFetching?: boolean;
|
||||
} => {
|
||||
const resourceTree = usePrimarySidebarStore(state => state.resourceTree);
|
||||
const isFetching = usePrimarySidebarStore(state => state.isFetching);
|
||||
const initLoaded = usePrimarySidebarStore(state => state.initLoaded);
|
||||
|
||||
const workflowResource = useMemo<BizResourceType[]>(
|
||||
() =>
|
||||
resourceTree.find(
|
||||
group => group.groupType === ProjectResourceGroupType.Workflow,
|
||||
)?.resourceList || [],
|
||||
[resourceTree],
|
||||
);
|
||||
const pluginResource = useMemo<BizResourceType[]>(
|
||||
() =>
|
||||
resourceTree.find(
|
||||
group => group.groupType === ProjectResourceGroupType.Plugin,
|
||||
)?.resourceList || [],
|
||||
[resourceTree],
|
||||
);
|
||||
const dataResource = useMemo<BizResourceType[]>(
|
||||
() =>
|
||||
resourceTree.find(
|
||||
group => group.groupType === ProjectResourceGroupType.Data,
|
||||
)?.resourceList || [],
|
||||
[resourceTree],
|
||||
);
|
||||
return {
|
||||
workflowResource,
|
||||
pluginResource,
|
||||
dataResource,
|
||||
initLoaded,
|
||||
isFetching,
|
||||
};
|
||||
};
|
||||
31
frontend/packages/project-ide/biz-components/src/index.ts
Normal file
31
frontend/packages/project-ide/biz-components/src/index.ts
Normal file
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* 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 {
|
||||
ResourceFolderCoze,
|
||||
type BizResourceType,
|
||||
BizResourceTypeEnum,
|
||||
type ResourceFolderCozeProps,
|
||||
createResourceFolderPlugin,
|
||||
BizResourceContextMenuBtnType,
|
||||
type BizResourceTree,
|
||||
VARIABLE_RESOURCE_ID,
|
||||
CustomResourceFolderShortcutService,
|
||||
} from './resource-folder-coze';
|
||||
export { usePrimarySidebarStore } from './stores';
|
||||
export * from './hooks';
|
||||
export { ProjectResourceGroupType } from '@coze-arch/bot-api/plugin_develop';
|
||||
export { validateNameConflict } from './resource-folder-coze/utils';
|
||||
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import { I18n } from '@coze-arch/i18n';
|
||||
import {
|
||||
IconCozWorkflow,
|
||||
IconCozPlugin,
|
||||
IconCozDocument,
|
||||
IconCozVariables,
|
||||
} from '@coze-arch/coze-design/icons';
|
||||
import {
|
||||
ProjectResourceActionKey,
|
||||
ProjectResourceGroupType,
|
||||
} from '@coze-arch/bot-api/plugin_develop';
|
||||
import { ResourceTypeEnum } from '@coze-project-ide/framework';
|
||||
|
||||
import { BizResourceContextMenuBtnType, BizResourceTypeEnum } from './type';
|
||||
export const iconFolder = (
|
||||
<i style={{ fontSize: 14 }} className={'codicon codicon-folder'} />
|
||||
);
|
||||
export const iconFolderOpended = (
|
||||
<i style={{ fontSize: 14 }} className={'codicon codicon-folder-opened'} />
|
||||
);
|
||||
|
||||
export const VARIABLE_RESOURCE_ID = 'variables';
|
||||
|
||||
/* 资源文件名最大字符数 */
|
||||
export const RESOURCE_NAME_MAX_LEN = 50;
|
||||
export const resourceIconMap = {
|
||||
[BizResourceTypeEnum.Workflow]: <IconCozWorkflow />,
|
||||
[BizResourceTypeEnum.Plugin]: <IconCozPlugin />,
|
||||
[BizResourceTypeEnum.Knowledge]: <IconCozDocument />,
|
||||
[BizResourceTypeEnum.Variable]: <IconCozVariables />,
|
||||
};
|
||||
|
||||
export const resourceTitleMap = {
|
||||
[ProjectResourceGroupType.Workflow]: I18n.t('library_resource_type_workflow'),
|
||||
[ProjectResourceGroupType.Plugin]: I18n.t('library_resource_type_plugin'),
|
||||
[ProjectResourceGroupType.Data]: I18n.t('dataide001'),
|
||||
};
|
||||
|
||||
export const createResourceLabelMap = {
|
||||
[ResourceTypeEnum.Folder]: I18n.t(
|
||||
'project_resource_sidebar_create_new_folder',
|
||||
),
|
||||
[ProjectResourceGroupType.Workflow]: I18n.t(
|
||||
'project_resource_sidebar_create_new_resource',
|
||||
{ resource: I18n.t('library_resource_type_workflow') },
|
||||
),
|
||||
[ProjectResourceGroupType.Plugin]: I18n.t(
|
||||
'project_resource_sidebar_create_new_resource',
|
||||
{ resource: I18n.t('library_resource_type_plugin') },
|
||||
),
|
||||
[ProjectResourceGroupType.Data]: I18n.t(
|
||||
'project_resource_sidebar_create_new_resource',
|
||||
{ resource: I18n.t('project_resource_sidebar_data_section') },
|
||||
),
|
||||
};
|
||||
|
||||
export const createResourceIconMap = {
|
||||
[ProjectResourceGroupType.Workflow]: <IconCozWorkflow />,
|
||||
[ProjectResourceGroupType.Plugin]: <IconCozPlugin />,
|
||||
[ProjectResourceGroupType.Data]: <IconCozDocument />,
|
||||
};
|
||||
|
||||
export const contextMenuDTOToVOMap = {
|
||||
[ProjectResourceActionKey.Rename]: BizResourceContextMenuBtnType.Rename,
|
||||
[ProjectResourceActionKey.Copy]:
|
||||
BizResourceContextMenuBtnType.DuplicateResource,
|
||||
[ProjectResourceActionKey.Delete]: BizResourceContextMenuBtnType.Delete,
|
||||
[ProjectResourceActionKey.CopyToLibrary]:
|
||||
BizResourceContextMenuBtnType.CopyToLibrary,
|
||||
[ProjectResourceActionKey.MoveToLibrary]:
|
||||
BizResourceContextMenuBtnType.MoveToLibrary,
|
||||
[ProjectResourceActionKey.Enable]:
|
||||
BizResourceContextMenuBtnType.EnableKnowledge,
|
||||
[ProjectResourceActionKey.Disable]:
|
||||
BizResourceContextMenuBtnType.DisableKnowledge,
|
||||
[ProjectResourceActionKey.SwitchToChatflow]:
|
||||
BizResourceContextMenuBtnType.SwitchToChatflow,
|
||||
[ProjectResourceActionKey.SwitchToFuncflow]:
|
||||
BizResourceContextMenuBtnType.SwitchToWorkflow,
|
||||
[ProjectResourceActionKey.UpdateDesc]:
|
||||
BizResourceContextMenuBtnType.UpdateDesc,
|
||||
};
|
||||
|
||||
export const MAX_DEEP = 6;
|
||||
export const TAB_SIZE = 14;
|
||||
export const ITEM_HEIGHT = 28;
|
||||
/* 禁用文件夹功能 */
|
||||
export const DISABLE_FOLDER = true;
|
||||
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import React, { type FC, useMemo } from 'react';
|
||||
|
||||
import { I18n } from '@coze-arch/i18n';
|
||||
import { ProjectResourceGroupType } from '@coze-arch/bot-api/plugin_develop';
|
||||
|
||||
import styles from './styles.module.less';
|
||||
export interface EmptyProps {
|
||||
type: ProjectResourceGroupType;
|
||||
}
|
||||
|
||||
export const Empty: FC<EmptyProps> = ({ type }) => {
|
||||
const title = useMemo(() => {
|
||||
switch (type) {
|
||||
case ProjectResourceGroupType.Workflow:
|
||||
return I18n.t('project_resource_sidebar_resource_not_added', {
|
||||
resource: I18n.t('library_resource_type_workflow'),
|
||||
});
|
||||
case ProjectResourceGroupType.Plugin:
|
||||
return I18n.t('project_resource_sidebar_resource_not_added', {
|
||||
resource: I18n.t('library_resource_type_plugin'),
|
||||
});
|
||||
case ProjectResourceGroupType.Data:
|
||||
return I18n.t('project_resource_sidebar_resource_not_added', {
|
||||
resource: I18n.t('project_resource_sidebar_data_section'),
|
||||
});
|
||||
default:
|
||||
return '';
|
||||
}
|
||||
}, [type]);
|
||||
return (
|
||||
<div className={styles.empty}>
|
||||
<div className={styles['empty-card']}>
|
||||
<div className={styles['empty-icon']} />
|
||||
<div className={styles['empty-skeleton']}>
|
||||
<span />
|
||||
<span />
|
||||
</div>
|
||||
</div>
|
||||
<div className={styles['empty-title']}>{title}</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import { IconCozArrowRightFill } from '@coze-arch/coze-design/icons';
|
||||
|
||||
export const ExpandableArrow = ({ expand }: { expand?: boolean }) => (
|
||||
<IconCozArrowRightFill
|
||||
className="text-[10px] coz-fg-secondary transition-transform"
|
||||
style={expand ? { transform: 'rotate(90deg)' } : undefined}
|
||||
/>
|
||||
);
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
export { useDeleteModal } from './use-delete-modal';
|
||||
export { useResourceFolderConfig } from './use-resource-folder-config';
|
||||
export { useResourceOpen } from './use-resource-open';
|
||||
export { withRenameSync } from './with-rename-sync';
|
||||
@@ -0,0 +1,123 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import React, { type ReactNode, useMemo, useState } from 'react';
|
||||
|
||||
import classnames from 'classnames';
|
||||
import { I18n } from '@coze-arch/i18n';
|
||||
import { Modal } from '@coze-arch/coze-design';
|
||||
import {
|
||||
getURIByResource,
|
||||
type ResourceFolderProps,
|
||||
type ResourceType,
|
||||
type URI,
|
||||
useProjectIDEServices,
|
||||
} from '@coze-project-ide/framework';
|
||||
|
||||
import { VARIABLE_RESOURCE_ID } from '@/resource-folder-coze/constants';
|
||||
|
||||
import { getResourceIconByResource } from '../utils';
|
||||
import styles from '../styles.module.less';
|
||||
|
||||
export const useDeleteModal = ({
|
||||
onDelete,
|
||||
}: {
|
||||
onDelete?: (resources: ResourceType[]) => Promise<void> | void;
|
||||
}): {
|
||||
node: ReactNode;
|
||||
handleDeleteResource: ResourceFolderProps['onDelete'];
|
||||
} => {
|
||||
const projectIDEServices = useProjectIDEServices();
|
||||
const [resources, setResources] = useState<ResourceType[]>([]);
|
||||
const [visible, setVisible] = useState(false);
|
||||
const open = () => setVisible(true);
|
||||
const close = () => {
|
||||
setResources([]);
|
||||
setVisible(false);
|
||||
};
|
||||
const content = useMemo(() => {
|
||||
if (!resources.length) {
|
||||
return <></>;
|
||||
}
|
||||
let contentText = '';
|
||||
if (resources.length > 1) {
|
||||
contentText = I18n.t('project_resource_sidebar_confirm_batch_delete', {
|
||||
count: resources.length,
|
||||
});
|
||||
} else {
|
||||
contentText = I18n.t('project_resource_sidebar_confirm_delete', {
|
||||
resourceName: resources[0].name,
|
||||
});
|
||||
}
|
||||
return (
|
||||
<div className="break-all">
|
||||
<span className="coz-fg-secondary">{contentText}</span>
|
||||
{resources.length > 1 ? (
|
||||
<div className={styles['file-list-wrapper']}>
|
||||
<div className={styles['file-list']}>
|
||||
{resources.map(r => (
|
||||
<span className={styles['file-item']}>
|
||||
<span className={classnames(styles['file-icon'])}>
|
||||
{getResourceIconByResource(r)}
|
||||
</span>
|
||||
<span className={styles['file-name']}>{r.name}</span>
|
||||
</span>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
);
|
||||
}, [resources]);
|
||||
const modal = (
|
||||
<Modal
|
||||
type="dialog"
|
||||
okButtonColor="red"
|
||||
title={
|
||||
<span className="text-[16px] font-medium coz-fg-plus">
|
||||
{I18n.t('project_resource_sidebar_delete')}
|
||||
</span>
|
||||
}
|
||||
visible={visible}
|
||||
okText={I18n.t('Delete')}
|
||||
cancelText={I18n.t('Cancel')}
|
||||
autoLoading={true}
|
||||
onOk={async () => {
|
||||
await onDelete?.(resources);
|
||||
resources
|
||||
.map(resource =>
|
||||
resource.type ? getURIByResource(resource.type, resource.id) : null,
|
||||
)
|
||||
.filter((uri): uri is URI => Boolean(uri))
|
||||
.forEach(uri => projectIDEServices.view.closeWidgetByUri(uri));
|
||||
close();
|
||||
}}
|
||||
onCancel={() => close()}
|
||||
>
|
||||
{content}
|
||||
</Modal>
|
||||
);
|
||||
const handleDeleteResource = (res: ResourceType[]) => {
|
||||
console.log('[ResourceFolder]on delete resource>>>', res);
|
||||
const resourceToDelete = res.filter(r => r.id !== VARIABLE_RESOURCE_ID);
|
||||
if (!resourceToDelete.length) {
|
||||
return;
|
||||
}
|
||||
setResources(resourceToDelete);
|
||||
open();
|
||||
};
|
||||
return { node: modal, handleDeleteResource };
|
||||
};
|
||||
@@ -0,0 +1,297 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/* eslint-disable complexity */
|
||||
import React, { useCallback, useMemo } from 'react';
|
||||
|
||||
import classNames from 'classnames';
|
||||
import { I18n, type I18nKeysNoOptionsType } from '@coze-arch/i18n';
|
||||
import { IconCozWarningCircleFill } from '@coze-arch/coze-design/icons';
|
||||
import { Loading, Tooltip } from '@coze-arch/coze-design';
|
||||
import { useFlags } from '@coze-arch/bot-flags';
|
||||
import {
|
||||
type ProjectResourceAction,
|
||||
ProjectResourceActionKey,
|
||||
type ProjectResourceGroupType,
|
||||
} from '@coze-arch/bot-api/plugin_develop';
|
||||
import {
|
||||
type CommonRenderProps,
|
||||
getURIByResource,
|
||||
type RenderMoreSuffixType,
|
||||
type ResourceFolderProps,
|
||||
ResourceTypeEnum,
|
||||
type RightPanelConfigType,
|
||||
ROOT_KEY,
|
||||
} from '@coze-project-ide/framework';
|
||||
|
||||
import { usePrimarySidebarStore } from '@/stores';
|
||||
|
||||
import {
|
||||
getContextMenuLabel,
|
||||
getResourceIconByResource,
|
||||
isDynamicAction,
|
||||
isResourceActionEnabled,
|
||||
validateNameBasic,
|
||||
validateNameConflict,
|
||||
} from '../utils';
|
||||
import {
|
||||
type BizGroupTypeWithFolder,
|
||||
BizResourceContextMenuBtnType,
|
||||
type BizResourceType,
|
||||
BizResourceTypeEnum,
|
||||
type ResourceFolderCozeProps,
|
||||
type ResourceSubType,
|
||||
} from '../type';
|
||||
import { Empty } from '../empty';
|
||||
import {
|
||||
contextMenuDTOToVOMap,
|
||||
createResourceLabelMap,
|
||||
DISABLE_FOLDER,
|
||||
ITEM_HEIGHT,
|
||||
MAX_DEEP,
|
||||
TAB_SIZE,
|
||||
VARIABLE_RESOURCE_ID,
|
||||
} from '../constants';
|
||||
|
||||
export type UseResourceFolderConfigProps = {
|
||||
groupType: ProjectResourceGroupType;
|
||||
iconRender?: ResourceFolderProps['iconRender'];
|
||||
onAction?: (
|
||||
action: BizResourceContextMenuBtnType,
|
||||
resource?: BizResourceType,
|
||||
) => void;
|
||||
onCreateSubTypeResource?: (
|
||||
resourceType: BizGroupTypeWithFolder,
|
||||
subType?: ResourceSubType,
|
||||
) => void;
|
||||
createResourceConfig?: ResourceFolderCozeProps['createResourceConfig'];
|
||||
/**
|
||||
* 隐藏更多菜单按钮
|
||||
*/
|
||||
hideMoreBtn?: boolean;
|
||||
} & Pick<ResourceFolderProps, 'validateConfig'>;
|
||||
// eslint-disable-next-line @coze-arch/max-line-per-function
|
||||
export const useResourceFolderConfig = ({
|
||||
groupType,
|
||||
iconRender,
|
||||
onAction,
|
||||
onCreateSubTypeResource,
|
||||
createResourceConfig,
|
||||
validateConfig,
|
||||
hideMoreBtn,
|
||||
}: UseResourceFolderConfigProps): Partial<ResourceFolderProps> => {
|
||||
const textRender = useCallback(
|
||||
({ resource, isSelected }: CommonRenderProps) => (
|
||||
<span
|
||||
className={classNames('text-[14px]', isSelected ? 'font-medium' : '')}
|
||||
>
|
||||
{resource.name}
|
||||
</span>
|
||||
),
|
||||
[],
|
||||
);
|
||||
|
||||
const [FLAGS] = useFlags();
|
||||
|
||||
const contextMenuHandler = useCallback(
|
||||
(selectedResources: BizResourceType[]): RightPanelConfigType[] => {
|
||||
if (!selectedResources.length || hideMoreBtn) {
|
||||
return [];
|
||||
}
|
||||
if (selectedResources.length === 1) {
|
||||
const resource = selectedResources[0];
|
||||
if (resource.id === VARIABLE_RESOURCE_ID) {
|
||||
return [];
|
||||
}
|
||||
if (resource.id === ROOT_KEY) {
|
||||
// 新建文件夹,新建文件,引入资源库
|
||||
const createHandlers = createResourceConfig
|
||||
? createResourceConfig.map(({ label, subType }) => ({
|
||||
id: `${BizResourceContextMenuBtnType.CreateResource}-${subType}`,
|
||||
execute: () => onCreateSubTypeResource?.(groupType, subType),
|
||||
label,
|
||||
}))
|
||||
: [
|
||||
{
|
||||
id: BizResourceContextMenuBtnType.CreateResource,
|
||||
label: createResourceLabelMap[groupType],
|
||||
},
|
||||
];
|
||||
return [
|
||||
DISABLE_FOLDER
|
||||
? null
|
||||
: {
|
||||
id: BizResourceContextMenuBtnType.CreateFolder,
|
||||
label: createResourceLabelMap[ResourceTypeEnum.Folder],
|
||||
},
|
||||
...createHandlers,
|
||||
{
|
||||
id: BizResourceContextMenuBtnType.ImportLibraryResource,
|
||||
label: getContextMenuLabel(
|
||||
BizResourceContextMenuBtnType.ImportLibraryResource,
|
||||
),
|
||||
execute: () =>
|
||||
onAction?.(BizResourceContextMenuBtnType.ImportLibraryResource),
|
||||
},
|
||||
].filter(Boolean) as RightPanelConfigType[];
|
||||
}
|
||||
|
||||
const mapFunc = ({
|
||||
key,
|
||||
enable,
|
||||
hint,
|
||||
}: ProjectResourceAction): RightPanelConfigType | null => {
|
||||
const menuType = contextMenuDTOToVOMap[key];
|
||||
if (!menuType) {
|
||||
return null;
|
||||
}
|
||||
return {
|
||||
id: menuType,
|
||||
disabled: !enable,
|
||||
tooltip: I18n.t((hint || '') as I18nKeysNoOptionsType, {}, hint),
|
||||
label: getContextMenuLabel(menuType, resource),
|
||||
execute: isDynamicAction(menuType)
|
||||
? () => onAction?.(menuType, resource)
|
||||
: undefined,
|
||||
};
|
||||
};
|
||||
const noDeleteActions = resource.actions?.filter(
|
||||
action => action.key !== ProjectResourceActionKey.Delete,
|
||||
);
|
||||
|
||||
const deleteAction = resource.actions?.filter(
|
||||
action => action.key === ProjectResourceActionKey.Delete,
|
||||
);
|
||||
const noDeleteHandlers =
|
||||
noDeleteActions
|
||||
?.map<RightPanelConfigType | null>(mapFunc)
|
||||
?.filter((c): c is RightPanelConfigType => Boolean(c)) || [];
|
||||
const deleteHandler =
|
||||
deleteAction
|
||||
?.map<RightPanelConfigType | null>(mapFunc)
|
||||
?.filter((c): c is RightPanelConfigType => Boolean(c)) || [];
|
||||
|
||||
if (!noDeleteHandlers?.length || !deleteHandler?.length) {
|
||||
return [...noDeleteHandlers, ...deleteHandler];
|
||||
}
|
||||
return [...noDeleteHandlers, { type: 'separator' }, ...deleteHandler];
|
||||
}
|
||||
if (
|
||||
selectedResources.every(resource =>
|
||||
isResourceActionEnabled(resource, ProjectResourceActionKey.Delete),
|
||||
)
|
||||
) {
|
||||
return [
|
||||
{
|
||||
id: BizResourceContextMenuBtnType.Delete,
|
||||
label: getContextMenuLabel(BizResourceContextMenuBtnType.Delete),
|
||||
},
|
||||
];
|
||||
}
|
||||
return [];
|
||||
},
|
||||
[
|
||||
createResourceConfig,
|
||||
groupType,
|
||||
onAction,
|
||||
onCreateSubTypeResource,
|
||||
FLAGS,
|
||||
hideMoreBtn,
|
||||
],
|
||||
);
|
||||
|
||||
const setCanClosePopover = usePrimarySidebarStore(
|
||||
state => state.setCanClosePopover,
|
||||
);
|
||||
|
||||
return {
|
||||
textRender,
|
||||
iconRender: useCallback(
|
||||
(renderProps: CommonRenderProps): React.ReactElement | undefined => {
|
||||
const { resource, isExpand } = renderProps;
|
||||
const icon =
|
||||
iconRender?.(renderProps) ||
|
||||
getResourceIconByResource(resource, isExpand);
|
||||
return (
|
||||
<span className="inline-flex coz-fg-secondary text-[14px]">
|
||||
{icon}
|
||||
</span>
|
||||
);
|
||||
},
|
||||
[iconRender],
|
||||
),
|
||||
useOptimismUI: {
|
||||
loadingRender: () => (
|
||||
<Loading className="relative mr-1 top-0.5" loading={true} size="mini" />
|
||||
),
|
||||
},
|
||||
contextMenuHandler,
|
||||
validateConfig: useMemo(
|
||||
() => ({
|
||||
customValidator: params =>
|
||||
validateNameBasic(params) || validateNameConflict(params),
|
||||
errorMsgRender: msg => (
|
||||
<Tooltip theme={'dark'} position="right" content={msg}>
|
||||
<IconCozWarningCircleFill className="coz-fg-hglt-red absolute right-1 text-[13px]" />
|
||||
</Tooltip>
|
||||
),
|
||||
...validateConfig,
|
||||
}),
|
||||
[validateConfig],
|
||||
),
|
||||
config: useMemo(
|
||||
() => ({
|
||||
itemHeight: ITEM_HEIGHT,
|
||||
maxDeep: MAX_DEEP,
|
||||
tabSize: TAB_SIZE,
|
||||
input: {
|
||||
placeholder: I18n.t('project_resource_sidebar_please_enter'),
|
||||
style: { borderRadius: 'var(--coze-4)' },
|
||||
},
|
||||
resourceUriHandler: resource =>
|
||||
resource.type
|
||||
? getURIByResource(resource.type as string, resource.id)
|
||||
: null,
|
||||
}),
|
||||
[],
|
||||
),
|
||||
renderMoreSuffix: useMemo<RenderMoreSuffixType>(
|
||||
() =>
|
||||
hideMoreBtn
|
||||
? false
|
||||
: {
|
||||
style: { borderRadius: 'var(--coze-4)' },
|
||||
render: ({ baseBtn, resource }) => {
|
||||
if (
|
||||
resource.type === BizResourceTypeEnum.Variable ||
|
||||
((resource as BizResourceType).actions || []).length === 0
|
||||
) {
|
||||
return <></>;
|
||||
}
|
||||
return baseBtn;
|
||||
},
|
||||
},
|
||||
[hideMoreBtn],
|
||||
),
|
||||
empty: <Empty type={groupType} />,
|
||||
powerBlackMap: {
|
||||
dragAndDrop: false,
|
||||
folder: DISABLE_FOLDER,
|
||||
},
|
||||
onContextMenuVisibleChange: (visible: boolean) =>
|
||||
setCanClosePopover(!visible),
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* 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 { useLocation } from 'react-router-dom';
|
||||
import { useEffect } from 'react';
|
||||
|
||||
import { useShallow } from 'zustand/react/shallow';
|
||||
import {
|
||||
getResourceByPathname,
|
||||
type ResourceType,
|
||||
ResourceTypeEnum,
|
||||
useIDENavigate,
|
||||
} from '@coze-project-ide/framework';
|
||||
|
||||
import { usePrimarySidebarStore } from '@/stores';
|
||||
import { BizResourceTypeEnum } from '@/resource-folder-coze/type';
|
||||
|
||||
export const useResourceOpen = () => {
|
||||
const { selectedResource, setSelectedResource } = usePrimarySidebarStore(
|
||||
useShallow(store => ({
|
||||
selectedResource: store.selectedResource,
|
||||
setSelectedResource: store.setSelectedResource,
|
||||
})),
|
||||
);
|
||||
const location = useLocation();
|
||||
const navigate = useIDENavigate();
|
||||
const handleOpenResource = (
|
||||
resourceId: string | number,
|
||||
resource: ResourceType,
|
||||
) => {
|
||||
if (resource.type === ResourceTypeEnum.Folder) {
|
||||
return;
|
||||
}
|
||||
if (resource.type === BizResourceTypeEnum.Variable) {
|
||||
navigate(`/${resource.type}`);
|
||||
return;
|
||||
}
|
||||
navigate(`/${resource.type}/${resourceId}`);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (location) {
|
||||
const { resourceType, resourceId } = getResourceByPathname(
|
||||
location.pathname,
|
||||
);
|
||||
if (resourceType === BizResourceTypeEnum.Variable) {
|
||||
setSelectedResource(resourceType);
|
||||
} else {
|
||||
setSelectedResource(resourceId);
|
||||
}
|
||||
}
|
||||
}, [location]);
|
||||
|
||||
return { selectedResource, handleOpenResource };
|
||||
};
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* 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 React from 'react';
|
||||
|
||||
import {
|
||||
getURIByResource,
|
||||
type ResourceFolderProps,
|
||||
ResourceTypeEnum,
|
||||
useProjectIDEServices,
|
||||
} from '@coze-project-ide/framework';
|
||||
|
||||
import { type ResourceFolderCozeProps } from '../type';
|
||||
export const withRenameSync =
|
||||
(Comp: FC<ResourceFolderCozeProps>): FC<ResourceFolderCozeProps> =>
|
||||
({ onChangeName, ...props }) => {
|
||||
const { view } = useProjectIDEServices();
|
||||
const wrappedChangeName: ResourceFolderProps['onChangeName'] =
|
||||
async event => {
|
||||
await onChangeName?.(event);
|
||||
if (
|
||||
event.resource?.type &&
|
||||
event.resource?.id &&
|
||||
event.resource.type !== ResourceTypeEnum.Folder
|
||||
) {
|
||||
const uri = getURIByResource(event.resource.type, event.resource.id);
|
||||
const widgetContext = view.getWidgetContextFromURI(uri);
|
||||
widgetContext?.widget?.setTitle(event.name);
|
||||
}
|
||||
};
|
||||
return <Comp {...props} onChangeName={wrappedChangeName} />;
|
||||
};
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* 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 { ResourceFolderCoze } from './resource-folder-coze';
|
||||
export {
|
||||
BizResourceTypeEnum,
|
||||
type BizResourceType,
|
||||
type ResourceFolderCozeProps,
|
||||
type BizResourceTree,
|
||||
BizResourceContextMenuBtnType,
|
||||
} from './type';
|
||||
export {
|
||||
createResourceFolderPlugin,
|
||||
CustomResourceFolderShortcutService,
|
||||
} from './plugins';
|
||||
export { VARIABLE_RESOURCE_ID } from './constants';
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* 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 {
|
||||
definePluginCreator,
|
||||
type PluginCreator,
|
||||
bindContributions,
|
||||
CommandContribution,
|
||||
ShortcutsContribution,
|
||||
} from '@coze-project-ide/framework';
|
||||
|
||||
import { CustomResourceFolderShortcutService } from './shortcut-service';
|
||||
import { ResourceFolderContribution } from './resource-folder-contribution';
|
||||
export { CustomResourceFolderShortcutService };
|
||||
export const createResourceFolderPlugin: PluginCreator<void> =
|
||||
definePluginCreator({
|
||||
onBind({ bind }) {
|
||||
bind(CustomResourceFolderShortcutService).toSelf().inSingletonScope();
|
||||
bindContributions(bind, ResourceFolderContribution, [
|
||||
CommandContribution,
|
||||
ShortcutsContribution,
|
||||
]);
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
* 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 { createResourceFolderPlugin } from './create-resource-folder-plugin';
|
||||
export { CustomResourceFolderShortcutService } from './shortcut-service';
|
||||
@@ -0,0 +1,166 @@
|
||||
/*
|
||||
* 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 { inject, injectable, postConstruct } from 'inversify';
|
||||
import { I18n } from '@coze-arch/i18n';
|
||||
import {
|
||||
type CommandContribution,
|
||||
type CommandRegistry,
|
||||
ContextKeyService,
|
||||
RESOURCE_FOLDER_CONTEXT_KEY,
|
||||
type ResourceFolderShortCutContextType,
|
||||
type ShortcutsContribution,
|
||||
type ShortcutsRegistry,
|
||||
} from '@coze-project-ide/framework';
|
||||
|
||||
import { BizResourceContextMenuBtnType } from '../type';
|
||||
import { CustomResourceFolderShortcutService } from './shortcut-service';
|
||||
|
||||
const SHORTCUT_HANDLER_RESOURCE = 'resourceFolder';
|
||||
@injectable()
|
||||
export class ResourceFolderContribution
|
||||
implements CommandContribution, ShortcutsContribution
|
||||
{
|
||||
@inject(CustomResourceFolderShortcutService)
|
||||
protected readonly shortcutService: CustomResourceFolderShortcutService;
|
||||
@inject(ContextKeyService)
|
||||
protected readonly contextKey: ContextKeyService;
|
||||
|
||||
@postConstruct()
|
||||
init() {
|
||||
this.contextKey.setContext(RESOURCE_FOLDER_CONTEXT_KEY, undefined);
|
||||
}
|
||||
|
||||
registerShortcuts(registry: ShortcutsRegistry): void {
|
||||
// 重命名
|
||||
registry.registerHandlers({
|
||||
commandId: BizResourceContextMenuBtnType.Rename,
|
||||
keybinding: 'enter',
|
||||
preventDefault: false,
|
||||
source: SHORTCUT_HANDLER_RESOURCE,
|
||||
when: RESOURCE_FOLDER_CONTEXT_KEY,
|
||||
});
|
||||
|
||||
// 删除
|
||||
registry.registerHandlers({
|
||||
commandId: BizResourceContextMenuBtnType.Delete,
|
||||
keybinding: 'meta backspace',
|
||||
preventDefault: false,
|
||||
source: SHORTCUT_HANDLER_RESOURCE,
|
||||
when: RESOURCE_FOLDER_CONTEXT_KEY,
|
||||
});
|
||||
|
||||
// 创建文件夹
|
||||
registry.registerHandlers({
|
||||
commandId: BizResourceContextMenuBtnType.CreateFolder,
|
||||
keybinding: 'alt shift n',
|
||||
preventDefault: false,
|
||||
source: SHORTCUT_HANDLER_RESOURCE,
|
||||
when: RESOURCE_FOLDER_CONTEXT_KEY,
|
||||
});
|
||||
|
||||
// 创建资源
|
||||
registry.registerHandlers({
|
||||
commandId: BizResourceContextMenuBtnType.CreateResource,
|
||||
keybinding: 'alt n',
|
||||
preventDefault: false,
|
||||
source: SHORTCUT_HANDLER_RESOURCE,
|
||||
when: RESOURCE_FOLDER_CONTEXT_KEY,
|
||||
});
|
||||
|
||||
// 创建副本
|
||||
registry.registerHandlers({
|
||||
commandId: BizResourceContextMenuBtnType.DuplicateResource,
|
||||
keybinding: 'alt d',
|
||||
preventDefault: false,
|
||||
source: SHORTCUT_HANDLER_RESOURCE,
|
||||
when: RESOURCE_FOLDER_CONTEXT_KEY,
|
||||
});
|
||||
}
|
||||
registerCommands(commands: CommandRegistry): void {
|
||||
// 重命名 command
|
||||
commands.registerCommand(
|
||||
{
|
||||
id: BizResourceContextMenuBtnType.Rename,
|
||||
label: I18n.t('project_resource_sidebar_rename'),
|
||||
},
|
||||
{
|
||||
execute: () => this.shortcutService.renameResource(),
|
||||
|
||||
isEnabled: opt => !opt?.disabled,
|
||||
isVisible: opt => !opt?.isHidden,
|
||||
},
|
||||
);
|
||||
|
||||
// 删除 command
|
||||
commands.registerCommand(
|
||||
{
|
||||
id: BizResourceContextMenuBtnType.Delete,
|
||||
},
|
||||
{
|
||||
execute: () => this.shortcutService.deleteResource(),
|
||||
isEnabled: opt => !opt?.disabled,
|
||||
isVisible: opt => !opt?.isHidden,
|
||||
},
|
||||
);
|
||||
|
||||
// 新建文件夹 command
|
||||
commands.registerCommand(
|
||||
{
|
||||
id: BizResourceContextMenuBtnType.CreateFolder,
|
||||
label: I18n.t('project_resource_sidebar_create_new_folder'),
|
||||
},
|
||||
{
|
||||
execute: () => {
|
||||
const resourceFolderDispatch =
|
||||
this.contextKey.getContext<ResourceFolderShortCutContextType>(
|
||||
RESOURCE_FOLDER_CONTEXT_KEY,
|
||||
);
|
||||
resourceFolderDispatch?.onCreateFolder?.();
|
||||
},
|
||||
// 禁用文件夹创建
|
||||
isEnabled: opt => false, //!opt?.disabled,
|
||||
isVisible: opt => !opt?.isHidden,
|
||||
},
|
||||
);
|
||||
|
||||
// 新建资源 command
|
||||
commands.registerCommand(
|
||||
{
|
||||
id: BizResourceContextMenuBtnType.CreateResource,
|
||||
label: 'Create Resource',
|
||||
shortLabel: 'Create Resource',
|
||||
},
|
||||
{
|
||||
execute: () => this.shortcutService.createResource(),
|
||||
isEnabled: opt => !opt?.disabled,
|
||||
isVisible: opt => !opt?.isHidden,
|
||||
},
|
||||
);
|
||||
// 新建副本 command
|
||||
commands.registerCommand(
|
||||
{
|
||||
id: BizResourceContextMenuBtnType.DuplicateResource,
|
||||
label: I18n.t('project_resource_sidebar_copy'),
|
||||
},
|
||||
{
|
||||
execute: () => this.shortcutService.duplicateResource(),
|
||||
isEnabled: opt => !opt?.disabled,
|
||||
isVisible: opt => !opt?.isHidden,
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
/*
|
||||
* 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 { inject, injectable } from 'inversify';
|
||||
import { ProjectResourceActionKey } from '@coze-arch/bot-api/plugin_develop';
|
||||
import {
|
||||
ContextKeyService,
|
||||
Emitter,
|
||||
type Event,
|
||||
RESOURCE_FOLDER_CONTEXT_KEY,
|
||||
type ResourceFolderShortCutContextType,
|
||||
type IdType,
|
||||
} from '@coze-project-ide/framework';
|
||||
|
||||
import { isResourceActionEnabled } from '../utils';
|
||||
import { type BizResourceType } from '../type';
|
||||
|
||||
export type DuplicateEvent = Pick<
|
||||
ResourceFolderShortCutContextType,
|
||||
'id' | 'tempSelectedMap'
|
||||
>;
|
||||
|
||||
export interface RenameEvent {
|
||||
id: IdType;
|
||||
}
|
||||
|
||||
export type CreateResourceEvent = Pick<ResourceFolderShortCutContextType, 'id'>;
|
||||
@injectable()
|
||||
export class CustomResourceFolderShortcutService {
|
||||
private onDuplicateEmitter = new Emitter<DuplicateEvent>();
|
||||
private onCreateResourceEmitter = new Emitter<CreateResourceEvent>();
|
||||
@inject(ContextKeyService)
|
||||
protected readonly contextKey: ContextKeyService;
|
||||
public onDuplicateEvent: Event<DuplicateEvent> =
|
||||
this.onDuplicateEmitter.event;
|
||||
public onCreateResourceEvent: Event<CreateResourceEvent> =
|
||||
this.onCreateResourceEmitter.event;
|
||||
private onRenameResourceEmitter = new Emitter<RenameEvent>();
|
||||
public onRenameResource = this.onRenameResourceEmitter.event;
|
||||
|
||||
public isResourceActionEnabled(action: ProjectResourceActionKey): boolean {
|
||||
return Object.values(
|
||||
this.resourceFolderDispatch?.tempSelectedMap || {},
|
||||
).every(resource =>
|
||||
isResourceActionEnabled(resource as BizResourceType, action),
|
||||
);
|
||||
}
|
||||
|
||||
public renameResource(id?: IdType) {
|
||||
if (id) {
|
||||
this.onRenameResourceEmitter.fire({ id });
|
||||
return;
|
||||
}
|
||||
if (this.isResourceActionEnabled(ProjectResourceActionKey.Rename)) {
|
||||
this.resourceFolderDispatch?.onEnter?.();
|
||||
}
|
||||
}
|
||||
|
||||
public deleteResource() {
|
||||
if (this.isResourceActionEnabled(ProjectResourceActionKey.Delete)) {
|
||||
this.resourceFolderDispatch?.onDelete?.();
|
||||
}
|
||||
}
|
||||
|
||||
public duplicateResource() {
|
||||
if (this.isResourceActionEnabled(ProjectResourceActionKey.Copy)) {
|
||||
this.onDuplicateEmitter.fire({
|
||||
id: this.resourceFolderDispatch.id,
|
||||
tempSelectedMap: this.resourceFolderDispatch.tempSelectedMap,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private get resourceFolderDispatch() {
|
||||
return this.contextKey.getContext<ResourceFolderShortCutContextType>(
|
||||
RESOURCE_FOLDER_CONTEXT_KEY,
|
||||
);
|
||||
}
|
||||
|
||||
public createResource() {
|
||||
this.onCreateResourceEmitter.fire({
|
||||
id: this.resourceFolderDispatch.id,
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,247 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import React, {
|
||||
type FC,
|
||||
type RefObject,
|
||||
useEffect,
|
||||
useMemo,
|
||||
useRef,
|
||||
} from 'react';
|
||||
|
||||
import { type ProjectResourceGroupType } from '@coze-arch/bot-api/plugin_develop';
|
||||
import {
|
||||
mapResourceTree,
|
||||
ResourceFolder,
|
||||
type ResourceFolderProps,
|
||||
type ResourceFolderRefType,
|
||||
ResourceTypeEnum,
|
||||
useIDEService,
|
||||
} from '@coze-project-ide/framework';
|
||||
|
||||
import { usePrimarySidebarStore } from '@/stores';
|
||||
|
||||
import {
|
||||
type BizGroupTypeWithFolder,
|
||||
BizResourceContextMenuBtnType,
|
||||
type ResourceFolderCozeProps,
|
||||
type ResourceSubType,
|
||||
} from './type';
|
||||
import { ResourceGroupActions } from './resource-group-actions';
|
||||
import { ResourceGroup } from './resource-group';
|
||||
import { CustomResourceFolderShortcutService } from './plugins/shortcut-service';
|
||||
import {
|
||||
useDeleteModal,
|
||||
useResourceFolderConfig,
|
||||
useResourceOpen,
|
||||
withRenameSync,
|
||||
} from './hooks';
|
||||
import { resourceTitleMap } from './constants';
|
||||
|
||||
import styles from './styles.module.less';
|
||||
|
||||
// eslint-disable-next-line @coze-arch/max-line-per-function
|
||||
const ResourceFolderCozeImpl: FC<ResourceFolderCozeProps> = ({
|
||||
groupType,
|
||||
resourceTree,
|
||||
onDelete,
|
||||
onAction,
|
||||
onCreate,
|
||||
onCustomCreate,
|
||||
canCreate,
|
||||
iconRender,
|
||||
initLoaded,
|
||||
createResourceConfig,
|
||||
defaultResourceType,
|
||||
validateConfig,
|
||||
hideMoreBtn,
|
||||
...props
|
||||
}) => {
|
||||
const resourceMap = useMemo(
|
||||
() => mapResourceTree(resourceTree),
|
||||
[resourceTree],
|
||||
);
|
||||
|
||||
const ref = useRef<ResourceFolderRefType>();
|
||||
const handleFocusResourceFolder = (visible: boolean) => {
|
||||
if (visible) {
|
||||
ref.current?.focus();
|
||||
ref.current?.closeContextMenu();
|
||||
}
|
||||
};
|
||||
|
||||
const groupExpandMap = usePrimarySidebarStore(state => state.groupExpandMap);
|
||||
const updateGroupExpand = usePrimarySidebarStore(
|
||||
state => state.updateGroupExpand,
|
||||
);
|
||||
|
||||
const handleExpandChange = (_expand: boolean) => {
|
||||
ref.current?.focus();
|
||||
updateGroupExpand?.(groupType, _expand);
|
||||
};
|
||||
|
||||
const shortcutService = useIDEService<CustomResourceFolderShortcutService>(
|
||||
CustomResourceFolderShortcutService,
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
const disposable1 = shortcutService.onDuplicateEvent(event => {
|
||||
if (event.id !== props.id) {
|
||||
return;
|
||||
}
|
||||
const selectResources = Object.values(event.tempSelectedMap || {}).filter(
|
||||
item => item.type !== ResourceTypeEnum.Folder,
|
||||
);
|
||||
if (!selectResources?.length) {
|
||||
return;
|
||||
}
|
||||
if (selectResources.length === 1) {
|
||||
onAction?.(
|
||||
BizResourceContextMenuBtnType.DuplicateResource,
|
||||
selectResources[0],
|
||||
);
|
||||
}
|
||||
});
|
||||
const disposable2 = shortcutService.onCreateResourceEvent(event => {
|
||||
if (!canCreate) {
|
||||
return;
|
||||
}
|
||||
if (event.id !== props.id) {
|
||||
return;
|
||||
}
|
||||
// 多个创建资源菜单,不使用快捷键
|
||||
if (createResourceConfig) {
|
||||
return;
|
||||
}
|
||||
// 快捷键触发的创建资源
|
||||
handleCreateResource(groupType);
|
||||
});
|
||||
|
||||
return () => {
|
||||
disposable1.dispose();
|
||||
disposable2.dispose();
|
||||
};
|
||||
}, [
|
||||
defaultResourceType,
|
||||
groupType,
|
||||
onCustomCreate,
|
||||
onAction,
|
||||
shortcutService,
|
||||
canCreate,
|
||||
createResourceConfig,
|
||||
]);
|
||||
|
||||
useEffect(() => {
|
||||
const disposable = shortcutService.onRenameResource(event => {
|
||||
ref.current?.renameResource(event.id);
|
||||
});
|
||||
return () => {
|
||||
disposable.dispose();
|
||||
};
|
||||
}, [shortcutService]);
|
||||
|
||||
const creatingResourceSubTypeRef = useRef<ResourceSubType>();
|
||||
const handleCreateResource = (
|
||||
_groupType: BizGroupTypeWithFolder,
|
||||
subType?: ResourceSubType,
|
||||
) => {
|
||||
if (!canCreate) {
|
||||
return;
|
||||
}
|
||||
handleExpandChange(true);
|
||||
if (_groupType === ResourceTypeEnum.Folder) {
|
||||
ref.current?.createFolder();
|
||||
} else {
|
||||
if (onCustomCreate) {
|
||||
onCustomCreate(_groupType, subType);
|
||||
} else if (defaultResourceType) {
|
||||
creatingResourceSubTypeRef.current = subType;
|
||||
ref.current?.createResource(defaultResourceType);
|
||||
} else {
|
||||
console.error(
|
||||
'[ResourceFolderCoze]must specify defaultResourceType when use props onCreate creating resource',
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const handleDefaultCreateResource: ResourceFolderProps['onCreate'] =
|
||||
createEvent => onCreate?.(createEvent, creatingResourceSubTypeRef.current);
|
||||
|
||||
const handleImportResource = (_groupType: ProjectResourceGroupType) => {
|
||||
if (!canCreate) {
|
||||
return;
|
||||
}
|
||||
handleExpandChange(true);
|
||||
onAction?.(BizResourceContextMenuBtnType.ImportLibraryResource);
|
||||
};
|
||||
|
||||
const { handleDeleteResource, node: deleteModal } = useDeleteModal({
|
||||
onDelete,
|
||||
});
|
||||
|
||||
const configProps = useResourceFolderConfig({
|
||||
groupType,
|
||||
iconRender,
|
||||
onAction,
|
||||
createResourceConfig,
|
||||
validateConfig,
|
||||
onCreateSubTypeResource: handleCreateResource,
|
||||
hideMoreBtn,
|
||||
});
|
||||
|
||||
const { selectedResource, handleOpenResource } = useResourceOpen();
|
||||
return (
|
||||
<>
|
||||
<ResourceGroup
|
||||
className={styles['resource-folder-coze']}
|
||||
title={resourceTitleMap[groupType]}
|
||||
content={
|
||||
initLoaded ? (
|
||||
<ResourceFolder
|
||||
ref={ref as RefObject<ResourceFolderRefType>}
|
||||
resourceTree={resourceTree}
|
||||
resourceMap={resourceMap}
|
||||
onDelete={handleDeleteResource}
|
||||
onCreate={handleDefaultCreateResource}
|
||||
selected={selectedResource}
|
||||
onSelected={handleOpenResource}
|
||||
defaultResourceType={defaultResourceType}
|
||||
{...configProps}
|
||||
{...props}
|
||||
/>
|
||||
) : null
|
||||
}
|
||||
expand={groupExpandMap[groupType]}
|
||||
onExpandChange={handleExpandChange}
|
||||
actions={
|
||||
canCreate ? (
|
||||
<ResourceGroupActions
|
||||
createResourceConfig={createResourceConfig}
|
||||
groupType={groupType}
|
||||
onCreateResource={handleCreateResource}
|
||||
onImportResource={handleImportResource}
|
||||
onActionVisibleChange={handleFocusResourceFolder}
|
||||
/>
|
||||
) : null
|
||||
}
|
||||
/>
|
||||
{deleteModal}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export const ResourceFolderCoze = withRenameSync(ResourceFolderCozeImpl);
|
||||
@@ -0,0 +1,168 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import React, { useMemo } from 'react';
|
||||
|
||||
import {
|
||||
ResourceTypeEnum,
|
||||
ShortcutsService,
|
||||
useIDEService,
|
||||
} from '@coze-project-ide/framework';
|
||||
import { I18n } from '@coze-arch/i18n';
|
||||
import {
|
||||
IconCozPlus,
|
||||
IconCozFolder,
|
||||
IconCozTray,
|
||||
} from '@coze-arch/coze-design/icons';
|
||||
import { IconButton, Menu, Tooltip } from '@coze-arch/coze-design';
|
||||
import { ProjectResourceGroupType } from '@coze-arch/bot-api/plugin_develop';
|
||||
|
||||
import {
|
||||
type BizGroupTypeWithFolder,
|
||||
BizResourceContextMenuBtnType,
|
||||
type ResourceFolderCozeProps,
|
||||
type ResourceSubType,
|
||||
} from './type';
|
||||
import {
|
||||
createResourceIconMap,
|
||||
createResourceLabelMap,
|
||||
DISABLE_FOLDER,
|
||||
} from './constants';
|
||||
|
||||
import styles from './styles.module.less';
|
||||
|
||||
const ProjectResourceStringType = {
|
||||
[ProjectResourceGroupType.Workflow]: 'workflow',
|
||||
[ProjectResourceGroupType.Plugin]: 'plugin',
|
||||
[ProjectResourceGroupType.Data]: 'data',
|
||||
};
|
||||
|
||||
interface ResourceGroupActionsProps {
|
||||
groupType: ProjectResourceGroupType;
|
||||
onActionVisibleChange?: (visible: boolean) => void;
|
||||
onCreateResource?: (
|
||||
groupType: BizGroupTypeWithFolder,
|
||||
subType?: ResourceSubType,
|
||||
) => void;
|
||||
onImportResource?: (groupType: ProjectResourceGroupType) => void;
|
||||
createResourceConfig: ResourceFolderCozeProps['createResourceConfig'];
|
||||
}
|
||||
|
||||
export const ResourceGroupActions: React.FC<ResourceGroupActionsProps> = ({
|
||||
groupType,
|
||||
onActionVisibleChange,
|
||||
onCreateResource,
|
||||
onImportResource,
|
||||
createResourceConfig,
|
||||
}) => {
|
||||
const shortcutService = useIDEService<ShortcutsService>(ShortcutsService);
|
||||
const keybindingContent = useMemo(() => {
|
||||
const keybindings = shortcutService.getShortcutByCommandId(
|
||||
BizResourceContextMenuBtnType.CreateResource,
|
||||
);
|
||||
return keybindings?.map(k => k.join(' ')).join(' / ') || '';
|
||||
}, [shortcutService]);
|
||||
|
||||
const createResourceNode = Array.isArray(createResourceConfig) ? (
|
||||
createResourceConfig.map(({ icon, label, tooltip, subType }) => {
|
||||
const children = (
|
||||
<Menu.Item
|
||||
data-testid={`project-ide.resource-group.actions.menu-item.${subType}`}
|
||||
onClick={(value, event) => {
|
||||
event.stopPropagation();
|
||||
onCreateResource?.(groupType, subType);
|
||||
}}
|
||||
icon={icon}
|
||||
>
|
||||
{label}
|
||||
</Menu.Item>
|
||||
);
|
||||
if (tooltip) {
|
||||
return (
|
||||
<Tooltip
|
||||
trigger="hover"
|
||||
position="rightTop"
|
||||
key={subType}
|
||||
showArrow={false}
|
||||
content={tooltip}
|
||||
style={{ width: 208, padding: 4, borderRadius: 'var(--coze-8)' }}
|
||||
>
|
||||
{children}
|
||||
</Tooltip>
|
||||
);
|
||||
}
|
||||
return children;
|
||||
})
|
||||
) : (
|
||||
<Menu.Item
|
||||
suffix={<span className={styles.shortcut}>{keybindingContent}</span>}
|
||||
onClick={(value, event) => {
|
||||
event.stopPropagation();
|
||||
onCreateResource?.(groupType);
|
||||
}}
|
||||
icon={createResourceIconMap[groupType]}
|
||||
>
|
||||
{createResourceLabelMap[groupType]}
|
||||
</Menu.Item>
|
||||
);
|
||||
const menuWidth = useMemo(() => (IS_OVERSEA ? 260 : 198), []);
|
||||
return (
|
||||
<Menu
|
||||
trigger="hover"
|
||||
position="bottomLeft"
|
||||
onVisibleChange={visible => onActionVisibleChange?.(visible)}
|
||||
render={
|
||||
<div onClick={e => e.stopPropagation()}>
|
||||
<Menu.SubMenu
|
||||
className={'w-[198px]'}
|
||||
mode="menu"
|
||||
style={{ width: menuWidth }}
|
||||
>
|
||||
{DISABLE_FOLDER ? null : (
|
||||
<Menu.Item
|
||||
onClick={(value, event) => {
|
||||
event.stopPropagation();
|
||||
onCreateResource?.(ResourceTypeEnum.Folder);
|
||||
}}
|
||||
icon={<IconCozFolder />}
|
||||
>
|
||||
{I18n.t('project_resource_sidebar_create_new_folder')}
|
||||
</Menu.Item>
|
||||
)}
|
||||
{createResourceNode}
|
||||
<Menu.Item
|
||||
onClick={(value, event) => {
|
||||
event.stopPropagation();
|
||||
onImportResource?.(groupType);
|
||||
}}
|
||||
icon={<IconCozTray />}
|
||||
>
|
||||
{I18n.t('project_resource_sidebar_import_from_library')}
|
||||
</Menu.Item>
|
||||
</Menu.SubMenu>
|
||||
</div>
|
||||
}
|
||||
>
|
||||
<IconButton
|
||||
data-testid={`project-${ProjectResourceStringType[groupType]}-add-resource`}
|
||||
color="secondary"
|
||||
size="small"
|
||||
icon={<IconCozPlus className="coz-fg-primary" />}
|
||||
onClick={e => e.stopPropagation()}
|
||||
/>
|
||||
</Menu>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,34 @@
|
||||
.resource-group {
|
||||
.resource-group-header {
|
||||
cursor: pointer;
|
||||
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
|
||||
height: 36px;
|
||||
padding: 0 14px 0 17px;
|
||||
|
||||
.header-left {
|
||||
display: flex;
|
||||
gap: 4px;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.header-title {
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
line-height: 20px;
|
||||
}
|
||||
|
||||
.action-group {
|
||||
display: flex;
|
||||
gap: 2px;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
|
||||
.resource-group-content {
|
||||
padding: 0 6px;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import classNames from 'classnames';
|
||||
|
||||
import { ExpandableArrow } from './expandable-arrow';
|
||||
|
||||
import styles from './resource-group.module.less';
|
||||
export interface ResourceGroupProps {
|
||||
title: string;
|
||||
expand?: boolean;
|
||||
className?: string;
|
||||
onExpandChange?: (expand: boolean) => void;
|
||||
actions?: React.ReactNode;
|
||||
content?: React.ReactNode;
|
||||
}
|
||||
|
||||
export const ResourceGroup = ({
|
||||
title,
|
||||
actions,
|
||||
content,
|
||||
expand,
|
||||
onExpandChange,
|
||||
className,
|
||||
}: ResourceGroupProps) => (
|
||||
<div className={classNames(className, styles['resource-group'])}>
|
||||
<div
|
||||
className={styles['resource-group-header']}
|
||||
onClick={() => onExpandChange?.(!expand)}
|
||||
>
|
||||
<div className={styles['header-left']}>
|
||||
<ExpandableArrow expand={expand} />
|
||||
<span className={styles['header-title']}>{title}</span>
|
||||
</div>
|
||||
{actions ? <div className={styles['action-group']}>{actions}</div> : null}
|
||||
</div>
|
||||
<div
|
||||
className={styles['resource-group-content']}
|
||||
style={expand ? undefined : { display: 'none' }}
|
||||
>
|
||||
{content}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
@@ -0,0 +1,159 @@
|
||||
.resource-list {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.resource-folder-coze {
|
||||
:global {
|
||||
.resource-list-wrapper .resource-list-drag-and-drop-wrapper {
|
||||
.item-is-selected {
|
||||
background-color: var(--coz-mg-primary);
|
||||
|
||||
&:hover {
|
||||
background-color: var(--coz-mg-secondary-hovered);
|
||||
}
|
||||
}
|
||||
|
||||
.item-is-temp-selected {
|
||||
&.item-is-selected {
|
||||
background-color: var(--coz-mg-primary);
|
||||
}
|
||||
}
|
||||
|
||||
.base-item-hover-class:hover {
|
||||
background-color: var(--coz-mg-secondary-hovered);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.shortcut {
|
||||
font-family: Inter, sans-serif;
|
||||
font-size: 12px;
|
||||
font-weight: 700;
|
||||
color: var(--coz-fg-dim);
|
||||
}
|
||||
|
||||
.file-list-wrapper {
|
||||
overflow: auto;
|
||||
|
||||
max-height: 124px;
|
||||
margin-top: 4px;
|
||||
|
||||
border: 1px solid var(--coz-stroke-primary);
|
||||
border-radius: var(--coze-8);
|
||||
|
||||
&::-webkit-scrollbar {
|
||||
width: 0;
|
||||
height: 10px;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar:hover {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar-thumb {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar-corner {
|
||||
background: transparent;
|
||||
}
|
||||
}
|
||||
|
||||
.file-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
padding: 6px 0;
|
||||
|
||||
|
||||
.file-item {
|
||||
overflow: hidden;
|
||||
|
||||
width: 100%;
|
||||
height: 22px;
|
||||
padding: 0 8px;
|
||||
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
|
||||
.file-icon {
|
||||
position: relative;
|
||||
top: 2px;
|
||||
margin-right: 4px;
|
||||
color: var(--coz-fg-secondary);
|
||||
}
|
||||
|
||||
.file-name {
|
||||
font-size: 14px;
|
||||
color: var(--coz-fg-primary);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.empty {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
width: 232px;
|
||||
height: 80px;
|
||||
margin: 0 auto;
|
||||
|
||||
.empty-card {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
gap: 4px;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
|
||||
padding: 4.5px;
|
||||
|
||||
background-color: var(--coz-bg-max);
|
||||
border: 0.5px solid rgb(240, 240, 240);
|
||||
border-radius: var(--coze-4);
|
||||
|
||||
}
|
||||
|
||||
.empty-icon {
|
||||
width: 15px;
|
||||
height: 15px;
|
||||
background-color: var(--coz-mg-primary);
|
||||
border-radius: var(--coze-3);
|
||||
}
|
||||
|
||||
.empty-skeleton {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 2.5px;
|
||||
align-items: flex-start;
|
||||
|
||||
opacity: 0.12;
|
||||
|
||||
span {
|
||||
height: 4.5px;
|
||||
background-color: var(--coz-fg-secondary);
|
||||
border-radius: var(--coze-2);
|
||||
|
||||
&:first-child {
|
||||
width: 20px;
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
width: 33px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.empty-title {
|
||||
font-size: 12px;
|
||||
font-weight: 400;
|
||||
line-height: 16px;
|
||||
color: var(--coz-fg-dim);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,153 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import type { ReactNode } from 'react';
|
||||
|
||||
import {
|
||||
type ProjectResourceGroupType,
|
||||
type ProjectResourceInfo,
|
||||
} from '@coze-arch/bot-api/plugin_develop';
|
||||
import {
|
||||
type CreateResourcePropType,
|
||||
type ResourceFolderProps,
|
||||
type ResourceType,
|
||||
type ResourceTypeEnum,
|
||||
} from '@coze-project-ide/framework';
|
||||
|
||||
/**
|
||||
* 用于 ResourceType['type'] 里指定资源类型
|
||||
*/
|
||||
export enum BizResourceTypeEnum {
|
||||
Workflow = 'workflow',
|
||||
Plugin = 'plugin',
|
||||
Knowledge = 'knowledge',
|
||||
Database = 'database',
|
||||
Variable = 'variables',
|
||||
}
|
||||
|
||||
export interface BizResourceTree {
|
||||
groupType?: ProjectResourceGroupType;
|
||||
resourceList: BizResourceType[];
|
||||
}
|
||||
|
||||
export enum BizResourceContextMenuBtnType {
|
||||
/* 创建资源 */
|
||||
CreateResource = 'resource-folder-create-resource',
|
||||
/* 创建文件夹 */
|
||||
CreateFolder = 'resource-folder-create-folder',
|
||||
/* 重命名 */
|
||||
Rename = 'resource-folder-rename',
|
||||
/* 删除 */
|
||||
Delete = 'resource-folder-delete',
|
||||
|
||||
/* ----------------- 下面的事件会通过 onAction 进行回调 ----------------- */
|
||||
/* 创建副本 */
|
||||
DuplicateResource = 'resource-folder-duplicate-resource',
|
||||
/* 引入资源库文件 */
|
||||
ImportLibraryResource = 'resource-folder-import-library-resource',
|
||||
/* 移动到资源库 */
|
||||
MoveToLibrary = 'resource-folder-move-to-library',
|
||||
/* 复制到资源库 */
|
||||
CopyToLibrary = 'resource-folder-copy-to-library',
|
||||
/* 启用知识库 */
|
||||
EnableKnowledge = 'resource-folder-enable-knowledge',
|
||||
/* 禁用知识库 */
|
||||
DisableKnowledge = 'resource-folder-disable-knowledge',
|
||||
/* 切换为 chatflow */
|
||||
SwitchToChatflow = 'resource-folder-switch-to-chatflow',
|
||||
/* 切换为 workflow */
|
||||
SwitchToWorkflow = 'resource-folder-switch-to-workflow',
|
||||
/* 修改描述 */
|
||||
UpdateDesc = 'resource-folder-update-desc',
|
||||
}
|
||||
|
||||
export type BizGroupTypeWithFolder =
|
||||
| ProjectResourceGroupType
|
||||
| ResourceTypeEnum.Folder;
|
||||
|
||||
export type Validator = Required<
|
||||
Required<ResourceFolderProps>['validateConfig']
|
||||
>['customValidator'];
|
||||
|
||||
export type BizResourceType = ResourceType & ProjectResourceInfo;
|
||||
|
||||
export type ResourceSubType = string | number;
|
||||
|
||||
export type ResourceFolderCozeProps = {
|
||||
/** 资源类型 */
|
||||
groupType: ProjectResourceGroupType;
|
||||
/** 后端资源列表数据 */
|
||||
resourceTree: BizResourceType[];
|
||||
/** 自定义事件回调,点击右键菜单/上下文菜单会触发,由业务方实现自定义事件的资源更新逻辑逻辑 */
|
||||
onAction?: (
|
||||
action: BizResourceContextMenuBtnType,
|
||||
resource?: BizResourceType,
|
||||
) => void;
|
||||
/**
|
||||
* 自定义资源创建流程时使用这个 props,需要业务自己展示资源创建表单,然后更新 resource
|
||||
* 如果没有自定义逻辑,使用 onCreate
|
||||
*/
|
||||
onCustomCreate?: (
|
||||
groupType: ProjectResourceGroupType,
|
||||
subType?: ResourceSubType,
|
||||
) => void;
|
||||
/**
|
||||
* 使用默认创建资源的方式,创建资源后的回调,在这里调用业务的创建资源接口
|
||||
* 配置了 onCustomCreate 会使 onCreate 失效
|
||||
* 默认创建资源方式:点击新建菜单后,资源列表增加新资源 input 输入框,输入资源名称回车完成创建,触发 onCreate 回调
|
||||
* @param createEvent
|
||||
* @param subType 如果配置了 createResourceConfig 数组,会有多个创建资源的菜单,通过 subType 区分子类型
|
||||
*/
|
||||
onCreate?: (
|
||||
createEvent: CreateResourcePropType,
|
||||
subType?: ResourceSubType,
|
||||
) => void;
|
||||
/**
|
||||
* 是否可以创建资源
|
||||
*/
|
||||
canCreate?: boolean;
|
||||
/**
|
||||
* 完成初始加载,用于判断显示空状态
|
||||
*/
|
||||
initLoaded?: boolean;
|
||||
/**
|
||||
* 创建资源的 UI 配置
|
||||
* 如果资源有多个子类型,可以配置为数组
|
||||
* 触发 onCreateResource 会传第二个参数 subType
|
||||
*/
|
||||
createResourceConfig?: Array<{
|
||||
icon: ReactNode;
|
||||
label: string;
|
||||
subType: number | string;
|
||||
tooltip: ReactNode;
|
||||
}>;
|
||||
/**
|
||||
* 主要用于快捷键创建资源的默认类型。
|
||||
*/
|
||||
defaultResourceType?: BizResourceTypeEnum;
|
||||
/**
|
||||
* 隐藏更多菜单按钮
|
||||
*/
|
||||
hideMoreBtn?: boolean;
|
||||
} & Pick<
|
||||
ResourceFolderProps,
|
||||
| 'id'
|
||||
| 'onChangeName'
|
||||
| 'onDelete'
|
||||
| 'iconRender'
|
||||
| 'onContextMenuVisibleChange'
|
||||
| 'validateConfig'
|
||||
>;
|
||||
@@ -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 { type ReactNode } from 'react';
|
||||
|
||||
import {
|
||||
WORKFLOW_NAME_MAX_LEN,
|
||||
WORKFLOW_NAME_REGEX,
|
||||
} from '@coze-workflow/base';
|
||||
import { I18n, type I18nKeysNoOptionsType } from '@coze-arch/i18n';
|
||||
import { type ProjectResourceActionKey } from '@coze-arch/bot-api/plugin_develop';
|
||||
import {
|
||||
type ResourceType,
|
||||
ResourceTypeEnum,
|
||||
} from '@coze-project-ide/framework';
|
||||
|
||||
import {
|
||||
BizResourceContextMenuBtnType,
|
||||
type BizResourceType,
|
||||
BizResourceTypeEnum,
|
||||
type Validator,
|
||||
} from './type';
|
||||
import { iconFolder, iconFolderOpended, resourceIconMap } from './constants';
|
||||
|
||||
export const validateNameBasic: Validator = ({ label }) => {
|
||||
// 检测 name 是否空
|
||||
if (!label) {
|
||||
return I18n.t('project_resource_sidebar_warning_empty_key');
|
||||
}
|
||||
|
||||
if (label.length > WORKFLOW_NAME_MAX_LEN) {
|
||||
return I18n.t('project_resource_sidebar_warning_length_exceeds');
|
||||
}
|
||||
|
||||
// 检测 name 的命名规则
|
||||
if (!WORKFLOW_NAME_REGEX.test(label)) {
|
||||
return I18n.t('workflow_list_create_modal_name_rule_reg');
|
||||
}
|
||||
|
||||
return '';
|
||||
};
|
||||
|
||||
export const validateNameConflict: Validator = ({
|
||||
label,
|
||||
parentPath,
|
||||
id,
|
||||
resourceTree,
|
||||
}) => {
|
||||
const currentParentPath: Array<ResourceType['id']> = [];
|
||||
const checkSubTree = (subTree: ResourceType) => {
|
||||
currentParentPath.push(subTree.id);
|
||||
if (currentParentPath.join('/') === parentPath.join('/')) {
|
||||
return subTree.children?.some(child => {
|
||||
const isSelf = id === child.id && id !== '-1';
|
||||
return !isSelf && child.name === label;
|
||||
});
|
||||
} else {
|
||||
for (const child of subTree.children || []) {
|
||||
const conflict = checkSubTree(child);
|
||||
if (conflict) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
currentParentPath.pop();
|
||||
};
|
||||
const nameConflict = checkSubTree(resourceTree);
|
||||
if (nameConflict) {
|
||||
return I18n.t('project_resource_sidebar_warning_label_exists', { label });
|
||||
}
|
||||
return '';
|
||||
};
|
||||
|
||||
export const getResourceIconByResource = (
|
||||
resource: ResourceType,
|
||||
isExpand?: boolean,
|
||||
) => {
|
||||
let icon: ReactNode;
|
||||
switch (resource.type) {
|
||||
case ResourceTypeEnum.Folder:
|
||||
icon = isExpand ? iconFolderOpended : iconFolder;
|
||||
break;
|
||||
default:
|
||||
icon = resourceIconMap[resource.type as BizResourceTypeEnum] || '';
|
||||
break;
|
||||
}
|
||||
return icon;
|
||||
};
|
||||
|
||||
export const isResourceActionEnabled = (
|
||||
resource: BizResourceType,
|
||||
action: ProjectResourceActionKey,
|
||||
): boolean =>
|
||||
resource.actions?.find(item => item.key === action)?.enable || false;
|
||||
|
||||
// eslint-disable-next-line complexity
|
||||
export const getContextMenuLabel = (
|
||||
contextMenuType: BizResourceContextMenuBtnType,
|
||||
resource?: ResourceType,
|
||||
): string => {
|
||||
let resourceLabelKey: I18nKeysNoOptionsType | '' = '';
|
||||
switch (resource?.type) {
|
||||
case BizResourceTypeEnum.Workflow:
|
||||
resourceLabelKey = 'library_resource_type_workflow';
|
||||
break;
|
||||
case BizResourceTypeEnum.Plugin:
|
||||
resourceLabelKey = 'library_resource_type_plugin';
|
||||
break;
|
||||
case BizResourceTypeEnum.Knowledge:
|
||||
resourceLabelKey = 'library_resource_type_knowledge';
|
||||
break;
|
||||
case BizResourceTypeEnum.Database:
|
||||
resourceLabelKey = 'db_table_entry';
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
switch (contextMenuType) {
|
||||
case BizResourceContextMenuBtnType.Rename:
|
||||
return I18n.t('workflow_detail_node_rename');
|
||||
case BizResourceContextMenuBtnType.DuplicateResource:
|
||||
return I18n.t('workflow_add_list_copy');
|
||||
case BizResourceContextMenuBtnType.Delete:
|
||||
return resource?.type === ResourceTypeEnum.Folder
|
||||
? I18n.t('filebox_0042')
|
||||
: I18n.t('project_resource_sidebar_delete');
|
||||
case BizResourceContextMenuBtnType.CopyToLibrary:
|
||||
return I18n.t('project_resource_sidebar_copy_to_library');
|
||||
case BizResourceContextMenuBtnType.MoveToLibrary:
|
||||
return I18n.t('project_resource_sidebar_move_to_library');
|
||||
case BizResourceContextMenuBtnType.EnableKnowledge: {
|
||||
return I18n.t('project_resource_sidebar_enable_resource', {
|
||||
resource: I18n.t(resourceLabelKey as I18nKeysNoOptionsType),
|
||||
});
|
||||
}
|
||||
case BizResourceContextMenuBtnType.DisableKnowledge:
|
||||
return I18n.t('project_resource_sidebar_disable_resource', {
|
||||
resource: I18n.t(resourceLabelKey as I18nKeysNoOptionsType),
|
||||
});
|
||||
case BizResourceContextMenuBtnType.ImportLibraryResource:
|
||||
return I18n.t('project_resource_sidebar_import_from_library', {}, '');
|
||||
case BizResourceContextMenuBtnType.UpdateDesc:
|
||||
return I18n.t('project_241115', {}, '修改描述');
|
||||
case BizResourceContextMenuBtnType.SwitchToChatflow:
|
||||
return I18n.t('wf_chatflow_121', { flowMode: I18n.t('wf_chatflow_76') });
|
||||
case BizResourceContextMenuBtnType.SwitchToWorkflow:
|
||||
return I18n.t('wf_chatflow_121', { flowMode: I18n.t('Workflow') });
|
||||
default:
|
||||
return '';
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 是否动态注册的 action
|
||||
* @param action
|
||||
*/
|
||||
export const isDynamicAction = (action: BizResourceContextMenuBtnType) =>
|
||||
![
|
||||
BizResourceContextMenuBtnType.CreateResource,
|
||||
BizResourceContextMenuBtnType.CreateFolder,
|
||||
BizResourceContextMenuBtnType.Rename,
|
||||
BizResourceContextMenuBtnType.Delete,
|
||||
BizResourceContextMenuBtnType.DuplicateResource,
|
||||
].includes(action);
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
export { usePrimarySidebarStore } from './primary-sidebar-store';
|
||||
@@ -0,0 +1,151 @@
|
||||
/*
|
||||
* 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 { devtools } from 'zustand/middleware';
|
||||
import { create } from 'zustand';
|
||||
import { ProjectResourceGroupType } from '@coze-arch/bot-api/plugin_develop';
|
||||
import { PluginDevelopApi } from '@coze-arch/bot-api';
|
||||
|
||||
import { resTypeDTOToVO } from '@/utils';
|
||||
import { type BizResourceTree } from '@/resource-folder-coze/type';
|
||||
|
||||
export interface PrimarySidebarActions {
|
||||
updateGroupExpand: (
|
||||
groupType: ProjectResourceGroupType,
|
||||
expand: boolean,
|
||||
) => void;
|
||||
isFetching?: boolean;
|
||||
initLoaded?: boolean;
|
||||
setSelectedResource: (resourceId?: string) => void;
|
||||
/**
|
||||
* 调用 store 里的 refetch 方法通知资源列表刷新
|
||||
* @param resourceType 刷新的资源类型,可选,不传时刷新所有类型的资源
|
||||
*/
|
||||
refetch: (callback?: (tree?: BizResourceTree[]) => void) => Promise<void>;
|
||||
/**
|
||||
* 设置资源列表的刷新方法到 store 里,供其他 widget 里调用 store.refetch(xxx) 刷新资源列表
|
||||
* @param refetchFunc 刷新方法,刷新方法里内部需要处理资源列表的 setResource
|
||||
*/
|
||||
fetchResource: (
|
||||
spaceId: string,
|
||||
projectId: string,
|
||||
version?: string,
|
||||
callback?: (tree?: BizResourceTree[]) => void,
|
||||
) => Promise<void>;
|
||||
setCanClosePopover: (canClose: boolean) => void;
|
||||
}
|
||||
|
||||
export interface PrimarySidebarState {
|
||||
projectId?: string;
|
||||
spaceId?: string;
|
||||
version?: string;
|
||||
resourceTree: BizResourceTree[];
|
||||
/**
|
||||
* 资源分组展开状态,按资源分组类型分开记录
|
||||
*/
|
||||
groupExpandMap: Record<ProjectResourceGroupType, boolean>;
|
||||
/**
|
||||
* 当前选中的资源
|
||||
*/
|
||||
selectedResource?: string;
|
||||
/**
|
||||
* 是否可以关闭 popover sidebar,右键菜单打开时不允许关闭,供 ResourceFolderCoze 组件消费
|
||||
*/
|
||||
canClosePopover?: boolean;
|
||||
}
|
||||
|
||||
const defaultState: PrimarySidebarState = {
|
||||
resourceTree: [],
|
||||
canClosePopover: true,
|
||||
groupExpandMap: {
|
||||
[ProjectResourceGroupType.Workflow]: true,
|
||||
[ProjectResourceGroupType.Plugin]: true,
|
||||
[ProjectResourceGroupType.Data]: true,
|
||||
},
|
||||
};
|
||||
export const usePrimarySidebarStore = create<
|
||||
PrimarySidebarState & PrimarySidebarActions
|
||||
>()(
|
||||
devtools(
|
||||
(set, get) => ({
|
||||
...defaultState,
|
||||
updateGroupExpand: (
|
||||
groupType: ProjectResourceGroupType,
|
||||
expand: boolean,
|
||||
) => {
|
||||
set({
|
||||
groupExpandMap: {
|
||||
...get().groupExpandMap,
|
||||
[groupType]: expand,
|
||||
},
|
||||
});
|
||||
},
|
||||
setSelectedResource: (resourceId?: string) => {
|
||||
set({
|
||||
selectedResource: resourceId,
|
||||
});
|
||||
},
|
||||
// eslint-disable-next-line max-params
|
||||
fetchResource: async (spaceId, projectId, version, callback) => {
|
||||
set({
|
||||
isFetching: true,
|
||||
spaceId,
|
||||
projectId,
|
||||
version,
|
||||
});
|
||||
const res = await PluginDevelopApi.ProjectResourceList({
|
||||
project_id: projectId ?? '',
|
||||
space_id: spaceId,
|
||||
project_version: version,
|
||||
});
|
||||
const resourceTree = res.resource_groups?.map<BizResourceTree>(
|
||||
group => ({
|
||||
groupType: group.group_type,
|
||||
resourceList:
|
||||
group.resource_list?.map(resourceInfo => ({
|
||||
id: String(resourceInfo.res_id ?? ''),
|
||||
type: resTypeDTOToVO(resourceInfo.res_type),
|
||||
name: resourceInfo.name ?? '',
|
||||
...resourceInfo,
|
||||
})) || [],
|
||||
}),
|
||||
);
|
||||
callback?.(resourceTree);
|
||||
set({
|
||||
resourceTree,
|
||||
isFetching: false,
|
||||
initLoaded: true,
|
||||
});
|
||||
},
|
||||
refetch: async callback => {
|
||||
const { spaceId, projectId, version } = get();
|
||||
if (!spaceId || !projectId) {
|
||||
return;
|
||||
}
|
||||
// 服务端数据同步延迟
|
||||
await new Promise<void>(resolve => setTimeout(() => resolve(), 700));
|
||||
return get().fetchResource(spaceId, projectId, version, callback);
|
||||
},
|
||||
setCanClosePopover: (canClose: boolean) => {
|
||||
set({ canClosePopover: canClose });
|
||||
},
|
||||
}),
|
||||
{
|
||||
name: 'projectIDE.primarySidebar',
|
||||
enabled: IS_DEV_MODE,
|
||||
},
|
||||
),
|
||||
);
|
||||
17
frontend/packages/project-ide/biz-components/src/typings.d.ts
vendored
Normal file
17
frontend/packages/project-ide/biz-components/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' />
|
||||
42
frontend/packages/project-ide/biz-components/src/utils.ts
Normal file
42
frontend/packages/project-ide/biz-components/src/utils.ts
Normal file
@@ -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 { ResType } from '@coze-arch/bot-api/plugin_develop';
|
||||
|
||||
import { BizResourceTypeEnum } from '@/resource-folder-coze/type';
|
||||
|
||||
export const resTypeDTOToVO = (
|
||||
resType?: ResType,
|
||||
): BizResourceTypeEnum | undefined => {
|
||||
if (!resType) {
|
||||
return;
|
||||
}
|
||||
switch (resType) {
|
||||
case ResType.Imageflow:
|
||||
case ResType.Workflow:
|
||||
return BizResourceTypeEnum.Workflow;
|
||||
case ResType.Knowledge:
|
||||
return BizResourceTypeEnum.Knowledge;
|
||||
case ResType.Plugin:
|
||||
return BizResourceTypeEnum.Plugin;
|
||||
case ResType.Variable:
|
||||
return BizResourceTypeEnum.Variable;
|
||||
case ResType.Database:
|
||||
return BizResourceTypeEnum.Database;
|
||||
default:
|
||||
return BizResourceTypeEnum.Workflow;
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* 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 { DemoComponent } from '../src';
|
||||
|
||||
export default {
|
||||
title: 'Example/Demo',
|
||||
component: DemoComponent,
|
||||
parameters: {
|
||||
// Optional parameter to center the component in the Canvas. More info: https://storybook.js.org/docs/configure/story-layout
|
||||
layout: 'centered',
|
||||
},
|
||||
// This component will have an automatically generated Autodocs entry: https://storybook.js.org/docs/writing-docs/autodocs
|
||||
tags: ['autodocs'],
|
||||
// More on argTypes: https://storybook.js.org/docs/api/argtypes
|
||||
argTypes: {},
|
||||
};
|
||||
|
||||
// More on writing stories with args: https://storybook.js.org/docs/writing-stories/args
|
||||
export const Base = {
|
||||
args: {
|
||||
name: 'tecvan',
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,34 @@
|
||||
import { Meta } from "@storybook/blocks";
|
||||
|
||||
<Meta title="Hello world" />
|
||||
|
||||
<div className="sb-container">
|
||||
<div className='sb-section-title'>
|
||||
# Hello world
|
||||
|
||||
Hello world
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
{`
|
||||
.sb-container {
|
||||
margin-bottom: 48px;
|
||||
}
|
||||
|
||||
.sb-section {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
gap: 20px;
|
||||
}
|
||||
|
||||
img {
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
.sb-section-title {
|
||||
margin-bottom: 32px;
|
||||
}
|
||||
`}
|
||||
</style>
|
||||
@@ -0,0 +1,57 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/tsconfig",
|
||||
"extends": "@coze-arch/ts-config/tsconfig.web.json",
|
||||
"compilerOptions": {
|
||||
"baseUrl": "./",
|
||||
"types": [],
|
||||
"jsx": "react",
|
||||
"isolatedModules": true,
|
||||
"strictNullChecks": true,
|
||||
"strictPropertyInitialization": false,
|
||||
"paths": {
|
||||
"@/*": ["./src/*"]
|
||||
},
|
||||
"rootDir": "./src",
|
||||
"outDir": "./dist",
|
||||
"tsBuildInfoFile": "./dist/tsconfig.build.tsbuildinfo"
|
||||
},
|
||||
"include": ["src"],
|
||||
"references": [
|
||||
{
|
||||
"path": "../../arch/bot-api/tsconfig.build.json"
|
||||
},
|
||||
{
|
||||
"path": "../../arch/bot-flags/tsconfig.build.json"
|
||||
},
|
||||
{
|
||||
"path": "../../arch/bot-typings/tsconfig.build.json"
|
||||
},
|
||||
{
|
||||
"path": "../../arch/i18n/tsconfig.build.json"
|
||||
},
|
||||
{
|
||||
"path": "../../components/bot-icons/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"
|
||||
},
|
||||
{
|
||||
"path": "../framework/tsconfig.build.json"
|
||||
},
|
||||
{
|
||||
"path": "../../studio/user-store/tsconfig.build.json"
|
||||
},
|
||||
{
|
||||
"path": "../../workflow/base/tsconfig.build.json"
|
||||
}
|
||||
]
|
||||
}
|
||||
15
frontend/packages/project-ide/biz-components/tsconfig.json
Normal file
15
frontend/packages/project-ide/biz-components/tsconfig.json
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/tsconfig",
|
||||
"exclude": ["**/*"],
|
||||
"compilerOptions": {
|
||||
"composite": true
|
||||
},
|
||||
"references": [
|
||||
{
|
||||
"path": "./tsconfig.build.json"
|
||||
},
|
||||
{
|
||||
"path": "./tsconfig.misc.json"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"extends": "@coze-arch/ts-config/tsconfig.web.json",
|
||||
"$schema": "https://json.schemastore.org/tsconfig",
|
||||
"include": ["__tests__", "stories", "vitest.config.ts", "tailwind.config.ts"],
|
||||
"exclude": ["**/node_modules", "./dist"],
|
||||
"references": [
|
||||
{
|
||||
"path": "./tsconfig.build.json"
|
||||
}
|
||||
],
|
||||
"compilerOptions": {
|
||||
"baseUrl": "./",
|
||||
"types": ["react", "react-dom"],
|
||||
"jsx": "react",
|
||||
"isolatedModules": true,
|
||||
"strictNullChecks": true,
|
||||
"strictPropertyInitialization": false,
|
||||
"paths": {
|
||||
"@/*": ["./src/*"]
|
||||
},
|
||||
"rootDir": "./",
|
||||
"outDir": "./dist"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* 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',
|
||||
});
|
||||
5
frontend/packages/project-ide/biz-data/.stylelintrc.js
Normal file
5
frontend/packages/project-ide/biz-data/.stylelintrc.js
Normal file
@@ -0,0 +1,5 @@
|
||||
const { defineConfig } = require('@coze-arch/stylelint-config');
|
||||
|
||||
module.exports = defineConfig({
|
||||
extends: [],
|
||||
});
|
||||
16
frontend/packages/project-ide/biz-data/README.md
Normal file
16
frontend/packages/project-ide/biz-data/README.md
Normal file
@@ -0,0 +1,16 @@
|
||||
# biz-data
|
||||
|
||||
> Project template for react component with storybook.
|
||||
|
||||
## 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,12 @@
|
||||
{
|
||||
"operationSettings": [
|
||||
{
|
||||
"operationName": "test:cov",
|
||||
"outputFolderNames": ["coverage"]
|
||||
},
|
||||
{
|
||||
"operationName": "ts-check",
|
||||
"outputFolderNames": ["./dist"]
|
||||
}
|
||||
]
|
||||
}
|
||||
7
frontend/packages/project-ide/biz-data/eslint.config.js
Normal file
7
frontend/packages/project-ide/biz-data/eslint.config.js
Normal file
@@ -0,0 +1,7 @@
|
||||
const { defineConfig } = require('@coze-arch/eslint-config');
|
||||
|
||||
module.exports = defineConfig({
|
||||
packageRoot: __dirname,
|
||||
preset: 'web',
|
||||
rules: {},
|
||||
});
|
||||
73
frontend/packages/project-ide/biz-data/package.json
Normal file
73
frontend/packages/project-ide/biz-data/package.json
Normal file
@@ -0,0 +1,73 @@
|
||||
{
|
||||
"name": "@coze-project-ide/biz-data",
|
||||
"version": "0.0.1",
|
||||
"description": "knowledge in project ide",
|
||||
"license": "Apache-2.0",
|
||||
"author": "meixuliang.3@bytedance.com",
|
||||
"maintainers": [],
|
||||
"exports": {
|
||||
".": "./src/index.tsx",
|
||||
"./registry": "./src/registry.tsx"
|
||||
},
|
||||
"main": "src/index.tsx",
|
||||
"typesVersions": {
|
||||
"*": {
|
||||
"registry": [
|
||||
"./src/registry.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-data/database-v2": "workspace:*",
|
||||
"@coze-data/knowledge-ide-adapter": "workspace:*",
|
||||
"@coze-data/knowledge-ide-base": "workspace:*",
|
||||
"@coze-data/knowledge-modal-adapter": "workspace:*",
|
||||
"@coze-data/knowledge-modal-base": "workspace:*",
|
||||
"@coze-data/knowledge-resource-processor-adapter": "workspace:*",
|
||||
"@coze-data/knowledge-resource-processor-base": "workspace:*",
|
||||
"@coze-data/knowledge-resource-processor-core": "workspace:*",
|
||||
"@coze-data/knowledge-stores": "workspace:*",
|
||||
"@coze-data/utils": "workspace:*",
|
||||
"@coze-data/variable": "workspace:*",
|
||||
"@coze-project-ide/biz-components": "workspace:*",
|
||||
"@coze-project-ide/framework": "workspace:*",
|
||||
"classnames": "^2.3.2",
|
||||
"lodash-es": "^4.17.21",
|
||||
"qs": "^6.11.2",
|
||||
"zustand": "^4.4.7"
|
||||
},
|
||||
"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:*",
|
||||
"@testing-library/jest-dom": "^6.1.5",
|
||||
"@testing-library/react": "^14.1.2",
|
||||
"@testing-library/react-hooks": "^8.0.1",
|
||||
"@types/react": "18.2.37",
|
||||
"@types/react-dom": "18.2.15",
|
||||
"@vitest/coverage-v8": "~3.0.5",
|
||||
"react": "~18.2.0",
|
||||
"react-dom": "~18.2.0",
|
||||
"stylelint": "^15.11.0",
|
||||
"typescript": "~5.8.2",
|
||||
"vite-plugin-svgr": "~3.3.0",
|
||||
"vitest": "~3.0.5"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": ">=18.2.0",
|
||||
"react-dom": ">=18.2.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
import classNames from 'classnames';
|
||||
import { IconCozKnowledgeFill } from '@coze-arch/coze-design/icons';
|
||||
|
||||
interface SiderCategoryProps {
|
||||
label: string;
|
||||
selected: boolean;
|
||||
|
||||
onClick?: React.MouseEventHandler<HTMLDivElement>;
|
||||
}
|
||||
|
||||
const SiderCategory = ({ label, onClick, selected }: SiderCategoryProps) => (
|
||||
<div
|
||||
onClick={onClick}
|
||||
className={classNames([
|
||||
'flex items-center gap-[8px] px-[12px]',
|
||||
'px-[12px] py-[6px] rounded-[8px]',
|
||||
'cursor-pointer',
|
||||
'hover:text-[var(--light-usage-text-color-text-0,#1c1f23)]',
|
||||
'hover:bg-[var(--light-usage-fill-color-fill-0,rgba(46,50,56,5%))]',
|
||||
selected &&
|
||||
'text-[var(--light-usage-text-color-text-0,#1c1d23)] bg-[var(--light-usage-fill-color-fill-0,rgba(46,47,56,5%))]',
|
||||
])}
|
||||
>
|
||||
<IconCozKnowledgeFill />
|
||||
{label}
|
||||
</div>
|
||||
);
|
||||
|
||||
export default SiderCategory;
|
||||
92
frontend/packages/project-ide/biz-data/src/database-main.tsx
Normal file
92
frontend/packages/project-ide/biz-data/src/database-main.tsx
Normal file
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import qs from 'qs';
|
||||
import {
|
||||
useTitle,
|
||||
useCurrentWidgetContext,
|
||||
useIDEParams,
|
||||
useIDENavigate,
|
||||
useSpaceId,
|
||||
useProjectId,
|
||||
useCommitVersion,
|
||||
} from '@coze-project-ide/framework';
|
||||
import { usePrimarySidebarStore } from '@coze-project-ide/biz-components';
|
||||
import { KnowledgeParamsStoreProvider } from '@coze-data/knowledge-stores';
|
||||
import {
|
||||
type UnitType,
|
||||
type OptType,
|
||||
} from '@coze-data/knowledge-resource-processor-core';
|
||||
import { DatabaseDetail, type DatabaseTabs } from '@coze-data/database-v2';
|
||||
|
||||
const Main = () => {
|
||||
const spaceID = useSpaceId();
|
||||
const projectID = useProjectId();
|
||||
const { uri, widget } = useCurrentWidgetContext();
|
||||
const IDENav = useIDENavigate();
|
||||
const title = useTitle();
|
||||
const { version } = useCommitVersion();
|
||||
|
||||
const refetch = usePrimarySidebarStore(state => state.refetch);
|
||||
|
||||
const queryObject = useIDEParams();
|
||||
|
||||
const { type, opt, doc_id, page_mode, bot_id, workflow_id, agent_id, tab } =
|
||||
queryObject;
|
||||
|
||||
return (
|
||||
<KnowledgeParamsStoreProvider
|
||||
params={{
|
||||
version,
|
||||
projectID,
|
||||
spaceID,
|
||||
tableID: uri?.path.name ?? '',
|
||||
type: type as UnitType,
|
||||
opt: opt as OptType,
|
||||
docID: doc_id,
|
||||
pageMode: page_mode as 'modal' | 'normal',
|
||||
biz: 'project',
|
||||
botID: bot_id,
|
||||
workflowID: workflow_id,
|
||||
agentID: agent_id,
|
||||
}}
|
||||
onUpdateDisplayName={displayName => {
|
||||
widget.setTitle(displayName); // 设置 tab 标题
|
||||
if (displayName && displayName !== title) {
|
||||
refetch(); // 更新侧边栏 name
|
||||
}
|
||||
}}
|
||||
onStatusChange={status => {
|
||||
widget.setUIState(status);
|
||||
}}
|
||||
resourceNavigate={{
|
||||
// eslint-disable-next-line max-params
|
||||
toResource: (resource, resourceID, query, opts) =>
|
||||
IDENav(`/${resource}/${resourceID}?${qs.stringify(query)}`, opts),
|
||||
}}
|
||||
>
|
||||
<DatabaseDetail
|
||||
needHideCloseIcon
|
||||
initialTab={tab as DatabaseTabs}
|
||||
version={version}
|
||||
/>
|
||||
</KnowledgeParamsStoreProvider>
|
||||
);
|
||||
};
|
||||
|
||||
export default Main;
|
||||
@@ -0,0 +1,135 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import React, { type ReactNode, useMemo } from 'react';
|
||||
|
||||
import {
|
||||
BizResourceContextMenuBtnType,
|
||||
BizResourceTypeEnum,
|
||||
type ResourceFolderCozeProps,
|
||||
} from '@coze-project-ide/biz-components';
|
||||
import { validateNameConflict } from '@coze-project-ide/biz-components';
|
||||
import { I18n } from '@coze-arch/i18n';
|
||||
import { ResType } from '@coze-arch/bot-api/plugin_develop';
|
||||
import { IconCozDatabase, IconCozKnowledge } from '@coze-arch/coze-design/icons';
|
||||
|
||||
import useKnowledgeResource from './use-knowledge-resource';
|
||||
import useImportData from './use-import-data';
|
||||
import useDatabaseResource from './use-database-resource';
|
||||
|
||||
type UseDataResourceReturn = Pick<
|
||||
ResourceFolderCozeProps,
|
||||
| 'onCustomCreate'
|
||||
| 'onDelete'
|
||||
| 'onChangeName'
|
||||
| 'onAction'
|
||||
| 'createResourceConfig'
|
||||
| 'iconRender'
|
||||
| 'validateConfig'
|
||||
> & { modals: ReactNode };
|
||||
|
||||
const useDataResource = (): UseDataResourceReturn => {
|
||||
const createResourceConfig = useMemo(
|
||||
() => [
|
||||
{
|
||||
icon: <IconCozKnowledge />,
|
||||
label: I18n.t('project_resource_sidebar_create_new_resource', {
|
||||
resource: I18n.t('performance_knowledge'),
|
||||
}),
|
||||
subType: BizResourceTypeEnum.Knowledge,
|
||||
tooltip: null,
|
||||
},
|
||||
{
|
||||
icon: <IconCozDatabase />,
|
||||
label: I18n.t('project_resource_sidebar_create_new_resource', {
|
||||
resource: I18n.t('review_bot_database'),
|
||||
}),
|
||||
subType: BizResourceTypeEnum.Database,
|
||||
tooltip: null,
|
||||
},
|
||||
],
|
||||
[],
|
||||
);
|
||||
|
||||
const { modal, open } = useImportData();
|
||||
|
||||
const knowledgeResource = useKnowledgeResource();
|
||||
const databaseResource = useDatabaseResource();
|
||||
|
||||
return {
|
||||
onCustomCreate(groupType, subType) {
|
||||
if (subType === BizResourceTypeEnum.Knowledge) {
|
||||
knowledgeResource.onCustomCreate?.(groupType, subType);
|
||||
}
|
||||
if (subType === BizResourceTypeEnum.Database) {
|
||||
databaseResource.onCustomCreate?.(groupType, subType);
|
||||
}
|
||||
},
|
||||
onChangeName(event) {
|
||||
if (event.resource?.res_type === ResType.Knowledge) {
|
||||
knowledgeResource.onChangeName?.(event);
|
||||
}
|
||||
if (event.resource?.res_type === ResType.Database) {
|
||||
databaseResource.onChangeName?.(event);
|
||||
}
|
||||
},
|
||||
onAction(action, resource) {
|
||||
if (action === BizResourceContextMenuBtnType.ImportLibraryResource) {
|
||||
open();
|
||||
} else {
|
||||
if (resource?.res_type === ResType.Knowledge) {
|
||||
knowledgeResource.onAction?.(action, resource);
|
||||
}
|
||||
if (resource?.res_type === ResType.Database) {
|
||||
databaseResource.onAction?.(action, resource);
|
||||
}
|
||||
}
|
||||
},
|
||||
onDelete(resources) {
|
||||
const deleteKnowledgeResource = resources.filter(
|
||||
resource => resource?.res_type === ResType.Knowledge,
|
||||
);
|
||||
const deleteDatabaseResource = resources.filter(
|
||||
resource => resource?.res_type === ResType.Database,
|
||||
);
|
||||
|
||||
if (deleteKnowledgeResource.length) {
|
||||
knowledgeResource.onDelete?.(deleteKnowledgeResource);
|
||||
}
|
||||
|
||||
if (deleteDatabaseResource.length) {
|
||||
databaseResource.onDelete?.(deleteDatabaseResource);
|
||||
}
|
||||
},
|
||||
createResourceConfig,
|
||||
modals: [knowledgeResource.modals, databaseResource.modals, modal],
|
||||
validateConfig: {
|
||||
customValidator: params => {
|
||||
if (!params.label) {
|
||||
return I18n.t('dataset-name-empty-tooltip');
|
||||
}
|
||||
|
||||
if (!/^[^"'`\\]+$/.test(params.label)) {
|
||||
return I18n.t('dataset-name-has-wrong-word-tooltip');
|
||||
}
|
||||
|
||||
return validateNameConflict(params);
|
||||
},
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
export default useDataResource;
|
||||
@@ -0,0 +1,166 @@
|
||||
/*
|
||||
* 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, useCallback } from 'react';
|
||||
|
||||
import {
|
||||
type ResourceFolderProps,
|
||||
type ResourceType,
|
||||
useProjectId,
|
||||
useSpaceId,
|
||||
useIDENavigate,
|
||||
} from '@coze-project-ide/framework';
|
||||
import {
|
||||
BizResourceContextMenuBtnType,
|
||||
type BizResourceType,
|
||||
BizResourceTypeEnum,
|
||||
type ResourceFolderCozeProps,
|
||||
// useOpenResource,
|
||||
usePrimarySidebarStore,
|
||||
} from '@coze-project-ide/biz-components';
|
||||
import { useLibraryCreateDatabaseModal } from '@coze-data/database-v2';
|
||||
import { I18n } from '@coze-arch/i18n';
|
||||
import { ResourceCopyScene } from '@coze-arch/bot-api/plugin_develop';
|
||||
import { MemoryApi } from '@coze-arch/bot-api';
|
||||
import { Toast } from '@coze-arch/coze-design';
|
||||
|
||||
import { useResourceOperation } from './use-resource-operation';
|
||||
|
||||
// import { useImportLibraryDatabase } from './use-import-library-database';
|
||||
|
||||
type UseDatabaseResourceReturn = Pick<
|
||||
ResourceFolderCozeProps,
|
||||
| 'onCustomCreate'
|
||||
| 'onDelete'
|
||||
| 'onChangeName'
|
||||
| 'onAction'
|
||||
| 'createResourceConfig'
|
||||
| 'iconRender'
|
||||
> & { modals: ReactNode };
|
||||
|
||||
const useDatabaseResource = (): UseDatabaseResourceReturn => {
|
||||
const refetch = usePrimarySidebarStore(state => state.refetch);
|
||||
const spaceId = useSpaceId();
|
||||
const projectId = useProjectId();
|
||||
const IDENav = useIDENavigate();
|
||||
// const openResource = useOpenResource();
|
||||
|
||||
// 创建 Database
|
||||
const {
|
||||
modal: createDatabaseModal,
|
||||
open: openCreateDatabaseModal,
|
||||
close: closeCreateDatabaseModal,
|
||||
} = useLibraryCreateDatabaseModal({
|
||||
projectID: projectId,
|
||||
enterFrom: 'project',
|
||||
onFinish: databaseID => {
|
||||
refetch();
|
||||
closeCreateDatabaseModal();
|
||||
IDENav(`/database/${databaseID}?page_modal=normal&from=create`);
|
||||
},
|
||||
});
|
||||
|
||||
const onCustomCreate: ResourceFolderCozeProps['onCustomCreate'] = (
|
||||
resourceType,
|
||||
subType,
|
||||
) => {
|
||||
console.log('[ResourceFolder]on custom create>>>', resourceType, subType);
|
||||
openCreateDatabaseModal();
|
||||
};
|
||||
|
||||
const onChangeName: ResourceFolderProps['onChangeName'] =
|
||||
async changeNameEvent => {
|
||||
try {
|
||||
console.log('[ResourceFolder]on change name>>>', changeNameEvent);
|
||||
const resp = await MemoryApi.UpdateDatabase({
|
||||
id: changeNameEvent.id,
|
||||
table_name: changeNameEvent.name,
|
||||
});
|
||||
console.log('[ResourceFolder]rename database response>>>', resp);
|
||||
} catch (e) {
|
||||
console.log('[ResourceFolder]rename database error>>>', e);
|
||||
} finally {
|
||||
refetch();
|
||||
}
|
||||
};
|
||||
|
||||
const onDelete = useCallback(
|
||||
async (resources: ResourceType[]) => {
|
||||
try {
|
||||
console.log('[ResourceFolder]on delete>>>', resources);
|
||||
const resp = await MemoryApi.DeleteDatabase({
|
||||
id: resources.filter(
|
||||
r => r.type === BizResourceTypeEnum.Database,
|
||||
)?.[0].res_id,
|
||||
});
|
||||
Toast.success(I18n.t('Delete_success'));
|
||||
refetch();
|
||||
console.log('[ResourceFolder]delete database response>>>', resp);
|
||||
} catch (e) {
|
||||
console.log('[ResourceFolder]delete database error>>>', e);
|
||||
Toast.error(I18n.t('Delete_failed'));
|
||||
}
|
||||
},
|
||||
[refetch, spaceId],
|
||||
);
|
||||
|
||||
// const { modal: databaseModal, importLibrary } = useImportLibraryDatabase({
|
||||
// projectId,
|
||||
// });
|
||||
|
||||
const resourceOperation = useResourceOperation({ projectId });
|
||||
const onAction = (
|
||||
action: BizResourceContextMenuBtnType,
|
||||
resource?: BizResourceType,
|
||||
) => {
|
||||
console.log('on action>>>', action, resource);
|
||||
switch (action) {
|
||||
case BizResourceContextMenuBtnType.ImportLibraryResource:
|
||||
// return importLibrary();
|
||||
// return openDatabase();
|
||||
return;
|
||||
case BizResourceContextMenuBtnType.DuplicateResource:
|
||||
return resourceOperation({
|
||||
scene: ResourceCopyScene.CopyProjectResource,
|
||||
resource,
|
||||
});
|
||||
case BizResourceContextMenuBtnType.MoveToLibrary:
|
||||
return resourceOperation({
|
||||
scene: ResourceCopyScene.MoveResourceToLibrary,
|
||||
resource,
|
||||
});
|
||||
case BizResourceContextMenuBtnType.CopyToLibrary:
|
||||
return resourceOperation({
|
||||
scene: ResourceCopyScene.CopyResourceToLibrary,
|
||||
resource,
|
||||
});
|
||||
default:
|
||||
console.warn('[DatabaseResource]unsupported action>>>', action);
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
onChangeName,
|
||||
onAction,
|
||||
onDelete,
|
||||
onCustomCreate,
|
||||
// createResourceConfig,
|
||||
modals: [createDatabaseModal],
|
||||
};
|
||||
};
|
||||
|
||||
export default useDatabaseResource;
|
||||
@@ -0,0 +1,171 @@
|
||||
/*
|
||||
* 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 { useProjectId, useSpaceId } from '@coze-project-ide/framework';
|
||||
import { usePrimarySidebarStore } from '@coze-project-ide/biz-components';
|
||||
import { FilterKnowledgeType } from '@coze-data/knowledge-modal-base';
|
||||
import { useKnowledgeListModalContent } from '@coze-data/knowledge-modal-adapter';
|
||||
import { useSelectDatabaseModal } from '@coze-data/database-v2';
|
||||
import { I18n } from '@coze-arch/i18n';
|
||||
import { UITabsModal } from '@coze-arch/bot-semi';
|
||||
import { ResType, ResourceCopyScene } from '@coze-arch/bot-api/plugin_develop';
|
||||
|
||||
import SiderCategory from '../components/sider-category';
|
||||
import { useResourceOperation } from './use-resource-operation';
|
||||
|
||||
type TabType = 'knowledge' | 'database';
|
||||
|
||||
export const ImportDataModal = (props: { onClose?: () => void }) => {
|
||||
const { onClose } = props;
|
||||
const [activeKey, setActiveKey] = useState<TabType>('knowledge');
|
||||
|
||||
const projectID = useProjectId();
|
||||
const spaceID = useSpaceId();
|
||||
|
||||
const refetch = usePrimarySidebarStore(state => state.refetch);
|
||||
|
||||
const resourceOperation = useResourceOperation({ projectId: projectID });
|
||||
|
||||
const { renderContent, renderSearch } = useKnowledgeListModalContent({
|
||||
showFilters: ['scope-type', 'search-type'],
|
||||
datasetList: [],
|
||||
onDatasetListChange: async list => {
|
||||
if (list[0].dataset_id && list[0].name) {
|
||||
await resourceOperation({
|
||||
scene: ResourceCopyScene.CopyResourceFromLibrary,
|
||||
resource: {
|
||||
id: list[0].dataset_id,
|
||||
res_id: list[0].dataset_id,
|
||||
name: list[0].name,
|
||||
res_type: ResType.Knowledge,
|
||||
},
|
||||
});
|
||||
refetch();
|
||||
onClose?.();
|
||||
}
|
||||
},
|
||||
canCreate: false,
|
||||
defaultType: FilterKnowledgeType.ALL,
|
||||
});
|
||||
|
||||
const {
|
||||
renderContent: renderDatabaseContent,
|
||||
renderFilter: renderDatabaseFilter,
|
||||
renderInput: renderDatabaseInput,
|
||||
} = useSelectDatabaseModal({
|
||||
visible: true,
|
||||
onClose: () => void 0,
|
||||
onAddDatabase: async id => {
|
||||
await resourceOperation({
|
||||
scene: ResourceCopyScene.CopyResourceFromLibrary,
|
||||
resource: {
|
||||
id,
|
||||
res_id: id,
|
||||
name: '',
|
||||
res_type: ResType.Database,
|
||||
},
|
||||
});
|
||||
refetch();
|
||||
onClose?.();
|
||||
},
|
||||
onClickDatabase: () => void 0,
|
||||
enterFrom: 'project',
|
||||
spaceId: spaceID,
|
||||
});
|
||||
|
||||
return (
|
||||
<UITabsModal
|
||||
keepDOM={false}
|
||||
visible
|
||||
onCancel={onClose}
|
||||
tabs={{
|
||||
tabsProps: {
|
||||
lazyRender: true,
|
||||
activeKey,
|
||||
onChange: (key: string) => setActiveKey(key as TabType),
|
||||
},
|
||||
tabPanes: [
|
||||
{
|
||||
tabPaneProps: {
|
||||
tab: I18n.t('resource_type_knowledge'),
|
||||
itemKey: 'knowledge',
|
||||
},
|
||||
content: (
|
||||
<div className="w-full h-full flex">
|
||||
<div className="w-[218px] pt-[16px] px-[12px] shrink-0 flex flex-col gap-[12px]">
|
||||
{renderSearch()}
|
||||
<SiderCategory
|
||||
label={I18n.t('project_resource_modal_library_resources', {
|
||||
resource: I18n.t('resource_type_knowledge'),
|
||||
})}
|
||||
selected
|
||||
></SiderCategory>
|
||||
</div>
|
||||
<div className="grow-[1] bg-[white] pt-[16px] px-[12px]">
|
||||
{renderContent()}
|
||||
</div>
|
||||
</div>
|
||||
),
|
||||
},
|
||||
{
|
||||
tabPaneProps: {
|
||||
tab: I18n.t('resource_type_database'),
|
||||
itemKey: 'database',
|
||||
},
|
||||
content: (
|
||||
<div className="w-full h-full flex">
|
||||
<div className="w-[218px] pt-[16px] px-[12px] shrink-0 flex flex-col gap-[12px]">
|
||||
{renderDatabaseInput()}
|
||||
<SiderCategory
|
||||
label={I18n.t('project_resource_modal_library_resources', {
|
||||
resource: I18n.t('resource_type_database'),
|
||||
})}
|
||||
selected
|
||||
></SiderCategory>
|
||||
</div>
|
||||
<div className="grow-[1] bg-[white] pt-[16px] px-[12px] flex flex-col">
|
||||
{renderDatabaseFilter()}
|
||||
{renderDatabaseContent()}
|
||||
</div>
|
||||
</div>
|
||||
),
|
||||
},
|
||||
],
|
||||
}}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
const useImportData = () => {
|
||||
const [visible, setVisible] = useState(false);
|
||||
|
||||
const open = () => {
|
||||
setVisible(true);
|
||||
};
|
||||
|
||||
const close = () => {
|
||||
setVisible(false);
|
||||
};
|
||||
return {
|
||||
modal: visible ? <ImportDataModal onClose={close} /> : null,
|
||||
open,
|
||||
close,
|
||||
};
|
||||
};
|
||||
|
||||
export default useImportData;
|
||||
@@ -0,0 +1,185 @@
|
||||
/*
|
||||
* 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, useCallback } from 'react';
|
||||
|
||||
import {
|
||||
type ResourceFolderProps,
|
||||
type ResourceType,
|
||||
useProjectId,
|
||||
useSpaceId,
|
||||
useIDENavigate,
|
||||
} from '@coze-project-ide/framework';
|
||||
import {
|
||||
BizResourceContextMenuBtnType,
|
||||
type BizResourceType,
|
||||
BizResourceTypeEnum,
|
||||
type ResourceFolderCozeProps,
|
||||
// useOpenResource,
|
||||
usePrimarySidebarStore,
|
||||
} from '@coze-project-ide/biz-components';
|
||||
import { useCreateKnowledgeModalV2 } from '@coze-data/knowledge-modal-adapter';
|
||||
import { I18n } from '@coze-arch/i18n';
|
||||
import { ResourceCopyScene } from '@coze-arch/bot-api/plugin_develop';
|
||||
import { DatasetStatus } from '@coze-arch/bot-api/knowledge';
|
||||
import { KnowledgeApi } from '@coze-arch/bot-api';
|
||||
import { Toast } from '@coze-arch/coze-design';
|
||||
|
||||
import { useResourceOperation } from './use-resource-operation';
|
||||
|
||||
// import { useImportLibraryKnowledge } from './use-import-library-knowledge';
|
||||
|
||||
type UseKnowledgeResourceReturn = Pick<
|
||||
ResourceFolderCozeProps,
|
||||
| 'onCustomCreate'
|
||||
| 'onDelete'
|
||||
| 'onChangeName'
|
||||
| 'onAction'
|
||||
| 'createResourceConfig'
|
||||
| 'iconRender'
|
||||
> & { modals: ReactNode };
|
||||
|
||||
const useKnowledgeResource = (): UseKnowledgeResourceReturn => {
|
||||
const refetch = usePrimarySidebarStore(state => state.refetch);
|
||||
const spaceId = useSpaceId();
|
||||
const projectID = useProjectId();
|
||||
const IDENav = useIDENavigate();
|
||||
// const openResource = useOpenResource();
|
||||
|
||||
// 创建knowledge
|
||||
const {
|
||||
modal: createKnowledgeModal,
|
||||
open: openCreateKnowledgeModal,
|
||||
close,
|
||||
} = useCreateKnowledgeModalV2({
|
||||
projectID,
|
||||
onFinish: (datasetID, unitType, shouldUpload) => {
|
||||
refetch();
|
||||
close();
|
||||
IDENav(
|
||||
`/knowledge/${datasetID}?type=${unitType}${shouldUpload ? '&module=upload' : ''}`,
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
// 更新 knowledge 状态,主要用于禁用启用
|
||||
const updateKnowledge = async (
|
||||
datasetID: string,
|
||||
datasetName: string,
|
||||
status: DatasetStatus,
|
||||
) => {
|
||||
try {
|
||||
await KnowledgeApi.UpdateDataset({
|
||||
dataset_id: datasetID,
|
||||
name: datasetName,
|
||||
status,
|
||||
});
|
||||
} catch (e) {
|
||||
console.log('[ResourceFolder]update knowledge error>>>', e);
|
||||
} finally {
|
||||
refetch();
|
||||
}
|
||||
};
|
||||
|
||||
const onCustomCreate: ResourceFolderCozeProps['onCustomCreate'] = () => {
|
||||
openCreateKnowledgeModal();
|
||||
};
|
||||
|
||||
const onChangeName: ResourceFolderProps['onChangeName'] =
|
||||
async changeNameEvent => {
|
||||
try {
|
||||
await KnowledgeApi.UpdateDataset({
|
||||
dataset_id: changeNameEvent.id,
|
||||
name: changeNameEvent.name,
|
||||
});
|
||||
} catch (e) {
|
||||
console.log('[ResourceFolder]rename knowledge error>>>', e);
|
||||
} finally {
|
||||
refetch();
|
||||
}
|
||||
};
|
||||
|
||||
const onDelete = useCallback(
|
||||
async (resources: ResourceType[]) => {
|
||||
try {
|
||||
await KnowledgeApi.DeleteDataset({
|
||||
dataset_id: resources.filter(
|
||||
r => r.type === BizResourceTypeEnum.Knowledge,
|
||||
)?.[0].res_id,
|
||||
});
|
||||
Toast.success(I18n.t('Delete_success'));
|
||||
refetch();
|
||||
} catch (e) {
|
||||
Toast.error(I18n.t('Delete_failed'));
|
||||
}
|
||||
},
|
||||
[refetch, spaceId],
|
||||
);
|
||||
|
||||
const resourceOperation = useResourceOperation({ projectId: projectID });
|
||||
const onAction = (
|
||||
action: BizResourceContextMenuBtnType,
|
||||
resource?: BizResourceType,
|
||||
) => {
|
||||
switch (action) {
|
||||
case BizResourceContextMenuBtnType.DuplicateResource:
|
||||
return resourceOperation({
|
||||
scene: ResourceCopyScene.CopyProjectResource,
|
||||
resource,
|
||||
});
|
||||
case BizResourceContextMenuBtnType.MoveToLibrary:
|
||||
return resourceOperation({
|
||||
scene: ResourceCopyScene.MoveResourceToLibrary,
|
||||
resource,
|
||||
});
|
||||
case BizResourceContextMenuBtnType.CopyToLibrary:
|
||||
return resourceOperation({
|
||||
scene: ResourceCopyScene.CopyResourceToLibrary,
|
||||
resource,
|
||||
});
|
||||
case BizResourceContextMenuBtnType.DisableKnowledge:
|
||||
if (resource?.id) {
|
||||
updateKnowledge(
|
||||
resource.id,
|
||||
resource.name,
|
||||
DatasetStatus.DatasetForbid,
|
||||
);
|
||||
}
|
||||
break;
|
||||
case BizResourceContextMenuBtnType.EnableKnowledge:
|
||||
if (resource?.id) {
|
||||
updateKnowledge(
|
||||
resource.id,
|
||||
resource.name,
|
||||
DatasetStatus.DatasetReady,
|
||||
);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
onChangeName,
|
||||
onAction,
|
||||
onDelete,
|
||||
onCustomCreate,
|
||||
modals: [createKnowledgeModal],
|
||||
};
|
||||
};
|
||||
|
||||
export default useKnowledgeResource;
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* 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 BizResourceType,
|
||||
useResourceCopyDispatch,
|
||||
} from '@coze-project-ide/biz-components';
|
||||
import { type resource_resource_common } from '@coze-arch/bot-api/plugin_develop';
|
||||
|
||||
export interface ResourceOperationProps {
|
||||
projectId: string;
|
||||
}
|
||||
|
||||
export const useResourceOperation = ({ projectId }: ResourceOperationProps) => {
|
||||
const copyDispatch = useResourceCopyDispatch();
|
||||
return async ({
|
||||
scene,
|
||||
resource,
|
||||
}: {
|
||||
scene: resource_resource_common.ResourceCopyScene;
|
||||
resource?: BizResourceType;
|
||||
}) => {
|
||||
try {
|
||||
console.log(
|
||||
`[ResourceFolder]workflow resource copy dispatch, scene ${scene}>>>`,
|
||||
resource,
|
||||
);
|
||||
await copyDispatch({
|
||||
scene,
|
||||
res_id: resource?.id,
|
||||
res_type: resource?.res_type,
|
||||
project_id: projectId,
|
||||
res_name: resource?.name || '',
|
||||
});
|
||||
} catch (e) {
|
||||
console.error(
|
||||
`[ResourceFolder]workflow resource copy dispatch, scene ${scene} error>>>`,
|
||||
e,
|
||||
);
|
||||
}
|
||||
};
|
||||
};
|
||||
23
frontend/packages/project-ide/biz-data/src/index.tsx
Normal file
23
frontend/packages/project-ide/biz-data/src/index.tsx
Normal file
@@ -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.
|
||||
*/
|
||||
|
||||
export {
|
||||
KnowledgeWidgetRegistry,
|
||||
VariablesWidgetRegistry,
|
||||
DatabaseWidgetRegistry,
|
||||
} from './registry';
|
||||
|
||||
export { default as useDataResource } from './hooks/use-data-resource';
|
||||
132
frontend/packages/project-ide/biz-data/src/main.tsx
Normal file
132
frontend/packages/project-ide/biz-data/src/main.tsx
Normal file
@@ -0,0 +1,132 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import qs from 'qs';
|
||||
import {
|
||||
useTitle,
|
||||
useCurrentWidgetContext,
|
||||
useIDEParams,
|
||||
useIDENavigate,
|
||||
useProjectId,
|
||||
useSpaceId,
|
||||
useCommitVersion,
|
||||
} from '@coze-project-ide/framework';
|
||||
import { usePrimarySidebarStore } from '@coze-project-ide/biz-components';
|
||||
import { KnowledgeParamsStoreProvider } from '@coze-data/knowledge-stores';
|
||||
import {
|
||||
UnitType,
|
||||
OptType,
|
||||
} from '@coze-data/knowledge-resource-processor-core';
|
||||
import {
|
||||
getUploadConfig,
|
||||
KnowledgeResourceProcessor,
|
||||
} from '@coze-data/knowledge-resource-processor-adapter';
|
||||
import { type ActionType } from '@coze-data/knowledge-ide-base/types';
|
||||
import { BizProjectKnowledgeIDE } from '@coze-data/knowledge-ide-adapter';
|
||||
|
||||
const Main = () => {
|
||||
const spaceID = useSpaceId();
|
||||
const { uri, widget } = useCurrentWidgetContext();
|
||||
const IDENav = useIDENavigate();
|
||||
const title = useTitle();
|
||||
const { version } = useCommitVersion();
|
||||
|
||||
const projectID = useProjectId();
|
||||
|
||||
const refetch = usePrimarySidebarStore(state => state.refetch);
|
||||
|
||||
const queryObject = useIDEParams();
|
||||
|
||||
const {
|
||||
type,
|
||||
opt,
|
||||
doc_id,
|
||||
page_mode,
|
||||
biz,
|
||||
bot_id,
|
||||
workflow_id,
|
||||
agent_id,
|
||||
module,
|
||||
action_type,
|
||||
first_auto_open_edit_document_id,
|
||||
create,
|
||||
} = queryObject;
|
||||
|
||||
const uploadConfig = getUploadConfig(
|
||||
(type as UnitType) ?? UnitType.TEXT,
|
||||
(opt as OptType) ?? OptType.ADD,
|
||||
);
|
||||
|
||||
const datasetID = uri?.path.name ?? '';
|
||||
|
||||
return (
|
||||
<KnowledgeParamsStoreProvider
|
||||
params={{
|
||||
version,
|
||||
projectID,
|
||||
datasetID,
|
||||
spaceID,
|
||||
type: type as UnitType,
|
||||
opt: opt as OptType,
|
||||
docID: doc_id,
|
||||
pageMode: page_mode as 'modal' | 'normal',
|
||||
biz:
|
||||
(biz as 'agentIDE' | 'workflow' | 'project' | undefined) ?? 'project',
|
||||
botID: bot_id,
|
||||
workflowID: workflow_id,
|
||||
agentID: agent_id,
|
||||
actionType: action_type as ActionType,
|
||||
first_auto_open_edit_document_id,
|
||||
create,
|
||||
}}
|
||||
onUpdateDisplayName={displayName => {
|
||||
widget.setTitle(displayName); // 设置 tab 标题
|
||||
if (displayName && displayName !== title) {
|
||||
refetch(); // 更新侧边栏 name
|
||||
}
|
||||
}}
|
||||
onStatusChange={status => {
|
||||
widget.setUIState(status);
|
||||
}}
|
||||
resourceNavigate={{
|
||||
// eslint-disable-next-line max-params
|
||||
toResource: (resource, resourceID, query, opts) =>
|
||||
IDENav(`/${resource}/${resourceID}?${qs.stringify(query)}`, opts),
|
||||
upload: (query, opts) => {
|
||||
IDENav(
|
||||
`/knowledge/${datasetID}?module=upload&${qs.stringify(query)}`,
|
||||
opts,
|
||||
);
|
||||
},
|
||||
}}
|
||||
>
|
||||
{module === 'upload' ? (
|
||||
uploadConfig ? (
|
||||
<KnowledgeResourceProcessor
|
||||
keepDocTitle
|
||||
uploadConfig={uploadConfig}
|
||||
/>
|
||||
) : null
|
||||
) : (
|
||||
<BizProjectKnowledgeIDE layoutProps={{ keepDocTitle: true }} />
|
||||
)}
|
||||
</KnowledgeParamsStoreProvider>
|
||||
);
|
||||
};
|
||||
|
||||
export default Main;
|
||||
65
frontend/packages/project-ide/biz-data/src/registry.tsx
Normal file
65
frontend/packages/project-ide/biz-data/src/registry.tsx
Normal file
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import {
|
||||
IconCozDatabase,
|
||||
IconCozKnowledge,
|
||||
IconCozVariables,
|
||||
} from '@coze-arch/coze-design/icons';
|
||||
import {
|
||||
LayoutPanelType,
|
||||
withLazyLoad,
|
||||
type WidgetRegistry,
|
||||
} from '@coze-project-ide/framework';
|
||||
|
||||
export const KnowledgeWidgetRegistry: WidgetRegistry = {
|
||||
match: /\/knowledge\/.*/,
|
||||
area: LayoutPanelType.MAIN_PANEL,
|
||||
renderContent() {
|
||||
const Component = withLazyLoad(() => import('./main'));
|
||||
// return <div>this is knowledge</div>;
|
||||
return <Component />;
|
||||
},
|
||||
renderIcon() {
|
||||
return <IconCozKnowledge />;
|
||||
},
|
||||
};
|
||||
|
||||
export const VariablesWidgetRegistry: WidgetRegistry = {
|
||||
match: /\/variables\/?$/,
|
||||
area: LayoutPanelType.MAIN_PANEL,
|
||||
renderContent() {
|
||||
const Component = withLazyLoad(() => import('./variables-main'));
|
||||
return <Component />;
|
||||
},
|
||||
renderIcon() {
|
||||
return <IconCozVariables />;
|
||||
},
|
||||
};
|
||||
|
||||
export const DatabaseWidgetRegistry: WidgetRegistry = {
|
||||
match: /\/database\/.*/,
|
||||
area: LayoutPanelType.MAIN_PANEL,
|
||||
renderContent() {
|
||||
const Component = withLazyLoad(() => import('./database-main'));
|
||||
return <Component />;
|
||||
},
|
||||
renderIcon() {
|
||||
return <IconCozDatabase />;
|
||||
},
|
||||
};
|
||||
17
frontend/packages/project-ide/biz-data/src/typings.d.ts
vendored
Normal file
17
frontend/packages/project-ide/biz-data/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,71 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import React, { useEffect } from 'react';
|
||||
|
||||
import qs from 'qs';
|
||||
import {
|
||||
useCurrentWidgetContext,
|
||||
useIDENavigate,
|
||||
useProjectId,
|
||||
useCommitVersion,
|
||||
} from '@coze-project-ide/framework';
|
||||
import { VariablesPage } from '@coze-data/variable';
|
||||
import { KnowledgeParamsStoreProvider } from '@coze-data/knowledge-stores';
|
||||
import { I18n } from '@coze-arch/i18n';
|
||||
|
||||
const Main = () => {
|
||||
const IDENav = useIDENavigate();
|
||||
const { widget } = useCurrentWidgetContext();
|
||||
const projectID = useProjectId();
|
||||
|
||||
const { version } = useCommitVersion();
|
||||
|
||||
const { uri } = useCurrentWidgetContext();
|
||||
|
||||
const datasetID = uri?.path.name ?? '';
|
||||
|
||||
useEffect(() => {
|
||||
widget.setTitle(I18n.t('dataide002'));
|
||||
widget.setUIState('normal');
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<KnowledgeParamsStoreProvider
|
||||
params={{
|
||||
version,
|
||||
projectID,
|
||||
datasetID,
|
||||
biz: 'project',
|
||||
}}
|
||||
resourceNavigate={{
|
||||
// eslint-disable-next-line max-params
|
||||
toResource: (resource, resourceID, query, opts) =>
|
||||
IDENav(`/${resource}/${resourceID}?${qs.stringify(query)}`, opts),
|
||||
upload: (query, opts) =>
|
||||
IDENav(
|
||||
`/knowledge/${datasetID}?module=upload&${qs.stringify(query)}`,
|
||||
opts,
|
||||
),
|
||||
navigateTo: IDENav,
|
||||
}}
|
||||
>
|
||||
<VariablesPage />
|
||||
</KnowledgeParamsStoreProvider>
|
||||
);
|
||||
};
|
||||
|
||||
export default Main;
|
||||
79
frontend/packages/project-ide/biz-data/tsconfig.build.json
Normal file
79
frontend/packages/project-ide/biz-data/tsconfig.build.json
Normal file
@@ -0,0 +1,79 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/tsconfig",
|
||||
"extends": "@coze-arch/ts-config/tsconfig.web.json",
|
||||
"compilerOptions": {
|
||||
"types": [],
|
||||
"isolatedModules": true,
|
||||
"strictNullChecks": true,
|
||||
"strictPropertyInitialization": false,
|
||||
"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": "../biz-components/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"
|
||||
},
|
||||
{
|
||||
"path": "../../data/common/utils/tsconfig.build.json"
|
||||
},
|
||||
{
|
||||
"path": "../../data/knowledge/common/stores/tsconfig.build.json"
|
||||
},
|
||||
{
|
||||
"path": "../../data/knowledge/knowledge-ide-adapter/tsconfig.build.json"
|
||||
},
|
||||
{
|
||||
"path": "../../data/knowledge/knowledge-ide-base/tsconfig.build.json"
|
||||
},
|
||||
{
|
||||
"path": "../../data/knowledge/knowledge-modal-adapter/tsconfig.build.json"
|
||||
},
|
||||
{
|
||||
"path": "../../data/knowledge/knowledge-modal-base/tsconfig.build.json"
|
||||
},
|
||||
{
|
||||
"path": "../../data/knowledge/knowledge-resource-processor-adapter/tsconfig.build.json"
|
||||
},
|
||||
{
|
||||
"path": "../../data/knowledge/knowledge-resource-processor-base/tsconfig.build.json"
|
||||
},
|
||||
{
|
||||
"path": "../../data/knowledge/knowledge-resource-processor-core/tsconfig.build.json"
|
||||
},
|
||||
{
|
||||
"path": "../../data/memory/database-v2-main/tsconfig.build.json"
|
||||
},
|
||||
{
|
||||
"path": "../../data/memory/variables/tsconfig.build.json"
|
||||
},
|
||||
{
|
||||
"path": "../framework/tsconfig.build.json"
|
||||
}
|
||||
]
|
||||
}
|
||||
15
frontend/packages/project-ide/biz-data/tsconfig.json
Normal file
15
frontend/packages/project-ide/biz-data/tsconfig.json
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/tsconfig",
|
||||
"exclude": ["**/*"],
|
||||
"compilerOptions": {
|
||||
"composite": true
|
||||
},
|
||||
"references": [
|
||||
{
|
||||
"path": "./tsconfig.build.json"
|
||||
},
|
||||
{
|
||||
"path": "./tsconfig.misc.json"
|
||||
}
|
||||
]
|
||||
}
|
||||
19
frontend/packages/project-ide/biz-data/tsconfig.misc.json
Normal file
19
frontend/packages/project-ide/biz-data/tsconfig.misc.json
Normal file
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"extends": "@coze-arch/ts-config/tsconfig.web.json",
|
||||
"$schema": "https://json.schemastore.org/tsconfig",
|
||||
"include": ["__tests__", "stories", "vitest.config.ts", "tailwind.config.ts"],
|
||||
"exclude": ["**/node_modules", "./dist"],
|
||||
"references": [
|
||||
{
|
||||
"path": "./tsconfig.build.json"
|
||||
}
|
||||
],
|
||||
"compilerOptions": {
|
||||
"rootDir": "./",
|
||||
"outDir": "./dist",
|
||||
"types": ["vitest/globals"],
|
||||
"isolatedModules": true,
|
||||
"strictNullChecks": true,
|
||||
"strictPropertyInitialization": false
|
||||
}
|
||||
}
|
||||
22
frontend/packages/project-ide/biz-data/vitest.config.ts
Normal file
22
frontend/packages/project-ide/biz-data/vitest.config.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* 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',
|
||||
});
|
||||
@@ -0,0 +1,31 @@
|
||||
import { mergeConfig } from 'vite';
|
||||
import svgr from 'vite-plugin-svgr';
|
||||
|
||||
/** @type { import('@storybook/react-vite').StorybookConfig } */
|
||||
const config = {
|
||||
stories: ['../stories/**/*.mdx', '../stories/**/*.stories.tsx'],
|
||||
addons: [
|
||||
'@storybook/addon-links',
|
||||
'@storybook/addon-essentials',
|
||||
'@storybook/addon-onboarding',
|
||||
'@storybook/addon-interactions',
|
||||
],
|
||||
framework: {
|
||||
name: '@storybook/react-vite',
|
||||
options: {},
|
||||
},
|
||||
docs: {
|
||||
autodocs: 'tag',
|
||||
},
|
||||
viteFinal: config =>
|
||||
mergeConfig(config, {
|
||||
plugins: [
|
||||
svgr({
|
||||
svgrOptions: {
|
||||
native: false,
|
||||
},
|
||||
}),
|
||||
],
|
||||
}),
|
||||
};
|
||||
export default config;
|
||||
@@ -0,0 +1,14 @@
|
||||
/** @type { import('@storybook/react').Preview } */
|
||||
const preview = {
|
||||
parameters: {
|
||||
actions: { argTypesRegex: "^on[A-Z].*" },
|
||||
controls: {
|
||||
matchers: {
|
||||
color: /(background|color)$/i,
|
||||
date: /Date$/i,
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export default preview;
|
||||
@@ -0,0 +1,5 @@
|
||||
const { defineConfig } = require('@coze-arch/stylelint-config');
|
||||
|
||||
module.exports = defineConfig({
|
||||
extends: [],
|
||||
});
|
||||
@@ -0,0 +1,16 @@
|
||||
# @coze-project-ide/biz-plugin-registry
|
||||
|
||||
> Project template for react component with storybook.
|
||||
|
||||
## 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,12 @@
|
||||
{
|
||||
"operationSettings": [
|
||||
{
|
||||
"operationName": "test:cov",
|
||||
"outputFolderNames": ["coverage"]
|
||||
},
|
||||
{
|
||||
"operationName": "ts-check",
|
||||
"outputFolderNames": ["dist"]
|
||||
}
|
||||
]
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user