diff --git a/CHANGELOG.md b/CHANGELOG.md index c88842d58f..00a0eda99b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,49 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [v1.6.12](https://github.com/nocobase/nocobase/compare/v1.6.11...v1.6.12) - 2025-03-27 + +### 🐛 Bug Fixes + +- **[Block: Multi-step form]** + - the submit button has the same color in its default and highlighted by @jiannx + + - fixed the bug that form reset is invalid when the field is associated with other field by @jiannx + +- **[Workflow: Approval]** Fix approval form values to submit by @mytharcher + +## [v1.6.11](https://github.com/nocobase/nocobase/compare/v1.6.10...v1.6.11) - 2025-03-27 + +### 🚀 Improvements + +- **[client]** + - Optimize 502 error message ([#6547](https://github.com/nocobase/nocobase/pull/6547)) by @chenos + + - Only support plain text file to preview ([#6563](https://github.com/nocobase/nocobase/pull/6563)) by @mytharcher + +- **[Collection field: Sequence]** support setting sequence as the title field for calendar block ([#6562](https://github.com/nocobase/nocobase/pull/6562)) by @katherinehhh + +- **[Workflow: Approval]** Support to skip validator in settings by @mytharcher + +### 🐛 Bug Fixes + +- **[client]** + - issue with date field display in data scope filtering ([#6564](https://github.com/nocobase/nocobase/pull/6564)) by @katherinehhh + + - The 'Ellipsis overflow content' option requires a page refresh for the toggle state to take effect ([#6520](https://github.com/nocobase/nocobase/pull/6520)) by @zhangzhonghe + + - Unable to open another modal within a modal ([#6535](https://github.com/nocobase/nocobase/pull/6535)) by @zhangzhonghe + +- **[API documentation]** API document page cannot scroll ([#6566](https://github.com/nocobase/nocobase/pull/6566)) by @zhangzhonghe + +- **[Workflow]** Make sure workflow key is generated before save ([#6567](https://github.com/nocobase/nocobase/pull/6567)) by @mytharcher + +- **[Workflow: Post-action event]** Multiple records in bulk action should trigger multiple times ([#6559](https://github.com/nocobase/nocobase/pull/6559)) by @mytharcher + +- **[Authentication]** Localization issue for fields of sign up page ([#6556](https://github.com/nocobase/nocobase/pull/6556)) by @2013xile + +- **[Public forms]** issue with public form page title displaying 'Loading...' ([#6569](https://github.com/nocobase/nocobase/pull/6569)) by @katherinehhh + ## [v1.6.10](https://github.com/nocobase/nocobase/compare/v1.6.9...v1.6.10) - 2025-03-25 ### 🐛 Bug Fixes diff --git a/CHANGELOG.zh-CN.md b/CHANGELOG.zh-CN.md index 8d31b47137..e22c5a3d4a 100644 --- a/CHANGELOG.zh-CN.md +++ b/CHANGELOG.zh-CN.md @@ -5,6 +5,49 @@ 格式基于 [Keep a Changelog](https://keepachangelog.com/zh-CN/1.0.0/), 并且本项目遵循 [语义化版本](https://semver.org/spec/v2.0.0.html)。 +## [v1.6.12](https://github.com/nocobase/nocobase/compare/v1.6.11...v1.6.12) - 2025-03-27 + +### 🐛 修复 + +- **[区块:分步表单]** + - 提交按钮默认和高亮情况下颜色一样 by @jiannx + + - 修复当字段与其他表单字段存在关联时,表单重置无效 by @jiannx + +- **[工作流:审批]** 修复审批表单提交值的问题 by @mytharcher + +## [v1.6.11](https://github.com/nocobase/nocobase/compare/v1.6.10...v1.6.11) - 2025-03-27 + +### 🚀 优化 + +- **[client]** + - 优化 502 错误提示 ([#6547](https://github.com/nocobase/nocobase/pull/6547)) by @chenos + + - 仅支持纯文本文件预览 ([#6563](https://github.com/nocobase/nocobase/pull/6563)) by @mytharcher + +- **[数据表字段:自动编码]** 支持使用 sequence 作为日历区块的标题字段 ([#6562](https://github.com/nocobase/nocobase/pull/6562)) by @katherinehhh + +- **[工作流:审批]** 支持审批处理按钮跳过表单验证的设置 by @mytharcher + +### 🐛 修复 + +- **[client]** + - 数据范围中筛选日期字段显示异常 ([#6564](https://github.com/nocobase/nocobase/pull/6564)) by @katherinehhh + + - 选项“省略超出长度的内容”需要刷新页面,开关的状态才生效 ([#6520](https://github.com/nocobase/nocobase/pull/6520)) by @zhangzhonghe + + - 在弹窗中无法再次打开弹窗 ([#6535](https://github.com/nocobase/nocobase/pull/6535)) by @zhangzhonghe + +- **[API 文档]** API 文档页面不能滚动 ([#6566](https://github.com/nocobase/nocobase/pull/6566)) by @zhangzhonghe + +- **[工作流]** 确保创建工作流之前 key 已生成 ([#6567](https://github.com/nocobase/nocobase/pull/6567)) by @mytharcher + +- **[工作流:操作后事件]** 多行记录的批量操作需要触发多次 ([#6559](https://github.com/nocobase/nocobase/pull/6559)) by @mytharcher + +- **[用户认证]** 注册页面字段的本地化问题 ([#6556](https://github.com/nocobase/nocobase/pull/6556)) by @2013xile + +- **[公开表单]** 公开表单页面标题不应该显示 Loading... ([#6569](https://github.com/nocobase/nocobase/pull/6569)) by @katherinehhh + ## [v1.6.10](https://github.com/nocobase/nocobase/compare/v1.6.9...v1.6.10) - 2025-03-25 ### 🐛 修复 diff --git a/lerna.json b/lerna.json index 23e6020e76..994c7d1426 100644 --- a/lerna.json +++ b/lerna.json @@ -1,5 +1,5 @@ { - "version": "1.7.0-beta.9", + "version": "1.7.0-alpha.10", "npmClient": "yarn", "useWorkspaces": true, "npmClientArgs": ["--ignore-engines"], diff --git a/packages/core/acl/package.json b/packages/core/acl/package.json index bc56252d00..cddc749497 100644 --- a/packages/core/acl/package.json +++ b/packages/core/acl/package.json @@ -1,13 +1,13 @@ { "name": "@nocobase/acl", - "version": "1.7.0-beta.9", + "version": "1.7.0-alpha.10", "description": "", "license": "AGPL-3.0", "main": "./lib/index.js", "types": "./lib/index.d.ts", "dependencies": { - "@nocobase/resourcer": "1.7.0-beta.9", - "@nocobase/utils": "1.7.0-beta.9", + "@nocobase/resourcer": "1.7.0-alpha.10", + "@nocobase/utils": "1.7.0-alpha.10", "minimatch": "^5.1.1" }, "repository": { diff --git a/packages/core/actions/package.json b/packages/core/actions/package.json index 38dc5e54f6..441dc3e596 100644 --- a/packages/core/actions/package.json +++ b/packages/core/actions/package.json @@ -1,14 +1,14 @@ { "name": "@nocobase/actions", - "version": "1.7.0-beta.9", + "version": "1.7.0-alpha.10", "description": "", "license": "AGPL-3.0", "main": "./lib/index.js", "types": "./lib/index.d.ts", "dependencies": { - "@nocobase/cache": "1.7.0-beta.9", - "@nocobase/database": "1.7.0-beta.9", - "@nocobase/resourcer": "1.7.0-beta.9" + "@nocobase/cache": "1.7.0-alpha.10", + "@nocobase/database": "1.7.0-alpha.10", + "@nocobase/resourcer": "1.7.0-alpha.10" }, "repository": { "type": "git", diff --git a/packages/core/app/package.json b/packages/core/app/package.json index 5e313604bd..34ab32b74f 100644 --- a/packages/core/app/package.json +++ b/packages/core/app/package.json @@ -1,17 +1,17 @@ { "name": "@nocobase/app", - "version": "1.7.0-beta.9", + "version": "1.7.0-alpha.10", "description": "", "license": "AGPL-3.0", "main": "./lib/index.js", "types": "./lib/index.d.ts", "dependencies": { - "@nocobase/database": "1.7.0-beta.9", - "@nocobase/preset-nocobase": "1.7.0-beta.9", - "@nocobase/server": "1.7.0-beta.9" + "@nocobase/database": "1.7.0-alpha.10", + "@nocobase/preset-nocobase": "1.7.0-alpha.10", + "@nocobase/server": "1.7.0-alpha.10" }, "devDependencies": { - "@nocobase/client": "1.7.0-beta.9" + "@nocobase/client": "1.7.0-alpha.10" }, "repository": { "type": "git", diff --git a/packages/core/auth/package.json b/packages/core/auth/package.json index e9f3bc982c..8730279583 100644 --- a/packages/core/auth/package.json +++ b/packages/core/auth/package.json @@ -1,16 +1,16 @@ { "name": "@nocobase/auth", - "version": "1.7.0-beta.9", + "version": "1.7.0-alpha.10", "description": "", "license": "AGPL-3.0", "main": "./lib/index.js", "types": "./lib/index.d.ts", "dependencies": { - "@nocobase/actions": "1.7.0-beta.9", - "@nocobase/cache": "1.7.0-beta.9", - "@nocobase/database": "1.7.0-beta.9", - "@nocobase/resourcer": "1.7.0-beta.9", - "@nocobase/utils": "1.7.0-beta.9", + "@nocobase/actions": "1.7.0-alpha.10", + "@nocobase/cache": "1.7.0-alpha.10", + "@nocobase/database": "1.7.0-alpha.10", + "@nocobase/resourcer": "1.7.0-alpha.10", + "@nocobase/utils": "1.7.0-alpha.10", "@types/jsonwebtoken": "^8.5.8", "jsonwebtoken": "^8.5.1" }, diff --git a/packages/core/build/package.json b/packages/core/build/package.json index 640469707d..3a5a95f97d 100644 --- a/packages/core/build/package.json +++ b/packages/core/build/package.json @@ -1,6 +1,6 @@ { "name": "@nocobase/build", - "version": "1.7.0-beta.9", + "version": "1.7.0-alpha.10", "description": "Library build tool based on rollup.", "main": "lib/index.js", "types": "./lib/index.d.ts", diff --git a/packages/core/cache/package.json b/packages/core/cache/package.json index d140f17eb7..e9d9b21e92 100644 --- a/packages/core/cache/package.json +++ b/packages/core/cache/package.json @@ -1,12 +1,12 @@ { "name": "@nocobase/cache", - "version": "1.7.0-beta.9", + "version": "1.7.0-alpha.10", "description": "", "license": "AGPL-3.0", "main": "./lib/index.js", "types": "./lib/index.d.ts", "dependencies": { - "@nocobase/lock-manager": "1.7.0-beta.9", + "@nocobase/lock-manager": "1.7.0-alpha.10", "bloom-filters": "^3.0.1", "cache-manager": "^5.2.4", "cache-manager-redis-yet": "^4.1.2" diff --git a/packages/core/cli/package.json b/packages/core/cli/package.json index 9cccced612..f245798780 100644 --- a/packages/core/cli/package.json +++ b/packages/core/cli/package.json @@ -1,6 +1,6 @@ { "name": "@nocobase/cli", - "version": "1.7.0-beta.9", + "version": "1.7.0-alpha.10", "description": "", "license": "AGPL-3.0", "main": "./src/index.js", @@ -8,7 +8,7 @@ "nocobase": "./bin/index.js" }, "dependencies": { - "@nocobase/app": "1.7.0-beta.9", + "@nocobase/app": "1.7.0-alpha.10", "@types/fs-extra": "^11.0.1", "@umijs/utils": "3.5.20", "chalk": "^4.1.1", @@ -25,7 +25,7 @@ "tsx": "^4.19.0" }, "devDependencies": { - "@nocobase/devtools": "1.7.0-beta.9" + "@nocobase/devtools": "1.7.0-alpha.10" }, "repository": { "type": "git", diff --git a/packages/core/client/package.json b/packages/core/client/package.json index 66f15cedf8..20d8a898e7 100644 --- a/packages/core/client/package.json +++ b/packages/core/client/package.json @@ -1,6 +1,6 @@ { "name": "@nocobase/client", - "version": "1.7.0-beta.9", + "version": "1.7.0-alpha.10", "license": "AGPL-3.0", "main": "lib/index.js", "module": "es/index.mjs", @@ -27,9 +27,9 @@ "@formily/reactive-react": "^2.2.27", "@formily/shared": "^2.2.27", "@formily/validator": "^2.2.27", - "@nocobase/evaluators": "1.7.0-beta.9", - "@nocobase/sdk": "1.7.0-beta.9", - "@nocobase/utils": "1.7.0-beta.9", + "@nocobase/evaluators": "1.7.0-alpha.10", + "@nocobase/sdk": "1.7.0-alpha.10", + "@nocobase/utils": "1.7.0-alpha.10", "ahooks": "^3.7.2", "antd": "5.24.2", "antd-style": "3.7.1", diff --git a/packages/core/client/src/formily/NocoBaseRecursionField.tsx b/packages/core/client/src/formily/NocoBaseRecursionField.tsx index c2c75af9bb..cf0d00c880 100644 --- a/packages/core/client/src/formily/NocoBaseRecursionField.tsx +++ b/packages/core/client/src/formily/NocoBaseRecursionField.tsx @@ -48,6 +48,7 @@ interface INocoBaseRecursionFieldProps extends IRecursionFieldProps { * Whether to use Formily Field class - performance will be reduced but provides better compatibility with Formily */ isUseFormilyField?: boolean; + parentSchema?: Schema; } const CollectionFieldUISchemaContext = React.createContext({}); @@ -266,6 +267,7 @@ export const NocoBaseRecursionField: ReactFC = Rea values, isUseFormilyField = true, uiSchema, + parentSchema, } = props; const basePath = useBasePath(props); const newFieldSchemaRef = useRef(null); @@ -279,6 +281,14 @@ export const NocoBaseRecursionField: ReactFC = Rea const fieldSchema: Schema = newFieldSchemaRef.current || oldFieldSchema; + // Establish connection with the Schema tree + if (!fieldSchema.parent && parentSchema) { + fieldSchema.parent = parentSchema; + if (!fieldSchema.parent?.properties?.[fieldSchema.name] && fieldSchema.name) { + _.set(fieldSchema.parent, `properties.${fieldSchema.name}`, fieldSchema); + } + } + const refresh = useCallback(() => { const parent = fieldSchema.parent; newFieldSchemaRef.current = new Schema(fieldSchema.toJSON(), parent); diff --git a/packages/core/client/src/locale/nl-NL.json b/packages/core/client/src/locale/nl-NL.json index ade6cca425..9a945ea0bb 100644 --- a/packages/core/client/src/locale/nl-NL.json +++ b/packages/core/client/src/locale/nl-NL.json @@ -1,5 +1,7 @@ { "Display <1><0>10<1>20<2>50<3>100 items per page": "Toon <1><0>10<1>20<2>50<3>100 items per pagina", + "Page number": "Paginanummer", + "Page size": "Paginagrootte", "Meet <1><0>All<1>Any conditions in the group": "Voldoe aan <1><0>Alle<1>Een voorwaarde(n) in de groep", "Open in<1><0>Modal<1>Drawer<2>Window": "Open in<1><0>Modal<1>Drawer<2>Venster", "{{count}} filter items": "{{count}} filter items", @@ -38,15 +40,20 @@ "Unconnected": "Niet verbonden", "System settings": "Systeeminstellingen", "System title": "Systeemtitel", + "Setting" : "Instelling", "Settings": "Instellingen", + "Enable": "Inschakelen", + "Disable": "Uitschakelen", + "On": "Aan", + "Off": "Uit", "Logo": "Logo", "Add menu item": "Menu-item toevoegen", "Page": "Pagina", + "Tab": "Tab", "Name": "Naam", "Icon": "Icoon", "Group": "Groep", "Link": "Link", - "Tab": "Tab", "Save conditions": "Voorwaarden opslaan", "Edit menu item": "Menu-item bewerken", "Move to": "Verplaats naar", @@ -82,9 +89,6 @@ "Disabled": "Uitgeschakeld", "Enabled": "Ingeschakeld", "Problematic": "Problematisch", - "Setting": "Instelling", - "On": "Aan", - "Off": "Uit", "Empty": "Leeg", "Linkage rule": "Koppelingregel", "Linkage rules": "Koppelingregels", @@ -434,7 +438,7 @@ "Allow linking to multiple records": "Koppelen aan meerdere records toestaan", "Allow uploading multiple files": "Meerdere bestanden uploaden toestaan", "Configure calendar": "Kalender configureren", - "Title field": "Titelfeld", + "Title field": "Titelveld", "Custom title": "Aangepaste titel", "Daily": "Dagelijks", "Weekly": "Wekelijks", @@ -884,5 +888,171 @@ "If selected, the page will display Tab pages.": "Indien geselecteerd, worden tabbladen op de pagina weergegeven.", "If selected, the route will be displayed in the menu.": "Indien geselecteerd, wordt de route weergegeven in het menu.", "Are you sure you want to hide this tab?": "Weet je zeker dat je dit tabblad wil verbergen?", - "After hiding, this tab will no longer appear in the tab bar. To show it again, you need to go to the route management page to set it.": "Na verbergen wordt dit tabblad niet meer weergegeven in de tabbalk. Om het opnieuw te tonen, moet je naar de routebeheerpagina gaan om het in te stellen." - } \ No newline at end of file + "After hiding, this tab will no longer appear in the tab bar. To show it again, you need to go to the route management page to set it.": "Na verbergen wordt dit tabblad niet meer weergegeven in de tabbalk. Om het opnieuw te tonen, moet je naar de routebeheerpagina gaan om het in te stellen.", + "Calculation engine": "Berekeningsengine", + "Expression collection": "Expressiecollectie", + "Tree collection": "Boomcollectie", + "Parent ID": "Ouder-ID", + "Parent": "Ouder", + "Children": "Kinderen", + "Confirm": "Bevestigen", + "Block": "Blok", + "Unnamed": "Naamloos", + "SQL collection": "SQL-collectie", + "Configure field": "Veld configureren", + "Username": "Gebruikersnaam", + "Null": "Leeg", + "Boolean": "Boolean", + "String": "Tekst", + "Syntax references": "Syntax-referenties", + "Math.js comes with a large set of built-in functions and constants, and offers an integrated solution to work with different data types.": "Math.js wordt geleverd met een groot aantal ingebouwde functies en constanten en biedt een geïntegreerde oplossing om met verschillende gegevenstypen te werken.", + "Formula.js supports most Microsoft Excel formula functions.": "Formula.js ondersteunt de meeste Microsoft Excel-formulefuncties.", + "String template": "Tekstsjabloon", + "Simple string replacement, can be used to interpolate variables in a string.": "Eenvoudige tekstvervanging, kan worden gebruikt om variabelen in een tekst te interpoleren.", + "https://docs.nocobase.com/handbook/calculation-engines/formula": "https://docs.nocobase.com/handbook/calculation-engines/formula", + "https://docs.nocobase.com/handbook/calculation-engines/mathjs": "https://docs.nocobase.com/handbook/calculation-engines/mathjs", + "Display when unchecked": "Toon wanneer niet aangevinkt", + "Allow dissociate": "Loskoppelen toestaan", + "Edit block title & description": "Blok titel & beschrijving bewerken", + "Add Markdown": "Markdown toevoegen", + "Must be 1-50 characters in length (excluding @.<>\"'/)": "Moet 1-50 tekens lang zijn (exclusief @.<>\"'/)", + "Original title: ": "Originele titel: ", + "Original field title: ": "Originele veldtitel: ", + "Data source permissions": "Datatoegangsrechten", + "Now": "Nu", + "Access control": "Toegangscontrole", + "Remove": "Verwijderen", + "Docs": "Documentatie", + "Enable page header": "Paginahoofd inschakelen", + "Display page title": "Paginatitel weergeven", + "Edit page title": "Paginatitel bewerken", + "Enable page tabs": "Pagina-tabbladen inschakelen", + "Constant": "Constant", + "Select a variable": "Selecteer een variabele", + "Double click to choose entire object": "Dubbelklik om het hele object te kiezen", + "TRUE": "WAAR", + "FALSE": "ONWAAR", + "Prettify": "Opknappen", + "Theme": "Thema", + "Default theme": "Standaardthema", + "Compact theme": "Compact thema", + "Download": "Downloaden", + "File type is not supported for previewing, please download it to preview.": "Bestandstype wordt niet ondersteund voor voorbeeldweergave, download het om te bekijken.", + "Click or drag file to this area to upload": "Klik of sleep een bestand naar dit gebied om te uploaden.", + "Support for a single or bulk upload.": "Ondersteuning voor enkele of bulk-upload.", + "File size should not exceed {{size}}.": "Bestandsgrootte mag {{size}} niet overschrijden.", + "File size exceeds the limit": "Bestandsgrootte overschrijdt de limiet.", + "File type is not allowed": "Bestandstype is niet toegestaan.", + "Incomplete uploading files need to be resolved": "Onvolledig geüploade bestanden moeten worden opgelost.", + "Default title for each record": "Standaardtitel voor elk record.", + "If collection inherits, choose inherited collections as templates": "Als de collectie overerft, kies geërfde collecties als sjablonen.", + "Select an existing piece of data as the initialization data for the form": "Selecteer een bestaand gegeven als initiële data voor het formulier.", + "Only the selected fields will be used as the initialization data for the form": "Alleen de geselecteerde velden worden gebruikt als initiële data voor het formulier.", + "Template Data": "Sjabloongegevens", + "Data fields": "Gegevensvelden", + "Add template": "Sjabloon toevoegen", + "Enable form data template": "Formuliersjabloon inschakelen", + "Form data templates": "Formuliersjablonen", + "No configuration available.": "Geen configuratie beschikbaar.", + "Reload application": "Herlaad applicatie", + "The application is reloading, please do not close the page.": "De applicatie wordt opnieuw geladen, sluit de pagina niet.", + "Application reloading": "Applicatie wordt opnieuw geladen", + "Allows to clear cache, reboot application": "Sta toe om cache te wissen en applicatie te herstarten.", + "The will interrupt service, it may take a few seconds to restart. Are you sure to continue?": "Dit onderbreekt de service en kan enkele seconden duren. Weet je zeker dat je wilt doorgaan?", + "Clear cache": "Cache wissen", + "Are you sure you want to clear cache ?": "Weet je zeker dat je de cache wilt wissen?", + "Quick create": "Snel aanmaken", + "Dropdown": "Keuzelijst", + "Pop-up": "Pop-up", + "Direct duplicate": "Direct dupliceren", + "Copy into the form and continue to fill in": "Kopieer in het formulier en vul verder in.", + "Failed to load plugin": "Kan plug-in niet laden.", + "Date range limit": "Datumbereiklimiet", + "MinDate": "Minimale datum", + "MaxDate": "Maximale datum", + "Please select time or variable": "Selecteer een tijd of variabele.", + "Filter out a single piece or a group of records as a template": "Filter een enkel item of een groep records als sjabloon.", + "The title field is used to identify the template record": "Het titelveld wordt gebruikt om het sjabloonrecord te identificeren.", + "Template fields": "Sjabloonvelden", + "The selected fields will automatically populate the form": "De geselecteerde velden vullen automatisch het formulier in.", + "UnSelect all": "Alles deselecteren", + "Secondary confirmation": "Secundaire bevestiging", + "Perform the {{title}}": "Voer {{title}} uit.", + "Are you sure you want to perform the {{title}} action?": "Weet je zeker dat je de actie {{title}} wilt uitvoeren?", + "Permission denied": "Toestemming geweigerd.", + "Allow add new": "Sta toe om nieuw toe te voegen.", + "Data model": "Gegevensmodel", + "Security": "Beveiliging", + "Action": "Actie", + "System": "Systeem", + "Other": "Overige", + "Allow selection of existing records": "Sta selectie van bestaande records toe.", + "Data Model": "Gegevensmodel", + "Blocks": "Blokken", + "Users & permissions": "Gebruikers en machtigingen", + "System management": "Systeembeheer", + "System & security": "Systeem en beveiliging", + "Workflow": "Werkstroom", + "Third party services": "Diensten van derden", + "Data model tools": "Gegevensmodeltools", + "Data sources": "Gegevensbronnen", + "Collections": "Collecties", + "Collection fields": "Collectievelden", + "Authentication": "Authenticatie", + "Logging and monitoring": "Logging en monitoring", + "Main": "Hoofd", + "Index": "Index", + "Field values must be unique.": "Veldwaarden moeten uniek zijn.", + "Alphabet": "Alfabet", + "Accuracy": "Nauwkeurigheid", + "Millisecond": "Milliseconde", + "Second": "Seconde", + "Unix Timestamp": "Unix-tijdstempel", + "Field value do not meet the requirements": "Veldwaarde voldoet niet aan de vereisten.", + "Field value size is": "Veldwaardegrootte is", + "Unit conversion": "Eenheidsconversie", + "Separator": "Scheidingsteken", + "Prefix": "Voorvoegsel", + "Suffix": "Achtervoegsel", + "Record unique key": "Unieke recordsleutel", + "Filter target key": "Filterdoelsleutel", + "If a collection lacks a primary key, you must configure a unique record key to locate row records within a block, failure to configure this will prevent the creation of data blocks for the collection.": "Als een collectie geen primaire sleutel heeft, moet je een unieke recordsleutel configureren om rijen binnen een blok te lokaliseren. Anders kunnen er geen gegevensblokken worden aangemaakt.", + "Filter data based on the specific field, with the requirement that the field value must be unique.": "Filter gegevens op basis van een specifiek veld, waarbij de veldwaarde uniek moet zijn.", + "Multiply by": "Vermenigvuldigen met", + "Divide by": "Delen door", + "Scientifix notation": "Wetenschappelijke notatie", + "Normal": "Normaal", + "Automatically generate default values": "Automatisch standaardwaarden genereren.", + "Refresh data on close": "Ververs gegevens bij sluiten.", + "Refresh data on action": "Ververs gegevens bij actie.", + "Unknown field type": "Onbekend veldtype.", + "The following field types are not compatible and do not support output and display": "De volgende veldtypen zijn niet compatibel en ondersteunen geen uitvoer en weergave.", + "Not fixed": "Niet vastgezet", + "Left fixed": "Links vastgezet", + "Right fixed": "Rechts vastgezet", + "Fixed": "Vastgezet", + "Set block height": "Blokhoogte instellen", + "Specify height": "Hoogte specificeren", + "Full height": "Volledige hoogte", + "Please configure the URL": "Configureer de URL.", + "URL": "URL", + "Search parameters": "Zoekparameters", + "Do not concatenate search params in the URL": "Voeg zoekparameters niet samen in de URL.", + "Edit link": "Link bewerken", + "Add parameter": "Parameter toevoegen", + "Use simple pagination mode": "Gebruik eenvoudige paginering", + "Set Template Engine": "Sjabloonengine instellen", + "Template engine": "Sjabloonengine", + "Table size": "Tabelgrootte", + "No data": "Geen data", + "Show file name": "Toon bestandsnaam", + "Filled": "Gevuld", + "Enable index column": "Indexkolom inschakelen", + "Icon only": "Enkel icoon", + "Valid range: 100-900": "Geldige waarde: 100-900", + "Valid range: 10-40": "Geldige waarde: 10-40", + "Font Size(px)": "Lettergrootte(px)", + "Font Weight": "Letterdikte", + "Font Style": "Letterstijl", + "Italic": "Cursief" +} \ No newline at end of file diff --git a/packages/core/client/src/modules/fields/component/Input/inputComponentSettings.tsx b/packages/core/client/src/modules/fields/component/Input/inputComponentSettings.tsx index 8f53455a71..d86283a3f2 100644 --- a/packages/core/client/src/modules/fields/component/Input/inputComponentSettings.tsx +++ b/packages/core/client/src/modules/fields/component/Input/inputComponentSettings.tsx @@ -8,6 +8,7 @@ */ import { useField, useFieldSchema } from '@formily/react'; +import _ from 'lodash'; import { useTranslation } from 'react-i18next'; import { useBlockContext, useOpenModeContext } from '../../../../'; import { SchemaSettings } from '../../../../application/schema-settings/SchemaSettings'; @@ -45,11 +46,12 @@ export const ellipsisSettingsItem: SchemaSettingsItemType = { tableFieldInstanceList.forEach((fieldInstance) => { fieldInstance.componentProps.ellipsis = checked; }); - schema['x-component-props']['ellipsis'] = checked; } else { formField.componentProps.ellipsis = checked; } + _.set(schema, 'x-component-props.ellipsis', checked); + await dn.emit('patch', { schema: { 'x-uid': schema['x-uid'], diff --git a/packages/core/client/src/plugin-manager/PinnedPluginListProvider.tsx b/packages/core/client/src/plugin-manager/PinnedPluginListProvider.tsx index 095a5804c3..137458b9ee 100644 --- a/packages/core/client/src/plugin-manager/PinnedPluginListProvider.tsx +++ b/packages/core/client/src/plugin-manager/PinnedPluginListProvider.tsx @@ -88,7 +88,7 @@ const dividerTheme = { }, }; -export const PinnedPluginList = React.memo(() => { +export const PinnedPluginList = React.memo((props: { onClick?: () => void }) => { const { allowAll, snippets } = useACLRoleContext(); const getSnippetsAllow = (aclKey) => { return allowAll || aclKey === '*' || snippets?.includes(aclKey); @@ -98,13 +98,15 @@ export const PinnedPluginList = React.memo(() => { return (
- {Object.keys(ctx.items) - .sort((a, b) => ctx.items[a].order - ctx.items[b].order) - .filter((key) => getSnippetsAllow(ctx.items[key].snippet)) - .map((key) => { - const Action = get(components, ctx.items[key].component); - return Action ? : null; - })} +
+ {Object.keys(ctx.items) + .sort((a, b) => ctx.items[a].order - ctx.items[b].order) + .filter((key) => getSnippetsAllow(ctx.items[key].snippet)) + .map((key) => { + const Action = get(components, ctx.items[key].component); + return Action ? : null; + })} +
diff --git a/packages/core/client/src/route-switch/antd/admin-layout/index.tsx b/packages/core/client/src/route-switch/antd/admin-layout/index.tsx index 73d8bc2f48..50870551a9 100644 --- a/packages/core/client/src/route-switch/antd/admin-layout/index.tsx +++ b/packages/core/client/src/route-switch/antd/admin-layout/index.tsx @@ -12,6 +12,7 @@ import ProLayout, { RouteContext, RouteContextType } from '@ant-design/pro-layou import { HeaderViewProps } from '@ant-design/pro-layout/es/components/Header'; import { css } from '@emotion/css'; import { theme as antdTheme, ConfigProvider, Popover, Tooltip } from 'antd'; +import { createStyles } from 'antd-style'; import React, { createContext, FC, useCallback, useContext, useEffect, useMemo, useRef, useState } from 'react'; import ReactDOM from 'react-dom'; import { Link, Navigate, Outlet, useLocation, useNavigate } from 'react-router-dom'; @@ -52,7 +53,6 @@ import { KeepAlive } from './KeepAlive'; import { NocoBaseDesktopRoute, NocoBaseDesktopRouteType } from './convertRoutesToSchema'; import { MenuSchemaToolbar, ResetThemeTokenAndKeepAlgorithm } from './menuItemSettings'; import { userCenterSettings } from './userCenterSettings'; -import { createGlobalStyle, createStyles } from 'antd-style'; export { KeepAlive, NocoBaseDesktopRouteType }; @@ -155,10 +155,7 @@ const layoutContentClass = css` display: flex; flex-direction: column; position: relative; - /* 基础高度(所有浏览器支持) */ height: calc(100vh - var(--nb-header-height)); - /* 动态视口高度(现代浏览器支持) */ - height: calc(100dvh - var(--nb-header-height)); > div { position: relative; } @@ -202,10 +199,29 @@ const pageContentStyle: React.CSSProperties = { overflowY: 'auto', }; +// 移动端中需要使用 dvh 单位来计算高度,否则会出现滚动不到最底部的问题 +const mobileHeight = { + height: `calc(100dvh - var(--nb-header-height))`, +}; + +function isDvhSupported() { + // 创建一个测试元素 + const testEl = document.createElement('div'); + + // 尝试设置 dvh 单位 + testEl.style.height = '1dvh'; + + // 如果浏览器支持 dvh,则会解析这个值 + // 如果不支持,height 将保持为空字符串或被设置为无效值 + return testEl.style.height === '1dvh'; +} + export const LayoutContent = () => { + const style = useMemo(() => (isDvhSupported() ? mobileHeight : undefined), []); + /* Use the "nb-subpages-slot-without-header-and-side" class name to locate the position of the subpages */ return ( -
+
@@ -418,9 +434,22 @@ const popoverStyle = css` const MobileActions: FC = (props) => { const { token } = useToken(); + const [open, setOpen] = useState(false); + + // 点击时立即关闭 Popover,避免影响用户操作 + const handleContentClick = useCallback(() => { + setOpen(false); + }, []); return ( - } color={token.colorBgHeader}> + } + color={token.colorBgHeader} + trigger="click" + open={open} + onOpenChange={setOpen} + >
{ paddingPageVertical: 8, // Vertical page padding marginBlock: 12, // Spacing between blocks borderRadiusBlock: 8, // Block border radius - fontSize: 14, // Font size + fontSize: 16, // Font size }, algorithm: isDarkTheme ? [antdTheme.compactAlgorithm, antdTheme.darkAlgorithm] : antdTheme.compactAlgorithm, // Set mobile mode to always use compact algorithm }; diff --git a/packages/core/client/src/schema-component/antd/association-field/AssociationSelect.tsx b/packages/core/client/src/schema-component/antd/association-field/AssociationSelect.tsx index 708a2cff30..a2f4741536 100644 --- a/packages/core/client/src/schema-component/antd/association-field/AssociationSelect.tsx +++ b/packages/core/client/src/schema-component/antd/association-field/AssociationSelect.tsx @@ -69,6 +69,11 @@ export const filterAnalyses = (filters): any[] => { return results; }; +function getFieldPath(str) { + const lastIndex = str.lastIndexOf('.'); + return lastIndex === -1 ? str : str.slice(0, lastIndex); +} + const InternalAssociationSelect = observer( (props: AssociationSelectProps) => { const { objectValue = true, addMode: propsAddMode, ...rest } = props; @@ -100,11 +105,14 @@ const InternalAssociationSelect = observer( //支持深层次子表单 onFieldInputValueChange('*', (fieldPath: any) => { const linkageFields = filterAnalyses(field.componentProps?.service?.params?.filter) || []; + const linageFieldEntire = getFieldPath(fieldPath.address.entire); + const targetFieldEntire = getFieldPath(field.address.entire); if ( linkageFields.includes(fieldPath?.props?.name) && field.value && isEqual(fieldPath?.indexes, field?.indexes) && - fieldPath?.props?.name !== field.props.name + fieldPath?.props?.name !== field.props.name && + (!field?.indexes?.length || isEqual(linageFieldEntire, targetFieldEntire)) ) { field.setValue(null); setInnerValue(null); diff --git a/packages/core/client/src/schema-component/antd/page/PagePopups.tsx b/packages/core/client/src/schema-component/antd/page/PagePopups.tsx index faef6cce0c..818cf75460 100644 --- a/packages/core/client/src/schema-component/antd/page/PagePopups.tsx +++ b/packages/core/client/src/schema-component/antd/page/PagePopups.tsx @@ -273,31 +273,43 @@ const InternalPagePopups = (props: { paramsList?: PopupParams[] }) => { ); }); const schemas = await Promise.all(waitList); - const clonedSchemas = schemas.map((schema, index) => { - if (_.isEmpty(schema)) { - return get404Schema(); - } - - const params = popupParams[index]; - - if (params.puid) { - const popupSchema = findSchemaByUid(params.puid, fieldSchema?.root); - if (popupSchema) { - savePopupSchemaToSchema(_.omit(popupSchema, 'parent'), schema); + const clonedSchemas = await Promise.all( + schemas.map(async (schema, index) => { + if (_.isEmpty(schema)) { + return get404Schema(); } - } - // Using toJSON for deep clone, faster than lodash's cloneDeep - const result = _.cloneDeepWith(_.omit(schema, 'parent'), (value) => { - // If we clone the Tabs component, it will cause the configuration to be lost when reopening the popup after modifying its settings - if (value?.['x-component'] === 'Tabs') { - return value; + const params = popupParams[index]; + + if (params.puid) { + const popupSchema = findSchemaByUid(params.puid, fieldSchema?.root); + if (popupSchema) { + savePopupSchemaToSchema(_.omit(popupSchema, 'parent'), schema); + } else { + // 当本地找不到 popupSchema 时,通过接口请求 puid 对应的 schema + try { + const remoteSchema = await requestSchema(params.puid); + if (remoteSchema) { + savePopupSchemaToSchema(remoteSchema, schema); + } + } catch (error) { + console.error('Failed to fetch schema for puid:', params.puid, error); + } + } } - }); - result['x-read-pretty'] = true; - return result; - }); + // Using toJSON for deep clone, faster than lodash's cloneDeep + const result = _.cloneDeepWith(_.omit(schema, 'parent'), (value) => { + // If we clone the Tabs component, it will cause the configuration to be lost when reopening the popup after modifying its settings + if (value?.['x-component'] === 'Tabs') { + return value; + } + }); + result['x-read-pretty'] = true; + + return result; + }), + ); popupPropsRef.current = clonedSchemas.map((schema, index, items) => { const schemaContext = getPopupContextFromActionOrAssociationFieldSchema(schema); let hidden = false; diff --git a/packages/core/client/src/schema-component/antd/upload/Upload.tsx b/packages/core/client/src/schema-component/antd/upload/Upload.tsx index 728e1f70ad..6a1893ce3e 100644 --- a/packages/core/client/src/schema-component/antd/upload/Upload.tsx +++ b/packages/core/client/src/schema-component/antd/upload/Upload.tsx @@ -89,7 +89,7 @@ attachmentFileTypes.add({ }, }); -const iframePreviewSupportedTypes = ['application/pdf', 'audio/*', 'image/*', 'video/*', 'text/*']; +const iframePreviewSupportedTypes = ['application/pdf', 'audio/*', 'image/*', 'video/*', 'text/plain']; function IframePreviewer({ index, list, onSwitchIndex }) { const { t } = useTranslation(); diff --git a/packages/core/client/src/schema-component/core/RemoteSchemaComponent.tsx b/packages/core/client/src/schema-component/core/RemoteSchemaComponent.tsx index 356705c31b..f220126041 100644 --- a/packages/core/client/src/schema-component/core/RemoteSchemaComponent.tsx +++ b/packages/core/client/src/schema-component/core/RemoteSchemaComponent.tsx @@ -8,7 +8,7 @@ */ import { createForm } from '@formily/core'; -import { Schema } from '@formily/react'; +import { Schema, useFieldSchema } from '@formily/react'; import { Spin } from 'antd'; import React, { memo, useMemo } from 'react'; import { useRemoteCollectionManagerLoading } from '../../collection-manager/CollectionManagerProvider'; @@ -62,6 +62,7 @@ const RequestSchemaComponent: React.FC = (props) => }); const NotFoundComponent = useComponent(NotFoundPage); const collectionManagerLoading = useRemoteCollectionManagerLoading(); + const parentSchema = useFieldSchema(); if (collectionManagerLoading || loading || hidden) { return ; @@ -73,10 +74,20 @@ const RequestSchemaComponent: React.FC = (props) => } return noForm ? ( - + ) : ( - + ); }; diff --git a/packages/core/client/src/schema-component/core/SchemaComponent.tsx b/packages/core/client/src/schema-component/core/SchemaComponent.tsx index 5a51340ace..2443eb5c43 100644 --- a/packages/core/client/src/schema-component/core/SchemaComponent.tsx +++ b/packages/core/client/src/schema-component/core/SchemaComponent.tsx @@ -28,6 +28,7 @@ function toSchema(schema?: any) { properties: { [schema.name]: schema, }, + name: `p_${schema.name}`, }); } return new Schema(schema); @@ -52,58 +53,65 @@ interface DistributedProps { */ export const SchemaComponentOnChangeContext = createContext({ onChange: _.noop }); -const RecursionSchemaComponent = memo((props: ISchemaFieldProps & SchemaComponentOnChange & DistributedProps) => { - const { components, scope, schema: _schema, distributed, onChange: _onChange, ...others } = props; - const ctx = useContext(SchemaComponentContext); - const schema = useMemo(() => toSchema(_schema), [_schema]); - const value = useMemo( - () => ({ - ...ctx, - distributed: ctx.distributed == false ? false : distributed, - /** - * @deprecated - */ - refresh: ctx.refresh || _.noop, - }), - [ctx, distributed], - ); +const RecursionSchemaComponent = memo( + (props: ISchemaFieldProps & SchemaComponentOnChange & DistributedProps & { parentSchema?: Schema }) => { + const { components, scope, schema: _schema, distributed, onChange: _onChange, parentSchema, ...others } = props; + const ctx = useContext(SchemaComponentContext); + const schema = useMemo(() => toSchema(_schema), [_schema]); + const value = useMemo( + () => ({ + ...ctx, + distributed: ctx.distributed == false ? false : distributed, + /** + * @deprecated + */ + refresh: ctx.refresh || _.noop, + }), + [ctx, distributed], + ); - const { onChange: onChangeFromContext } = useContext(SchemaComponentOnChangeContext); + const { onChange: onChangeFromContext } = useContext(SchemaComponentOnChangeContext); - const onChangeValue = useMemo( - () => ({ - onChange: () => { - _onChange?.(schema); - onChangeFromContext?.(); - }, - }), - [_onChange, onChangeFromContext, schema], - ); + const onChangeValue = useMemo( + () => ({ + onChange: () => { + _onChange?.(schema); + onChangeFromContext?.(); + }, + }), + [_onChange, onChangeFromContext, schema], + ); - return ( - - - - - - - - ); -}); + return ( + + + + + + + + ); + }, +); RecursionSchemaComponent.displayName = 'RecursionSchemaComponent'; -const MemoizedSchemaComponent = memo((props: ISchemaFieldProps & SchemaComponentOnChange & DistributedProps) => { - const { schema, ...others } = props; - const s = useMemoizedSchema(schema); - return ; -}); +const MemoizedSchemaComponent = memo( + (props: ISchemaFieldProps & SchemaComponentOnChange & DistributedProps & { parentSchema?: Schema }) => { + const { schema, parentSchema, ...others } = props; + const s = useMemoizedSchema(schema); + return ; + }, +); MemoizedSchemaComponent.displayName = 'MemoizedSchemaComponent'; export const SchemaComponent = memo( ( - props: (ISchemaFieldProps | IRecursionFieldProps) & { memoized?: boolean } & SchemaComponentOnChange & + props: (ISchemaFieldProps | IRecursionFieldProps) & { + memoized?: boolean; + parentSchema?: Schema; + } & SchemaComponentOnChange & DistributedProps, ) => { const { memoized, ...others } = props; diff --git a/packages/core/create-nocobase-app/package.json b/packages/core/create-nocobase-app/package.json index 05084946fa..e0e866a138 100755 --- a/packages/core/create-nocobase-app/package.json +++ b/packages/core/create-nocobase-app/package.json @@ -1,6 +1,6 @@ { "name": "create-nocobase-app", - "version": "1.7.0-beta.9", + "version": "1.7.0-alpha.10", "main": "src/index.js", "license": "AGPL-3.0", "dependencies": { diff --git a/packages/core/data-source-manager/package.json b/packages/core/data-source-manager/package.json index 6f579e30d1..b765f7792a 100644 --- a/packages/core/data-source-manager/package.json +++ b/packages/core/data-source-manager/package.json @@ -1,16 +1,16 @@ { "name": "@nocobase/data-source-manager", - "version": "1.7.0-beta.9", + "version": "1.7.0-alpha.10", "description": "", "license": "AGPL-3.0", "main": "./lib/index.js", "types": "./lib/index.d.ts", "dependencies": { - "@nocobase/actions": "1.7.0-beta.9", - "@nocobase/cache": "1.7.0-beta.9", - "@nocobase/database": "1.7.0-beta.9", - "@nocobase/resourcer": "1.7.0-beta.9", - "@nocobase/utils": "1.7.0-beta.9", + "@nocobase/actions": "1.7.0-alpha.10", + "@nocobase/cache": "1.7.0-alpha.10", + "@nocobase/database": "1.7.0-alpha.10", + "@nocobase/resourcer": "1.7.0-alpha.10", + "@nocobase/utils": "1.7.0-alpha.10", "@types/jsonwebtoken": "^8.5.8", "jsonwebtoken": "^8.5.1" }, diff --git a/packages/core/database/package.json b/packages/core/database/package.json index b07abbcfca..10b3a15682 100644 --- a/packages/core/database/package.json +++ b/packages/core/database/package.json @@ -1,13 +1,13 @@ { "name": "@nocobase/database", - "version": "1.7.0-beta.9", + "version": "1.7.0-alpha.10", "description": "", "main": "./lib/index.js", "types": "./lib/index.d.ts", "license": "AGPL-3.0", "dependencies": { - "@nocobase/logger": "1.7.0-beta.9", - "@nocobase/utils": "1.7.0-beta.9", + "@nocobase/logger": "1.7.0-alpha.10", + "@nocobase/utils": "1.7.0-alpha.10", "async-mutex": "^0.3.2", "chalk": "^4.1.1", "cron-parser": "4.4.0", diff --git a/packages/core/devtools/package.json b/packages/core/devtools/package.json index f567922e23..c1e97aac68 100644 --- a/packages/core/devtools/package.json +++ b/packages/core/devtools/package.json @@ -1,13 +1,13 @@ { "name": "@nocobase/devtools", - "version": "1.7.0-beta.9", + "version": "1.7.0-alpha.10", "description": "", "license": "AGPL-3.0", "main": "./src/index.js", "dependencies": { - "@nocobase/build": "1.7.0-beta.9", - "@nocobase/client": "1.7.0-beta.9", - "@nocobase/test": "1.7.0-beta.9", + "@nocobase/build": "1.7.0-alpha.10", + "@nocobase/client": "1.7.0-alpha.10", + "@nocobase/test": "1.7.0-alpha.10", "@types/koa": "^2.15.0", "@types/koa-bodyparser": "^4.3.4", "@types/lodash": "^4.14.177", diff --git a/packages/core/evaluators/package.json b/packages/core/evaluators/package.json index 87ab563ca3..40ab5ae68c 100644 --- a/packages/core/evaluators/package.json +++ b/packages/core/evaluators/package.json @@ -1,13 +1,13 @@ { "name": "@nocobase/evaluators", - "version": "1.7.0-beta.9", + "version": "1.7.0-alpha.10", "description": "", "main": "./lib/index.js", "types": "./lib/index.d.ts", "license": "AGPL-3.0", "dependencies": { "@formulajs/formulajs": "4.4.9", - "@nocobase/utils": "1.7.0-beta.9", + "@nocobase/utils": "1.7.0-alpha.10", "mathjs": "^10.6.0" }, "repository": { diff --git a/packages/core/lock-manager/package.json b/packages/core/lock-manager/package.json index 40bec6a979..46ffbb6df8 100644 --- a/packages/core/lock-manager/package.json +++ b/packages/core/lock-manager/package.json @@ -1,10 +1,10 @@ { "name": "@nocobase/lock-manager", - "version": "1.7.0-beta.9", + "version": "1.7.0-alpha.10", "main": "lib/index.js", "license": "AGPL-3.0", "devDependencies": { - "@nocobase/utils": "1.7.0-beta.9", + "@nocobase/utils": "1.7.0-alpha.10", "async-mutex": "^0.5.0" } } diff --git a/packages/core/logger/package.json b/packages/core/logger/package.json index 43bac59e8f..9bc975d571 100644 --- a/packages/core/logger/package.json +++ b/packages/core/logger/package.json @@ -1,6 +1,6 @@ { "name": "@nocobase/logger", - "version": "1.7.0-beta.9", + "version": "1.7.0-alpha.10", "description": "nocobase logging library", "license": "AGPL-3.0", "main": "./lib/index.js", diff --git a/packages/core/resourcer/package.json b/packages/core/resourcer/package.json index d391468d38..cd0cb4f2a5 100644 --- a/packages/core/resourcer/package.json +++ b/packages/core/resourcer/package.json @@ -1,12 +1,12 @@ { "name": "@nocobase/resourcer", - "version": "1.7.0-beta.9", + "version": "1.7.0-alpha.10", "description": "", "main": "./lib/index.js", "types": "./lib/index.d.ts", "license": "AGPL-3.0", "dependencies": { - "@nocobase/utils": "1.7.0-beta.9", + "@nocobase/utils": "1.7.0-alpha.10", "deepmerge": "^4.2.2", "koa-compose": "^4.1.0", "lodash": "^4.17.21", diff --git a/packages/core/sdk/package.json b/packages/core/sdk/package.json index dbae1fe657..08768cddae 100644 --- a/packages/core/sdk/package.json +++ b/packages/core/sdk/package.json @@ -1,6 +1,6 @@ { "name": "@nocobase/sdk", - "version": "1.7.0-beta.9", + "version": "1.7.0-alpha.10", "license": "AGPL-3.0", "main": "lib/index.js", "types": "lib/index.d.ts", diff --git a/packages/core/server/package.json b/packages/core/server/package.json index 6781c07eeb..1920b3b34d 100644 --- a/packages/core/server/package.json +++ b/packages/core/server/package.json @@ -1,6 +1,6 @@ { "name": "@nocobase/server", - "version": "1.7.0-beta.9", + "version": "1.7.0-alpha.10", "main": "lib/index.js", "types": "./lib/index.d.ts", "license": "AGPL-3.0", @@ -10,19 +10,19 @@ "@koa/cors": "^5.0.0", "@koa/multer": "^3.0.2", "@koa/router": "^9.4.0", - "@nocobase/acl": "1.7.0-beta.9", - "@nocobase/actions": "1.7.0-beta.9", - "@nocobase/auth": "1.7.0-beta.9", - "@nocobase/cache": "1.7.0-beta.9", - "@nocobase/data-source-manager": "1.7.0-beta.9", - "@nocobase/database": "1.7.0-beta.9", - "@nocobase/evaluators": "1.7.0-beta.9", - "@nocobase/lock-manager": "1.7.0-beta.9", - "@nocobase/logger": "1.7.0-beta.9", - "@nocobase/resourcer": "1.7.0-beta.9", - "@nocobase/sdk": "1.7.0-beta.9", - "@nocobase/telemetry": "1.7.0-beta.9", - "@nocobase/utils": "1.7.0-beta.9", + "@nocobase/acl": "1.7.0-alpha.10", + "@nocobase/actions": "1.7.0-alpha.10", + "@nocobase/auth": "1.7.0-alpha.10", + "@nocobase/cache": "1.7.0-alpha.10", + "@nocobase/data-source-manager": "1.7.0-alpha.10", + "@nocobase/database": "1.7.0-alpha.10", + "@nocobase/evaluators": "1.7.0-alpha.10", + "@nocobase/lock-manager": "1.7.0-alpha.10", + "@nocobase/logger": "1.7.0-alpha.10", + "@nocobase/resourcer": "1.7.0-alpha.10", + "@nocobase/sdk": "1.7.0-alpha.10", + "@nocobase/telemetry": "1.7.0-alpha.10", + "@nocobase/utils": "1.7.0-alpha.10", "@types/decompress": "4.2.7", "@types/ini": "^1.3.31", "@types/koa-send": "^4.1.3", diff --git a/packages/core/telemetry/package.json b/packages/core/telemetry/package.json index fa906c5420..1ae9d1b102 100644 --- a/packages/core/telemetry/package.json +++ b/packages/core/telemetry/package.json @@ -1,6 +1,6 @@ { "name": "@nocobase/telemetry", - "version": "1.7.0-beta.9", + "version": "1.7.0-alpha.10", "description": "nocobase telemetry library", "license": "AGPL-3.0", "main": "./lib/index.js", @@ -11,7 +11,7 @@ "directory": "packages/telemetry" }, "dependencies": { - "@nocobase/utils": "1.7.0-beta.9", + "@nocobase/utils": "1.7.0-alpha.10", "@opentelemetry/api": "^1.7.0", "@opentelemetry/instrumentation": "^0.46.0", "@opentelemetry/resources": "^1.19.0", diff --git a/packages/core/test/package.json b/packages/core/test/package.json index 41d3559b66..735c374e8f 100644 --- a/packages/core/test/package.json +++ b/packages/core/test/package.json @@ -1,6 +1,6 @@ { "name": "@nocobase/test", - "version": "1.7.0-beta.9", + "version": "1.7.0-alpha.10", "main": "lib/index.js", "module": "./src/index.ts", "types": "./lib/index.d.ts", @@ -51,7 +51,7 @@ }, "dependencies": { "@faker-js/faker": "8.1.0", - "@nocobase/server": "1.7.0-beta.9", + "@nocobase/server": "1.7.0-alpha.10", "@playwright/test": "^1.45.3", "@testing-library/jest-dom": "^6.4.2", "@testing-library/react": "^14.0.0", diff --git a/packages/core/utils/package.json b/packages/core/utils/package.json index 4232d4d795..fa168d0247 100644 --- a/packages/core/utils/package.json +++ b/packages/core/utils/package.json @@ -1,6 +1,6 @@ { "name": "@nocobase/utils", - "version": "1.7.0-beta.9", + "version": "1.7.0-alpha.10", "main": "lib/index.js", "types": "./lib/index.d.ts", "license": "AGPL-3.0", diff --git a/packages/plugins/@nocobase/plugin-acl/package.json b/packages/plugins/@nocobase/plugin-acl/package.json index 066d83863b..00c90f17a0 100644 --- a/packages/plugins/@nocobase/plugin-acl/package.json +++ b/packages/plugins/@nocobase/plugin-acl/package.json @@ -4,7 +4,7 @@ "displayName.zh-CN": "权限控制", "description": "Based on roles, resources, and actions, access control can precisely manage interface configuration permissions, data operation permissions, menu access permissions, and plugin permissions.", "description.zh-CN": "基于角色、资源和操作的权限控制,可以精确控制界面配置权限、数据操作权限、菜单访问权限、插件权限。", - "version": "1.7.0-beta.9", + "version": "1.7.0-alpha.10", "license": "AGPL-3.0", "main": "./dist/server/index.js", "homepage": "https://docs.nocobase.com/handbook/acl", diff --git a/packages/plugins/@nocobase/plugin-acl/src/locale/nl-NL.json b/packages/plugins/@nocobase/plugin-acl/src/locale/nl-NL.json index 1ab1ec5119..5ec04e7cf3 100644 --- a/packages/plugins/@nocobase/plugin-acl/src/locale/nl-NL.json +++ b/packages/plugins/@nocobase/plugin-acl/src/locale/nl-NL.json @@ -1,7 +1,11 @@ { "The current user has no roles. Please try another account.": "De huidige gebruiker heeft geen rol. Probeer een andere gebruikersaccount.", "The user role does not exist. Please try signing in again": "De gebruikersrol bestaat niet. Probeer opnieuw in te loggen.", + "Roles & Permissions": "Rollen & Permissies", + "General": "Algemeen", "New role": "Nieuwe rol", "Permissions": "Permissies", - "Desktop menu": "Desktop menu" + "Desktop menu": "Desktop menu", + "Plugin settings": "Plugin instellingen", + "Data sources": "Data bronnen" } \ No newline at end of file diff --git a/packages/plugins/@nocobase/plugin-action-bulk-edit/package.json b/packages/plugins/@nocobase/plugin-action-bulk-edit/package.json index 8df016986d..5428d9bd04 100644 --- a/packages/plugins/@nocobase/plugin-action-bulk-edit/package.json +++ b/packages/plugins/@nocobase/plugin-action-bulk-edit/package.json @@ -1,6 +1,6 @@ { "name": "@nocobase/plugin-action-bulk-edit", - "version": "1.7.0-beta.9", + "version": "1.7.0-alpha.10", "main": "dist/server/index.js", "homepage": "https://docs.nocobase.com/handbook/action-bulk-edit", "homepage.zh-CN": "https://docs-cn.nocobase.com/handbook/action-bulk-edit", diff --git a/packages/plugins/@nocobase/plugin-action-bulk-edit/src/locale/nl-NL.json b/packages/plugins/@nocobase/plugin-action-bulk-edit/src/locale/nl-NL.json index 4b5000c99d..68af320b36 100644 --- a/packages/plugins/@nocobase/plugin-action-bulk-edit/src/locale/nl-NL.json +++ b/packages/plugins/@nocobase/plugin-action-bulk-edit/src/locale/nl-NL.json @@ -1,4 +1,5 @@ { "Bulk edit": "Bewerken in bulk", - "Data will be updated": "Gegevens worden bijgewerkt" + "Data will be updated": "Gegevens worden bijgewerkt", + "Entire collection": "Gehele collectie" } \ No newline at end of file diff --git a/packages/plugins/@nocobase/plugin-action-bulk-update/package.json b/packages/plugins/@nocobase/plugin-action-bulk-update/package.json index fdcc0108e6..1627e5624b 100644 --- a/packages/plugins/@nocobase/plugin-action-bulk-update/package.json +++ b/packages/plugins/@nocobase/plugin-action-bulk-update/package.json @@ -1,6 +1,6 @@ { "name": "@nocobase/plugin-action-bulk-update", - "version": "1.7.0-beta.9", + "version": "1.7.0-alpha.10", "main": "dist/server/index.js", "homepage": "https://docs.nocobase.com/handbook/action-bulk-update", "homepage.zh-CN": "https://docs-cn.nocobase.com/handbook/action-bulk-update", diff --git a/packages/plugins/@nocobase/plugin-action-bulk-update/src/locale/nl-NL.json b/packages/plugins/@nocobase/plugin-action-bulk-update/src/locale/nl-NL.json index 906a7d6a02..7c6b6ed260 100644 --- a/packages/plugins/@nocobase/plugin-action-bulk-update/src/locale/nl-NL.json +++ b/packages/plugins/@nocobase/plugin-action-bulk-update/src/locale/nl-NL.json @@ -1,5 +1,6 @@ { "Bulk update": "Updaten in bulk", "After successful bulk update": "Na succesvolle update in bulk", - "Please select the records to be updated": "Selecteer de records die moeten worden bijgewerkt" + "Please select the records to be updated": "Selecteer de records die moeten worden bijgewerkt", + "Entire collection": "Gehele collectie" } \ No newline at end of file diff --git a/packages/plugins/@nocobase/plugin-action-custom-request/package.json b/packages/plugins/@nocobase/plugin-action-custom-request/package.json index ec13e6ca6a..d7d00289a2 100644 --- a/packages/plugins/@nocobase/plugin-action-custom-request/package.json +++ b/packages/plugins/@nocobase/plugin-action-custom-request/package.json @@ -1,6 +1,6 @@ { "name": "@nocobase/plugin-action-custom-request", - "version": "1.7.0-beta.9", + "version": "1.7.0-alpha.10", "main": "dist/server/index.js", "homepage": "https://docs.nocobase.com/handbook/action-custom-request", "homepage.zh-CN": "https://docs-cn.nocobase.com/handbook/action-custom-request", diff --git a/packages/plugins/@nocobase/plugin-action-custom-request/src/locale/nl-NL.json b/packages/plugins/@nocobase/plugin-action-custom-request/src/locale/nl-NL.json new file mode 100644 index 0000000000..742ad4e30d --- /dev/null +++ b/packages/plugins/@nocobase/plugin-action-custom-request/src/locale/nl-NL.json @@ -0,0 +1,27 @@ +{ + "Access control": "Toegangscontrole", + "Custom Request": "Aangepaste aanvraag", + "Request settings": "Aanvraaginstellingen", + "Roles": "Rollen", + "If not set, all roles can see this action": "Als niet ingesteld, kunnen alle rollen deze actie zien", + "Title": "Titel", + "HTTP method": "HTTP-methode", + "URL": "URL", + "Headers": "Kopteksten", + "Parameters": "Parameters", + "Add request header": "Voeg aanvraagkop toe", + "Add parameter": "Voeg parameter toe", + "Enter description info": "Voer beschrijvingsinformatie in", + "Body": "Inhoud", + "Use variable": "Gebruik variabele", + "Format": "Formaat", + "Insert": "Invoegen", + "Timeout config": "Time-outconfiguratie", + "ms": "ms", + "Input request data": "Voer aanvraaggegevens in", + "Only support standard JSON data": "Ondersteunt alleen standaard JSON-gegevens", + "\"Content-Type\" only support \"application/json\", and no need to specify": "\"Content-Type\" ondersteunt alleen \"application/json\", en hoeft niet te worden gespecificeerd", + "When the HTTP method is Post, Put or Patch, and this custom request inside the form, the request body will be automatically filled in with the form data": "Wanneer de HTTP-methode Post, Put of Patch is, en deze aangepaste aanvraag zich binnen het formulier bevindt, wordt de aanvraaginhoud automatisch ingevuld met de formuliergegevens", + "Please configure the request settings first": "Configureer eerst de aanvraaginstellingen" + } + \ No newline at end of file diff --git a/packages/plugins/@nocobase/plugin-action-duplicate/package.json b/packages/plugins/@nocobase/plugin-action-duplicate/package.json index 57d13611ee..cd2d0c5238 100644 --- a/packages/plugins/@nocobase/plugin-action-duplicate/package.json +++ b/packages/plugins/@nocobase/plugin-action-duplicate/package.json @@ -1,6 +1,6 @@ { "name": "@nocobase/plugin-action-duplicate", - "version": "1.7.0-beta.9", + "version": "1.7.0-alpha.10", "main": "dist/server/index.js", "homepage": "https://docs.nocobase.com/handbook/action-duplicate", "homepage.zh-CN": "https://docs-cn.nocobase.com/handbook/action-duplicate", diff --git a/packages/plugins/@nocobase/plugin-action-export/package.json b/packages/plugins/@nocobase/plugin-action-export/package.json index 9d840b0bf5..8bfd7c2ae9 100644 --- a/packages/plugins/@nocobase/plugin-action-export/package.json +++ b/packages/plugins/@nocobase/plugin-action-export/package.json @@ -4,7 +4,7 @@ "displayName.zh-CN": "操作:导出记录", "description": "Export filtered records to excel, you can configure which fields to export.", "description.zh-CN": "导出筛选后的记录到 Excel 中,可以配置导出哪些字段。", - "version": "1.7.0-beta.9", + "version": "1.7.0-alpha.10", "license": "AGPL-3.0", "main": "./dist/server/index.js", "homepage": "https://docs.nocobase.com/handbook/action-export", diff --git a/packages/plugins/@nocobase/plugin-action-export/src/locale/nl-NL.json b/packages/plugins/@nocobase/plugin-action-export/src/locale/nl-NL.json index 7bfd45fcb5..4e921a87cb 100644 --- a/packages/plugins/@nocobase/plugin-action-export/src/locale/nl-NL.json +++ b/packages/plugins/@nocobase/plugin-action-export/src/locale/nl-NL.json @@ -1,6 +1,7 @@ { "Export warning": "Je kunt maximaal {{limit}} rijen gegevens tegelijk exporteren, eventuele overschrijdingen worden genegeerd.", "Start export": "Start exporteren", + "another export action is running, please try again later.": "Er is al een andere exportactie bezig, probeer het later opnieuw.", "True": "Waar", "False": "Onwaar" } \ No newline at end of file diff --git a/packages/plugins/@nocobase/plugin-action-import/package.json b/packages/plugins/@nocobase/plugin-action-import/package.json index 1aa0aabc45..05c6600bcd 100644 --- a/packages/plugins/@nocobase/plugin-action-import/package.json +++ b/packages/plugins/@nocobase/plugin-action-import/package.json @@ -4,7 +4,7 @@ "displayName.zh-CN": "操作:导入记录", "description": "Import records using excel templates. You can configure which fields to import and templates will be generated automatically.", "description.zh-CN": "使用 Excel 模板导入数据,可以配置导入哪些字段,自动生成模板。", - "version": "1.7.0-beta.9", + "version": "1.7.0-alpha.10", "license": "AGPL-3.0", "main": "./dist/server/index.js", "homepage": "https://docs.nocobase.com/handbook/action-import", diff --git a/packages/plugins/@nocobase/plugin-action-import/src/locale/nl-NL.json b/packages/plugins/@nocobase/plugin-action-import/src/locale/nl-NL.json index 33d2208d33..6dcb9dd9ca 100644 --- a/packages/plugins/@nocobase/plugin-action-import/src/locale/nl-NL.json +++ b/packages/plugins/@nocobase/plugin-action-import/src/locale/nl-NL.json @@ -1,42 +1,50 @@ { - "Only one file is allowed to be uploaded": "Only one file is allowed to be uploaded", - "File size cannot exceed 10M": "File size cannot exceed 10M", - "Please upload the file of Excel": "Please upload the file of Excel", - "Import Data": "Import Data", - "Start import": "Start import", - "Import explain": "Guide", - "Download template": "Download template", - "Step 1: Download template": "Step 1: Download template", - "Step 2: Upload Excel": "Step 2: Upload Excel", - "Step 3: Import options": "Step 3: Import options", - "Download tips": "- Download the template and fill in the data according to the format \r\n - Import only the first worksheet \r\n - Do not change the header of the template to prevent import failure", - "Import warnings": "You can import up to {{limit}} rows of data at a time, any excess will be ignored.", - "Upload placeholder": "Drag and drop the file here or click to upload, file size should not exceed 80M", - "Excel data importing": "Excel data importing", - "{{successCount}} records have been successfully imported": "{{successCount}} records have been successfully imported", - "To download the failure data": "To download the failure data", - "Add importable field": "Add importable field", + "Only one file is allowed to be uploaded": "Er kan slechts één bestand worden geüpload", + "File size cannot exceed 10M": "Bestandsgrootte mag niet groter zijn dan 10M", + "Please upload the file of Excel": "Upload het Excel-bestand", + "Import Data": "Importeer gegevens", + "Start import": "Start importeren", + "Import explain": "Uitleg", + "Download template": "Download sjabloon", + "Step 1: Download template": "Stap 1: Download sjabloon", + "Step 2: Upload Excel": "Stap 2: Upload Excel", + "Step 3: Import options": "Stap 3: Importeer opties", + "Download tips": "- Download het sjabloon en vul de gegevens in volgens het formaat\r\n - Importeer alleen het eerste werkblad\r\n - Wijzig de sjabloontitel niet om importfouten te voorkomen", + "Import warnings": "Maximaal {{limit}} rijen gegevens kunnen tegelijk worden geïmporteerd, eventuele overschrijdingen worden genegeerd.", + "Upload placeholder": "Sleep het bestand hierheen of klik om te uploaden, bestandsgrootte niet groter dan 80M", + "Excel data importing": "Gegevens importeren, sluit het venster niet", + "{{successCount}} records have been successfully imported": "{{successCount}} records zijn succesvol geïmporteerd", + "To download the failure data": "Download de gegevens die niet konden worden geïmporteerd", + "Add importable field": "Voeg een importeerbaar veld toe", "Done": "Klaar", "Yes": "Ja", "No": "Nee", - "Field {{fieldName}} does not exist": "Field {{fieldName}} does not exist", - "can not find value": "can not find value", - "password is empty": "password is empty", - "Incorrect time format": "Incorrect time format", - "Incorrect date format": "Incorrect date format", - "Incorrect email format": "Incorrect email format", - "Illegal percentage format": "Illegal percentage format", - "Imported template does not match, please download again.": "Imported template does not match, please download again.", - "another import action is running, please try again later.": "another import action is running, please try again later.", - "Please select": "Please select", + "Field {{fieldName}} does not exist": "Veld {{fieldName}} bestaat niet", + "can not find value": "Kan de waarde niet vinden", + "password is empty": "Wachtwoord is leeg", + "Incorrect time format": "Onjuist tijdsformaat", + "Incorrect date format": "Onjuist datumformaat", + "Incorrect email format": "Onjuist e-mailformaat", + "Illegal percentage format": "Ongeldig percentageformaat", + "Imported template does not match, please download again.": "Het geïmporteerde sjabloon komt niet overeen, download het opnieuw.", + "another import action is running, please try again later.": "Er is al een andere importactie bezig, probeer het later opnieuw.", + "Please select": "Selecteer", "Custom column title": "Aangepaste kolomtitel", - "Field description": "Field description", - "Field description placeholder": "Enter field description", - "Columns configuration is empty": "Columns configuration is empty", - "Field not found: {{field}}": "Field not found: {{field}}", - "Headers not found. Expected headers: {{headers}}": "Headers not found. Expected headers: {{headers}}", - "Header mismatch at column {{column}}: expected \"{{expected}}\", but got \"{{actual}}\"": "Header mismatch at column {{column}}: expected \"{{expected}}\", but got \"{{actual}}\"", - "No data to import": "No data to import", - "Failed to import row {{row}}, {{message}}, row data: {{data}}": "Failed to import row {{row}}, {{message}}, row data: {{data}}", - "import-error": "Failed to import row {{rowIndex}}, row data: {{rowData}}, cause: {{causeMessage}}" + "Field description": "Veldbeschrijving", + "Field description placeholder": "Voer de veldbeschrijving in", + "Columns configuration is empty": "Kolomconfiguratie is leeg", + "Field not found: {{field}}": "Veld niet gevonden: {{field}}", + "Headers not found. Expected headers: {{headers}}": "Kopteksten niet gevonden. Verwachte kopteksten: {{headers}}", + "Header mismatch at column {{column}}: expected \"{{expected}}\", but got \"{{actual}}\"": "Koptekst komt niet overeen in kolom {{column}}: verwachtte \"{{expected}}\", maar kreeg \"{{actual}}\"", + "No data to import": "Geen gegevens om te importeren", + "Failed to import row {{row}}, {{message}}, row data: {{data}}": "Fout bij importeren van rij {{row}}, {{message}}, rijgegevens: {{data}}", + "import-error": "Fout bij importeren van rij {{rowIndex}}, rijgegevens: {{rowData}}, reden: {{causeMessage}}", + "Import completed": "Importeren voltooid: {{success}} records zijn geïmporteerd, {{updated}} records zijn bijgewerkt, {{skipped}} records zijn overgeslagen, totaal {{total}} records", + "Successfully imported": "Succesvol geïmporteerd", + "Updated records": "Bijgewerkte records", + "Skipped records": "Overgeslagen records", + "Total records": "Totaal aantal records", + "View result": "Bekijk resultaat", + "ImportResult": "{{success}} records zijn geïmporteerd, {{updated}} records zijn bijgewerkt, {{skipped}} records zijn overgeslagen, totaal {{total}} records", + "Task result": "Taakresultaat" } \ No newline at end of file diff --git a/packages/plugins/@nocobase/plugin-action-print/package.json b/packages/plugins/@nocobase/plugin-action-print/package.json index e47c9bd80c..1c9ac15fb3 100644 --- a/packages/plugins/@nocobase/plugin-action-print/package.json +++ b/packages/plugins/@nocobase/plugin-action-print/package.json @@ -1,6 +1,6 @@ { "name": "@nocobase/plugin-action-print", - "version": "1.7.0-beta.9", + "version": "1.7.0-alpha.10", "main": "dist/server/index.js", "homepage": "https://docs.nocobase.com/handbook/action-print", "homepage.zh-CN": "https://docs-cn.nocobase.com/handbook/action-print", diff --git a/packages/plugins/@nocobase/plugin-ai/package.json b/packages/plugins/@nocobase/plugin-ai/package.json index 32170b6e2f..af19de2126 100644 --- a/packages/plugins/@nocobase/plugin-ai/package.json +++ b/packages/plugins/@nocobase/plugin-ai/package.json @@ -4,7 +4,7 @@ "displayName.zh-CN": "AI 集成", "description": "Support integration with AI services, providing AI-related workflow nodes to enhance business processing capabilities.", "description.zh-CN": "支持接入 AI 服务,提供 AI 相关的工作流节点,增强业务处理能力。", - "version": "1.7.0-beta.9", + "version": "1.7.0-alpha.10", "main": "dist/server/index.js", "peerDependencies": { "@nocobase/client": "1.x", diff --git a/packages/plugins/@nocobase/plugin-ai/src/locale/nl-NL.json b/packages/plugins/@nocobase/plugin-ai/src/locale/nl-NL.json new file mode 100644 index 0000000000..12b7db4472 --- /dev/null +++ b/packages/plugins/@nocobase/plugin-ai/src/locale/nl-NL.json @@ -0,0 +1,26 @@ +{ + "AI integration": "AI integratie", + "LLM services": "LLM diensten", + "LLM service": "LLM dienst", + "Model": "Model", + "Messages": "Berichten", + "Structured output": "Gestructureerde output", + "Message": "Bericht", + "Role": "Rol", + "UID": "UID", + "Add content": "Voeg inhoud toe", + "Add prompt": "Voeg prompt toe", + "Provider": "Provider", + "Text": "Tekst", + "Image": "Afbeelding", + "Timout (ms)": "Timout (ms)", + "Max retries": "Max herhalingen", + "Frequency penalty description": "Nummer tussen -2.0 en 2.0. Positieve waarden straffen nieuwe tokens op basis van hun bestaande frequentie in de tekst tot nu toe, waardoor de kans van het model om dezelfde regel letterlijk te herhalen afneemt.", + "Max completion tokens description": "Een bovengrens voor het aantal tokens dat kan worden gegenereerd voor een voltooiing, inclusief zichtbare outputtokens en redeneertokens.", + "Presence penalty description": "Nummer tussen -2.0 en 2.0. Positieve waarden straffen nieuwe tokens op basis van of ze tot nu toe in de tekst voorkomen, waardoor de kans van het model om over nieuwe onderwerpen te praten toeneemt.", + "Response format description": "Belangrijk: bij gebruik van de JSON-modus moet u het model ook zelf opdracht geven om JSON te produceren via een systeem- of gebruikersbericht.", + "Temperature description": "Welke bemonsteringstemperatuur te gebruiken, tussen 0 en 2. Hogere waarden zoals 0,8 maken de output willekeuriger, terwijl lagere waarden zoals 0,2 deze meer gefocust en deterministisch maken.", + "Top P description": "Een alternatief voor bemonstering met temperatuur, genaamd nucleusbemonstering, waarbij het model de resultaten van de tokens met top_p waarschijnlijkheidsmassa overweegt. Dus 0,1 betekent dat alleen de tokens die de top 10% waarschijnlijkheidsmassa vormen, worden overwogen.", + "Get models list failed, you can enter a model name manually.": "Het ophalen van de lijst met modellen is mislukt, u kunt een modelnaam handmatig invoeren." + } + \ No newline at end of file diff --git a/packages/plugins/@nocobase/plugin-api-doc/package.json b/packages/plugins/@nocobase/plugin-api-doc/package.json index eac364fb15..cbe8653f5a 100644 --- a/packages/plugins/@nocobase/plugin-api-doc/package.json +++ b/packages/plugins/@nocobase/plugin-api-doc/package.json @@ -1,6 +1,6 @@ { "name": "@nocobase/plugin-api-doc", - "version": "1.7.0-beta.9", + "version": "1.7.0-alpha.10", "displayName": "API documentation", "displayName.zh-CN": "API 文档", "description": "An OpenAPI documentation generator for NocoBase HTTP API.", diff --git a/packages/plugins/@nocobase/plugin-api-doc/src/client/Document.tsx b/packages/plugins/@nocobase/plugin-api-doc/src/client/Document.tsx index a494b55c0f..c4a349cea0 100644 --- a/packages/plugins/@nocobase/plugin-api-doc/src/client/Document.tsx +++ b/packages/plugins/@nocobase/plugin-api-doc/src/client/Document.tsx @@ -67,6 +67,8 @@ const Documentation = () => { direction="vertical" style={{ width: '100%', + height: '100%', + overflowY: 'auto', }} >
({ export const SignUpForm = ({ authenticatorName: name }: { authenticatorName: string }) => { const { t } = useAuthTranslation(); + const { t: fieldT } = useTranslation('lm-collections'); const useBasicSignUp = () => { return useSignUp({ authenticator: name }); }; @@ -132,8 +133,12 @@ export const SignUpForm = ({ authenticatorName: name }: { authenticatorName: str return signupForm .filter((field: { show: boolean }) => field.show) .reduce((prev: any, item: { field: string; required: boolean; uiSchema: any }) => { - prev[item.field] = { + const uiSchema = { ...item.uiSchema, + title: item.uiSchema.title ? fieldT(Schema.compile(item.uiSchema.title, { t })) : '', + }; + prev[item.field] = { + ...uiSchema, required: item.required, 'x-decorator': 'FormItem', }; diff --git a/packages/plugins/@nocobase/plugin-backup-restore/package.json b/packages/plugins/@nocobase/plugin-backup-restore/package.json index 0f416d822c..e0e23c61f8 100644 --- a/packages/plugins/@nocobase/plugin-backup-restore/package.json +++ b/packages/plugins/@nocobase/plugin-backup-restore/package.json @@ -4,7 +4,7 @@ "displayName.zh-CN": "应用的备份与还原(废弃)", "description": "Backup and restore applications for scenarios such as application replication, migration, and upgrades.", "description.zh-CN": "备份和还原应用,可用于应用的复制、迁移、升级等场景。", - "version": "1.7.0-beta.9", + "version": "1.7.0-alpha.10", "license": "AGPL-3.0", "main": "./dist/server/index.js", "homepage": "https://docs.nocobase.com/handbook/backup-restore", diff --git a/packages/plugins/@nocobase/plugin-block-iframe/package.json b/packages/plugins/@nocobase/plugin-block-iframe/package.json index 366944d5c7..21a43b7c21 100644 --- a/packages/plugins/@nocobase/plugin-block-iframe/package.json +++ b/packages/plugins/@nocobase/plugin-block-iframe/package.json @@ -4,7 +4,7 @@ "displayName.zh-CN": "区块:iframe", "description": "Create an iframe block on the page to embed and display external web pages or content.", "description.zh-CN": "在页面上创建和管理iframe,用于嵌入和展示外部网页或内容。", - "version": "1.7.0-beta.9", + "version": "1.7.0-alpha.10", "license": "AGPL-3.0", "main": "./dist/server/index.js", "homepage": "https://docs.nocobase.com/handbook/block-iframe", diff --git a/packages/plugins/@nocobase/plugin-block-template/package.json b/packages/plugins/@nocobase/plugin-block-template/package.json index 7c61440ad4..cfffc11745 100644 --- a/packages/plugins/@nocobase/plugin-block-template/package.json +++ b/packages/plugins/@nocobase/plugin-block-template/package.json @@ -4,7 +4,7 @@ "displayName.zh-CN": "区块:模板", "description": "Create and manage block templates for reuse on pages.", "description.zh-CN": "创建和管理区块模板,用于在页面中重复使用。", - "version": "1.7.0-beta.9", + "version": "1.7.0-alpha.10", "license": "AGPL-3.0", "main": "dist/server/index.js", "homepage": "https://docs.nocobase.com/handbook/block-template", diff --git a/packages/plugins/@nocobase/plugin-block-template/src/client/index.tsx b/packages/plugins/@nocobase/plugin-block-template/src/client/index.tsx index 767779246f..f143dc158d 100644 --- a/packages/plugins/@nocobase/plugin-block-template/src/client/index.tsx +++ b/packages/plugins/@nocobase/plugin-block-template/src/client/index.tsx @@ -169,8 +169,6 @@ export class PluginBlockTemplateClient extends Plugin { 'blockSettings:createForm', 'blockSettings:details', 'blockSettings:detailsWithPagination', - 'blockSettings:multiDataDetails', - 'blockSettings:singleDataDetails', 'blockSettings:stepsForm', 'blockSettings:filterCollapse', 'blockSettings:filterForm', diff --git a/packages/plugins/@nocobase/plugin-block-workbench/package.json b/packages/plugins/@nocobase/plugin-block-workbench/package.json index 4e53982d26..d7b91dc4e9 100644 --- a/packages/plugins/@nocobase/plugin-block-workbench/package.json +++ b/packages/plugins/@nocobase/plugin-block-workbench/package.json @@ -1,6 +1,6 @@ { "name": "@nocobase/plugin-block-workbench", - "version": "1.7.0-beta.9", + "version": "1.7.0-alpha.10", "displayName": "Block: Action panel", "displayName.zh-CN": "区块:操作面板", "description": "Centrally manages and displays various actions, allowing users to efficiently perform tasks. It supports extensibility, with current action types including pop-ups, links, scanning, and custom requests.", diff --git a/packages/plugins/@nocobase/plugin-block-workbench/src/client/WorkbenchBlock.tsx b/packages/plugins/@nocobase/plugin-block-workbench/src/client/WorkbenchBlock.tsx index e2fe54b46b..88c0584782 100644 --- a/packages/plugins/@nocobase/plugin-block-workbench/src/client/WorkbenchBlock.tsx +++ b/packages/plugins/@nocobase/plugin-block-workbench/src/client/WorkbenchBlock.tsx @@ -122,6 +122,7 @@ const useStyles = createStyles(({ token, css }) => ({ margin: -12px -32px; width: calc(100% + 64px); text-align: start; + justify-content: start !important; color: ${token.colorText}; } } diff --git a/packages/plugins/@nocobase/plugin-calendar/package.json b/packages/plugins/@nocobase/plugin-calendar/package.json index d2791430a7..94917103a9 100644 --- a/packages/plugins/@nocobase/plugin-calendar/package.json +++ b/packages/plugins/@nocobase/plugin-calendar/package.json @@ -1,6 +1,6 @@ { "name": "@nocobase/plugin-calendar", - "version": "1.7.0-beta.9", + "version": "1.7.0-alpha.10", "displayName": "Calendar", "displayName.zh-CN": "日历", "description": "Provides callendar collection template and block for managing date data, typically for date/time related information such as events, appointments, tasks, and so on.", diff --git a/packages/plugins/@nocobase/plugin-calendar/src/locale/nl-NL.json b/packages/plugins/@nocobase/plugin-calendar/src/locale/nl-NL.json new file mode 100644 index 0000000000..50db11f27f --- /dev/null +++ b/packages/plugins/@nocobase/plugin-calendar/src/locale/nl-NL.json @@ -0,0 +1,56 @@ +{ + "Configure calendar": "Kalender configureren", + "Title field": "Titelveld", + "Custom title": "Aangepaste titel", + "Show lunar": "Maankalender weergeven", + "Start date field": "Startdatumveld", + "End date field": "Einddatumveld", + "Work week": "Werkweek", + "Today": "Vandaag", + "Day": "Dag", + "Agenda": "Agenda", + "Date": "Datum", + "Time": "Tijd", + "Event": "Gebeurtenis", + "None": "Geen", + "Calendar": "Kalender", + "Delete events": "Gebeurtenissen verwijderen", + "This event": "Dit evenement", + "This and following events": "Dit en volgende evenementen", + "All events": "Alle evenementen", + "Delete this event?": "Dit evenement verwijderen?", + "Delete Event": "Evenement verwijderen", + "Calendar collection": "Kalendercollectie", + "Create calendar block": "Kalenderblok maken", + "Filter": "Filter", + "Configure actions": "Acties configureren", + "Enable actions": "Acties inschakelen", + "Turn pages": "Bladeren", + "Select view": "Weergave selecteren", + "Add new": "Nieuw toevoegen", + "View record": "Record bekijken", + "Details": "Details", + "Customize": "Aanpassen", + "Update record": "Record bijwerken", + "Popup": "Popup", + "Updated successfully": "Succesvol bijgewerkt", + "Custom request": "Aangepast verzoek", + "Edit": "Bewerken", + "Delete": "Verwijderen", + "Print": "Afdrukken", + "Daily": "Dagelijks", + "Weekly": "Wekelijks", + "Monthly": "Maandelijks", + "Yearly": "Jaarlijks", + "Repeats": "Herhaalt", + "Title": "Titel", + "Month": "Maand", + "Week": "Week", + "{{count}} more items": "{{count}} meer items", + "Color field": "Kleurveld", + "Not selected": "Niet geselecteerd", + "Default view": "Standaardweergave", + "Event open mode": "Gebeurtenis openen modus", + "Quick create event": "Snel evenement maken" + } + \ No newline at end of file diff --git a/packages/plugins/@nocobase/plugin-charts/package.json b/packages/plugins/@nocobase/plugin-charts/package.json index 9867a3d5d1..70c2b21626 100644 --- a/packages/plugins/@nocobase/plugin-charts/package.json +++ b/packages/plugins/@nocobase/plugin-charts/package.json @@ -4,7 +4,7 @@ "displayName.zh-CN": "图表(废弃)", "description": "The plugin has been deprecated, please use the data visualization plugin instead.", "description.zh-CN": "已废弃插件,请使用数据可视化插件代替。", - "version": "1.7.0-beta.9", + "version": "1.7.0-alpha.10", "main": "./dist/server/index.js", "license": "AGPL-3.0", "devDependencies": { diff --git a/packages/plugins/@nocobase/plugin-client/package.json b/packages/plugins/@nocobase/plugin-client/package.json index e5933dd0ac..b0bef8efd9 100644 --- a/packages/plugins/@nocobase/plugin-client/package.json +++ b/packages/plugins/@nocobase/plugin-client/package.json @@ -4,7 +4,7 @@ "displayName.zh-CN": "WEB 客户端", "description": "Provides a client interface for the NocoBase server", "description.zh-CN": "为 NocoBase 服务端提供客户端界面", - "version": "1.7.0-beta.9", + "version": "1.7.0-alpha.10", "main": "./dist/server/index.js", "license": "AGPL-3.0", "devDependencies": { diff --git a/packages/plugins/@nocobase/plugin-collection-sql/package.json b/packages/plugins/@nocobase/plugin-collection-sql/package.json index c7cdb9e47e..6b3e552fba 100644 --- a/packages/plugins/@nocobase/plugin-collection-sql/package.json +++ b/packages/plugins/@nocobase/plugin-collection-sql/package.json @@ -4,7 +4,7 @@ "displayName.zh-CN": "数据表: SQL", "description": "Provides SQL collection template", "description.zh-CN": "提供 SQL 数据表模板", - "version": "1.7.0-beta.9", + "version": "1.7.0-alpha.10", "homepage": "https://docs-cn.nocobase.com/handbook/collection-sql", "homepage.zh-CN": "https://docs-cn.nocobase.com/handbook/collection-sql", "main": "dist/server/index.js", diff --git a/packages/plugins/@nocobase/plugin-collection-tree/package.json b/packages/plugins/@nocobase/plugin-collection-tree/package.json index 899485bdaa..ec049d4981 100644 --- a/packages/plugins/@nocobase/plugin-collection-tree/package.json +++ b/packages/plugins/@nocobase/plugin-collection-tree/package.json @@ -1,6 +1,6 @@ { "name": "@nocobase/plugin-collection-tree", - "version": "1.7.0-beta.9", + "version": "1.7.0-alpha.10", "displayName": "Collection: Tree", "displayName.zh-CN": "数据表:树", "description": "Provides tree collection template", diff --git a/packages/plugins/@nocobase/plugin-data-source-main/package.json b/packages/plugins/@nocobase/plugin-data-source-main/package.json index de97fc31a0..1dec250e94 100644 --- a/packages/plugins/@nocobase/plugin-data-source-main/package.json +++ b/packages/plugins/@nocobase/plugin-data-source-main/package.json @@ -4,7 +4,7 @@ "displayName.zh-CN": "数据源:主数据库", "description": "NocoBase main database, supports relational databases such as PostgreSQL, MySQL, MariaDB and so on.", "description.zh-CN": "NocoBase 主数据库,支持 PostgreSQL、MySQL、MariaDB 等关系型数据库。", - "version": "1.7.0-beta.9", + "version": "1.7.0-alpha.10", "main": "./dist/server/index.js", "homepage": "https://docs.nocobase.com/handbook/data-source-main", "homepage.zh-CN": "https://docs-cn.nocobase.com/handbook/data-source-main", diff --git a/packages/plugins/@nocobase/plugin-data-source-manager/package.json b/packages/plugins/@nocobase/plugin-data-source-manager/package.json index b622fe377a..182ed026c4 100644 --- a/packages/plugins/@nocobase/plugin-data-source-manager/package.json +++ b/packages/plugins/@nocobase/plugin-data-source-manager/package.json @@ -1,6 +1,6 @@ { "name": "@nocobase/plugin-data-source-manager", - "version": "1.7.0-beta.9", + "version": "1.7.0-alpha.10", "main": "dist/server/index.js", "displayName": "Data source manager", "displayName.zh-CN": "数据源管理", diff --git a/packages/plugins/@nocobase/plugin-data-source-manager/src/locale/nl-NL.json b/packages/plugins/@nocobase/plugin-data-source-manager/src/locale/nl-NL.json new file mode 100644 index 0000000000..958e0d81b4 --- /dev/null +++ b/packages/plugins/@nocobase/plugin-data-source-manager/src/locale/nl-NL.json @@ -0,0 +1,41 @@ +{ + "Data source name": "Databron naam", + "Data source display name": "Databron weergavenaam", + "Host": "Host", + "Port": "Poort", + "Database": "Database", + "Data source manager": "Databron manager", + "Data sources": "Databronnen", + "No external data source plugin installed": "Geen externe databron plugin geïnstalleerd", + "View documentation": "Bekijk documentatie", + "Test Connection": "Test verbinding", + "Connection successful": "Verbinding succesvol", + "Display name": "Weergavenaam", + "Username": "Gebruikersnaam", + "Password": "Wachtwoord", + "Type": "Type", + "Description": "Beschrijving", + "Storage": "Opslag", + "Collections": "Collecties", + "Permissions": "Rechten", + "Allow adding and modifying collection": "Toestaan toevoegen en wijzigen collectie", + "Unknown field type": "Onbekend veldtype", + "The following field types are not compatible and do not support output and display": "De volgende veldtypen zijn niet compatibel en ondersteunen geen uitvoer en weergave", + "Field database type": "Veld database type", + "Field interface": "Veld interface", + "Status": "Status", + "Loading": "Laden", + "Failed": "Mislukt", + "Loaded": "Geladen", + "Reloading": "Herladen", + "Data source synchronization in progress": "Databron synchronisatie in uitvoering", + "Data source synchronization successful": "Databron synchronisatie succesvol", + "Filter target key":"Filter doel sleutel", + "Select field": "Selecteer veld", + "OK": "OK", + "Please select a field.": "Selecteer een veld.", + "Are you sure you want to set the \"{{title}}\" field as a record unique key? This setting cannot be changed after it's been set.": "Weet je zeker dat je het veld \"{{title}}\" als een unieke sleutel wilt instellen? Deze instelling kan niet worden gewijzigd nadat deze is ingesteld.", + "If a collection lacks a primary key, you must configure a unique record key to locate row records within a block, failure to configure this will prevent the creation of data blocks for the collection.": "Als een collectie geen primaire sleutel heeft, moet je een unieke record sleutel configureren om rijrecords binnen een blok te lokaliseren, het niet configureren hiervan zal de creatie van datablokken voor de collectie voorkomen.", + "Filter data based on the specific field, with the requirement that the field value must be unique.": "Filter gegevens op basis van het specifieke veld, met de eis dat de veldwaarde uniek moet zijn." + } + \ No newline at end of file diff --git a/packages/plugins/@nocobase/plugin-data-visualization/package.json b/packages/plugins/@nocobase/plugin-data-visualization/package.json index a375415cd5..6cd3bad639 100644 --- a/packages/plugins/@nocobase/plugin-data-visualization/package.json +++ b/packages/plugins/@nocobase/plugin-data-visualization/package.json @@ -1,6 +1,6 @@ { "name": "@nocobase/plugin-data-visualization", - "version": "1.7.0-beta.9", + "version": "1.7.0-alpha.10", "displayName": "Data visualization", "displayName.zh-CN": "数据可视化", "description": "Provides data visualization feature, including chart block and chart filter block, support line charts, area charts, bar charts and more than a dozen kinds of charts, you can also extend more chart types.", diff --git a/packages/plugins/@nocobase/plugin-disable-pm-add/package.json b/packages/plugins/@nocobase/plugin-disable-pm-add/package.json index 0482a47f10..088b3f8d6c 100644 --- a/packages/plugins/@nocobase/plugin-disable-pm-add/package.json +++ b/packages/plugins/@nocobase/plugin-disable-pm-add/package.json @@ -1,6 +1,6 @@ { "name": "@nocobase/plugin-disable-pm-add", - "version": "1.7.0-beta.9", + "version": "1.7.0-alpha.10", "main": "./dist/server/index.js", "peerDependencies": { "@nocobase/client": "1.x", diff --git a/packages/plugins/@nocobase/plugin-environment-variables/package.json b/packages/plugins/@nocobase/plugin-environment-variables/package.json index a5412a5e8a..53f6b405b6 100644 --- a/packages/plugins/@nocobase/plugin-environment-variables/package.json +++ b/packages/plugins/@nocobase/plugin-environment-variables/package.json @@ -1,6 +1,6 @@ { "name": "@nocobase/plugin-environment-variables", - "version": "1.7.0-beta.9", + "version": "1.7.0-alpha.10", "main": "dist/server/index.js", "peerDependencies": { "@nocobase/client": "1.x", diff --git a/packages/plugins/@nocobase/plugin-environment-variables/src/client/components/EnvironmentTabs.tsx b/packages/plugins/@nocobase/plugin-environment-variables/src/client/components/EnvironmentTabs.tsx index 47989d4e88..ff2a5ead87 100644 --- a/packages/plugins/@nocobase/plugin-environment-variables/src/client/components/EnvironmentTabs.tsx +++ b/packages/plugins/@nocobase/plugin-environment-variables/src/client/components/EnvironmentTabs.tsx @@ -10,9 +10,18 @@ import { DeleteOutlined, DownOutlined, PlusOutlined, ReloadOutlined } from '@ant import { Checkbox, FormButtonGroup, FormItem, FormLayout, Input, Radio, Reset, Submit } from '@formily/antd-v5'; import { registerValidateRules } from '@formily/core'; import { createSchemaField, useField } from '@formily/react'; -import { SchemaComponent, SchemaComponentOptions, useAPIClient, FormDrawer, useGlobalTheme } from '@nocobase/client'; +import { + SchemaComponent, + SchemaComponentOptions, + useAPIClient, + FormDrawer, + useGlobalTheme, + removeNullCondition, +} from '@nocobase/client'; +import { useLocation } from 'react-router-dom'; import { Alert, App, Button, Card, Dropdown, Flex, Space, Table, Tag } from 'antd'; -import React, { useContext, useState } from 'react'; +import React, { useContext, useEffect, useState } from 'react'; +import { useTranslation } from 'react-i18next'; import { VAR_NAME_RE } from '../../re'; import { EnvAndSecretsContext } from '../EnvironmentVariablesAndSecretsProvider'; import { useT } from '../locale'; @@ -258,6 +267,13 @@ export function EnvironmentTabs() { const [selectRowKeys, setSelectRowKeys] = useState([]); const resource = api.resource('environmentVariables'); const { theme } = useGlobalTheme(); + const location = useLocation(); + useEffect(() => { + const { run, params } = variablesRequest; + if (params?.length) { + run(); + } + }, [location.key]); const handleBulkImport = async (importData) => { const arr = Object.entries(importData).map(([type, dataString]) => { return parseKeyValuePairs(dataString, type).filter(Boolean); @@ -359,13 +375,20 @@ export function EnvironmentTabs() { const useFilterActionProps = () => { const field = useField(); const { run } = variablesRequest; + const { t } = useTranslation(); return { options: filterOptions, onSubmit: async (values) => { run(values); - field.setValue(values); + const filter = removeNullCondition(values?.filter); + const items = filter?.$and || filter?.$or; + if (items?.length) { + field.title = t('{{count}} filter items', { count: items?.length || 0 }); + } else { + field.title = t('Filter'); + } }, onReset: (values) => { field.setValue(values); @@ -407,7 +430,7 @@ export function EnvironmentTabs() { $and: [{ name: { $includes: '' } }], }, 'x-component': 'Filter.Action', - + 'x-component-props': { icon: 'FilterOutlined' }, enum: filterOptions, 'x-use-component-props': useFilterActionProps, }} diff --git a/packages/plugins/@nocobase/plugin-environment-variables/src/locale/nl-NL.json b/packages/plugins/@nocobase/plugin-environment-variables/src/locale/nl-NL.json new file mode 100644 index 0000000000..08e92a9450 --- /dev/null +++ b/packages/plugins/@nocobase/plugin-environment-variables/src/locale/nl-NL.json @@ -0,0 +1,17 @@ +{ + "Environment": "Omgeving", + "Variables and secrets": "Variabelen en geheimen", + "Variables": "Variabelen", + "Secrets": "Geheimen", + "Add variable": "Variabele toevoegen", + "Bulk import": "Bulk importeren", + "Name": "Naam", + "Value": "Waarde", + "Type": "Type", + "Plain text": "Tekst", + "Encrypted": "Versleuteld", + "Delete variable": "Variabele verwijderen", + "Restart now": "Nu herstarten", + "Variables and secrets have been updated. A restart is required for the changes to take effect.": "Variabelen en geheimen zijn bijgewerkt. Een herstart is vereist voor de wijzigingen om van kracht te worden." + } + \ No newline at end of file diff --git a/packages/plugins/@nocobase/plugin-error-handler/package.json b/packages/plugins/@nocobase/plugin-error-handler/package.json index c0a8bf9fd3..99bb6de45b 100644 --- a/packages/plugins/@nocobase/plugin-error-handler/package.json +++ b/packages/plugins/@nocobase/plugin-error-handler/package.json @@ -4,7 +4,7 @@ "displayName.zh-CN": "错误处理器", "description": "Handling application errors and exceptions.", "description.zh-CN": "处理应用程序中的错误和异常。", - "version": "1.7.0-beta.9", + "version": "1.7.0-alpha.10", "license": "AGPL-3.0", "main": "./dist/server/index.js", "devDependencies": { diff --git a/packages/plugins/@nocobase/plugin-error-handler/src/locale/nl-NL.json b/packages/plugins/@nocobase/plugin-error-handler/src/locale/nl-NL.json index 8075e78967..85e911fabc 100644 --- a/packages/plugins/@nocobase/plugin-error-handler/src/locale/nl-NL.json +++ b/packages/plugins/@nocobase/plugin-error-handler/src/locale/nl-NL.json @@ -1,6 +1,5 @@ { "unique violation": "{{field}} bestaat al", "notNull violation": "{{field}} mag niet leeg zijn", - "Validation error": "{{field}} validatiefout", - "notNull Violation": "{{field}} mag niet leeg zijn" + "Validation error": "{{field}} validatiefout" } \ No newline at end of file diff --git a/packages/plugins/@nocobase/plugin-field-china-region/package.json b/packages/plugins/@nocobase/plugin-field-china-region/package.json index 85bd9ec9f3..9341292ce0 100644 --- a/packages/plugins/@nocobase/plugin-field-china-region/package.json +++ b/packages/plugins/@nocobase/plugin-field-china-region/package.json @@ -1,6 +1,6 @@ { "name": "@nocobase/plugin-field-china-region", - "version": "1.7.0-beta.9", + "version": "1.7.0-alpha.10", "displayName": "Collection field: administrative divisions of China", "displayName.zh-CN": "数据表字段:中国行政区划", "description": "Provides data and field type for administrative divisions of China.", diff --git a/packages/plugins/@nocobase/plugin-field-formula/package.json b/packages/plugins/@nocobase/plugin-field-formula/package.json index b5896575ac..062285d9cc 100644 --- a/packages/plugins/@nocobase/plugin-field-formula/package.json +++ b/packages/plugins/@nocobase/plugin-field-formula/package.json @@ -4,7 +4,7 @@ "displayName.zh-CN": "数据表字段:公式", "description": "Configure and store the results of calculations between multiple field values in the same record, supporting both Math.js and Excel formula functions.", "description.zh-CN": "可以配置并存储同一条记录的多字段值之间的计算结果,支持 Math.js 和 Excel formula functions 两种引擎", - "version": "1.7.0-beta.9", + "version": "1.7.0-alpha.10", "license": "AGPL-3.0", "main": "./dist/server/index.js", "homepage": "https://docs.nocobase.com/handbook/field-formula", diff --git a/packages/plugins/@nocobase/plugin-field-formula/src/locale/nl-NL.json b/packages/plugins/@nocobase/plugin-field-formula/src/locale/nl-NL.json index 960d8cec34..8c3ba3c7d1 100644 --- a/packages/plugins/@nocobase/plugin-field-formula/src/locale/nl-NL.json +++ b/packages/plugins/@nocobase/plugin-field-formula/src/locale/nl-NL.json @@ -4,5 +4,6 @@ "Expression": "Expressie", "Expression syntax error": "Fout in expressiesyntax", "Syntax references": "Syntaxverwijzingen", - "Compute a value based on the other fields": "Bereken een waarde op basis van de andere velden" + "Compute a value based on the other fields": "Bereken een waarde op basis van de andere velden", + "Configure and store the results of calculations between multiple field values in the same record, supporting both Math.js and Excel formula functions.": "Configureer en sla de resultaten op van berekeningen tussen meerdere veldwaarden in hetzelfde record, met ondersteuning voor zowel Math.js als Excel-formulefuncties." } diff --git a/packages/plugins/@nocobase/plugin-field-m2m-array/package.json b/packages/plugins/@nocobase/plugin-field-m2m-array/package.json index dd93f9338b..ff4c75ad9a 100644 --- a/packages/plugins/@nocobase/plugin-field-m2m-array/package.json +++ b/packages/plugins/@nocobase/plugin-field-m2m-array/package.json @@ -4,7 +4,7 @@ "displayName.zh-CN": "数据表字段:多对多 (数组)", "description": "Allows to create many to many relationships between two models by storing an array of unique keys of the target model.", "description.zh-CN": "支持通过在数组中存储目标表唯一键的方式建立多对多关系。", - "version": "1.7.0-beta.9", + "version": "1.7.0-alpha.10", "main": "dist/server/index.js", "peerDependencies": { "@nocobase/client": "1.x", diff --git a/packages/plugins/@nocobase/plugin-field-markdown-vditor/package.json b/packages/plugins/@nocobase/plugin-field-markdown-vditor/package.json index 3f957ad5df..bbd35c7580 100644 --- a/packages/plugins/@nocobase/plugin-field-markdown-vditor/package.json +++ b/packages/plugins/@nocobase/plugin-field-markdown-vditor/package.json @@ -4,7 +4,7 @@ "displayName.zh-CN": "数据表字段:Markdown(Vditor)", "description": "Used to store Markdown and render it using Vditor editor, supports common Markdown syntax such as list, code, quote, etc., and supports uploading images, recordings, etc.It also allows for instant rendering, where what you see is what you get.", "description.zh-CN": "用于存储 Markdown,并使用 Vditor 编辑器渲染,支持常见 Markdown 语法,如列表,代码,引用等,并支持上传图片,录音等。同时可以做到即时渲染,所见即所得。", - "version": "1.7.0-beta.9", + "version": "1.7.0-alpha.10", "license": "AGPL-3.0", "main": "dist/server/index.js", "homepage": "https://docs.nocobase.com/handbook/field-markdown-vditor", diff --git a/packages/plugins/@nocobase/plugin-field-markdown-vditor/src/client/components/Edit.tsx b/packages/plugins/@nocobase/plugin-field-markdown-vditor/src/client/components/Edit.tsx index 51adb9b37b..4791f92a13 100644 --- a/packages/plugins/@nocobase/plugin-field-markdown-vditor/src/client/components/Edit.tsx +++ b/packages/plugins/@nocobase/plugin-field-markdown-vditor/src/client/components/Edit.tsx @@ -7,10 +7,12 @@ * For more information, please refer to: https://www.nocobase.com/agreement. */ -import { useAPIClient, useApp, withDynamicSchemaProps } from '@nocobase/client'; +import { useAPIClient, useCompile, usePlugin, withDynamicSchemaProps } from '@nocobase/client'; import React, { useEffect, useLayoutEffect, useMemo, useRef, useState } from 'react'; +import { useTranslation } from 'react-i18next'; import Vditor from 'vditor'; import { defaultToolbar } from '../interfaces/markdown-vditor'; +import { NAMESPACE } from '../locale'; import { useCDN } from './const'; import useStyle from './style'; @@ -24,11 +26,15 @@ export const Edit = withDynamicSchemaProps((props) => { const vdFullscreen = useRef(false); const containerRef = useRef(null); const containerParentRef = useRef(null); - const app = useApp(); const apiClient = useAPIClient(); const cdn = useCDN(); const { wrapSSR, hashId, componentCls: containerClassName } = useStyle(); const locale = apiClient.auth.locale || 'en-US'; + const fileManagerPlugin: any = usePlugin('@nocobase/plugin-file-manager'); + const compile = useCompile(); + const compileRef = useRef(compile); + compileRef.current = compile; + const { t } = useTranslation(); const lang: any = useMemo(() => { const currentLang = locale.replace(/-/g, '_'); @@ -41,7 +47,6 @@ export const Edit = withDynamicSchemaProps((props) => { useEffect(() => { if (!containerRef.current) return; - const uploadFileCollection = fileCollection || 'attachments'; const toolbarConfig = toolbar ?? defaultToolbar; const vditor = new Vditor(containerRef.current, { @@ -68,24 +73,63 @@ export const Edit = withDynamicSchemaProps((props) => { onChange(value); }, upload: { - url: app.getApiUrl(`${uploadFileCollection}:create`), - headers: apiClient.getHeaders(), multiple: false, fieldName: 'file', - max: 1024 * 1024 * 1024, // 1G - format(files, responseText) { - const response = JSON.parse(responseText); - const formatResponse = { - msg: '', - code: 0, - data: { - errFiles: [], - succMap: { - [response.data.filename]: response.data.url, - }, - }, - }; - return JSON.stringify(formatResponse); + async handler(files: File[]) { + const file = files[0]; + + // Need to ensure focus is in the current input box before uploading + vditor.focus(); + + const { data: checkData } = await apiClient.resource('vditor').check({ + fileCollectionName: fileCollection, + }); + + if (!checkData?.data?.isSupportToUploadFiles) { + vditor.tip( + t('vditor.uploadError.message', { ns: NAMESPACE, storageTitle: checkData.data.storage?.title }), + 0, + ); + return; + } + + vditor.tip(t('uploading'), 0); + const { data, errorMessage } = await fileManagerPlugin.uploadFile({ + file, + fileCollectionName: fileCollection, + storageId: checkData?.data?.storage?.id, + storageType: checkData?.data?.storage?.type, + storageRules: checkData?.data?.storage?.rules, + }); + + if (errorMessage) { + vditor.tip(compileRef.current(errorMessage), 3000); + return; + } + + if (!data) { + vditor.tip(t('Response data is empty', { ns: NAMESPACE }), 3000); + return; + } + + const fileName = data.filename; + const fileUrl = data.url; + + // Check if the uploaded file is an image + const isImage = file.type.startsWith('image/'); + + if (isImage) { + // Insert as an image - will be displayed in the editor + vditor.insertValue(`![${fileName}](${fileUrl})`); + } else { + // For non-image files, insert as a download link + vditor.insertValue(`[${fileName}](${fileUrl})`); + } + + // hide the tip + vditor.tip(t(''), 10); + + return null; }, }, }); @@ -94,7 +138,8 @@ export const Edit = withDynamicSchemaProps((props) => { vdRef.current?.destroy(); vdRef.current = undefined; }; - }, [fileCollection, toolbar?.join(',')]); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [toolbar?.join(',')]); useEffect(() => { if (editorReady && vdRef.current) { @@ -155,7 +200,7 @@ export const Edit = withDynamicSchemaProps((props) => { return wrapSSR(
-
+
, ); }); diff --git a/packages/plugins/@nocobase/plugin-field-markdown-vditor/src/client/interfaces/markdown-vditor.tsx b/packages/plugins/@nocobase/plugin-field-markdown-vditor/src/client/interfaces/markdown-vditor.tsx index b5b8b54b7e..608ca0ed08 100644 --- a/packages/plugins/@nocobase/plugin-field-markdown-vditor/src/client/interfaces/markdown-vditor.tsx +++ b/packages/plugins/@nocobase/plugin-field-markdown-vditor/src/client/interfaces/markdown-vditor.tsx @@ -7,9 +7,9 @@ * For more information, please refer to: https://www.nocobase.com/agreement. */ +import { ISchema } from '@formily/react'; import { CollectionFieldInterface, interfacesProperties } from '@nocobase/client'; import { generateNTemplate } from '../locale'; -import { ISchema } from '@formily/react'; const { defaultProps, operators } = interfacesProperties; @@ -58,7 +58,9 @@ export class MarkdownVditorFieldInterface extends CollectionFieldInterface { 'x-reactions': { fulfill: { schema: { - description: generateNTemplate('Used to store files uploaded in the Markdown editor'), + description: generateNTemplate( + 'Used to store files uploaded in the Markdown editor (default: attachments)', + ), }, }, }, diff --git a/packages/plugins/@nocobase/plugin-field-markdown-vditor/src/client/locale/index.ts b/packages/plugins/@nocobase/plugin-field-markdown-vditor/src/client/locale/index.ts index 5c461f7c06..e2f3cbb485 100644 --- a/packages/plugins/@nocobase/plugin-field-markdown-vditor/src/client/locale/index.ts +++ b/packages/plugins/@nocobase/plugin-field-markdown-vditor/src/client/locale/index.ts @@ -9,7 +9,7 @@ import { tval } from '@nocobase/utils/client'; -const NAMESPACE = 'field-markdown-vditor'; +export const NAMESPACE = 'field-markdown-vditor'; export function generateNTemplate(key: string) { return tval(key, { ns: NAMESPACE }) diff --git a/packages/plugins/@nocobase/plugin-field-markdown-vditor/src/locale/de-DE.json b/packages/plugins/@nocobase/plugin-field-markdown-vditor/src/locale/de-DE.json index ba814c4387..4b25ad4cd2 100644 --- a/packages/plugins/@nocobase/plugin-field-markdown-vditor/src/locale/de-DE.json +++ b/packages/plugins/@nocobase/plugin-field-markdown-vditor/src/locale/de-DE.json @@ -1,7 +1,7 @@ { "Vditor": "Markdown(Vditor)", "File collection": "Dateisammlung", - "Used to store files uploaded in the Markdown editor": "Wird verwendet, um Dateien zu speichern, die im Markdown-Editor hochgeladen wurden", + "Used to store files uploaded in the Markdown editor (default: attachments)": "Dateisammlung, die in den Markdown-Editor hochgeladen wurde (Standard: attachments)", "Toolbar": "Editor-Symbolleistenkonfiguration", "Emoji": "Emoji", "Headings": "Überschriften", @@ -29,5 +29,10 @@ "Both": "Editor & Vorschau", "Preview": "Vorschau", "Fullscreen": "Vollbild umschalten", - "Outline": "Gliederung" + "Outline": "Gliederung", + "uploading": "Hochladen...", + "upload failed": "Hochladen fehlgeschlagen", + "vditor.uploadError.message": "Dateien können nicht in den aktuellen Speicher hochgeladen werden. Sie versuchen, Dateien in den Markdown-Editor hochzuladen, aber die aktuelle Speicher-Konfiguration unterstützt diese Operation nicht. Um die Upload-Funktionalität zu aktivieren, schließen Sie bitte die folgenden Einstellungen ab: 1. Gehen Sie zu \"Dateimanager\". 2. Wählen Sie den aktuell verwendeten Speicher ({{storageTitle}}) aus. 3. Legen Sie die \"Basis-URL\" fest und aktivieren Sie die Option \"Öffentlicher Zugriff\".", + "Storage configuration not found. Please configure a storage provider first.": "Speicherkonfiguration nicht gefunden. Bitte konfigurieren Sie zuerst einen Speicheranbieter.", + "Response data is empty": "Antwortdaten sind leer" } diff --git a/packages/plugins/@nocobase/plugin-field-markdown-vditor/src/locale/en-US.json b/packages/plugins/@nocobase/plugin-field-markdown-vditor/src/locale/en-US.json index 2c71874069..98743a02e2 100644 --- a/packages/plugins/@nocobase/plugin-field-markdown-vditor/src/locale/en-US.json +++ b/packages/plugins/@nocobase/plugin-field-markdown-vditor/src/locale/en-US.json @@ -1,7 +1,7 @@ { "Vditor": "Markdown(Vditor)", "File collection": "File collection", - "Used to store files uploaded in the Markdown editor": "Used to store files uploaded in the Markdown editor", + "Used to store files uploaded in the Markdown editor (default: attachments)": "Used to store files uploaded in the Markdown editor (default: attachments)", "Toolbar": "Editor toolbar configuration", "Emoji": "Emoji", "Headings": "Headings", @@ -29,5 +29,10 @@ "Both": "Editor & Preview", "Preview": "Preview", "Fullscreen": "Toggle Fullscreen", - "Outline": "Outline" -} \ No newline at end of file + "Outline": "Outline", + "uploading": "Uploading...", + "upload failed": "upload failed", + "vditor.uploadError.message": "Unable to upload files to the current storage. You are trying to upload files to the Markdown editor, but the current storage configuration does not support this operation. To enable upload functionality, please complete the following settings: 1. Go to \"File Manager\". 2. Select the storage currently in use ({{storageTitle}}). 3. Set \"Base URL\" and enable the \"Public access\" option.", + "Storage configuration not found. Please configure a storage provider first.": "Storage configuration not found. Please configure a storage provider first.", + "Response data is empty": "Response data is empty" +} diff --git a/packages/plugins/@nocobase/plugin-field-markdown-vditor/src/locale/it-IT.json b/packages/plugins/@nocobase/plugin-field-markdown-vditor/src/locale/it-IT.json index e9cb61630a..19ae179978 100644 --- a/packages/plugins/@nocobase/plugin-field-markdown-vditor/src/locale/it-IT.json +++ b/packages/plugins/@nocobase/plugin-field-markdown-vditor/src/locale/it-IT.json @@ -1,7 +1,7 @@ -{ + { "Vditor": "Markdown(Vditor)", "File collection": "Raccolta file", - "Used to store files uploaded in the Markdown editor": "Utilizzato per archiviare i file caricati nell'editor Markdown", + "Used to store files uploaded in the Markdown editor (default: attachments)": "Utilizzato per archiviare i file caricati nell'editor Markdown (default: attachments)", "Toolbar": "Configurazione barra degli strumenti dell'editor", "Emoji": "Emoji", "Headings": "Intestazioni", @@ -29,5 +29,10 @@ "Both": "Editor e Anteprima", "Preview": "Anteprima", "Fullscreen": "Attiva/disattiva schermo intero", - "Outline": "Struttura" + "Outline": "Struttura", + "uploading": "Uploading...", + "upload failed": "upload failed", + "vditor.uploadError.message": "Impossibile caricare file nello storage corrente. Stai tentando di caricare file nell'editor Markdown, ma la configurazione di archiviazione corrente non supporta questa operazione. Per abilitare la funzionalità di caricamento, completa le seguenti impostazioni: 1. Vai a \"Gestione file\". 2. Seleziona lo storage attualmente in uso ({{storageTitle}}). 3. Imposta \"URL di base\" e abilita l'opzione \"Accesso pubblico\".", + "Storage configuration not found. Please configure a storage provider first.": "Configurazione dello storage non trovata. Configura prima un provider di storage.", + "Response data is empty": "I dati di risposta sono vuoti" } diff --git a/packages/plugins/@nocobase/plugin-field-markdown-vditor/src/locale/ja-JP.json b/packages/plugins/@nocobase/plugin-field-markdown-vditor/src/locale/ja-JP.json index e41532b670..cec3dc563b 100644 --- a/packages/plugins/@nocobase/plugin-field-markdown-vditor/src/locale/ja-JP.json +++ b/packages/plugins/@nocobase/plugin-field-markdown-vditor/src/locale/ja-JP.json @@ -1,7 +1,7 @@ { "Vditor": "Markdown(Vditor)", "File collection": "ファイルコレクション", - "Used to store files uploaded in the Markdown editor": "Markdownエディタでアップロードされたファイルを保存するために使用", + "Used to store files uploaded in the Markdown editor (default: attachments)": "Markdownエディタでアップロードされたファイルを保存するために使用 (デフォルト: attachments)", "Toolbar": "ツールバー", "Emoji": "絵文字", "Headings": "見出し", @@ -29,5 +29,10 @@ "Both": "編集とプレビュー", "Preview": "プレビュー", "Fullscreen": "全画面表示の切り替え", - "Outline": "アウトライン" -} \ No newline at end of file + "Outline": "アウトライン", + "uploading": "Uploading...", + "upload failed": "upload failed", + "vditor.uploadError.message": "現在のストレージにファイルをアップロードできません。Markdownエディタにファイルをアップロードしようとしていますが、現在のストレージ設定ではこの操作はサポートされていません。アップロード機能を有効にするには、次の設定を完了してください:1.「ファイルマネージャー」に移動します。2.現在使用しているストレージ({{storageTitle}})を選択します。3.「ベースURL」を設定し、「パブリックアクセス」オプションを有効にします。", + "Storage configuration not found. Please configure a storage provider first.": "ストレージ構成が見つかりません。最初にストレージプロバイダーを構成してください。", + "Response data is empty": "応答データが空です" +} diff --git a/packages/plugins/@nocobase/plugin-field-markdown-vditor/src/locale/ko-KR.json b/packages/plugins/@nocobase/plugin-field-markdown-vditor/src/locale/ko-KR.json index ebae584d99..8d3ce5628f 100644 --- a/packages/plugins/@nocobase/plugin-field-markdown-vditor/src/locale/ko-KR.json +++ b/packages/plugins/@nocobase/plugin-field-markdown-vditor/src/locale/ko-KR.json @@ -1,7 +1,7 @@ { "Vditor": "Markdown(Vditor)", "File collection": "파일 데이터 테이블", - "Used to store files uploaded in the Markdown editor": "Markdown 편집기에 업로드된 파일을 저장하는 데 사용됩니다", + "Used to store files uploaded in the Markdown editor (default: attachments)": "Markdown 편집기에 업로드된 파일을 저장하는 데 사용됩니다 (default: attachments)", "Toolbar": "편집기 도구 모음 구성", "Emoji": "이모지", "Headings": "제목크기", @@ -29,5 +29,10 @@ "Both": "에디터 & 미리보기", "Preview": "미리보기", "Fullscreen": "전체화면", - "Outline": "개요" -} \ No newline at end of file + "Outline": "개요", + "uploading": "Uploading...", + "upload failed": "upload failed", + "vditor.uploadError.message": "현재 스토리지에 파일을 업로드할 수 없습니다. Markdown 편집기에 파일을 업로드하려고 하지만 현재 스토리지 구성에서는 이 작업을 지원하지 않습니다. 업로드 기능을 활성화하려면 다음 설정을 완료하십시오: 1. \"파일 관리\"로 이동합니다. 2. 현재 사용 중인 스토리지({{storageTitle}})를 선택합니다. 3. \"기본 URL\"을 설정하고 \"공개 액세스\" 옵션을 활성화합니다.", + "Storage configuration not found. Please configure a storage provider first.": "저장소 구성을 찾을 수 없습니다. 먼저 저장소 공급자를 구성하십시오.", + "Response data is empty": "응답 데이터가 비어 있습니다" +} diff --git a/packages/plugins/@nocobase/plugin-field-markdown-vditor/src/locale/zh-CN.json b/packages/plugins/@nocobase/plugin-field-markdown-vditor/src/locale/zh-CN.json index d2bc2eb6b1..93d23cc859 100644 --- a/packages/plugins/@nocobase/plugin-field-markdown-vditor/src/locale/zh-CN.json +++ b/packages/plugins/@nocobase/plugin-field-markdown-vditor/src/locale/zh-CN.json @@ -1,7 +1,7 @@ { "Vditor": "Markdown(Vditor)", "File collection": "文件数据表", - "Used to store files uploaded in the Markdown editor": "用于存储在Markdown编辑器中上传的文件", + "Used to store files uploaded in the Markdown editor (default: attachments)": "用于存储在Markdown编辑器中上传的文件 (默认: attachments)", "Toolbar": "编辑器工具栏配置", "Emoji": "表情", "Headings": "标题", @@ -29,5 +29,10 @@ "Both": "编辑 & 预览", "Preview": "预览", "Fullscreen": "全屏切换", - "Outline": "大纲" -} \ No newline at end of file + "Outline": "大纲", + "uploading": "上传中...", + "upload failed": "上传失败", + "vditor.uploadError.message": "无法上传文件到当前存储。您正在尝试上传文件到 Markdown 编辑器,但当前的存储配置不支持此操作。要启用上传功能,请完成以下设置:1. 前往「文件管理器」。2. 选择当前正在使用的存储({{storageTitle}})。3. 设置「基础 URL」并启用「公开访问」选项。", + "Storage configuration not found. Please configure a storage provider first.": "存储配置未找到。请先配置存储提供程序。", + "Response data is empty": "接口返回的数据为空" +} diff --git a/packages/plugins/@nocobase/plugin-field-markdown-vditor/src/server/__tests__/vditor-check.test.ts b/packages/plugins/@nocobase/plugin-field-markdown-vditor/src/server/__tests__/vditor-check.test.ts new file mode 100644 index 0000000000..b5ed87ad93 --- /dev/null +++ b/packages/plugins/@nocobase/plugin-field-markdown-vditor/src/server/__tests__/vditor-check.test.ts @@ -0,0 +1,282 @@ +/** + * This file is part of the NocoBase (R) project. + * Copyright (c) 2020-2024 NocoBase Co., Ltd. + * Authors: NocoBase Team. + * + * This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License. + * For more information, please refer to: https://www.nocobase.com/agreement. + */ + +import { mockServer } from '@nocobase/test'; +import { afterEach, beforeEach, describe, expect, it } from 'vitest'; + +describe('vditor:check', () => { + let app; + let db; + let agent; + + beforeEach(async () => { + app = mockServer({ + cors: { + origin: '*', + }, + plugins: ['field-sort', 'users', 'auth', 'file-manager', 'field-markdown-vditor'], + }); + + await app.load(); + + db = app.db; + agent = app.agent(); + + // 确保集合已同步 + await db.sync(); + + // 清除数据并准备测试数据 + await db.clean({ drop: true }); + + // 确保集合重新同步 + await db.sync(); + + // 创建测试所需的存储和文件集合 + await db.getRepository('storages').create({ + values: { + name: 'default-storage', + type: 'local', + default: true, + }, + }); + + await db.getRepository('storages').create({ + values: { + name: 's3-storage', + type: 's3-compatible', + default: false, + }, + }); + + await db.getRepository('storages').create({ + values: { + name: 's3-storage-with-baseurl', + type: 's3-compatible', + default: false, + options: { + baseUrl: 'https://example.com', + public: true, + }, + }, + }); + + // 创建测试文件集合 + await db.collection({ + name: 'file-collection-default', + fields: [ + { + type: 'string', + name: 'title', + }, + ], + }); + + await db.collection({ + name: 'file-collection-s3', + fields: [ + { + type: 'string', + name: 'title', + }, + ], + storage: 's3-storage', + }); + + await db.collection({ + name: 'file-collection-s3-with-baseurl', + fields: [ + { + type: 'string', + name: 'title', + }, + ], + storage: 's3-storage-with-baseurl', + }); + + await db.sync(); + }); + + afterEach(async () => { + await app.destroy(); + }); + + it('should return default storage when no fileCollectionName provided', async () => { + const response = await agent.resource('vditor').check(); + + expect(response.status).toBe(200); + expect(response.body.data.isSupportToUploadFiles).toBe(true); + expect(response.body.data.storage).toMatchInlineSnapshot(` + { + "id": 1, + "name": "default-storage", + "rules": {}, + "title": null, + "type": "local", + } + `); + }); + + it('should return default storage when fileCollectionName without storage is provided', async () => { + const response = await agent.resource('vditor').check({ + fileCollectionName: 'file-collection-default', + }); + + expect(response.status).toBe(200); + expect(response.body.data.isSupportToUploadFiles).toBe(true); + expect(response.body.data.storage).toMatchInlineSnapshot(` + { + "id": 1, + "name": "default-storage", + "rules": {}, + "title": null, + "type": "local", + } + `); + }); + + it('should return s3 storage and not support upload when s3 collection without baseUrl is provided', async () => { + const response = await agent.resource('vditor').check({ + fileCollectionName: 'file-collection-s3', + }); + + expect(response.status).toBe(200); + expect(response.body.data.isSupportToUploadFiles).toBe(false); + expect(response.body.data.storage).toMatchInlineSnapshot(` + { + "id": 2, + "name": "s3-storage", + "rules": {}, + "title": null, + "type": "s3-compatible", + } + `); + }); + + it('should return s3 storage and support upload when s3 collection with baseUrl is provided', async () => { + const response = await agent.resource('vditor').check({ + fileCollectionName: 'file-collection-s3-with-baseurl', + }); + + expect(response.status).toBe(200); + expect(response.body.data.isSupportToUploadFiles).toBe(true); + expect(response.body.data.storage).toMatchInlineSnapshot(` + { + "id": 3, + "name": "s3-storage-with-baseurl", + "rules": {}, + "title": null, + "type": "s3-compatible", + } + `); + }); + + it('should handle non-existent fileCollectionName gracefully', async () => { + const response = await agent.resource('vditor').check({ + fileCollectionName: 'non-existent-collection', + }); + + expect(response.status).toBe(200); + expect(response.body.data.isSupportToUploadFiles).toBe(true); + expect(response.body.data.storage).toMatchInlineSnapshot(` + { + "id": 1, + "name": "default-storage", + "rules": {}, + "title": null, + "type": "local", + } + `); + }); + + it('should handle s3 storage with baseUrl but not public attribute', async () => { + // 创建测试所需的非公开 s3 存储 + await db.getRepository('storages').create({ + values: { + name: 's3-storage-with-baseurl-not-public', + type: 's3-compatible', + default: false, + options: { + baseUrl: 'https://example.com', + public: false, + }, + }, + }); + + // 创建关联的文件集合 + await db.collection({ + name: 'file-collection-s3-baseurl-not-public', + fields: [ + { + type: 'string', + name: 'title', + }, + ], + storage: 's3-storage-with-baseurl-not-public', + }); + + await db.sync(); + + const response = await agent.resource('vditor').check({ + fileCollectionName: 'file-collection-s3-baseurl-not-public', + }); + + expect(response.status).toBe(200); + expect(response.body.data.isSupportToUploadFiles).toBe(false); + expect(response.body.data.storage).toMatchInlineSnapshot(` + { + "id": 4, + "name": "s3-storage-with-baseurl-not-public", + "rules": {}, + "title": null, + "type": "s3-compatible", + } + `); + }); + + it('should handle non-s3 storage types correctly', async () => { + // 创建一个非 s3 类型的存储 + await db.getRepository('storages').create({ + values: { + name: 'other-storage-type', + type: 'oss', + default: false, + }, + }); + + // 创建关联的文件集合 + await db.collection({ + name: 'file-collection-oss', + fields: [ + { + type: 'string', + name: 'title', + }, + ], + storage: 'other-storage-type', + }); + + await db.sync(); + + const response = await agent.resource('vditor').check({ + fileCollectionName: 'file-collection-oss', + }); + + expect(response.status).toBe(200); + expect(response.body.data.isSupportToUploadFiles).toBe(true); + expect(response.body.data.storage).toMatchInlineSnapshot(` + { + "id": 4, + "name": "other-storage-type", + "rules": {}, + "title": null, + "type": "oss", + } + `); + }); +}); diff --git a/packages/plugins/@nocobase/plugin-field-markdown-vditor/src/server/plugin.ts b/packages/plugins/@nocobase/plugin-field-markdown-vditor/src/server/plugin.ts index 2338e56f90..53cbba6921 100644 --- a/packages/plugins/@nocobase/plugin-field-markdown-vditor/src/server/plugin.ts +++ b/packages/plugins/@nocobase/plugin-field-markdown-vditor/src/server/plugin.ts @@ -11,6 +11,11 @@ import { Plugin } from '@nocobase/server'; import fs from 'fs-extra'; import path from 'path'; +// @ts-ignore +import pkg from '../../package.json'; + +const namespace = pkg.name; + export class PluginFieldMarkdownVditorServer extends Plugin { async afterAdd() {} @@ -18,6 +23,63 @@ export class PluginFieldMarkdownVditorServer extends Plugin { async load() { await this.copyVditorDist(); + this.setResource(); + this.app.acl.allow('vditor', 'check', 'loggedIn'); + } + + setResource() { + this.app.resourceManager.define({ + name: 'vditor', + actions: { + check: async (context, next) => { + const { fileCollectionName } = context.action.params; + let storage; + + const fileCollection = this.db.getCollection(fileCollectionName || 'attachments'); + const storageName = fileCollection?.options?.storage; + if (storageName) { + storage = await this.db.getRepository('storages').findOne({ + where: { + name: storageName, + }, + }); + } else { + storage = await this.db.getRepository('storages').findOne({ + where: { + default: true, + }, + }); + } + + if (!storage) { + context.throw( + 400, + context.t('Storage configuration not found. Please configure a storage provider first.', { + ns: namespace, + }), + ); + } + + const isSupportToUploadFiles = + storage.type !== 's3-compatible' || (storage.options?.baseUrl && storage.options?.public); + + const storageInfo = { + id: storage.id, + title: storage.title, + name: storage.name, + type: storage.type, + rules: storage.rules, + }; + + context.body = { + isSupportToUploadFiles: !!isSupportToUploadFiles, + storage: storageInfo, + }; + + await next(); + }, + }, + }); } async copyVditorDist() { diff --git a/packages/plugins/@nocobase/plugin-field-sequence/package.json b/packages/plugins/@nocobase/plugin-field-sequence/package.json index cc1ef1fa8c..8e7aa8e8b6 100644 --- a/packages/plugins/@nocobase/plugin-field-sequence/package.json +++ b/packages/plugins/@nocobase/plugin-field-sequence/package.json @@ -4,7 +4,7 @@ "displayName.zh-CN": "数据表字段:自动编码", "description": "Automatically generate codes based on configured rules, supporting combinations of dates, numbers, and text.", "description.zh-CN": "根据配置的规则自动生成编码,支持日期、数字、文本的组合。", - "version": "1.7.0-beta.9", + "version": "1.7.0-alpha.10", "license": "AGPL-3.0", "main": "./dist/server/index.js", "homepage": "https://docs.nocobase.com/handbook/field-sequence", diff --git a/packages/plugins/@nocobase/plugin-field-sequence/src/client/index.tsx b/packages/plugins/@nocobase/plugin-field-sequence/src/client/index.tsx index 0f0f8d0956..b3ad392b81 100644 --- a/packages/plugins/@nocobase/plugin-field-sequence/src/client/index.tsx +++ b/packages/plugins/@nocobase/plugin-field-sequence/src/client/index.tsx @@ -15,6 +15,9 @@ export class PluginFieldSequenceClient extends Plugin { async load() { this.app.use(SequenceFieldProvider); this.app.dataSourceManager.addFieldInterfaces([SequenceFieldInterface]); + const calendarPlugin: any = this.app.pm.get('calendar'); + // 注册标题字段 + calendarPlugin.registerTitleFieldInterface('sequence'); } } diff --git a/packages/plugins/@nocobase/plugin-field-sequence/src/locale/nl-NL.json b/packages/plugins/@nocobase/plugin-field-sequence/src/locale/nl-NL.json index 429067cd26..c90f18cc4e 100644 --- a/packages/plugins/@nocobase/plugin-field-sequence/src/locale/nl-NL.json +++ b/packages/plugins/@nocobase/plugin-field-sequence/src/locale/nl-NL.json @@ -1,5 +1,6 @@ { "Sequence": "Reeks", + "Automatically generate codes based on configured rules, supporting combinations of dates, numbers, and text.": "Automatisch codes genereren op basis van geconfigureerde regels, met ondersteuning voor combinaties van datums, nummers en tekst.", "Sequence rules": "Reeksregels", "Add rule": "Voeg regel toe", "Inputable": "Invoerbaar", @@ -8,6 +9,9 @@ "Autoincrement": "Automatisch verhogen", "Fixed text": "Vaste tekst", "Text content": "Tekstinhoud", + "Date": "Datum", + "Date format": "Datumformaat", + "Supports all formats of the Day.js library, such as \"YYYYMMDD\", \"YYYY-MM-DD\", etc.": "Ondersteunt alle formaten van de Day.js-bibliotheek, zoals \"YYYYMMDD\", \"YYYY-MM-DD\", enz.", "Rule content": "Regelinhoud", "{{value}} Digits": "{{value}} cijfers", "Digits": "Cijfers", @@ -20,5 +24,14 @@ "Monthly": "Maandelijks", "Yearly": "Jaarlijks", "Operations": "Operaties", - "Customize": "Pas aan" + "Customize": "Pas aan", + "Random character": "Willekeurig karakter", + "Length": "Lengte", + "Will generate random characters with specified length.": "Genereert willekeurige tekens met de opgegeven lengte.", + "Character sets": "Karaktersets", + "Select character sets to generate random characters.": "Selecteer karaktersets om willekeurige tekens te genereren.", + "Number": "Nummer", + "Lowercase letters": "Kleine letters", + "Uppercase letters": "Hoofdletters", + "Symbols": "Symbolen" } \ No newline at end of file diff --git a/packages/plugins/@nocobase/plugin-field-sort/package.json b/packages/plugins/@nocobase/plugin-field-sort/package.json index ea01d57c67..f7bcf1cf1f 100644 --- a/packages/plugins/@nocobase/plugin-field-sort/package.json +++ b/packages/plugins/@nocobase/plugin-field-sort/package.json @@ -1,6 +1,6 @@ { "name": "@nocobase/plugin-field-sort", - "version": "1.7.0-beta.9", + "version": "1.7.0-alpha.10", "license": "AGPL-3.0", "displayName": "Collection field: Sort", "displayName.zh-CN": "数据表字段:排序", diff --git a/packages/plugins/@nocobase/plugin-file-manager/package.json b/packages/plugins/@nocobase/plugin-file-manager/package.json index 7bfa8eb887..b8813dbf55 100644 --- a/packages/plugins/@nocobase/plugin-file-manager/package.json +++ b/packages/plugins/@nocobase/plugin-file-manager/package.json @@ -1,6 +1,6 @@ { "name": "@nocobase/plugin-file-manager", - "version": "1.7.0-beta.9", + "version": "1.7.0-alpha.10", "displayName": "File manager", "displayName.zh-CN": "文件管理器", "description": "Provides files storage services with files collection template and attachment field.", diff --git a/packages/plugins/@nocobase/plugin-file-manager/src/client/hooks/useStorageUploadProps.ts b/packages/plugins/@nocobase/plugin-file-manager/src/client/hooks/useStorageUploadProps.ts index 75a1d27071..e7bd924f28 100644 --- a/packages/plugins/@nocobase/plugin-file-manager/src/client/hooks/useStorageUploadProps.ts +++ b/packages/plugins/@nocobase/plugin-file-manager/src/client/hooks/useStorageUploadProps.ts @@ -7,19 +7,8 @@ * For more information, please refer to: https://www.nocobase.com/agreement. */ -import { - Input, - Upload, - useCollection, - useCollectionField, - useCollectionManager, - useCollectionRecordData, - usePlugin, - useRequest, - withDynamicSchemaProps, -} from '@nocobase/client'; -import React, { useEffect } from 'react'; -import { connect, mapProps, mapReadPretty, useField } from '@formily/react'; +import { useCollection, useCollectionField, useCollectionManager, usePlugin, useRequest } from '@nocobase/client'; +import { useEffect } from 'react'; import FileManagerPlugin from '../'; export function useStorage(storage) { diff --git a/packages/plugins/@nocobase/plugin-file-manager/src/client/index.tsx b/packages/plugins/@nocobase/plugin-file-manager/src/client/index.tsx index e7c4025a0b..6a923d0dfa 100644 --- a/packages/plugins/@nocobase/plugin-file-manager/src/client/index.tsx +++ b/packages/plugins/@nocobase/plugin-file-manager/src/client/index.tsx @@ -8,15 +8,16 @@ */ import { Plugin, useCollection } from '@nocobase/client'; +import { STORAGE_TYPE_ALI_OSS, STORAGE_TYPE_LOCAL, STORAGE_TYPE_S3, STORAGE_TYPE_TX_COS } from '../constants'; import { FileManagerProvider } from './FileManagerProvider'; +import { FileSizeField } from './FileSizeField'; import { FileStoragePane } from './FileStorage'; +import { useAttachmentFieldProps, useFileCollectionStorageRules } from './hooks'; +import { useStorageCfg } from './hooks/useStorageUploadProps'; +import { AttachmentFieldInterface } from './interfaces/attachment'; import { NAMESPACE } from './locale'; import { storageTypes } from './schemas/storageTypes'; -import { AttachmentFieldInterface } from './interfaces/attachment'; import { FileCollectionTemplate } from './templates'; -import { useAttachmentFieldProps, useFileCollectionStorageRules } from './hooks'; -import { FileSizeField } from './FileSizeField'; -import { STORAGE_TYPE_ALI_OSS, STORAGE_TYPE_LOCAL, STORAGE_TYPE_S3, STORAGE_TYPE_TX_COS } from '../constants'; export class PluginFileManagerClient extends Plugin { // refer by plugin-field-attachment-url @@ -58,6 +59,7 @@ export class PluginFileManagerClient extends Plugin { this.app.addScopes({ useAttachmentFieldProps, useFileCollectionStorageRules, + useStorageCfg, }); this.app.addComponents({ @@ -72,6 +74,49 @@ export class PluginFileManagerClient extends Plugin { getStorageType(name: string) { return this.storageTypes.get(name); } + + async uploadFile(options?: { + file: File; + fileCollectionName?: string; + storageType?: string; + /** 后面可能会废弃这个参数 */ + storageId?: number; + storageRules?: { + size: number; + }; + }): Promise<{ errorMessage?: string; data?: any }> { + const storageTypeObj = this.getStorageType(options?.storageType); + if (storageTypeObj?.upload) { + // 1. If storageType is provided, call the upload method directly + return await storageTypeObj.upload({ + file: options.file, + apiClient: this.app.apiClient, + storageType: options.storageType, + storageId: options.storageId, + storageRules: options.storageRules, + fileCollectionName: options.fileCollectionName, + }); + } + + // 2. If storageType is not provided, use the default upload method + try { + const formData = new FormData(); + formData.append('file', options.file); + const res = await this.app.apiClient.request({ + url: `${options.fileCollectionName || 'attachments'}:create`, + method: 'post', + data: formData, + }); + + return { + data: res.data?.data, + }; + } catch (error) { + return { + errorMessage: error.message, + }; + } + } } export default PluginFileManagerClient; diff --git a/packages/plugins/@nocobase/plugin-file-manager/src/client/schemas/storage.ts b/packages/plugins/@nocobase/plugin-file-manager/src/client/schemas/storage.ts index bad767884e..16b4526836 100644 --- a/packages/plugins/@nocobase/plugin-file-manager/src/client/schemas/storage.ts +++ b/packages/plugins/@nocobase/plugin-file-manager/src/client/schemas/storage.ts @@ -53,7 +53,7 @@ const collection = { name: 'baseUrl', interface: 'input', uiSchema: { - title: `{{t("Access base URL", { ns: "${NAMESPACE}" })}}`, + title: `{{t("Base URL", { ns: "${NAMESPACE}" })}}`, type: 'string', 'x-component': 'TextAreaWithGlobalScope', required: true, diff --git a/packages/plugins/@nocobase/plugin-file-manager/src/client/schemas/storageTypes/ali-oss.tsx b/packages/plugins/@nocobase/plugin-file-manager/src/client/schemas/storageTypes/ali-oss.tsx index dcd868160f..96383fc282 100644 --- a/packages/plugins/@nocobase/plugin-file-manager/src/client/schemas/storageTypes/ali-oss.tsx +++ b/packages/plugins/@nocobase/plugin-file-manager/src/client/schemas/storageTypes/ali-oss.tsx @@ -7,11 +7,8 @@ * For more information, please refer to: https://www.nocobase.com/agreement. */ -import React from 'react'; - import { NAMESPACE } from '../../locale'; import common from './common'; -import { useTranslation } from 'react-i18next'; export default { title: `{{t("Aliyun OSS", { ns: "${NAMESPACE}" })}}`, diff --git a/packages/plugins/@nocobase/plugin-file-manager/src/client/schemas/storageTypes/tx-cos.tsx b/packages/plugins/@nocobase/plugin-file-manager/src/client/schemas/storageTypes/tx-cos.tsx index b86dc0c499..8c0f1f6ccf 100644 --- a/packages/plugins/@nocobase/plugin-file-manager/src/client/schemas/storageTypes/tx-cos.tsx +++ b/packages/plugins/@nocobase/plugin-file-manager/src/client/schemas/storageTypes/tx-cos.tsx @@ -7,10 +7,8 @@ * For more information, please refer to: https://www.nocobase.com/agreement. */ -import { useTranslation } from 'react-i18next'; import { NAMESPACE } from '../../locale'; import common from './common'; -import React from 'react'; export default { title: `{{t("Tencent COS", { ns: "${NAMESPACE}" })}}`, diff --git a/packages/plugins/@nocobase/plugin-file-manager/src/locale/de-DE.json b/packages/plugins/@nocobase/plugin-file-manager/src/locale/de-DE.json index 42a9c9da42..41d5215a86 100644 --- a/packages/plugins/@nocobase/plugin-file-manager/src/locale/de-DE.json +++ b/packages/plugins/@nocobase/plugin-file-manager/src/locale/de-DE.json @@ -20,7 +20,7 @@ "Storage type": "Speichertyp", "Default storage": "Standardspeicher", "Storage base URL": "Basis-URL des Speichers", - "Access base URL": "Basis-URL für den Zugriff", + "Base URL": "Basis-URL", "Base URL for file access, could be your CDN base URL. For example: \"https://cdn.nocobase.com\".": "Basis-URL für den Dateizugriff, könnte Ihre CDN-Basis-URL sein. Zum Beispiel: \"https://cdn.nocobase.com\".", "Destination": "Ziel", "Use the built-in static file server": "Den integrierten statischen Dateiserver verwenden", diff --git a/packages/plugins/@nocobase/plugin-file-manager/src/locale/it-IT.json b/packages/plugins/@nocobase/plugin-file-manager/src/locale/it-IT.json index 778734b98a..01b1e9bf9b 100644 --- a/packages/plugins/@nocobase/plugin-file-manager/src/locale/it-IT.json +++ b/packages/plugins/@nocobase/plugin-file-manager/src/locale/it-IT.json @@ -30,7 +30,7 @@ "Allow uploading multiple files": "Consenti caricamento di più file", "Storage": "Spazio di archiviazione", "Storages": "Spazi di archiviazione", - "Access base URL": "URL base accesso", + "Base URL": "URL base", "Base URL for file access, could be your CDN base URL. For example: \"https://cdn.nocobase.com\".": "URL base per l'accesso ai file, potrebbe essere l'URL base del tuo CDN. Ad esempio: \"https://cdn.nocobase.com\".", "Relative path the file will be saved to. Left blank as root path. The leading and trailing slashes \"/\" will be ignored. For example: \"user/avatar\".": "Percorso relativo in cui verrà salvato il file. Lasciare vuoto per il percorso radice. Le barre iniziali e finali \"/\" verranno ignorate. Ad esempio: \"user/avatar\".", "Default storage will be used when not selected": "Se non selezionato verrà utilizzato lo spazio di archiviazione predefinito", diff --git a/packages/plugins/@nocobase/plugin-file-manager/src/locale/ja-JP.json b/packages/plugins/@nocobase/plugin-file-manager/src/locale/ja-JP.json index aadd212423..afb39b45b9 100644 --- a/packages/plugins/@nocobase/plugin-file-manager/src/locale/ja-JP.json +++ b/packages/plugins/@nocobase/plugin-file-manager/src/locale/ja-JP.json @@ -32,7 +32,7 @@ "Allow uploading multiple files": "複数ファイルのアップロードを許可する", "Storage": "ストレージ", "Storages": "ストレージ", - "Access base URL": "アクセスURLのベース", + "Base URL": "ベースURL", "Base URL for file access, could be your CDN base URL. For example: \"https://cdn.nocobase.com\".": "术语调整,“基礎URL”改为“ベースURL”", "Relative path the file will be saved to. Left blank as root path. The leading and trailing slashes \"/\" will be ignored. For example: \"user/avatar\".": "更清晰的表达方式,符合技术描述", "Default storage will be used when not selected": "空欄の場合はデフォルトのストレージが使用されます。", diff --git a/packages/plugins/@nocobase/plugin-file-manager/src/locale/nl-NL.json b/packages/plugins/@nocobase/plugin-file-manager/src/locale/nl-NL.json index fdb009d495..7733a5d6d1 100644 --- a/packages/plugins/@nocobase/plugin-file-manager/src/locale/nl-NL.json +++ b/packages/plugins/@nocobase/plugin-file-manager/src/locale/nl-NL.json @@ -1,22 +1,40 @@ { - "File manager": "Bestandsbeheer", + "File collection": "Bestandcollectie", + "File name": "Bestandsnaam", + "Extension name": "Extensienaam", + "Size": "Grootte", + "File size limit": "Bestandsgrootte limiet", + "Minimum from 1 byte, maximum up to 1GB.": "Minimaal vanaf 1 byte, maximaal tot 1 GB.", + "MIME type": "MIME type", + "File type (in MIME type format)": "Bestandstype (in MIME type formaat)", + "Multi-types seperated with comma, for example: \"image/*\", \"image/png\", \"image/*, application/pdf\" etc.": "Meerdere typen gescheiden door een komma, bijvoorbeeld: \"image/*\", \"image/png\", \"image/*, application/pdf\" enz.", + "URL": "URL", + "File storage": "Bestandsopslag", + "File manager": "Bestandsbeheerder", "Attachment": "Bijlage", - "MIME type": "MIME-type", - "Storage display name": "Weergavenaam van opslag", + "Allow uploading multiple files": "Meerdere bestanden uploaden toestaan", + "Storage": "Opslagruimte", + "Storages": "Opslagruimtes", "Storage name": "Opslagnaam", "Storage type": "Opslagtype", - "Default storage": "Standaardopslag", - "Storage base URL": "Opslag basis-URL", - "Destination": "Bestemming", + "Default storage": "Standaard opslagruimte", + "Access base URL": "Toegangsbasis-URL", + "Base URL for file access, could be your CDN base URL. For example: \"https://cdn.nocobase.com\".": "Basis-URL voor bestandstoegang, kan uw CDN-basis-URL zijn. Bijvoorbeeld: \"https://cdn.nocobase.com\".", + "Destination": "Bestemmingsmap", "Use the built-in static file server": "Gebruik de ingebouwde statische bestandsserver", "Local storage": "Lokale opslag", "Aliyun OSS": "Aliyun OSS", - "Tencent COS": "Tencent COS", "Amazon S3": "Amazon S3", + "Tencent COS": "Tencent COS", "Region": "Regio", "Bucket": "Bucket", "Path": "Pad", + "Relative path the file will be saved to. Left blank as root path. The leading and trailing slashes \"/\" will be ignored. For example: \"user/avatar\".": "Relatief pad waar het bestand zal worden opgeslagen. Laat leeg als hoofdmap. De voorloop- en achterloop-slashes \"/\" worden genegeerd. Bijvoorbeeld: \"gebruiker/avatar\".", "Filename": "Bestandsnaam", + "Will be used for API": "Zal worden gebruikt voor API", + "Default storage will be used when not selected": "Standaard opslagruimte wordt gebruikt wanneer niet geselecteerd", + "Keep file in storage when destroy record": "Bestand in opslag houden bij vernietiging van record", "See more": "Bekijk meer", - "Will be used for API": "Wordt gebruikt voor API" -} \ No newline at end of file + "Aliyun OSS region part of the bucket. For example: \"oss-cn-beijing\".": "Aliyun OSS regio-onderdeel van de bucket. Bijvoorbeeld: \"oss-cn-beijing\"." + } + \ No newline at end of file diff --git a/packages/plugins/@nocobase/plugin-file-manager/src/locale/zh-CN.json b/packages/plugins/@nocobase/plugin-file-manager/src/locale/zh-CN.json index d08ac66fb0..7873a4dbca 100644 --- a/packages/plugins/@nocobase/plugin-file-manager/src/locale/zh-CN.json +++ b/packages/plugins/@nocobase/plugin-file-manager/src/locale/zh-CN.json @@ -18,7 +18,7 @@ "Storage name": "存储空间标识", "Storage type": "存储类型", "Default storage": "默认存储空间", - "Access base URL": "访问 URL 基础", + "Base URL": "基础 URL", "Base URL for file access, could be your CDN base URL. For example: \"https://cdn.nocobase.com\".": "文件访问的基础 URL,可以是你的 CDN 基础 URL。例如:\"https://cdn.nocobase.com\"。", "Destination": "上传目标文件夹", "Use the built-in static file server": "使用内置静态文件服务", diff --git a/packages/plugins/@nocobase/plugin-file-manager/src/server/__tests__/utils.test.ts b/packages/plugins/@nocobase/plugin-file-manager/src/server/__tests__/utils.test.ts new file mode 100644 index 0000000000..9264ef780a --- /dev/null +++ b/packages/plugins/@nocobase/plugin-file-manager/src/server/__tests__/utils.test.ts @@ -0,0 +1,50 @@ +/** + * This file is part of the NocoBase (R) project. + * Copyright (c) 2020-2024 NocoBase Co., Ltd. + * Authors: NocoBase Team. + * + * This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License. + * For more information, please refer to: https://www.nocobase.com/agreement. + */ + +import { getApp } from '.'; +import PluginFileManagerServer from '../server'; + +import { STORAGE_TYPE_LOCAL } from '../../constants'; + +import { getFileKey } from '../utils'; + +describe('file manager > utils', () => { + let app; + let agent; + let db; + let plugin: PluginFileManagerServer; + let StorageRepo; + let AttachmentRepo; + let local; + + beforeEach(async () => { + app = await getApp(); + agent = app.agent(); + db = app.db; + plugin = app.pm.get(PluginFileManagerServer) as PluginFileManagerServer; + + AttachmentRepo = db.getCollection('attachments').repository; + StorageRepo = db.getCollection('storages').repository; + local = await StorageRepo.findOne({ + filter: { + type: STORAGE_TYPE_LOCAL, + }, + }); + }); + + afterEach(async () => { + await app.destroy(); + }); + + describe('getFileKey', () => { + it('path as null should works', async () => { + expect(getFileKey({ path: null, filename: 'test.jpg' })).toBe('test.jpg'); + }); + }); +}); diff --git a/packages/plugins/@nocobase/plugin-file-manager/src/server/actions/storages.ts b/packages/plugins/@nocobase/plugin-file-manager/src/server/actions/storages.ts index b1f4c218e3..abcafd5159 100644 --- a/packages/plugins/@nocobase/plugin-file-manager/src/server/actions/storages.ts +++ b/packages/plugins/@nocobase/plugin-file-manager/src/server/actions/storages.ts @@ -30,6 +30,8 @@ export async function getBasicInfo(context, next) { name: result.name, type: result.type, rules: result.rules, + baseUrl: result.options?.baseUrl, + public: result.options?.public, }; next(); diff --git a/packages/plugins/@nocobase/plugin-file-manager/src/server/server.ts b/packages/plugins/@nocobase/plugin-file-manager/src/server/server.ts index aaef4c1e79..d581ba8772 100644 --- a/packages/plugins/@nocobase/plugin-file-manager/src/server/server.ts +++ b/packages/plugins/@nocobase/plugin-file-manager/src/server/server.ts @@ -7,12 +7,12 @@ * For more information, please refer to: https://www.nocobase.com/agreement. */ -import { basename } from 'path'; import fs from 'fs'; +import { basename } from 'path'; -import { Plugin } from '@nocobase/server'; -import { isURL, Registry } from '@nocobase/utils'; import { Collection, Model, Transactionable } from '@nocobase/database'; +import { Plugin } from '@nocobase/server'; +import { Registry } from '@nocobase/utils'; import { STORAGE_TYPE_ALI_OSS, STORAGE_TYPE_LOCAL, STORAGE_TYPE_S3, STORAGE_TYPE_TX_COS } from '../constants'; import initActions from './actions'; import { AttachmentInterface } from './interfaces/attachment-interface'; diff --git a/packages/plugins/@nocobase/plugin-file-manager/src/server/utils.ts b/packages/plugins/@nocobase/plugin-file-manager/src/server/utils.ts index a5d6b1334d..989aa8dd81 100644 --- a/packages/plugins/@nocobase/plugin-file-manager/src/server/utils.ts +++ b/packages/plugins/@nocobase/plugin-file-manager/src/server/utils.ts @@ -28,7 +28,7 @@ export const cloudFilenameGetter = (storage) => (req, file, cb) => { }; export function getFileKey(record) { - return urlJoin(record.path, record.filename).replace(/^\//, ''); + return urlJoin(record.path || '', record.filename).replace(/^\//, ''); } export function ensureUrlEncoded(value) { diff --git a/packages/plugins/@nocobase/plugin-gantt/package.json b/packages/plugins/@nocobase/plugin-gantt/package.json index 73e015f575..4bd4f9054e 100644 --- a/packages/plugins/@nocobase/plugin-gantt/package.json +++ b/packages/plugins/@nocobase/plugin-gantt/package.json @@ -1,6 +1,6 @@ { "name": "@nocobase/plugin-gantt", - "version": "1.7.0-beta.9", + "version": "1.7.0-alpha.10", "displayName": "Block: Gantt", "displayName.zh-CN": "区块:甘特图", "description": "Provides Gantt block.", diff --git a/packages/plugins/@nocobase/plugin-graph-collection-manager/package.json b/packages/plugins/@nocobase/plugin-graph-collection-manager/package.json index 1e831d0f5f..7e5af12047 100644 --- a/packages/plugins/@nocobase/plugin-graph-collection-manager/package.json +++ b/packages/plugins/@nocobase/plugin-graph-collection-manager/package.json @@ -4,7 +4,7 @@ "displayName.zh-CN": "可视化数据表管理", "description": "An ER diagram-like tool. Currently only the Master database is supported.", "description.zh-CN": "类似 ER 图的工具,目前只支持主数据库。", - "version": "1.7.0-beta.9", + "version": "1.7.0-alpha.10", "license": "AGPL-3.0", "main": "./dist/server/index.js", "homepage": "https://docs.nocobase.com/handbook/graph-collection-manager", diff --git a/packages/plugins/@nocobase/plugin-kanban/package.json b/packages/plugins/@nocobase/plugin-kanban/package.json index e786609456..289f5d5b13 100644 --- a/packages/plugins/@nocobase/plugin-kanban/package.json +++ b/packages/plugins/@nocobase/plugin-kanban/package.json @@ -1,6 +1,6 @@ { "name": "@nocobase/plugin-kanban", - "version": "1.7.0-beta.9", + "version": "1.7.0-alpha.10", "main": "dist/server/index.js", "homepage": "https://docs.nocobase.com/handbook/block-kanban", "homepage.zh-CN": "https://docs-cn.nocobase.com/handbook/block-kanban", diff --git a/packages/plugins/@nocobase/plugin-kanban/src/client/Kanban.Card.tsx b/packages/plugins/@nocobase/plugin-kanban/src/client/Kanban.Card.tsx index d554caef17..f534d649cd 100644 --- a/packages/plugins/@nocobase/plugin-kanban/src/client/Kanban.Card.tsx +++ b/packages/plugins/@nocobase/plugin-kanban/src/client/Kanban.Card.tsx @@ -135,20 +135,22 @@ export const KanbanCard: any = () => { return ( <> - - - - - - - - - + + + + + + + + + + + @@ -163,8 +165,12 @@ function getPopupSchemaFromParent(fieldSchema: Schema) { return fieldSchema.parent.properties.cardViewer.properties.drawer; } - const cardSchema = findSchemaByUid(fieldSchema['x-uid'], fieldSchema.root); - return cardSchema.parent.properties.cardViewer.properties.drawer; + try { + const cardSchema = findSchemaByUid(fieldSchema['x-uid'], fieldSchema.root); + return cardSchema.parent.properties.cardViewer.properties.drawer; + } catch (e) { + console.warn(e); + } } function findSchemaByUid(uid: string, rootSchema: Schema, resultRef: { value: Schema } = { value: null }) { diff --git a/packages/plugins/@nocobase/plugin-localization/package.json b/packages/plugins/@nocobase/plugin-localization/package.json index 4c4d6f6bb6..405744fda8 100644 --- a/packages/plugins/@nocobase/plugin-localization/package.json +++ b/packages/plugins/@nocobase/plugin-localization/package.json @@ -1,6 +1,6 @@ { "name": "@nocobase/plugin-localization", - "version": "1.7.0-beta.9", + "version": "1.7.0-alpha.10", "main": "dist/server/index.js", "homepage": "https://docs.nocobase.com/handbook/localization-management", "homepage.zh-CN": "https://docs-cn.nocobase.com/handbook/localization-management", diff --git a/packages/plugins/@nocobase/plugin-logger/package.json b/packages/plugins/@nocobase/plugin-logger/package.json index a2710cdb24..e280aac447 100644 --- a/packages/plugins/@nocobase/plugin-logger/package.json +++ b/packages/plugins/@nocobase/plugin-logger/package.json @@ -4,7 +4,7 @@ "displayName.zh-CN": "日志", "description": "Server-side logs, mainly including API request logs and system runtime logs, and allows to package and download log files.", "description.zh-CN": "服务端日志,主要包括接口请求日志和系统运行日志,并支持打包和下载日志文件。", - "version": "1.7.0-beta.9", + "version": "1.7.0-alpha.10", "license": "AGPL-3.0", "main": "dist/server/index.js", "homepage": "https://docs.nocobase.com/handbook/logger", diff --git a/packages/plugins/@nocobase/plugin-map/package.json b/packages/plugins/@nocobase/plugin-map/package.json index 80b47b9896..e42ea56ede 100644 --- a/packages/plugins/@nocobase/plugin-map/package.json +++ b/packages/plugins/@nocobase/plugin-map/package.json @@ -2,7 +2,7 @@ "name": "@nocobase/plugin-map", "displayName": "Block: Map", "displayName.zh-CN": "区块:地图", - "version": "1.7.0-beta.9", + "version": "1.7.0-alpha.10", "description": "Map block, support Gaode map and Google map, you can also extend more map types.", "description.zh-CN": "地图区块,支持高德地图和 Google 地图,你也可以扩展更多地图类型。", "license": "AGPL-3.0", diff --git a/packages/plugins/@nocobase/plugin-map/src/locale/nl-NL.json b/packages/plugins/@nocobase/plugin-map/src/locale/nl-NL.json index e66a6cf096..ae5488fd1e 100644 --- a/packages/plugins/@nocobase/plugin-map/src/locale/nl-NL.json +++ b/packages/plugins/@nocobase/plugin-map/src/locale/nl-NL.json @@ -1,35 +1,35 @@ { - "Map": "Map", - "Map-based geometry": "Map-based geometry", - "Map type": "Map type", - "Point": "Point", - "Line": "Line", - "Circle": "Circle", - "Polygon": "Polygon", - "Access key": "Access key", - "securityJsCode or serviceHost": "securityJsCode or serviceHost", + "Map": "Kaart", + "Map-based geometry": "Kaartgebaseerde geometrie", + "Map type": "Kaarttype", + "Point": "Punt", + "Line": "Lijn", + "Circle": "Cirkel", + "Polygon": "Veelhoek", + "Access key": "Toegangssleutel", + "securityJsCode or serviceHost": "securityJsCode of serviceHost", "AMap": "AMap", "Google Maps": "Google Maps", "Clear": "Wissen", - "Click to select the starting point and double-click to end the drawing": "Click to select the starting point and double-click to end the drawing", - "Clear the canvas": "Clear the canvas", - "Are you sure to clear the canvas?": "Are you sure to clear the canvas?", - "Confirm": "Confirm", + "Click to select the starting point and double-click to end the drawing": "Klik om het startpunt te selecteren en dubbelklik om het tekenen te beëindigen", + "Clear the canvas": "Wis het canvas", + "Are you sure to clear the canvas?": "Weet je zeker dat je het canvas wilt wissen?", + "Confirm": "Bevestigen", "Cancel": "Annuleren", - "Enter keywords to search": "Enter keywords to search", - "The AccessKey is incorrect, please check it": "The AccessKey is incorrect, please check it", - "Please configure the AMap securityCode or serviceHost correctly": "Please configure the AMap securityCode or serviceHost correctly", - "Map Manager": "Map Manager", - "Configuration": "Configuration", + "Enter keywords to search": "Voer zoekwoorden in om te zoeken", + "The AccessKey is incorrect, please check it": "De AccessKey is onjuist, controleer het", + "Please configure the AMap securityCode or serviceHost correctly": "Configureer de AMap securityCode of serviceHost correct", + "Map Manager": "Kaartbeheerder", + "Configuration": "Configuratie", "Saved successfully": "Succesvol opgeslagen", - "Saved failed": "Saved failed", + "Saved failed": "Opslaan mislukt", "Edit": "Bewerken", "Save": "Opslaan", - "Please configure the AccessKey and SecurityJsCode first": "Please configure the AccessKey and SecurityJsCode first", - "Go to the configuration page": "Go to the configuration page", + "Please configure the AccessKey and SecurityJsCode first": "Configureer eerst de AccessKey en SecurityJsCode", + "Go to the configuration page": "Ga naar de configuratiepagina", "Zoom": "Zoom", - "Set default zoom level": "Set default zoom level", - "The default zoom level of the map": "The default zoom level of the map", + "Set default zoom level": "Stel het standaard zoomniveau in", + "The default zoom level of the map": "Het standaard zoomniveau van de kaart", "Edit field title": "Veldtitel bewerken", "Field title": "Veldtitel", "Edit tooltip": "Tooltip bewerken", @@ -41,11 +41,14 @@ "Readonly": "Alleen-lezen", "Easy-reading": "Gemakkelijk te lezen", "Edit description": "Bewerk beschrijving", - "Map field": "Map field", - "Marker field": "Marker field", - "Load google maps failed, Please check the Api key and refresh the page": "Load google maps failed, Please check the Api key and refresh the page", - "Create map block": "Create map block", - "Start point": "Start point", - "End point": "End point", - "Concatenation order field": "Concatenation order field" + "Map field": "Kaartveld", + "Marker field": "Markerveld", + "Load google maps failed, Please check the Api key and refresh the page": "Google Maps laden mislukt, controleer de Api-sleutel en vernieuw de pagina", + "Create map block": "Kaartblok maken", + "Start point": "Startpunt", + "End point": "Eindpunt", + "Concatenation order field": "Concatenatievolgordeveld", + "securityJsCode or serviceHost is required": "securityJsCode of serviceHost is verplicht", + "Access key is required": "Toegangssleutel is verplicht", + "Api key is required": "Api-sleutel is verplicht" } \ No newline at end of file diff --git a/packages/plugins/@nocobase/plugin-mobile-client/package.json b/packages/plugins/@nocobase/plugin-mobile-client/package.json index b6f11a0c72..7cc94e26d9 100644 --- a/packages/plugins/@nocobase/plugin-mobile-client/package.json +++ b/packages/plugins/@nocobase/plugin-mobile-client/package.json @@ -1,6 +1,6 @@ { "name": "@nocobase/plugin-mobile-client", - "version": "1.7.0-beta.9", + "version": "1.7.0-alpha.10", "main": "./dist/server/index.js", "homepage": "https://docs.nocobase.com/handbook/mobile-client", "homepage.zh-CN": "https://docs-cn.nocobase.com/handbook/mobile-client", diff --git a/packages/plugins/@nocobase/plugin-mobile/package.json b/packages/plugins/@nocobase/plugin-mobile/package.json index eb151c133f..927fd1c3c0 100644 --- a/packages/plugins/@nocobase/plugin-mobile/package.json +++ b/packages/plugins/@nocobase/plugin-mobile/package.json @@ -1,6 +1,6 @@ { "name": "@nocobase/plugin-mobile", - "version": "1.7.0-beta.9", + "version": "1.7.0-alpha.10", "main": "dist/server/index.js", "homepage": "https://docs.nocobase.com/handbook/mobile", "homepage.zh-CN": "https://docs-cn.nocobase.com/handbook/mobile", diff --git a/packages/plugins/@nocobase/plugin-mobile/src/client/MobileComponentsProvider.tsx b/packages/plugins/@nocobase/plugin-mobile/src/client/MobileComponentsProvider.tsx index d1b702cb9f..8e85cfea21 100644 --- a/packages/plugins/@nocobase/plugin-mobile/src/client/MobileComponentsProvider.tsx +++ b/packages/plugins/@nocobase/plugin-mobile/src/client/MobileComponentsProvider.tsx @@ -14,7 +14,7 @@ import { ActionDrawerUsedInMobile, useToAdaptActionDrawerToMobile } from './adap import { useToAdaptFilterActionToMobile } from './adaptor-of-desktop/FilterAction'; import { mobileComponents } from './pages/dynamic-page/MobilePage'; -const GlobalStyle = createGlobalStyle` +const ResetScrollbar = createGlobalStyle` ::-webkit-scrollbar { display: none; } @@ -49,7 +49,7 @@ const MobileAdapter: FC = (props) => { return ( <> - + {props.children} diff --git a/packages/plugins/@nocobase/plugin-mobile/src/client/adaptor-of-desktop/ActionDrawer.tsx b/packages/plugins/@nocobase/plugin-mobile/src/client/adaptor-of-desktop/ActionDrawer.tsx index bed4abaaa8..1dfbc525d5 100644 --- a/packages/plugins/@nocobase/plugin-mobile/src/client/adaptor-of-desktop/ActionDrawer.tsx +++ b/packages/plugins/@nocobase/plugin-mobile/src/client/adaptor-of-desktop/ActionDrawer.tsx @@ -20,55 +20,54 @@ import { import { ConfigProvider } from 'antd'; import { Popup } from 'antd-mobile'; import { CloseOutline } from 'antd-mobile-icons'; -import React, { useCallback, useEffect, useMemo } from 'react'; +import React, { FC, ReactNode, useCallback, useEffect, useMemo } from 'react'; +import { useTranslation } from 'react-i18next'; import { useMobileActionDrawerStyle } from './ActionDrawer.style'; import { usePopupContainer } from './FilterAction'; import { MIN_Z_INDEX_INCREMENT } from './zIndex'; -export const ActionDrawerUsedInMobile: any = observer((props: { footerNodeName?: string }) => { - const fieldSchema = useFieldSchema(); - const field = useField(); - const { visible, setVisible } = useActionContext(); - const { popupContainerRef, visiblePopup } = usePopupContainer(visible); +export interface MobilePopupProps { + title?: string; + visible: boolean; + minHeight?: number | string; + onClose: () => void; + children: ReactNode; +} + +export const MobilePopup: FC = (props) => { + const { + title, + visible, + onClose: closePopup, + children, + minHeight, + } = props; + const { t } = useTranslation(); + const { popupContainerRef } = usePopupContainer(visible); const { componentCls, hashId } = useMobileActionDrawerStyle(); const parentZIndex = useZIndexContext(); const { theme: globalTheme } = useGlobalTheme(); - // this schema need to add padding in the content area of the popup - const isSpecialSchema = isChangePasswordSchema(fieldSchema) || isEditProfileSchema(fieldSchema); - - const footerNodeName = isSpecialSchema ? 'Action.Drawer.Footer' : props.footerNodeName; - - const specialStyle = isSpecialSchema ? { backgroundColor: 'white' } : {}; - const newZIndex = parentZIndex + MIN_Z_INDEX_INCREMENT; const zIndexStyle = useMemo(() => { return { zIndex: newZIndex, + minHeight, }; - }, [newZIndex]); - - const footerSchema = fieldSchema.reduceProperties((buf, s) => { - if (s['x-component'] === footerNodeName) { - return s; - } - return buf; - }); - - const title = field.title || ''; - - const closePopup = useCallback(() => { - setVisible(false); - }, [setVisible]); + }, [newZIndex, minHeight]); const theme = useMemo(() => { return { ...globalTheme, token: { ...globalTheme.token, - marginBlock: 12, zIndexPopupBase: newZIndex, + paddingPageHorizontal: 8, + paddingPageVertical: 8, + marginBlock: 12, + borderRadiusBlock: 8, + fontSize: 14, }, }; }, [globalTheme, newZIndex]); @@ -78,7 +77,7 @@ export const ActionDrawerUsedInMobile: any = observer((props: { footerNodeName?: popupContainerRef.current} @@ -93,43 +92,90 @@ export const ActionDrawerUsedInMobile: any = observer((props: { footerNodeName?: {title} - +
- {isSpecialSchema ? ( -
- { - return s['x-component'] !== footerNodeName; - }} - /> -
- ) : ( - { - return s['x-component'] !== footerNodeName; - }} - /> - )} - {footerSchema ? ( -
- { - return s['x-component'] === footerNodeName; - }} - /> -
- ) : null} + {children} + ) +} + +export const ActionDrawerUsedInMobile: any = observer((props: { footerNodeName?: string }) => { + const fieldSchema = useFieldSchema(); + const field = useField(); + const { visible, setVisible } = useActionContext(); + const { visiblePopup } = usePopupContainer(visible); + + // this schema need to add padding in the content area of the popup + const isSpecialSchema = isChangePasswordSchema(fieldSchema) || isEditProfileSchema(fieldSchema); + + const footerNodeName = isSpecialSchema ? 'Action.Drawer.Footer' : props.footerNodeName; + + const specialStyle = isSpecialSchema ? { backgroundColor: 'white' } : {}; + + const footerSchema = fieldSchema.reduceProperties((buf, s) => { + if (s['x-component'] === footerNodeName) { + return s; + } + return buf; + }); + + const title = field.title || ''; + + const closePopup = useCallback(() => { + setVisible(false); + }, [setVisible]); + + const popupContent = isSpecialSchema ? ( +
+ { + return s['x-component'] !== footerNodeName; + }} + /> +
+ ) : ( + { + return s['x-component'] !== footerNodeName; + }} + /> + ); + + const footerContent = footerSchema ? ( +
+ { + return s['x-component'] === footerNodeName; + }} + /> +
+ ) : null; + + return ( + + {popupContent} + {footerContent} + ); }); diff --git a/packages/plugins/@nocobase/plugin-mobile/src/client/index.tsx b/packages/plugins/@nocobase/plugin-mobile/src/client/index.tsx index 6016313b48..0fea40523d 100644 --- a/packages/plugins/@nocobase/plugin-mobile/src/client/index.tsx +++ b/packages/plugins/@nocobase/plugin-mobile/src/client/index.tsx @@ -55,6 +55,7 @@ import { MobileSettingsBlockSchemaSettings } from './mobile-blocks/settings-bloc import pkg from './../../package.json'; import { MobileComponentsProvider } from './MobileComponentsProvider'; +export { MobilePopup } from './adaptor-of-desktop/ActionDrawer'; export * from './desktop-mode'; export * from './mobile'; export * from './mobile-layout'; diff --git a/packages/plugins/@nocobase/plugin-mobile/src/client/pages/dynamic-page/content/MobilePageContentContainer.tsx b/packages/plugins/@nocobase/plugin-mobile/src/client/pages/dynamic-page/content/MobilePageContentContainer.tsx index 1285cf538a..7a35c8b085 100644 --- a/packages/plugins/@nocobase/plugin-mobile/src/client/pages/dynamic-page/content/MobilePageContentContainer.tsx +++ b/packages/plugins/@nocobase/plugin-mobile/src/client/pages/dynamic-page/content/MobilePageContentContainer.tsx @@ -12,7 +12,7 @@ import _ from 'lodash'; import React, { FC, useEffect } from 'react'; import { PageBackgroundColor } from '../../../constants'; -export const MobilePageContentContainer: FC<{ hideTabBar?: boolean }> = ({ children, hideTabBar }) => { +export const MobilePageContentContainer: FC<{ hideTabBar?: boolean; displayPageHeader?: boolean }> = ({ children, hideTabBar, displayPageHeader = true }) => { const [mobileTabBarHeight, setMobileTabBarHeight] = React.useState(0); const [mobilePageHeader, setMobilePageHeader] = React.useState(0); const { token } = useToken(); @@ -29,7 +29,7 @@ export const MobilePageContentContainer: FC<{ hideTabBar?: boolean }> = ({ child }); return ( <> - {mobilePageHeader ?
: null} + {(mobilePageHeader && displayPageHeader) ?
: null}
{ - const { title } = useMobileTitle(); + const { title } = useMobileTitle() || {}; const { displayNavigationBar = true, displayPageTitle = true } = useMobilePage(); const fieldSchema = useFieldSchema(); const { componentCls, hashId } = useStyles(); diff --git a/packages/plugins/@nocobase/plugin-mobile/src/client/pages/dynamic-page/header/styles.ts b/packages/plugins/@nocobase/plugin-mobile/src/client/pages/dynamic-page/header/styles.ts index 548eb9ebaa..9536c49d93 100644 --- a/packages/plugins/@nocobase/plugin-mobile/src/client/pages/dynamic-page/header/styles.ts +++ b/packages/plugins/@nocobase/plugin-mobile/src/client/pages/dynamic-page/header/styles.ts @@ -9,7 +9,6 @@ export const mobilePageHeaderStyle: any = { position: 'absolute', - top: 0, left: 0, right: 0, borderBottom: '1px solid var(--adm-color-border)', diff --git a/packages/plugins/@nocobase/plugin-mobile/src/locale/nl-NL.json b/packages/plugins/@nocobase/plugin-mobile/src/locale/nl-NL.json index fb6e0daff3..b83a8d4aa2 100644 --- a/packages/plugins/@nocobase/plugin-mobile/src/locale/nl-NL.json +++ b/packages/plugins/@nocobase/plugin-mobile/src/locale/nl-NL.json @@ -1,29 +1,35 @@ { - "App settings": "App settings", - "Page settings": "Page settings", + "App settings": "App instellingen", + "Page settings": "Pagina instellingen", "Info": "Info", - "Back": "Back", + "Back": "Terug", "Link": "Link", - "Remove": "Remove", + "Remove": "Verwijderen", "Add page": "Pagina toevoegen", "Title": "Titel", "Icon": "Icoon", - "Selected icon": "Selected icon", + "Selected icon": "Geselecteerd icoon", "Add link": "Link toevoegen", - "Display tab bar": "Display tab bar", - "Display page header": "Display page header", - "Display navigation bar": "Display navigation bar", - "Display page title": "Display page title", - "Display tabs": "Display tabs", + "Display tab bar": "Tabbladbalk weergeven", + "Display page header": "Paginakoptekst weergeven", + "Display navigation bar": "Navigatiebalk weergeven", + "Display page title": "Paginatitel weergeven", + "Display tabs": "Tabbladen weergeven", "Add tab": "Voeg tabblad toe", - "Mobile": "Mobile", - "Title field is required": "Title field is required", - "Icon field is required": "Icon field is required", - "Desktop data blocks": "Desktop data blocks", - "Other desktop blocks": "Other desktop blocks", + "Mobile": "Mobiel", + "Title field is required": "Titelveld is verplicht", + "Icon field is required": "Icoonveld is verplicht", + "Desktop data blocks": "Desktop data blokken", + "Other desktop blocks": "Andere desktop blokken", "Settings": "Instellingen", - "Mobile menu": "Mobile menu", - "No accessible pages found": "No accessible pages found", - "This might be due to permission configuration issues": "This might be due to permission configuration issues", - "Select time": "Select time" + "Mobile menu": "Mobiel menu", + "No accessible pages found": "Geen toegankelijke pagina's gevonden", + "This might be due to permission configuration issues": "Dit kan te wijten zijn aan machtigingsconfiguratieproblemen", + "Select time": "Selecteer tijd", + "Fill": "Vullen", + "Mobile routes": "Mobiele routes", + "Clear": "Wissen", + "Confirm": "Bevestigen", + "Cancel": "Annuleren", + "Display < back button": "Weergave < terug knop" } \ No newline at end of file diff --git a/packages/plugins/@nocobase/plugin-mock-collections/package.json b/packages/plugins/@nocobase/plugin-mock-collections/package.json index 9918d91a92..599dab8ed7 100644 --- a/packages/plugins/@nocobase/plugin-mock-collections/package.json +++ b/packages/plugins/@nocobase/plugin-mock-collections/package.json @@ -2,7 +2,7 @@ "name": "@nocobase/plugin-mock-collections", "displayName": "mock-collections", "description": "mock-collections", - "version": "1.7.0-beta.9", + "version": "1.7.0-alpha.10", "main": "./dist/server/index.js", "license": "AGPL-3.0", "peerDependencies": { diff --git a/packages/plugins/@nocobase/plugin-multi-app-manager/package.json b/packages/plugins/@nocobase/plugin-multi-app-manager/package.json index c8e9c56eb8..95acdb23d1 100644 --- a/packages/plugins/@nocobase/plugin-multi-app-manager/package.json +++ b/packages/plugins/@nocobase/plugin-multi-app-manager/package.json @@ -4,7 +4,7 @@ "displayName.zh-CN": "多应用管理器", "description": "Dynamically create multiple apps without separate deployments.", "description.zh-CN": "无需单独部署即可动态创建多个应用。", - "version": "1.7.0-beta.9", + "version": "1.7.0-alpha.10", "license": "AGPL-3.0", "main": "./dist/server/index.js", "homepage": "https://docs.nocobase.com/handbook/multi-app-manager", diff --git a/packages/plugins/@nocobase/plugin-multi-app-share-collection/package.json b/packages/plugins/@nocobase/plugin-multi-app-share-collection/package.json index 90f030c47e..596128a6cc 100644 --- a/packages/plugins/@nocobase/plugin-multi-app-share-collection/package.json +++ b/packages/plugins/@nocobase/plugin-multi-app-share-collection/package.json @@ -4,7 +4,7 @@ "displayName.zh-CN": "多应用数据表共享", "description": "", "description.zh-CN": "", - "version": "1.7.0-beta.9", + "version": "1.7.0-alpha.10", "main": "./dist/server/index.js", "devDependencies": { "@formily/react": "2.x", diff --git a/packages/plugins/@nocobase/plugin-notification-email/package.json b/packages/plugins/@nocobase/plugin-notification-email/package.json index 5e6ca8f425..867fe8a98b 100644 --- a/packages/plugins/@nocobase/plugin-notification-email/package.json +++ b/packages/plugins/@nocobase/plugin-notification-email/package.json @@ -1,6 +1,6 @@ { "name": "@nocobase/plugin-notification-email", - "version": "1.7.0-beta.9", + "version": "1.7.0-alpha.10", "displayName": "Notification: Email", "displayName.zh-CN": "通知:电子邮件", "description": "Used for sending email notifications with built-in SMTP transport.", diff --git a/packages/plugins/@nocobase/plugin-notification-in-app-message/package.json b/packages/plugins/@nocobase/plugin-notification-in-app-message/package.json index 71bd3e924a..e92083b5cb 100644 --- a/packages/plugins/@nocobase/plugin-notification-in-app-message/package.json +++ b/packages/plugins/@nocobase/plugin-notification-in-app-message/package.json @@ -1,6 +1,6 @@ { "name": "@nocobase/plugin-notification-in-app-message", - "version": "1.7.0-beta.9", + "version": "1.7.0-alpha.10", "displayName": "Notification: In-app message", "displayName.zh-CN": "通知:站内信", "description": "It supports users in receiving real-time message notifications within the NocoBase application.", diff --git a/packages/plugins/@nocobase/plugin-notification-in-app-message/src/client/components/Inbox.tsx b/packages/plugins/@nocobase/plugin-notification-in-app-message/src/client/components/Inbox.tsx index 1a04a6ac76..0269a22427 100644 --- a/packages/plugins/@nocobase/plugin-notification-in-app-message/src/client/components/Inbox.tsx +++ b/packages/plugins/@nocobase/plugin-notification-in-app-message/src/client/components/Inbox.tsx @@ -16,27 +16,23 @@ * For more information, please rwefer to: https://www.nocobase.com/agreement. */ -import React, { useEffect, useCallback } from 'react'; import { reaction } from '@formily/reactive'; -import { Badge, Button, ConfigProvider, Drawer, Tooltip, notification, theme } from 'antd'; -import { CloseOutlined } from '@ant-design/icons'; -import { createStyles } from 'antd-style'; -import { Icon } from '@nocobase/client'; -import { InboxContent } from './InboxContent'; -import { useLocalTranslation } from '../../locale'; -import { fetchChannels } from '../observables'; import { observer } from '@formily/reactive-react'; -import { useCurrentUserContext } from '@nocobase/client'; +import { Icon, useCurrentUserContext, useMobileLayout } from '@nocobase/client'; +import { MobilePopup } from '@nocobase/plugin-mobile/client'; +import { Badge, Button, ConfigProvider, Drawer, notification, theme, Tooltip } from 'antd'; +import { createStyles } from 'antd-style'; +import React, { FC, useCallback, useEffect, useState } from 'react'; +import { useLocalTranslation } from '../../locale'; +import { Channel } from '../../types'; import { - updateUnreadMsgsCount, - unreadMsgsCountObs, - startMsgSSEStreamWithRetry, - inboxVisible, - userIdObs, - liveSSEObs, + fetchChannels, inboxVisible, liveSSEObs, messageMapObs, - selectedChannelNameObs, + selectedChannelNameObs, startMsgSSEStreamWithRetry, unreadMsgsCountObs, updateUnreadMsgsCount, userIdObs } from '../observables'; +import { InboxContent } from './InboxContent'; +import { MobileChannelPage } from './mobile/ChannelPage'; +import { MobileMessagePage } from './mobile/MessagePage'; const useStyles = createStyles(({ token }) => { return { button: { @@ -46,6 +42,42 @@ const useStyles = createStyles(({ token }) => { }; }); +const InboxPopup: FC<{ title: string; visible: boolean; onClose: () => void }> = (props) => { + const { token } = theme.useToken(); + const { isMobileLayout } = useMobileLayout(); + const [selectedChannel, setSelectedChannel] = useState(null); + + if (isMobileLayout) { + return ( + <> + + + + setSelectedChannel(null)} minHeight={'60vh'}> + + + + ) + } + + return ( + {props.title}
} + open={props.visible} + width={900} + onClose={props.onClose} + styles={{ + header: { + paddingLeft: token.paddingMD, + }, + }} + > + + + ) +} + + const InnerInbox = (props) => { const { t } = useLocalTranslation(); const { styles } = useStyles(); @@ -89,7 +121,6 @@ const InnerInbox = (props) => { document.removeEventListener('visibilitychange', onVisibilityChange); }; }, []); - const DrawerTitle =
{t('Message')}
; useEffect(() => { const dispose = reaction( () => liveSSEObs.value, @@ -138,21 +169,7 @@ const InnerInbox = (props) => { - { - inboxVisible.value = false; - }} - styles={{ - header: { - paddingLeft: token.paddingMD, - }, - }} - > - - + { inboxVisible.value = false; }} /> ); }; diff --git a/packages/plugins/@nocobase/plugin-notification-in-app-message/src/client/components/mobile/ChannelList.tsx b/packages/plugins/@nocobase/plugin-notification-in-app-message/src/client/components/mobile/ChannelList.tsx index 7acaa97665..b55441c018 100644 --- a/packages/plugins/@nocobase/plugin-notification-in-app-message/src/client/components/mobile/ChannelList.tsx +++ b/packages/plugins/@nocobase/plugin-notification-in-app-message/src/client/components/mobile/ChannelList.tsx @@ -7,18 +7,18 @@ * For more information, please refer to: https://www.nocobase.com/agreement. */ -import React, { useRef, useEffect, useState } from 'react'; -import { observer } from '@formily/reactive-react'; -import { reaction } from '@formily/reactive'; -import { List, Badge, InfiniteScroll, ListRef } from 'antd-mobile'; -import { useNavigate } from 'react-router-dom'; -import { dayjs } from '@nocobase/utils/client'; -import InfiniteScrollContent from './InfiniteScrollContent'; -import { channelListObs, channelStatusFilterObs, showChannelLoadingMoreObs, fetchChannels } from '../../observables'; import { Schema } from '@formily/react'; +import { reaction } from '@formily/reactive'; +import { observer } from '@formily/reactive-react'; import { useApp } from '@nocobase/client'; +import { dayjs } from '@nocobase/utils/client'; +import { Badge, InfiniteScroll, List, ListRef } from 'antd-mobile'; +import React, { useEffect, useRef, useState } from 'react'; +import { useNavigate } from 'react-router-dom'; +import { channelListObs, channelStatusFilterObs, fetchChannels, showChannelLoadingMoreObs } from '../../observables'; +import InfiniteScrollContent from './InfiniteScrollContent'; -const InternalChannelList = () => { +const InternalChannelList = (props: { onClickItem?: (item: any) => void }) => { const app = useApp(); const navigate = useNavigate(); const channels = channelListObs.value; @@ -66,7 +66,11 @@ const InternalChannelList = () => { { - navigate(`/page/in-app-message/messages?channel=${item.name}`); + if (props.onClickItem) { + props.onClickItem(item); + } else { + navigate(`/page/in-app-message/messages?channel=${item.name}`); + } }} description={
diff --git a/packages/plugins/@nocobase/plugin-notification-in-app-message/src/client/components/mobile/ChannelPage.tsx b/packages/plugins/@nocobase/plugin-notification-in-app-message/src/client/components/mobile/ChannelPage.tsx index e258b71520..4a34bc9d7b 100644 --- a/packages/plugins/@nocobase/plugin-notification-in-app-message/src/client/components/mobile/ChannelPage.tsx +++ b/packages/plugins/@nocobase/plugin-notification-in-app-message/src/client/components/mobile/ChannelPage.tsx @@ -7,20 +7,20 @@ * For more information, please refer to: https://www.nocobase.com/agreement. */ -import React, { useEffect, useCallback } from 'react'; -import { Tabs } from 'antd-mobile'; import { observer } from '@formily/reactive-react'; -import { useCurrentUserContext, css } from '@nocobase/client'; +import { css, useCurrentUserContext } from '@nocobase/client'; import { + MobilePageContentContainer, MobilePageHeader, MobilePageNavigationBar, MobilePageProvider, - MobilePageContentContainer, } from '@nocobase/plugin-mobile/client'; -import { userIdObs, fetchChannels, ChannelStatus, channelStatusFilterObs } from '../../observables'; -import { ChannelList } from './ChannelList'; +import { Tabs } from 'antd-mobile'; +import React, { useEffect } from 'react'; import { useLocalTranslation } from '../../../locale'; -const MobileMessageBoxInner = () => { +import { ChannelStatus, channelStatusFilterObs, fetchChannels, userIdObs } from '../../observables'; +import { ChannelList } from './ChannelList'; +const MobileMessageBoxInner = (props: { displayNavigationBar?: boolean; onClickItem?: (item: any) => void; }) => { const { t } = useLocalTranslation(); const ctx = useCurrentUserContext(); const currUserId = ctx.data?.data?.id; @@ -31,7 +31,7 @@ const MobileMessageBoxInner = () => { fetchChannels({}); }, []); return ( - + { - + ); diff --git a/packages/plugins/@nocobase/plugin-notification-in-app-message/src/client/components/mobile/MessagePage.tsx b/packages/plugins/@nocobase/plugin-notification-in-app-message/src/client/components/mobile/MessagePage.tsx index d0befaa9d1..9ef319165f 100644 --- a/packages/plugins/@nocobase/plugin-notification-in-app-message/src/client/components/mobile/MessagePage.tsx +++ b/packages/plugins/@nocobase/plugin-notification-in-app-message/src/client/components/mobile/MessagePage.tsx @@ -7,35 +7,34 @@ * For more information, please refer to: https://www.nocobase.com/agreement. */ -import React, { useEffect, useCallback, useState } from 'react'; -import { useNavigate } from 'react-router-dom'; -import { List, Badge, InfiniteScroll, NavBar, DotLoading } from 'antd-mobile'; import { observer } from '@formily/reactive-react'; -import { useCurrentUserContext, css, useApp } from '@nocobase/client'; -import { useSearchParams } from 'react-router-dom'; +import { css, useApp, useCurrentUserContext } from '@nocobase/client'; import { dayjs } from '@nocobase/utils/client'; +import { Badge, InfiniteScroll, List, NavBar } from 'antd-mobile'; +import React, { useCallback, useEffect, useState } from 'react'; +import { useNavigate, useSearchParams } from 'react-router-dom'; +import { Schema } from '@formily/react'; import { - MobilePageHeader, - MobilePageProvider, MobilePageContentContainer, - useMobileTitle, + MobilePageHeader, + MobilePageProvider } from '@nocobase/plugin-mobile/client'; +import { useLocalTranslation } from '../../../locale'; import { - userIdObs, + fetchChannels, + fetchMessages, + inboxVisible, selectedChannelNameObs, selectedChannelObs, selectedMessageListObs, - fetchChannels, - updateMessage, - fetchMessages, showMsgLoadingMoreObs, + updateMessage, + userIdObs, } from '../../observables'; -import { useLocalTranslation } from '../../../locale'; import InfiniteScrollContent from './InfiniteScrollContent'; -import { Schema } from '@formily/react'; -const MobileMessagePageInner = () => { +const MobileMessagePageInner = (props: { displayPageHeader?: boolean }) => { const app = useApp(); const { t } = useLocalTranslation(); const navigate = useNavigate(); @@ -58,11 +57,13 @@ const MobileMessagePageInner = () => { }, [currUserId]); const messages = selectedMessageListObs.value; const viewMessageDetail = (message) => { - const url = message.options?.mobileUrl; + const url = message.options?.mobileUrl || message.options?.url; if (url) { if (url.startsWith('/m/')) navigate(url.substring(2)); - else if (url.startsWith('/')) navigate(url); - else { + else if (url.startsWith('/')) { + navigate(url); + inboxVisible.value = false; + } else { window.location.href = url; } } @@ -101,13 +102,13 @@ const MobileMessagePageInner = () => { const title = Schema.compile(selectedChannelObs.value?.title, { t: app.i18n.t }) || t('Message'); return ( - + navigate('/page/in-app-message')}> {title} - +
{ // 3、预期结果:触发次数为1 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); // 4、后置处理:删除工作流 @@ -223,7 +223,7 @@ test.describe('Configuration page to configure the Trigger node', () => { // 3、预期结果:触发次数为1 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); // 4、后置处理:删除工作流 diff --git a/packages/plugins/@nocobase/plugin-workflow-action-trigger/src/client/__e2e__/configuration3.test.ts b/packages/plugins/@nocobase/plugin-workflow-action-trigger/src/client/__e2e__/configuration3.test.ts index 7fc523ce49..a8f50825ea 100644 --- a/packages/plugins/@nocobase/plugin-workflow-action-trigger/src/client/__e2e__/configuration3.test.ts +++ b/packages/plugins/@nocobase/plugin-workflow-action-trigger/src/client/__e2e__/configuration3.test.ts @@ -71,7 +71,7 @@ test.describe('Configuration page disable enable', () => { // 3、预期结果:触发次数为1 let getWorkflow = await apiGetWorkflow(workflowId); let getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - let getWorkflowExecuted = getWorkflowObj.executed; + let getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(0); await page.goto(`admin/workflow/workflows/${workflowId}`); @@ -85,7 +85,7 @@ test.describe('Configuration page disable enable', () => { getWorkflow = await apiGetWorkflow(workflowId); getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - getWorkflowExecuted = getWorkflowObj.executed; + getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); // 4、后置处理:删除工作流 @@ -142,7 +142,7 @@ test.describe('Configuration page disable enable', () => { // 3、预期结果:触发次数为1 let getWorkflow = await apiGetWorkflow(workflowId); let getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - let getWorkflowExecuted = getWorkflowObj.executed; + let getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); await page.goto(`admin/workflow/workflows/${workflowId}`); @@ -156,7 +156,7 @@ test.describe('Configuration page disable enable', () => { getWorkflow = await apiGetWorkflow(workflowId); getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - getWorkflowExecuted = getWorkflowObj.executed; + getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); // 4、后置处理:删除工作流 diff --git a/packages/plugins/@nocobase/plugin-workflow-action-trigger/src/server/ActionTrigger.ts b/packages/plugins/@nocobase/plugin-workflow-action-trigger/src/server/ActionTrigger.ts index df577cf496..3c970d84f5 100644 --- a/packages/plugins/@nocobase/plugin-workflow-action-trigger/src/server/ActionTrigger.ts +++ b/packages/plugins/@nocobase/plugin-workflow-action-trigger/src/server/ActionTrigger.ts @@ -174,7 +174,7 @@ export default class extends Trigger { }); } } - event.push({ data: toJSON(payload), ...userInfo }); + (workflow.sync ? syncGroup : asyncGroup).push([workflow, { data: toJSON(payload), ...userInfo }]); } } else { const { filterTargetKey, repository } = (context.app).dataSourceManager.dataSources @@ -188,9 +188,8 @@ export default class extends Trigger { appends, }); } - event.push({ data, ...userInfo }); + (workflow.sync ? syncGroup : asyncGroup).push([workflow, { data, ...userInfo }]); } - (workflow.sync ? syncGroup : asyncGroup).push(event); } for (const event of syncGroup) { diff --git a/packages/plugins/@nocobase/plugin-workflow-action-trigger/src/server/__tests__/trigger.test.ts b/packages/plugins/@nocobase/plugin-workflow-action-trigger/src/server/__tests__/trigger.test.ts index 8654bf9b4c..d29d71facf 100644 --- a/packages/plugins/@nocobase/plugin-workflow-action-trigger/src/server/__tests__/trigger.test.ts +++ b/packages/plugins/@nocobase/plugin-workflow-action-trigger/src/server/__tests__/trigger.test.ts @@ -260,6 +260,40 @@ describe('workflow > action-trigger', () => { expect(e2.context.data).toHaveProperty('title', 't2'); expect(e2.context.data).toHaveProperty('createdBy'); }); + + it('bulk update', async () => { + const workflow = await WorkflowModel.create({ + enabled: true, + type: 'action', + config: { + collection: 'posts', + }, + }); + + const p1 = await PostRepo.create({ + values: { title: 't1' }, + }); + const p2 = await PostRepo.create({ + values: { title: 't2' }, + }); + + const res1 = await userAgents[0].resource('posts').update({ + filter: { + id: [p1.id, p2.id], + }, + values: { title: 't3' }, + triggerWorkflows: `${workflow.key}`, + }); + + await sleep(500); + + const e1s = await workflow.getExecutions(); + expect(e1s.length).toBe(2); + expect(e1s[0].status).toBe(EXECUTION_STATUS.RESOLVED); + expect(e1s[0].context.data).toHaveProperty('title', 't3'); + expect(e1s[1].status).toBe(EXECUTION_STATUS.RESOLVED); + expect(e1s[1].context.data).toHaveProperty('title', 't3'); + }); }); describe.skip('destroy', () => { diff --git a/packages/plugins/@nocobase/plugin-workflow-aggregate/package.json b/packages/plugins/@nocobase/plugin-workflow-aggregate/package.json index 2d2e90370e..e05e37f228 100644 --- a/packages/plugins/@nocobase/plugin-workflow-aggregate/package.json +++ b/packages/plugins/@nocobase/plugin-workflow-aggregate/package.json @@ -4,7 +4,7 @@ "displayName.zh-CN": "工作流:聚合查询节点", "description": "Used to aggregate data against the database in workflow, such as: statistics, sum, average, etc.", "description.zh-CN": "可用于在工作流中对数据库进行聚合查询,如:统计数量、求和、平均值等。", - "version": "1.7.0-beta.9", + "version": "1.7.0-alpha.10", "license": "AGPL-3.0", "main": "./dist/server/index.js", "homepage": "https://docs.nocobase.com/handbook/workflow-aggregate", diff --git a/packages/plugins/@nocobase/plugin-workflow-aggregate/src/client/__e2e__/DataOfCollection.test.ts b/packages/plugins/@nocobase/plugin-workflow-aggregate/src/client/__e2e__/DataOfCollection.test.ts index f3fbfecae2..0c75c2252b 100644 --- a/packages/plugins/@nocobase/plugin-workflow-aggregate/src/client/__e2e__/DataOfCollection.test.ts +++ b/packages/plugins/@nocobase/plugin-workflow-aggregate/src/client/__e2e__/DataOfCollection.test.ts @@ -114,7 +114,7 @@ test.describe('filter', () => { // 3、预期结果:工作流成功触发,数据查询成功 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); @@ -221,7 +221,7 @@ test.describe('filter', () => { // 3、预期结果:工作流成功触发,数据查询成功 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); @@ -332,7 +332,7 @@ test.describe('filter', () => { // 3、预期结果:工作流成功触发,数据查询成功 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); @@ -448,7 +448,7 @@ test.describe('filter', () => { // 3、预期结果:工作流成功触发,数据查询成功 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); @@ -560,7 +560,7 @@ test.describe('filter', () => { // 3、预期结果:工作流成功触发,数据查询成功 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); @@ -672,7 +672,7 @@ test.describe('filter', () => { // 3、预期结果:工作流成功触发,数据查询成功 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); @@ -780,7 +780,7 @@ test.describe('filter', () => { // 3、预期结果:工作流成功触发,数据查询成功 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); @@ -896,7 +896,7 @@ test.describe('filter', () => { // 3、预期结果:工作流成功触发,数据查询成功 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); @@ -1021,7 +1021,7 @@ test.describe('filter', () => { // 3、预期结果:工作流成功触发,数据查询成功 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); @@ -1134,7 +1134,7 @@ test.describe('filter', () => { // 3、预期结果:工作流成功触发,数据查询成功 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); diff --git a/packages/plugins/@nocobase/plugin-workflow-aggregate/src/client/__e2e__/DataOfCollection1.test.ts b/packages/plugins/@nocobase/plugin-workflow-aggregate/src/client/__e2e__/DataOfCollection1.test.ts index 4be1ac692c..b20f66be4f 100644 --- a/packages/plugins/@nocobase/plugin-workflow-aggregate/src/client/__e2e__/DataOfCollection1.test.ts +++ b/packages/plugins/@nocobase/plugin-workflow-aggregate/src/client/__e2e__/DataOfCollection1.test.ts @@ -107,7 +107,7 @@ test.describe('no filter', () => { // 3、预期结果:工作流成功触发,数据查询成功 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); @@ -207,7 +207,7 @@ test.describe('no filter', () => { // 3、预期结果:工作流成功触发,数据查询成功 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); @@ -310,7 +310,7 @@ test.describe('no filter', () => { // 3、预期结果:工作流成功触发,数据查询成功 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); @@ -415,7 +415,7 @@ test.describe('no filter', () => { // 3、预期结果:工作流成功触发,数据查询成功 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); @@ -519,7 +519,7 @@ test.describe('no filter', () => { // 3、预期结果:工作流成功触发,数据查询成功 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); @@ -623,7 +623,7 @@ test.describe('no filter', () => { // 3、预期结果:工作流成功触发,数据查询成功 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); @@ -724,7 +724,7 @@ test.describe('no filter', () => { // 3、预期结果:工作流成功触发,数据查询成功 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); @@ -830,7 +830,7 @@ test.describe('no filter', () => { // 3、预期结果:工作流成功触发,数据查询成功 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); @@ -938,7 +938,7 @@ test.describe('no filter', () => { // 3、预期结果:工作流成功触发,数据查询成功 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); @@ -1043,7 +1043,7 @@ test.describe('no filter', () => { // 3、预期结果:工作流成功触发,数据查询成功 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); diff --git a/packages/plugins/@nocobase/plugin-workflow-delay/package.json b/packages/plugins/@nocobase/plugin-workflow-delay/package.json index 1e31b8d49a..6254c65066 100644 --- a/packages/plugins/@nocobase/plugin-workflow-delay/package.json +++ b/packages/plugins/@nocobase/plugin-workflow-delay/package.json @@ -4,7 +4,7 @@ "displayName.zh-CN": "工作流:延时节点", "description": "Could be used in workflow parallel branch for waiting other branches.", "description.zh-CN": "可用于工作流并行分支中等待其他分支执行完成。", - "version": "1.7.0-beta.9", + "version": "1.7.0-alpha.10", "license": "AGPL-3.0", "main": "./dist/server/index.js", "homepage": "https://docs.nocobase.com/handbook/workflow-delay", diff --git a/packages/plugins/@nocobase/plugin-workflow-dynamic-calculation/package.json b/packages/plugins/@nocobase/plugin-workflow-dynamic-calculation/package.json index 1f2521e12e..50224e46b4 100644 --- a/packages/plugins/@nocobase/plugin-workflow-dynamic-calculation/package.json +++ b/packages/plugins/@nocobase/plugin-workflow-dynamic-calculation/package.json @@ -4,7 +4,7 @@ "displayName.zh-CN": "工作流:动态表达式计算节点", "description": "Useful plugin for doing dynamic calculation based on expression collection records in workflow.", "description.zh-CN": "用于在工作流中进行基于数据行的动态表达式计算。", - "version": "1.7.0-beta.9", + "version": "1.7.0-alpha.10", "license": "AGPL-3.0", "main": "./dist/server/index.js", "homepage": "https://docs.nocobase.com/handbook/workflow-dynamic-calculation", diff --git a/packages/plugins/@nocobase/plugin-workflow-loop/package.json b/packages/plugins/@nocobase/plugin-workflow-loop/package.json index 09ec5c99b8..0ab3367633 100644 --- a/packages/plugins/@nocobase/plugin-workflow-loop/package.json +++ b/packages/plugins/@nocobase/plugin-workflow-loop/package.json @@ -4,7 +4,7 @@ "displayName.zh-CN": "工作流:循环节点", "description": "Used to repeat the sub-process processing of each value in an array, and can also be used for fixed times of sub-process processing.", "description.zh-CN": "用于对一个数组中的每个值进行重复的子流程处理,也可用于固定次数的重复子流程处理。", - "version": "1.7.0-beta.9", + "version": "1.7.0-alpha.10", "license": "AGPL-3.0", "main": "./dist/server/index.js", "homepage": "https://docs.nocobase.com/handbook/workflow-loop", diff --git a/packages/plugins/@nocobase/plugin-workflow-mailer/package.json b/packages/plugins/@nocobase/plugin-workflow-mailer/package.json index 7d434c4a70..9eefa01b2a 100644 --- a/packages/plugins/@nocobase/plugin-workflow-mailer/package.json +++ b/packages/plugins/@nocobase/plugin-workflow-mailer/package.json @@ -4,7 +4,7 @@ "displayName.zh-CN": "工作流:邮件发送节点", "description": "Send email in workflow.", "description.zh-CN": "可用于在工作流中发送电子邮件。", - "version": "1.7.0-beta.9", + "version": "1.7.0-alpha.10", "license": "AGPL-3.0", "main": "./dist/server/index.js", "homepage": "https://docs.nocobase.com/handbook/workflow-smtp-mailer", diff --git a/packages/plugins/@nocobase/plugin-workflow-manual/package.json b/packages/plugins/@nocobase/plugin-workflow-manual/package.json index f42e1f8041..d87db76e0f 100644 --- a/packages/plugins/@nocobase/plugin-workflow-manual/package.json +++ b/packages/plugins/@nocobase/plugin-workflow-manual/package.json @@ -4,7 +4,7 @@ "displayName.zh-CN": "工作流:人工处理节点", "description": "Could be used for workflows which some of decisions are made by users.", "description.zh-CN": "用于人工控制部分决策的流程。", - "version": "1.7.0-beta.9", + "version": "1.7.0-alpha.10", "license": "AGPL-3.0", "main": "./dist/server/index.js", "homepage": "https://docs.nocobase.com/handbook/workflow-manual", diff --git a/packages/plugins/@nocobase/plugin-workflow-manual/src/client/__e2e__/createRecordForm1.test.ts b/packages/plugins/@nocobase/plugin-workflow-manual/src/client/__e2e__/createRecordForm1.test.ts index ce07b3321a..43da0d85da 100644 --- a/packages/plugins/@nocobase/plugin-workflow-manual/src/client/__e2e__/createRecordForm1.test.ts +++ b/packages/plugins/@nocobase/plugin-workflow-manual/src/client/__e2e__/createRecordForm1.test.ts @@ -120,7 +120,7 @@ test.describe('field data entry', () => { // 3、预期结果:工作流成功触发,待办弹窗表单中显示数据 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const newPage = mockPage(); @@ -256,7 +256,7 @@ test.describe('field data entry', () => { // 3、预期结果:工作流成功触发,待办弹窗表单中显示数据 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const newPage = mockPage(); @@ -391,7 +391,7 @@ test.describe('field data entry', () => { // 3、预期结果:工作流成功触发,待办弹窗表单中显示数据 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const newPage = mockPage(); diff --git a/packages/plugins/@nocobase/plugin-workflow-manual/src/client/__e2e__/createRecordForm2.test.ts b/packages/plugins/@nocobase/plugin-workflow-manual/src/client/__e2e__/createRecordForm2.test.ts index 98120f7a39..6246e70ca7 100644 --- a/packages/plugins/@nocobase/plugin-workflow-manual/src/client/__e2e__/createRecordForm2.test.ts +++ b/packages/plugins/@nocobase/plugin-workflow-manual/src/client/__e2e__/createRecordForm2.test.ts @@ -120,7 +120,7 @@ test.describe('action button', () => { // 3、预期结果:工作流成功触发,待办弹窗表单中显示数据 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const newPage = mockPage(); @@ -261,7 +261,7 @@ test.describe('action button', () => { // 3、预期结果:工作流成功触发,待办弹窗表单中显示数据 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const newPage = mockPage(); @@ -402,7 +402,7 @@ test.describe('action button', () => { // 3、预期结果:工作流成功触发,待办弹窗表单中显示数据 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const newPage = mockPage(); diff --git a/packages/plugins/@nocobase/plugin-workflow-manual/src/client/__e2e__/createRecordForm3.test.ts b/packages/plugins/@nocobase/plugin-workflow-manual/src/client/__e2e__/createRecordForm3.test.ts index 61617bd417..2b33b1cd83 100644 --- a/packages/plugins/@nocobase/plugin-workflow-manual/src/client/__e2e__/createRecordForm3.test.ts +++ b/packages/plugins/@nocobase/plugin-workflow-manual/src/client/__e2e__/createRecordForm3.test.ts @@ -120,7 +120,7 @@ test.describe('field data entry', () => { // 3、预期结果:工作流成功触发,待办弹窗表单中显示数据 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const newPage = mockPage(); @@ -263,7 +263,7 @@ test.describe('field data entry', () => { // 3、预期结果:工作流成功触发,待办弹窗表单中显示数据 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const newPage = mockPage(); @@ -397,7 +397,7 @@ test.describe('field data entry', () => { // 3、预期结果:工作流成功触发,待办弹窗表单中显示数据 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const newPage = mockPage(); @@ -538,7 +538,7 @@ test.describe('field data entry', () => { // 3、预期结果:工作流成功触发,待办弹窗表单中显示数据 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const newPage = mockPage(); diff --git a/packages/plugins/@nocobase/plugin-workflow-manual/src/client/__e2e__/createRecordForm4.test.ts b/packages/plugins/@nocobase/plugin-workflow-manual/src/client/__e2e__/createRecordForm4.test.ts index 766a2fafa8..f11d74728e 100644 --- a/packages/plugins/@nocobase/plugin-workflow-manual/src/client/__e2e__/createRecordForm4.test.ts +++ b/packages/plugins/@nocobase/plugin-workflow-manual/src/client/__e2e__/createRecordForm4.test.ts @@ -120,7 +120,7 @@ test.describe('field data entry', () => { // 3、预期结果:工作流成功触发,待办弹窗表单中显示数据 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const newPage = mockPage(); @@ -255,7 +255,7 @@ test.describe('field data entry', () => { // 3、预期结果:工作流成功触发,待办弹窗表单中显示数据 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const newPage = mockPage(); @@ -390,7 +390,7 @@ test.describe('field data entry', () => { // 3、预期结果:工作流成功触发,待办弹窗表单中显示数据 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const newPage = mockPage(); diff --git a/packages/plugins/@nocobase/plugin-workflow-manual/src/client/__e2e__/createRecordForm5.test.ts b/packages/plugins/@nocobase/plugin-workflow-manual/src/client/__e2e__/createRecordForm5.test.ts index caf1439d35..da47161a47 100644 --- a/packages/plugins/@nocobase/plugin-workflow-manual/src/client/__e2e__/createRecordForm5.test.ts +++ b/packages/plugins/@nocobase/plugin-workflow-manual/src/client/__e2e__/createRecordForm5.test.ts @@ -120,7 +120,7 @@ test.describe('field data entry', () => { // 3、预期结果:工作流成功触发,待办弹窗表单中显示数据 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const newPage = mockPage(); @@ -255,7 +255,7 @@ test.describe('field data entry', () => { // 3、预期结果:工作流成功触发,待办弹窗表单中显示数据 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const newPage = mockPage(); @@ -390,7 +390,7 @@ test.describe('field data entry', () => { // 3、预期结果:工作流成功触发,待办弹窗表单中显示数据 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const newPage = mockPage(); diff --git a/packages/plugins/@nocobase/plugin-workflow-manual/src/client/__e2e__/customFormBlocks.test.ts b/packages/plugins/@nocobase/plugin-workflow-manual/src/client/__e2e__/customFormBlocks.test.ts index a367f1b6ea..bd3d1c2a89 100644 --- a/packages/plugins/@nocobase/plugin-workflow-manual/src/client/__e2e__/customFormBlocks.test.ts +++ b/packages/plugins/@nocobase/plugin-workflow-manual/src/client/__e2e__/customFormBlocks.test.ts @@ -130,7 +130,7 @@ test.describe('field data entry', () => { // 3、预期结果:工作流成功触发,待办弹窗表单中显示数据 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const newPage = mockPage(); @@ -269,7 +269,7 @@ test.describe('field data entry', () => { // 3、预期结果:工作流成功触发,待办弹窗表单中显示数据 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const newPage = mockPage(); @@ -414,7 +414,7 @@ test.describe('field data entry', () => { // 3、预期结果:工作流成功触发,待办弹窗表单中显示数据 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const newPage = mockPage(); diff --git a/packages/plugins/@nocobase/plugin-workflow-manual/src/client/__e2e__/customFormBlocks1.test.ts b/packages/plugins/@nocobase/plugin-workflow-manual/src/client/__e2e__/customFormBlocks1.test.ts index 1e6c2411fb..e3e4b8bb22 100644 --- a/packages/plugins/@nocobase/plugin-workflow-manual/src/client/__e2e__/customFormBlocks1.test.ts +++ b/packages/plugins/@nocobase/plugin-workflow-manual/src/client/__e2e__/customFormBlocks1.test.ts @@ -132,7 +132,7 @@ test.describe('field data entry', () => { // 3、预期结果:工作流成功触发,待办弹窗表单中显示数据 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const newPage = mockPage(); @@ -285,7 +285,7 @@ test.describe('field data entry', () => { // 3、预期结果:工作流成功触发,待办弹窗表单中显示数据 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const newPage = mockPage(); @@ -430,7 +430,7 @@ test.describe('field data entry', () => { // 3、预期结果:工作流成功触发,待办弹窗表单中显示数据 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const newPage = mockPage(); @@ -575,7 +575,7 @@ test.describe('field data entry', () => { // 3、预期结果:工作流成功触发,待办弹窗表单中显示数据 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const newPage = mockPage(); diff --git a/packages/plugins/@nocobase/plugin-workflow-manual/src/client/__e2e__/customFormBlocks2.test.ts b/packages/plugins/@nocobase/plugin-workflow-manual/src/client/__e2e__/customFormBlocks2.test.ts index b8db06721c..3c86fab623 100644 --- a/packages/plugins/@nocobase/plugin-workflow-manual/src/client/__e2e__/customFormBlocks2.test.ts +++ b/packages/plugins/@nocobase/plugin-workflow-manual/src/client/__e2e__/customFormBlocks2.test.ts @@ -126,7 +126,7 @@ test.describe('field data entry', () => { // 3、预期结果:工作流成功触发,待办弹窗表单中显示数据 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const newPage = mockPage(); @@ -265,7 +265,7 @@ test.describe('field data entry', () => { // 3、预期结果:工作流成功触发,待办弹窗表单中显示数据 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const newPage = mockPage(); @@ -404,7 +404,7 @@ test.describe('field data entry', () => { // 3、预期结果:工作流成功触发,待办弹窗表单中显示数据 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const newPage = mockPage(); diff --git a/packages/plugins/@nocobase/plugin-workflow-manual/src/client/__e2e__/customFormBlocks3.test.ts b/packages/plugins/@nocobase/plugin-workflow-manual/src/client/__e2e__/customFormBlocks3.test.ts index 8eaf078d67..881ece9b63 100644 --- a/packages/plugins/@nocobase/plugin-workflow-manual/src/client/__e2e__/customFormBlocks3.test.ts +++ b/packages/plugins/@nocobase/plugin-workflow-manual/src/client/__e2e__/customFormBlocks3.test.ts @@ -126,7 +126,7 @@ test.describe('field data entry', () => { // 3、预期结果:工作流成功触发,待办弹窗表单中显示数据 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const newPage = mockPage(); @@ -265,7 +265,7 @@ test.describe('field data entry', () => { // 3、预期结果:工作流成功触发,待办弹窗表单中显示数据 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const newPage = mockPage(); @@ -404,7 +404,7 @@ test.describe('field data entry', () => { // 3、预期结果:工作流成功触发,待办弹窗表单中显示数据 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const newPage = mockPage(); diff --git a/packages/plugins/@nocobase/plugin-workflow-manual/src/client/__e2e__/datablocks.test.ts b/packages/plugins/@nocobase/plugin-workflow-manual/src/client/__e2e__/datablocks.test.ts index cdb3c501ac..db82222b0c 100644 --- a/packages/plugins/@nocobase/plugin-workflow-manual/src/client/__e2e__/datablocks.test.ts +++ b/packages/plugins/@nocobase/plugin-workflow-manual/src/client/__e2e__/datablocks.test.ts @@ -135,7 +135,7 @@ test.describe('field data', () => { // 3、预期结果:工作流成功触发,待办弹窗表单中显示数据 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const newPage = mockPage(); @@ -291,7 +291,7 @@ test.describe('field data', () => { // 3、预期结果:工作流成功触发,待办弹窗表单中显示数据 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const newPage = mockPage(); diff --git a/packages/plugins/@nocobase/plugin-workflow-manual/src/client/__e2e__/datablocks1.test.ts b/packages/plugins/@nocobase/plugin-workflow-manual/src/client/__e2e__/datablocks1.test.ts index bb4878bb6b..294a9071c3 100644 --- a/packages/plugins/@nocobase/plugin-workflow-manual/src/client/__e2e__/datablocks1.test.ts +++ b/packages/plugins/@nocobase/plugin-workflow-manual/src/client/__e2e__/datablocks1.test.ts @@ -164,7 +164,7 @@ test.describe('field data', () => { // 3、预期结果:工作流成功触发,待办弹窗表单中显示数据 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const newPage = mockPage(); @@ -321,7 +321,7 @@ test.describe('field data', () => { // 3、预期结果:工作流成功触发,待办弹窗表单中显示数据 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const newPage = mockPage(); @@ -526,7 +526,7 @@ test.describe('field data', () => { // 3、预期结果:工作流成功触发,待办弹窗表单中显示数据 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const newPage = mockPage(); diff --git a/packages/plugins/@nocobase/plugin-workflow-manual/src/client/__e2e__/datablocks2.test.ts b/packages/plugins/@nocobase/plugin-workflow-manual/src/client/__e2e__/datablocks2.test.ts index 8b82c7f562..710cc30c80 100644 --- a/packages/plugins/@nocobase/plugin-workflow-manual/src/client/__e2e__/datablocks2.test.ts +++ b/packages/plugins/@nocobase/plugin-workflow-manual/src/client/__e2e__/datablocks2.test.ts @@ -104,7 +104,7 @@ test.describe('field data', () => { // 3、预期结果:工作流成功触发,待办弹窗表单中显示数据 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const newPage = mockPage(); @@ -212,7 +212,7 @@ test.describe('field data', () => { // 3、预期结果:工作流成功触发,待办弹窗表单中显示数据 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const newPage = mockPage(); @@ -331,7 +331,7 @@ test.describe('field data', () => { // 3、预期结果:工作流成功触发,待办弹窗表单中显示数据 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const newPage = mockPage(); diff --git a/packages/plugins/@nocobase/plugin-workflow-manual/src/client/__e2e__/updateRecordForm.test.ts b/packages/plugins/@nocobase/plugin-workflow-manual/src/client/__e2e__/updateRecordForm.test.ts index cbb6117471..f7e031cafc 100644 --- a/packages/plugins/@nocobase/plugin-workflow-manual/src/client/__e2e__/updateRecordForm.test.ts +++ b/packages/plugins/@nocobase/plugin-workflow-manual/src/client/__e2e__/updateRecordForm.test.ts @@ -171,7 +171,7 @@ test.describe('field data update', () => { // 3、预期结果:工作流成功触发,待办弹窗表单中显示数据 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const newPage = mockPage(); @@ -350,7 +350,7 @@ test.describe('field data update', () => { // 3、预期结果:工作流成功触发,待办弹窗表单中显示数据 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const newPage = mockPage(); @@ -529,7 +529,7 @@ test.describe('field data update', () => { // 3、预期结果:工作流成功触发,待办弹窗表单中显示数据 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const newPage = mockPage(); @@ -709,7 +709,7 @@ test.describe('field data update', () => { // 3、预期结果:工作流成功触发,待办弹窗表单中显示数据 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const newPage = mockPage(); diff --git a/packages/plugins/@nocobase/plugin-workflow-manual/src/client/__e2e__/updateRecordForm1.test.ts b/packages/plugins/@nocobase/plugin-workflow-manual/src/client/__e2e__/updateRecordForm1.test.ts index b60688b1e4..ecf6822c52 100644 --- a/packages/plugins/@nocobase/plugin-workflow-manual/src/client/__e2e__/updateRecordForm1.test.ts +++ b/packages/plugins/@nocobase/plugin-workflow-manual/src/client/__e2e__/updateRecordForm1.test.ts @@ -163,7 +163,7 @@ test.describe('field data update', () => { // 3、预期结果:工作流成功触发,待办弹窗表单中显示数据 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const newPage = mockPage(); @@ -342,7 +342,7 @@ test.describe('field data update', () => { // 3、预期结果:工作流成功触发,待办弹窗表单中显示数据 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const newPage = mockPage(); @@ -527,7 +527,7 @@ test.describe('field data update', () => { // 3、预期结果:工作流成功触发,待办弹窗表单中显示数据 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const newPage = mockPage(); diff --git a/packages/plugins/@nocobase/plugin-workflow-manual/src/client/__e2e__/updateRecordForm2.test.ts b/packages/plugins/@nocobase/plugin-workflow-manual/src/client/__e2e__/updateRecordForm2.test.ts index 8792d8364b..3aa707a1b4 100644 --- a/packages/plugins/@nocobase/plugin-workflow-manual/src/client/__e2e__/updateRecordForm2.test.ts +++ b/packages/plugins/@nocobase/plugin-workflow-manual/src/client/__e2e__/updateRecordForm2.test.ts @@ -147,7 +147,7 @@ test.describe('field data update', () => { // 3、预期结果:工作流成功触发,待办弹窗表单中显示数据 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const newPage = mockPage(); @@ -310,7 +310,7 @@ test.describe('field data update', () => { // 3、预期结果:工作流成功触发,待办弹窗表单中显示数据 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const newPage = mockPage(); @@ -473,7 +473,7 @@ test.describe('field data update', () => { // 3、预期结果:工作流成功触发,待办弹窗表单中显示数据 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const newPage = mockPage(); diff --git a/packages/plugins/@nocobase/plugin-workflow-manual/src/client/__e2e__/updateRecordForm3.test.ts b/packages/plugins/@nocobase/plugin-workflow-manual/src/client/__e2e__/updateRecordForm3.test.ts index f27c51028e..38deac82d3 100644 --- a/packages/plugins/@nocobase/plugin-workflow-manual/src/client/__e2e__/updateRecordForm3.test.ts +++ b/packages/plugins/@nocobase/plugin-workflow-manual/src/client/__e2e__/updateRecordForm3.test.ts @@ -147,7 +147,7 @@ test.describe('field data update', () => { // 3、预期结果:工作流成功触发,待办弹窗表单中显示数据 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const newPage = mockPage(); @@ -310,7 +310,7 @@ test.describe('field data update', () => { // 3、预期结果:工作流成功触发,待办弹窗表单中显示数据 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const newPage = mockPage(); @@ -473,7 +473,7 @@ test.describe('field data update', () => { // 3、预期结果:工作流成功触发,待办弹窗表单中显示数据 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const newPage = mockPage(); diff --git a/packages/plugins/@nocobase/plugin-workflow-manual/src/client/__e2e__/workflowTodo.test.ts b/packages/plugins/@nocobase/plugin-workflow-manual/src/client/__e2e__/workflowTodo.test.ts index 0329d68e57..a661400de9 100644 --- a/packages/plugins/@nocobase/plugin-workflow-manual/src/client/__e2e__/workflowTodo.test.ts +++ b/packages/plugins/@nocobase/plugin-workflow-manual/src/client/__e2e__/workflowTodo.test.ts @@ -111,7 +111,7 @@ test('filter task node', async ({ page, mockPage, mockCollections, mockRecords } // 3、预期结果:工作流成功触发,待办弹窗表单中显示数据 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const newPage = mockPage(); @@ -225,7 +225,7 @@ test('filter workflow name', async ({ page, mockPage, mockCollections, mockRecor // 3、预期结果:工作流成功触发,待办弹窗表单中显示数据 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const newPage = mockPage(); diff --git a/packages/plugins/@nocobase/plugin-workflow-manual/src/client/instruction/SchemaConfig.tsx b/packages/plugins/@nocobase/plugin-workflow-manual/src/client/instruction/SchemaConfig.tsx index b949a7d7be..94edfff1a9 100644 --- a/packages/plugins/@nocobase/plugin-workflow-manual/src/client/instruction/SchemaConfig.tsx +++ b/packages/plugins/@nocobase/plugin-workflow-manual/src/client/instruction/SchemaConfig.tsx @@ -48,6 +48,7 @@ import WorkflowPlugin, { useFlowContext, useNodeContext, useTrigger, + useWorkflowExecuted, useWorkflowVariableOptions, } from '@nocobase/plugin-workflow/client'; import { Registry, lodash } from '@nocobase/utils/client'; @@ -428,7 +429,7 @@ export function SchemaConfig({ value, onChange }) { const node = useNodeContext(); const nodes = useAvailableUpstreams(node); const form = useForm(); - const { workflow } = useFlowContext(); + const executed = useWorkflowExecuted(); const refreshRef = useRef(() => {}); const nodeComponents = {}; @@ -509,7 +510,7 @@ export function SchemaConfig({ value, onChange }) { @@ -556,7 +557,7 @@ function validateForms(forms: Record = {}) { } export function SchemaConfigButton(props) { - const { workflow } = useFlowContext(); + const executed = useWorkflowExecuted(); const [visible, setVisible] = useState(false); const { values } = useForm(); const { t } = usePluginTranslation(); @@ -580,7 +581,7 @@ export function SchemaConfigButton(props) { return ( <> {props.children} diff --git a/packages/plugins/@nocobase/plugin-workflow-notification/package.json b/packages/plugins/@nocobase/plugin-workflow-notification/package.json index 3495c2b05d..9683df1bc2 100644 --- a/packages/plugins/@nocobase/plugin-workflow-notification/package.json +++ b/packages/plugins/@nocobase/plugin-workflow-notification/package.json @@ -4,7 +4,7 @@ "displayName.zh-CN": "工作流:通知节点", "description": "Send notification in workflow.", "description.zh-CN": "可用于在工作流中发送各类通知。", - "version": "1.7.0-beta.9", + "version": "1.7.0-alpha.10", "license": "AGPL-3.0", "main": "./dist/server/index.js", "homepage": "https://docs.nocobase.com/handbook/workflow-smtp-mailer", diff --git a/packages/plugins/@nocobase/plugin-workflow-parallel/package.json b/packages/plugins/@nocobase/plugin-workflow-parallel/package.json index 7698723168..bd986a36c2 100644 --- a/packages/plugins/@nocobase/plugin-workflow-parallel/package.json +++ b/packages/plugins/@nocobase/plugin-workflow-parallel/package.json @@ -4,7 +4,7 @@ "displayName.zh-CN": "工作流:并行分支节点", "description": "Could be used for parallel execution of branch processes in the workflow.", "description.zh-CN": "用于在工作流中需要并行执行的分支流程。", - "version": "1.7.0-beta.9", + "version": "1.7.0-alpha.10", "license": "AGPL-3.0", "main": "./dist/server/index.js", "homepage": "https://docs.nocobase.com/handbook/workflow-parallel", diff --git a/packages/plugins/@nocobase/plugin-workflow-parallel/src/client/ParallelInstruction.tsx b/packages/plugins/@nocobase/plugin-workflow-parallel/src/client/ParallelInstruction.tsx index 40baad818e..d12a88367c 100644 --- a/packages/plugins/@nocobase/plugin-workflow-parallel/src/client/ParallelInstruction.tsx +++ b/packages/plugins/@nocobase/plugin-workflow-parallel/src/client/ParallelInstruction.tsx @@ -21,10 +21,105 @@ import { useGetAriaLabelOfAddButton, RadioWithTooltip, Instruction, + useWorkflowExecuted, } from '@nocobase/plugin-workflow/client'; import { NAMESPACE, useLang } from '../locale'; +function NodeComponent({ data }) { + const { styles } = useStyles(); + const { + id, + config: { mode }, + } = data; + const { nodes } = useFlowContext(); + const executed = useWorkflowExecuted(); + const branches = nodes + .reduce((result, node) => { + if (node.upstreamId === id && node.branchIndex != null) { + return result.concat(node); + } + return result; + }, []) + .sort((a, b) => a.branchIndex - b.branchIndex); + const [branchCount, setBranchCount] = useState(Math.max(2, branches.length)); + const { getAriaLabel } = useGetAriaLabelOfAddButton(data); + const langAddBranch = useLang('Add branch'); + + const tempBranches = Array(Math.max(0, branchCount - branches.length)).fill(null); + const lastBranchHead = branches[branches.length - 1]; + + return ( + +
+
+ {branches.map((branch) => ( + + ))} + {tempBranches.map((_, i) => ( + 1 ? ( +
button { + line-height: 1; + + .anticon { + transform: rotate(45deg); + } + } + `} + > +
+ ) : null + } + /> + ))} +
+ +
+
+ ); +} + export default class extends Instruction { title = `{{t("Parallel branch", { ns: "${NAMESPACE}" })}}`; type = 'parallel'; @@ -63,101 +158,5 @@ export default class extends Instruction { components = { RadioWithTooltip, }; - Component({ data }) { - // eslint-disable-next-line react-hooks/rules-of-hooks - const { styles } = useStyles(); - const { - id, - config: { mode }, - } = data; - // eslint-disable-next-line react-hooks/rules-of-hooks - const { workflow, nodes } = useFlowContext(); - const branches = nodes - .reduce((result, node) => { - if (node.upstreamId === id && node.branchIndex != null) { - return result.concat(node); - } - return result; - }, []) - .sort((a, b) => a.branchIndex - b.branchIndex); - // eslint-disable-next-line react-hooks/rules-of-hooks - const [branchCount, setBranchCount] = useState(Math.max(2, branches.length)); - // eslint-disable-next-line react-hooks/rules-of-hooks - const { getAriaLabel } = useGetAriaLabelOfAddButton(data); - // eslint-disable-next-line react-hooks/rules-of-hooks - const langAddBranch = useLang('Add branch'); - - const tempBranches = Array(Math.max(0, branchCount - branches.length)).fill(null); - const lastBranchHead = branches[branches.length - 1]; - - return ( - -
-
- {branches.map((branch) => ( - - ))} - {tempBranches.map((_, i) => ( - 1 ? ( -
button { - line-height: 1; - - .anticon { - transform: rotate(45deg); - } - } - `} - > -
- ) : null - } - /> - ))} -
- -
-
- ); - } + Component = NodeComponent; } diff --git a/packages/plugins/@nocobase/plugin-workflow-parallel/src/client/__e2e__/parallelBranch1.test.ts b/packages/plugins/@nocobase/plugin-workflow-parallel/src/client/__e2e__/parallelBranch1.test.ts index 318d789cee..e0072385bf 100644 --- a/packages/plugins/@nocobase/plugin-workflow-parallel/src/client/__e2e__/parallelBranch1.test.ts +++ b/packages/plugins/@nocobase/plugin-workflow-parallel/src/client/__e2e__/parallelBranch1.test.ts @@ -136,7 +136,7 @@ test.describe('All succeeded', () => { // 3、预期结果:工作流成功触发,判断节点全部通过,后置计算节点执行成功 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); @@ -274,7 +274,7 @@ test.describe('All succeeded', () => { // 3、预期结果:工作流成功触发,判断节点全部通过,后置计算节点执行成功 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); @@ -411,7 +411,7 @@ test.describe('All succeeded', () => { // 3、预期结果:工作流成功触发,判断节点全部通过,后置计算节点执行成功 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); @@ -547,7 +547,7 @@ test.describe('All succeeded', () => { // 3、预期结果:工作流成功触发,判断节点全部通过,后置计算节点执行成功 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); diff --git a/packages/plugins/@nocobase/plugin-workflow-parallel/src/client/__e2e__/parallelBranch2.test.ts b/packages/plugins/@nocobase/plugin-workflow-parallel/src/client/__e2e__/parallelBranch2.test.ts index a5906c4311..5b60681961 100644 --- a/packages/plugins/@nocobase/plugin-workflow-parallel/src/client/__e2e__/parallelBranch2.test.ts +++ b/packages/plugins/@nocobase/plugin-workflow-parallel/src/client/__e2e__/parallelBranch2.test.ts @@ -139,7 +139,7 @@ test.describe('Any succeeded', () => { // 3、预期结果:工作流成功触发,判断节点全部通过,后置计算节点执行成功 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); @@ -278,7 +278,7 @@ test.describe('Any succeeded', () => { // 3、预期结果:工作流成功触发,判断节点全部通过,后置计算节点执行成功 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); @@ -418,7 +418,7 @@ test.describe('Any succeeded', () => { // 3、预期结果:工作流成功触发,判断节点全部通过,后置计算节点执行成功 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); diff --git a/packages/plugins/@nocobase/plugin-workflow-parallel/src/client/__e2e__/parallelBranch3.test.ts b/packages/plugins/@nocobase/plugin-workflow-parallel/src/client/__e2e__/parallelBranch3.test.ts index 8018a9bad1..6368f9f271 100644 --- a/packages/plugins/@nocobase/plugin-workflow-parallel/src/client/__e2e__/parallelBranch3.test.ts +++ b/packages/plugins/@nocobase/plugin-workflow-parallel/src/client/__e2e__/parallelBranch3.test.ts @@ -125,7 +125,7 @@ test.describe('Any succeeded or failed', () => { // 3、预期结果:工作流成功触发,判断节点全部通过,后置计算节点执行成功 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); @@ -248,7 +248,7 @@ test.describe('Any succeeded or failed', () => { // 3、预期结果:工作流成功触发,判断节点全部通过,后置计算节点执行成功 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); diff --git a/packages/plugins/@nocobase/plugin-workflow-request/package.json b/packages/plugins/@nocobase/plugin-workflow-request/package.json index c8fb351e9b..c4877a1798 100644 --- a/packages/plugins/@nocobase/plugin-workflow-request/package.json +++ b/packages/plugins/@nocobase/plugin-workflow-request/package.json @@ -4,7 +4,7 @@ "displayName.zh-CN": "工作流:HTTP 请求节点", "description": "Send HTTP requests to any HTTP service for data interaction in workflow.", "description.zh-CN": "可用于在工作流中向任意 HTTP 服务发送请求,进行数据交互。", - "version": "1.7.0-beta.9", + "version": "1.7.0-alpha.10", "license": "AGPL-3.0", "main": "./dist/server/index.js", "homepage": "https://docs.nocobase.com/handbook/workflow-request", diff --git a/packages/plugins/@nocobase/plugin-workflow-sql/package.json b/packages/plugins/@nocobase/plugin-workflow-sql/package.json index 0952913283..a544982da0 100644 --- a/packages/plugins/@nocobase/plugin-workflow-sql/package.json +++ b/packages/plugins/@nocobase/plugin-workflow-sql/package.json @@ -4,7 +4,7 @@ "displayName.zh-CN": "工作流:SQL 节点", "description": "Execute SQL statements in workflow.", "description.zh-CN": "可用于在工作流中对数据库执行任意 SQL 语句。", - "version": "1.7.0-beta.9", + "version": "1.7.0-alpha.10", "license": "AGPL-3.0", "main": "./dist/server/index.js", "homepage": "https://docs.nocobase.com/handbook/workflow-sql", diff --git a/packages/plugins/@nocobase/plugin-workflow-sql/src/client/__e2e__/dataCURD.test.ts b/packages/plugins/@nocobase/plugin-workflow-sql/src/client/__e2e__/dataCURD.test.ts index e0685ebaff..f828dcfeb0 100644 --- a/packages/plugins/@nocobase/plugin-workflow-sql/src/client/__e2e__/dataCURD.test.ts +++ b/packages/plugins/@nocobase/plugin-workflow-sql/src/client/__e2e__/dataCURD.test.ts @@ -109,7 +109,7 @@ test.describe('select data', () => { // 3、预期结果:工作流成功触发,数据查询成功 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); @@ -205,7 +205,7 @@ test.describe('select data', () => { // 3、预期结果:工作流成功触发,数据查询成功 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); @@ -307,7 +307,7 @@ test.describe('select data', () => { // 3、预期结果:工作流成功触发,数据查询成功 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); @@ -409,7 +409,7 @@ test.describe('select data', () => { // 3、预期结果:工作流成功触发,数据查询成功 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); @@ -514,7 +514,7 @@ test.describe('select data', () => { // 3、预期结果:工作流成功触发,数据查询成功 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); @@ -619,7 +619,7 @@ test.describe('select data', () => { // 3、预期结果:工作流成功触发,数据查询成功 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); @@ -703,7 +703,7 @@ test.describe('insert data', () => { // 3、预期结果:工作流成功触发,数据查询成功 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); @@ -791,7 +791,7 @@ test.describe('insert data', () => { // 3、预期结果:工作流成功触发,数据查询成功 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); @@ -893,7 +893,7 @@ test.describe('insert data', () => { // 3、预期结果:工作流成功触发,数据查询成功 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); @@ -991,7 +991,7 @@ test.describe('update data', () => { // 3、预期结果:工作流成功触发,数据查询成功 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); @@ -1097,7 +1097,7 @@ test.describe('update data', () => { // 3、预期结果:工作流成功触发,数据查询成功 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); @@ -1196,7 +1196,7 @@ test.describe('delete data', () => { // 3、预期结果:工作流成功触发,数据查询成功 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); @@ -1302,7 +1302,7 @@ test.describe('delete data', () => { // 3、预期结果:工作流成功触发,数据查询成功 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); diff --git a/packages/plugins/@nocobase/plugin-workflow-test/package.json b/packages/plugins/@nocobase/plugin-workflow-test/package.json index c6ff0c3bc9..61aed27ca1 100644 --- a/packages/plugins/@nocobase/plugin-workflow-test/package.json +++ b/packages/plugins/@nocobase/plugin-workflow-test/package.json @@ -2,7 +2,7 @@ "name": "@nocobase/plugin-workflow-test", "displayName": "Workflow: test kit", "displayName.zh-CN": "工作流:测试工具包", - "version": "1.7.0-beta.9", + "version": "1.7.0-alpha.10", "license": "AGPL-3.0", "main": "dist/server/index.js", "types": "./dist/server/index.d.ts", diff --git a/packages/plugins/@nocobase/plugin-workflow-test/src/e2e/e2eUtils.ts b/packages/plugins/@nocobase/plugin-workflow-test/src/e2e/e2eUtils.ts index e42e19a0cd..2f4a7a7d5d 100644 --- a/packages/plugins/@nocobase/plugin-workflow-test/src/e2e/e2eUtils.ts +++ b/packages/plugins/@nocobase/plugin-workflow-test/src/e2e/e2eUtils.ts @@ -152,9 +152,12 @@ export const apiGetWorkflow = async (id: number) => { const state = await api.storageState(); const headers = getHeaders(state); - const result = await api.get(`/api/workflows:get?filterByTk=${id}`, { - headers, - }); + const result = await api.get( + `/api/workflows:get?filterByTk=${id}&appends[]=stats.executed&appends[]=versionStats.executed`, + { + headers, + }, + ); if (!result.ok()) { throw new Error(await result.text()); @@ -172,10 +175,16 @@ export const apiGetWorkflow = async (id: number) => { "type": "collection", "config": { }, "useTransaction": true, - "executed": 0, - "allExecuted": 0, + // "executed": 0, + // "allExecuted": 0, "current": true, "options": { } + "versionStats": { + "executed": 0, + }, + "stats": { + "executed": 0, + } } } */ diff --git a/packages/plugins/@nocobase/plugin-workflow/package.json b/packages/plugins/@nocobase/plugin-workflow/package.json index ece246da0e..f18984030b 100644 --- a/packages/plugins/@nocobase/plugin-workflow/package.json +++ b/packages/plugins/@nocobase/plugin-workflow/package.json @@ -4,13 +4,13 @@ "displayName.zh-CN": "工作流", "description": "A powerful BPM tool that provides foundational support for business automation, with the capability to extend unlimited triggers and nodes.", "description.zh-CN": "一个强大的 BPM 工具,为业务自动化提供基础支持,并且可任意扩展更多的触发器和节点。", - "version": "1.7.0-beta.9", + "version": "1.7.0-alpha.10", "license": "AGPL-3.0", "main": "./dist/server/index.js", "homepage": "https://docs.nocobase.com/handbook/workflow", "homepage.zh-CN": "https://docs-cn.nocobase.com/handbook/workflow", "dependencies": { - "@nocobase/plugin-workflow-test": "1.7.0-beta.9" + "@nocobase/plugin-workflow-test": "1.7.0-alpha.10" }, "devDependencies": { "@ant-design/icons": "5.x", diff --git a/packages/plugins/@nocobase/plugin-workflow/src/client/AddNodeContext.tsx b/packages/plugins/@nocobase/plugin-workflow/src/client/AddNodeContext.tsx index 2fce9cddfe..9192fd1c62 100644 --- a/packages/plugins/@nocobase/plugin-workflow/src/client/AddNodeContext.tsx +++ b/packages/plugins/@nocobase/plugin-workflow/src/client/AddNodeContext.tsx @@ -23,7 +23,7 @@ import { usePlugin, } from '@nocobase/client'; -import WorkflowPlugin, { Instruction, useStyles } from '.'; +import WorkflowPlugin, { Instruction, useStyles, useWorkflowExecuted } from '.'; import { useFlowContext } from './FlowContext'; import { lang, NAMESPACE } from './locale'; import { RadioWithTooltip } from './components'; @@ -47,6 +47,7 @@ export function AddButton(props: AddButtonProps) { const { styles } = useStyles(); const { onCreate, creating } = useAddNodeContext(); const groupOptions = engine.useInstructionGroupOptions(); + const executed = useWorkflowExecuted(); const groups = useMemo(() => { return groupOptions @@ -91,7 +92,7 @@ export function AddButton(props: AddButtonProps) { items: groups, onClick, }} - disabled={workflow.executed} + disabled={executed} overlayClassName={css` .ant-dropdown-menu-root { max-height: 30em; diff --git a/packages/plugins/@nocobase/plugin-workflow/src/client/CanvasContent.tsx b/packages/plugins/@nocobase/plugin-workflow/src/client/CanvasContent.tsx index 6a345f959b..5e67971914 100644 --- a/packages/plugins/@nocobase/plugin-workflow/src/client/CanvasContent.tsx +++ b/packages/plugins/@nocobase/plugin-workflow/src/client/CanvasContent.tsx @@ -14,15 +14,15 @@ import { ErrorBoundary } from 'react-error-boundary'; import { cx, css, ErrorFallback } from '@nocobase/client'; import { Branch } from './Branch'; -import { useFlowContext } from './FlowContext'; import { lang } from './locale'; import useStyles from './style'; import { TriggerConfig } from './triggers'; import { AddNodeContextProvider } from './AddNodeContext'; +import { useWorkflowExecuted } from './hooks'; export function CanvasContent({ entry }) { const { styles } = useStyles(); - const { workflow } = useFlowContext(); + const executed = useWorkflowExecuted(); const [zoom, setZoom] = React.useState(100); return ( @@ -39,7 +39,7 @@ export function CanvasContent({ entry }) { )} >
- {workflow?.executed ? ( + {executed ? ( { action: 'get', params: { filter: params, - appends: ['jobs', 'workflow', 'workflow.nodes'], + appends: ['jobs', 'workflow', 'workflow.nodes', 'workflow.versionStats', 'workflow.stats'], except: ['jobs.result', 'workflow.options'], }, }, diff --git a/packages/plugins/@nocobase/plugin-workflow/src/client/WorkflowCanvas.tsx b/packages/plugins/@nocobase/plugin-workflow/src/client/WorkflowCanvas.tsx index 508bbf98e8..7c37c45461 100644 --- a/packages/plugins/@nocobase/plugin-workflow/src/client/WorkflowCanvas.tsx +++ b/packages/plugins/@nocobase/plugin-workflow/src/client/WorkflowCanvas.tsx @@ -7,7 +7,7 @@ * For more information, please refer to: https://www.nocobase.com/agreement. */ -import React, { useCallback, useEffect, useMemo, useState } from 'react'; +import React, { useCallback, useEffect, useState } from 'react'; import { Trans, useTranslation } from 'react-i18next'; import { Link, useNavigate } from 'react-router-dom'; import { Alert, App, Breadcrumb, Button, Dropdown, Result, Spin, Switch, Tag, Tooltip } from 'antd'; @@ -28,11 +28,9 @@ import { useResourceContext, useCompile, css, - usePlugin, } from '@nocobase/client'; import { dayjs } from '@nocobase/utils/client'; -import PluginWorkflowClient from '.'; import { CanvasContent } from './CanvasContent'; import { ExecutionStatusColumn } from './components/ExecutionStatus'; import { ExecutionLink } from './ExecutionLink'; @@ -44,8 +42,9 @@ import { linkNodes, getWorkflowDetailPath } from './utils'; import { Fieldset } from './components/Fieldset'; import { useRefreshActionProps } from './hooks/useRefreshActionProps'; import { useTrigger } from './triggers'; -import { ExecutionStatusOptionsMap } from './constants'; +import { ExecutionStatusOptions, ExecutionStatusOptionsMap } from './constants'; import { HideVariableContext } from './variable'; +import { useWorkflowAnyExecuted, useWorkflowExecuted } from './hooks'; function ExecutionResourceProvider({ request, filter = {}, ...others }) { const { workflow } = useFlowContext(); @@ -96,6 +95,7 @@ function useExecuteConfirmAction() { const ctx = useActionContext(); const navigate = useNavigateNoUpdate(); const { message: messageApi } = App.useApp(); + const executed = useWorkflowExecuted(); return { async run() { const { autoRevision, ...values } = form.values; @@ -107,7 +107,7 @@ function useExecuteConfirmAction() { } = await resource.execute({ filterByTk: workflow.id, values, - ...(!workflow.executed && autoRevision ? { autoRevision: 1 } : {}), + ...(!executed && autoRevision ? { autoRevision: 1 } : {}), }); form.reset(); ctx.setFormValueChanged(false); @@ -142,6 +142,7 @@ function ActionDisabledProvider({ children }) { function ExecuteActionButton() { const { workflow } = useFlowContext(); + const executed = useWorkflowExecuted(); const trigger = useTrigger(); return ( @@ -202,7 +203,7 @@ function ExecuteActionButton() { title: `{{t('Trigger variables', { ns: "${NAMESPACE}" })}}`, properties: trigger.triggerFieldset, }, - ...(workflow.executed + ...(executed ? {} : { autoRevision: { @@ -255,6 +256,8 @@ function WorkflowMenu() { const app = useApp(); const { resource } = useResourceContext(); const { message } = App.useApp(); + const executed = useWorkflowExecuted(); + const allExecuted = useWorkflowAnyExecuted(); const onRevision = useCallback(async () => { const { @@ -310,8 +313,8 @@ function WorkflowMenu() { ); const revisionable = - workflow.executed && - !revisions.find((item) => !item.executed && new Date(item.createdAt) > new Date(workflow.createdAt)); + executed && + !revisions.find((item) => !item.versionStats.executed && new Date(item.createdAt) > new Date(workflow.createdAt)); return ( <> @@ -331,7 +334,7 @@ function WorkflowMenu() { 'aria-label': 'history', key: 'history', label: lang('Execution history'), - disabled: !workflow.allExecuted, + disabled: !allExecuted, }, { role: 'button', @@ -360,6 +363,7 @@ function WorkflowMenu() { }} scope={{ useRefreshActionProps, + ExecutionStatusOptions, }} /> @@ -374,7 +378,6 @@ export function WorkflowCanvas() { const { resource } = useResourceContext(); const { setTitle } = useDocumentTitle(); const { styles } = useStyles(); - const workflowPlugin = usePlugin(PluginWorkflowClient); const { nodes = [], revisions = [], ...workflow } = data?.data ?? {}; linkNodes(nodes); @@ -463,8 +466,8 @@ export function WorkflowCanvas() { key: `${item.id}`, icon: item.current ? : null, className: cx({ - executed: item.executed, - unexecuted: !item.executed, + executed: item.versionStats.executed, + unexecuted: !item.versionStats.executed, enabled: item.enabled, }), label: ( diff --git a/packages/plugins/@nocobase/plugin-workflow/src/client/WorkflowPage.tsx b/packages/plugins/@nocobase/plugin-workflow/src/client/WorkflowPage.tsx index f18e210a71..da61111e26 100644 --- a/packages/plugins/@nocobase/plugin-workflow/src/client/WorkflowPage.tsx +++ b/packages/plugins/@nocobase/plugin-workflow/src/client/WorkflowPage.tsx @@ -42,8 +42,11 @@ export const WorkflowPage = () => { 'revisions.id', 'revisions.createdAt', 'revisions.current', - 'revisions.executed', + 'revisions.stats.executed', + 'revisions.versionStats.executed', 'revisions.enabled', + 'stats.executed', + 'versionStats.executed', ], }, }, diff --git a/packages/plugins/@nocobase/plugin-workflow/src/client/WorkflowPane.tsx b/packages/plugins/@nocobase/plugin-workflow/src/client/WorkflowPane.tsx index c78dd5bd43..8bbec984af 100644 --- a/packages/plugins/@nocobase/plugin-workflow/src/client/WorkflowPane.tsx +++ b/packages/plugins/@nocobase/plugin-workflow/src/client/WorkflowPane.tsx @@ -17,6 +17,7 @@ import { SchemaComponentContext, useActionContext, useApp, + useCollectionRecordData, usePlugin, useRecord, useResourceActionContext, @@ -29,9 +30,10 @@ import { WorkflowLink } from './WorkflowLink'; import OpenDrawer from './components/OpenDrawer'; import { workflowSchema } from './schemas/workflows'; import { ExecutionStatusSelect, ExecutionStatusColumn } from './components/ExecutionStatus'; -import WorkflowPlugin, { RadioWithTooltip } from '.'; +import WorkflowPlugin, { ExecutionStatusOptions, RadioWithTooltip } from '.'; import { useRefreshActionProps } from './hooks/useRefreshActionProps'; import { useTranslation } from 'react-i18next'; +import { TriggerOptionRender } from './components/TriggerOptionRender'; function SyncOptionSelect(props) { const field = useField(); @@ -117,6 +119,14 @@ function useRevisionAction() { }; } +function ExecutedLink(props) { + const record = useCollectionRecordData(); + return React.createElement('a', { + 'aria-label': `executed-${record.title}`, + ...props, + }); +} + export function WorkflowPane() { const ctx = useContext(SchemaComponentContext); const { useTriggersOptions } = usePlugin(WorkflowPlugin); @@ -141,6 +151,9 @@ export function WorkflowPane() { useSyncAction, useRefreshActionProps, useRevisionAction, + TriggerOptionRender, + ExecutedLink, + ExecutionStatusOptions, }} /> diff --git a/packages/plugins/@nocobase/plugin-workflow/src/client/__e2e__/ScheduleEventTrigger/configuration1.test.ts b/packages/plugins/@nocobase/plugin-workflow/src/client/__e2e__/ScheduleEventTrigger/configuration1.test.ts index 4ba792ba03..f4e011835a 100644 --- a/packages/plugins/@nocobase/plugin-workflow/src/client/__e2e__/ScheduleEventTrigger/configuration1.test.ts +++ b/packages/plugins/@nocobase/plugin-workflow/src/client/__e2e__/ScheduleEventTrigger/configuration1.test.ts @@ -100,7 +100,7 @@ test.describe('Configuration Page Path Jump Workflow Management Page', () => { await page.waitForTimeout(60000); const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); await page.goto(`admin/workflow/workflows/${workflowId}`); await page.waitForLoadState('load'); diff --git a/packages/plugins/@nocobase/plugin-workflow/src/client/__e2e__/ScheduleEventTrigger/configuration2.test.ts b/packages/plugins/@nocobase/plugin-workflow/src/client/__e2e__/ScheduleEventTrigger/configuration2.test.ts index c8717a2209..1e790fbf6f 100644 --- a/packages/plugins/@nocobase/plugin-workflow/src/client/__e2e__/ScheduleEventTrigger/configuration2.test.ts +++ b/packages/plugins/@nocobase/plugin-workflow/src/client/__e2e__/ScheduleEventTrigger/configuration2.test.ts @@ -67,7 +67,7 @@ test.describe('Configuration page to configure the Trigger node', () => { // 3、预期结果:工作流成功触发 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); // 4、后置处理:删除工作流 diff --git a/packages/plugins/@nocobase/plugin-workflow/src/client/__e2e__/calculationNode/formulaEngine.test.ts b/packages/plugins/@nocobase/plugin-workflow/src/client/__e2e__/calculationNode/formulaEngine.test.ts index dbc9a50021..cec4c3b1cd 100644 --- a/packages/plugins/@nocobase/plugin-workflow/src/client/__e2e__/calculationNode/formulaEngine.test.ts +++ b/packages/plugins/@nocobase/plugin-workflow/src/client/__e2e__/calculationNode/formulaEngine.test.ts @@ -92,7 +92,7 @@ test('Collection event add data trigger, get trigger node single line text varia // 3、预期结果:工作流成功触发,判断节点true通过 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); @@ -184,7 +184,7 @@ test('Collection event add data triggers, get predecessor Formula engine arithme // 3、预期结果:工作流成功触发,判断节点true通过 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); @@ -287,7 +287,7 @@ test('Collection events add data triggers, get single line of text data for fron // 3、预期结果:工作流成功触发,判断节点true通过 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); @@ -392,7 +392,7 @@ test('Collection event add data trigger, get front added data node single line t // 3、预期结果:工作流成功触发,判断节点true通过 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); @@ -488,7 +488,7 @@ test('Collection event adds data triggers, fetches data from front-end aggregati // 3、预期结果:工作流成功触发,判断节点true通过 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); @@ -755,7 +755,7 @@ test.skip('Collection event add data trigger, get front manual node add form sin // 3、预期结果:工作流成功触发,判断节点true通过 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); diff --git a/packages/plugins/@nocobase/plugin-workflow/src/client/__e2e__/calculationNode/mathEngine.test.ts b/packages/plugins/@nocobase/plugin-workflow/src/client/__e2e__/calculationNode/mathEngine.test.ts index 11b2335e4c..68f739e626 100644 --- a/packages/plugins/@nocobase/plugin-workflow/src/client/__e2e__/calculationNode/mathEngine.test.ts +++ b/packages/plugins/@nocobase/plugin-workflow/src/client/__e2e__/calculationNode/mathEngine.test.ts @@ -91,7 +91,7 @@ test('Collection event add data trigger, get trigger node single line text varia // 3、预期结果:工作流成功触发,判断节点true通过 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); @@ -182,7 +182,7 @@ test('Collection event add data triggers, get predecessor Math engine arithmetic // 3、预期结果:工作流成功触发,判断节点true通过 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); @@ -284,7 +284,7 @@ test('Collection events add data triggers, get single line of text data for fron // 3、预期结果:工作流成功触发,判断节点true通过 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); @@ -388,7 +388,7 @@ test('Collection event add data trigger, get front added data node single line t // 3、预期结果:工作流成功触发,判断节点true通过 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); @@ -483,7 +483,7 @@ test('Collection event adds data triggers, fetches data from front-end aggregati // 3、预期结果:工作流成功触发,判断节点true通过 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); @@ -749,7 +749,7 @@ test.skip('Collection event add data trigger, get front manual node add form sin // 3、预期结果:工作流成功触发,判断节点true通过 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); diff --git a/packages/plugins/@nocobase/plugin-workflow/src/client/__e2e__/collectionEventTrigger/configuration1.test.ts b/packages/plugins/@nocobase/plugin-workflow/src/client/__e2e__/collectionEventTrigger/configuration1.test.ts index b1ab501afa..c206129661 100644 --- a/packages/plugins/@nocobase/plugin-workflow/src/client/__e2e__/collectionEventTrigger/configuration1.test.ts +++ b/packages/plugins/@nocobase/plugin-workflow/src/client/__e2e__/collectionEventTrigger/configuration1.test.ts @@ -69,7 +69,7 @@ test.describe('Configuration page to configure the Trigger node', () => { // 3、预期结果:工作流成功触发,判断节点true通过 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); // 4、后置处理:删除工作流 @@ -126,7 +126,7 @@ test.describe('Configuration page to configure the Trigger node', () => { // 3、预期结果:工作流成功触发 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); // 4、后置处理:删除工作流 @@ -184,7 +184,7 @@ test.describe('Configuration page to configure the Trigger node', () => { // 3、预期结果:工作流成功触发 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(2); // 4、后置处理:删除工作流 @@ -252,7 +252,7 @@ test.describe('Configuration page to configure the Trigger node', () => { // 3、预期结果:工作流成功触发 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); // 4、后置处理:删除工作流 @@ -322,7 +322,7 @@ test.describe('Configuration page to configure the Trigger node', () => { // 3、预期结果:工作流成功触发 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); // 4、后置处理:删除工作流 diff --git a/packages/plugins/@nocobase/plugin-workflow/src/client/__e2e__/collectionEventTrigger/configuration3.test.ts b/packages/plugins/@nocobase/plugin-workflow/src/client/__e2e__/collectionEventTrigger/configuration3.test.ts index ce0cac5a38..18f2b4ed2c 100644 --- a/packages/plugins/@nocobase/plugin-workflow/src/client/__e2e__/collectionEventTrigger/configuration3.test.ts +++ b/packages/plugins/@nocobase/plugin-workflow/src/client/__e2e__/collectionEventTrigger/configuration3.test.ts @@ -64,7 +64,7 @@ test.describe('Configuration page disable enable', () => { // 3、预期结果:触发次数为1 let getWorkflow = await apiGetWorkflow(workflowId); let getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - let getWorkflowExecuted = getWorkflowObj.executed; + let getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); await page.goto(`admin/workflow/workflows/${workflowId}`); @@ -75,7 +75,7 @@ test.describe('Configuration page disable enable', () => { getWorkflow = await apiGetWorkflow(workflowId); getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - getWorkflowExecuted = getWorkflowObj.executed; + getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); // 4、后置处理:删除工作流 @@ -127,7 +127,7 @@ test.describe('Configuration page disable enable', () => { // 3、预期结果:触发次数为1 let getWorkflow = await apiGetWorkflow(workflowId); let getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - let getWorkflowExecuted = getWorkflowObj.executed; + let getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(0); await page.goto(`admin/workflow/workflows/${workflowId}`); @@ -138,7 +138,7 @@ test.describe('Configuration page disable enable', () => { getWorkflow = await apiGetWorkflow(workflowId); getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - getWorkflowExecuted = getWorkflowObj.executed; + getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); // 4、后置处理:删除工作流 diff --git a/packages/plugins/@nocobase/plugin-workflow/src/client/__e2e__/conditionNode/BranchIntoYesAndNoBasicType.test.ts b/packages/plugins/@nocobase/plugin-workflow/src/client/__e2e__/conditionNode/BranchIntoYesAndNoBasicType.test.ts index 3b614f4f29..3b8d72877b 100644 --- a/packages/plugins/@nocobase/plugin-workflow/src/client/__e2e__/conditionNode/BranchIntoYesAndNoBasicType.test.ts +++ b/packages/plugins/@nocobase/plugin-workflow/src/client/__e2e__/conditionNode/BranchIntoYesAndNoBasicType.test.ts @@ -152,7 +152,7 @@ test('Collection event add data trigger, determine trigger node integer variable // 3、预期结果:工作流成功触发,判断节点true const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); @@ -298,7 +298,7 @@ test('Collection event add data trigger, determine trigger node integer variable // 3、预期结果:工作流成功触发,判断节点false const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); @@ -445,7 +445,7 @@ test('Collection event add data trigger, determine trigger node integer variable // 3、预期结果:工作流成功触发,判断节点false const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); @@ -592,7 +592,7 @@ test('Collection event add data trigger, determine trigger node integer variable // 3、预期结果:工作流成功触发,判断节点true const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); diff --git a/packages/plugins/@nocobase/plugin-workflow/src/client/__e2e__/conditionNode/BranchIntoYesAndNoBasicType1.test.ts b/packages/plugins/@nocobase/plugin-workflow/src/client/__e2e__/conditionNode/BranchIntoYesAndNoBasicType1.test.ts index 6f799a76eb..e7a535a310 100644 --- a/packages/plugins/@nocobase/plugin-workflow/src/client/__e2e__/conditionNode/BranchIntoYesAndNoBasicType1.test.ts +++ b/packages/plugins/@nocobase/plugin-workflow/src/client/__e2e__/conditionNode/BranchIntoYesAndNoBasicType1.test.ts @@ -119,7 +119,7 @@ test('Collection event add data trigger, determines that the trigger node single // 3、预期结果:工作流成功触发,判断节点true通过 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); @@ -233,7 +233,7 @@ test('Collection event add data trigger, determines that the trigger node single // 3、预期结果:工作流成功触发,判断节点false const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); @@ -349,7 +349,7 @@ test('Collection event Add Data Trigger, determines that the trigger node single // 3、预期结果:工作流成功触发,判断节点false const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); @@ -465,7 +465,7 @@ test('Collection event add data trigger, determines that the trigger node single // 3、预期结果:工作流成功触发,判断节点true const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); diff --git a/packages/plugins/@nocobase/plugin-workflow/src/client/__e2e__/conditionNode/BranchIntoYesAndNoFormulaEngine.test.ts b/packages/plugins/@nocobase/plugin-workflow/src/client/__e2e__/conditionNode/BranchIntoYesAndNoFormulaEngine.test.ts index 382a34ecb1..dcdd14262c 100644 --- a/packages/plugins/@nocobase/plugin-workflow/src/client/__e2e__/conditionNode/BranchIntoYesAndNoFormulaEngine.test.ts +++ b/packages/plugins/@nocobase/plugin-workflow/src/client/__e2e__/conditionNode/BranchIntoYesAndNoFormulaEngine.test.ts @@ -135,7 +135,7 @@ test('Collection event Add Data Trigger, determines that the trigger node single // 3、预期结果:工作流成功触发,判断节点true const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); @@ -260,7 +260,7 @@ test('Collection event Add Data Trigger, determines that the trigger node single // 3、预期结果:工作流成功触发,判断节点false const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); @@ -388,7 +388,7 @@ test('Collection event Add Data Trigger, determines that the trigger node single // 3、预期结果:工作流成功触发,判断节点false const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); @@ -513,7 +513,7 @@ test('Collection event Add Data Trigger, determines that the trigger node single // 3、预期结果:工作流成功触发,判断节点true通过 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); @@ -665,7 +665,7 @@ test('Collection event add data trigger, determine the trigger node integer vari // 3、预期结果:工作流成功触发,判断节点true const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); @@ -821,7 +821,7 @@ test('Collection event add data trigger, determine trigger node integer variable // 3、预期结果:工作流成功触发,判断节点false const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); @@ -970,7 +970,7 @@ test('Collection event add data trigger, determine trigger node integer variable // 3、预期结果:工作流成功触发,判断节点false const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); @@ -1119,7 +1119,7 @@ test('Collection event add data trigger, determine the trigger node integer vari // 3、预期结果:工作流成功触发,判断节点true const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); diff --git a/packages/plugins/@nocobase/plugin-workflow/src/client/__e2e__/conditionNode/BranchIntoYesAndNoMathEngine.test.ts b/packages/plugins/@nocobase/plugin-workflow/src/client/__e2e__/conditionNode/BranchIntoYesAndNoMathEngine.test.ts index 9f22784b77..5f3887ebb1 100644 --- a/packages/plugins/@nocobase/plugin-workflow/src/client/__e2e__/conditionNode/BranchIntoYesAndNoMathEngine.test.ts +++ b/packages/plugins/@nocobase/plugin-workflow/src/client/__e2e__/conditionNode/BranchIntoYesAndNoMathEngine.test.ts @@ -129,7 +129,7 @@ test('Collection event add data trigger, determine trigger node integer field va // 3、预期结果:工作流成功触发,判断节点true const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); @@ -251,7 +251,7 @@ test('Collection event Add Data Trigger, determines that the trigger node intege // 3、预期结果:工作流成功触发,判断节点false const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); @@ -373,7 +373,7 @@ test('Collection event Add Data Trigger, determines that the trigger node intege // 3、预期结果:工作流成功触发,判断节点false const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); @@ -498,7 +498,7 @@ test('Collection event add data trigger, determines that the trigger node intege // 3、预期结果:工作流成功触发,判断节点true const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); diff --git a/packages/plugins/@nocobase/plugin-workflow/src/client/__e2e__/conditionNode/continueWhenYesBasicType.test.ts b/packages/plugins/@nocobase/plugin-workflow/src/client/__e2e__/conditionNode/continueWhenYesBasicType.test.ts index bcaf8eea83..c5c4de6c1b 100644 --- a/packages/plugins/@nocobase/plugin-workflow/src/client/__e2e__/conditionNode/continueWhenYesBasicType.test.ts +++ b/packages/plugins/@nocobase/plugin-workflow/src/client/__e2e__/conditionNode/continueWhenYesBasicType.test.ts @@ -95,7 +95,7 @@ test('Collection event add data trigger, determines that the trigger node single // 3、预期结果:工作流成功触发,判断节点true通过 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); @@ -179,7 +179,7 @@ test('Collection event add data trigger, determines that the trigger node single // 3、预期结果:工作流成功触发,判断节点true通过 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); @@ -265,7 +265,7 @@ test('Collection event Add Data Trigger, determines that the trigger node single // 3、预期结果:工作流成功触发,判断节点true通过 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); @@ -351,7 +351,7 @@ test('Collection event add data trigger, determines that the trigger node single // 3、预期结果:工作流成功触发,判断节点true通过 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); @@ -446,6 +446,7 @@ test('Collection event add data trigger, determine trigger node integer variable `Trigger variables / Trigger data / ${triggerNodeFieldDisplayName}`, ); await page.getByLabel('variable-button').nth(1).click(); + await page.waitForTimeout(200); await page.getByRole('menuitemcheckbox', { name: 'Node result' }).click(); await page.getByRole('menuitemcheckbox', { name: preQueryRecordNodeTitle }).click(); await page.getByRole('menuitemcheckbox', { name: triggerNodeFieldDisplayName }).click(); @@ -463,7 +464,7 @@ test('Collection event add data trigger, determine trigger node integer variable // 3、预期结果:工作流成功触发,判断节点true通过 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); @@ -576,7 +577,7 @@ test('Collection event add data trigger, determine trigger node integer variable // 3、预期结果:工作流成功触发,判断节点true通过 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); @@ -691,7 +692,7 @@ test('Collection event add data trigger, determine trigger node integer variable // 3、预期结果:工作流成功触发,判断节点true通过 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); @@ -805,7 +806,7 @@ test('Collection event add data trigger, determine trigger node integer variable // 3、预期结果:工作流成功触发,判断节点true通过 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); @@ -895,7 +896,7 @@ test('create non-branching condition node before first node, the original first // 3、预期结果:工作流成功触发,判断节点true通过 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); diff --git a/packages/plugins/@nocobase/plugin-workflow/src/client/__e2e__/conditionNode/continueWhenYesFormulaEngine.test.ts b/packages/plugins/@nocobase/plugin-workflow/src/client/__e2e__/conditionNode/continueWhenYesFormulaEngine.test.ts index 0c9e72a62e..a156606e54 100644 --- a/packages/plugins/@nocobase/plugin-workflow/src/client/__e2e__/conditionNode/continueWhenYesFormulaEngine.test.ts +++ b/packages/plugins/@nocobase/plugin-workflow/src/client/__e2e__/conditionNode/continueWhenYesFormulaEngine.test.ts @@ -102,7 +102,7 @@ test('Collection event Add Data Trigger, Formula engine, determines that the tri // 3、预期结果:工作流成功触发,判断节点true通过 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); @@ -195,7 +195,7 @@ test('Collection event Add Data Trigger, Formula engine, determines that the tri // 3、预期结果:工作流成功触发,判断节点true通过 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); @@ -282,7 +282,7 @@ test('Collection event Add Data Trigger, Formula engine, determines that the tri // 3、预期结果:工作流成功触发,判断节点true通过 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); @@ -372,7 +372,7 @@ test('Collection event Add Data Trigger, Formula engine, determines that the tri // 3、预期结果:工作流成功触发,判断节点true通过 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); @@ -489,7 +489,7 @@ test('Collection event add data trigger, Formula engine, determine the trigger n // 3、预期结果:工作流成功触发,判断节点true通过 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); @@ -607,7 +607,7 @@ test('Collection event add data trigger, Formula engine, determine trigger node // 3、预期结果:工作流成功触发,判断节点true通过 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); @@ -723,7 +723,7 @@ test('Collection event add data trigger, Formula engine, determine trigger node // 3、预期结果:工作流成功触发,判断节点true通过 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); @@ -841,7 +841,7 @@ test('Collection event add data trigger, Formula engine, determine the trigger n // 3、预期结果:工作流成功触发,判断节点true通过 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); diff --git a/packages/plugins/@nocobase/plugin-workflow/src/client/__e2e__/conditionNode/continueWhenYesMathEngine.test.ts b/packages/plugins/@nocobase/plugin-workflow/src/client/__e2e__/conditionNode/continueWhenYesMathEngine.test.ts index 7684d89b88..5691d6bdb0 100644 --- a/packages/plugins/@nocobase/plugin-workflow/src/client/__e2e__/conditionNode/continueWhenYesMathEngine.test.ts +++ b/packages/plugins/@nocobase/plugin-workflow/src/client/__e2e__/conditionNode/continueWhenYesMathEngine.test.ts @@ -100,7 +100,7 @@ test('Collection event add data trigger, Math engine, determine trigger node int // 3、预期结果:工作流成功触发,判断节点true通过 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); @@ -191,7 +191,7 @@ test('Collection event Add Data Trigger, Math engine, determines that the trigge // 3、预期结果:工作流成功触发,判断节点true通过 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); @@ -281,7 +281,7 @@ test('Collection event Add Data Trigger, Math engine, determines that the trigge // 3、预期结果:工作流成功触发,判断节点true通过 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); @@ -372,7 +372,7 @@ test('Collection event add data trigger, Math engine, determines that the trigge // 3、预期结果:工作流成功触发,判断节点true通过 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); diff --git a/packages/plugins/@nocobase/plugin-workflow/src/client/__e2e__/createRecordNode/CreateRecord.test.ts b/packages/plugins/@nocobase/plugin-workflow/src/client/__e2e__/createRecordNode/CreateRecord.test.ts index dc611c6eb6..cf07f754b9 100644 --- a/packages/plugins/@nocobase/plugin-workflow/src/client/__e2e__/createRecordNode/CreateRecord.test.ts +++ b/packages/plugins/@nocobase/plugin-workflow/src/client/__e2e__/createRecordNode/CreateRecord.test.ts @@ -107,7 +107,7 @@ test('Collection event add data trigger, single row text fields for common table // 3、预期结果:工作流成功触发,数据表成功新增记录 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); @@ -219,7 +219,7 @@ test('Collection event add data trigger, normal table single line text field, se // 3、预期结果:工作流成功触发,数据表成功新增记录 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); @@ -322,7 +322,7 @@ test('Collection event add data trigger, normal table integer field, set constan // 3、预期结果:工作流成功触发,数据表成功新增记录 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); @@ -434,7 +434,7 @@ test('Collection event add data trigger, normal table integer field, set trigger // 3、预期结果:工作流成功触发,数据表成功新增记录 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); @@ -537,7 +537,7 @@ test('Collection event add data trigger, normal table numeric field, set constan // 3、预期结果:工作流成功触发,数据表成功新增记录 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); @@ -649,7 +649,7 @@ test('Collection event add data trigger, normal table numeric field, set trigger // 3、预期结果:工作流成功触发,数据表成功新增记录 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); @@ -752,7 +752,7 @@ test('Collection event add data trigger, normal table dropdown radio field, set // 3、预期结果:工作流成功触发,数据表成功新增记录 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); @@ -864,7 +864,7 @@ test('Collection event add data trigger, normal table dropdown radio field, set // 3、预期结果:工作流成功触发,数据表成功新增记录 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); @@ -963,7 +963,7 @@ test('Collection event add data trigger, normal table dropdown radio fields, set // 3、预期结果:工作流成功触发,数据表成功新增记录 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); @@ -1075,7 +1075,7 @@ test('Collection event add data trigger, normal table dropdown radio fields, set // 3、预期结果:工作流成功触发,数据表成功新增记录 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); @@ -1185,7 +1185,7 @@ test('Collection event add data trigger, normal table date field, set constant d // 3、预期结果:工作流成功触发,数据表成功新增记录 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); @@ -1297,7 +1297,7 @@ test('Collection event add data trigger, normal table date field, set trigger no // 3、预期结果:工作流成功触发,数据表成功新增记录 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); diff --git a/packages/plugins/@nocobase/plugin-workflow/src/client/__e2e__/queryRecordNode/QueryRecord.test.ts b/packages/plugins/@nocobase/plugin-workflow/src/client/__e2e__/queryRecordNode/QueryRecord.test.ts index 1f32502b9d..1265cbfc75 100644 --- a/packages/plugins/@nocobase/plugin-workflow/src/client/__e2e__/queryRecordNode/QueryRecord.test.ts +++ b/packages/plugins/@nocobase/plugin-workflow/src/client/__e2e__/queryRecordNode/QueryRecord.test.ts @@ -84,7 +84,7 @@ test('Collection event add data trigger, no filter no sort query common table 1 // 3、预期结果:工作流成功触发,数据查询成功 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); @@ -163,7 +163,7 @@ test('Collection event add data trigger, no filtering and no sorting, query comm // 3、预期结果:工作流成功触发,数据查询成功 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); @@ -251,7 +251,7 @@ test('Collection event add data trigger, no filter ID ascending, query common ta // 3、预期结果:工作流成功触发,数据查询成功 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); @@ -360,7 +360,7 @@ test('Collection event add data trigger, no filter ID descending, query common t // 3、预期结果:工作流成功触发,数据查询成功 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); @@ -465,7 +465,7 @@ test('Collection event add data trigger, no filtering and no sorting, query mult // 3、预期结果:工作流成功触发,数据查询成功 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); @@ -570,7 +570,7 @@ test('Collection event add data trigger, no filtering and no sorting, query the // 3、预期结果:工作流成功触发,数据查询成功 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); @@ -676,7 +676,7 @@ test('Collection event add data trigger, no filtering and no sorting, query the // 3、预期结果:工作流成功触发,数据查询成功 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); @@ -811,7 +811,7 @@ test('Collection event add data trigger, filter to meet all conditions (status_s // 3、预期结果:工作流成功触发,数据查询成功 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); @@ -930,7 +930,7 @@ test('Collection event add data trigger, filter to satisfy any condition (status // 3、预期结果:工作流成功触发,数据查询成功 const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); diff --git a/packages/plugins/@nocobase/plugin-workflow/src/client/__e2e__/updateRecordNode/updateInABatch.test.ts b/packages/plugins/@nocobase/plugin-workflow/src/client/__e2e__/updateRecordNode/updateInABatch.test.ts index 6997ab725d..5f1b80172b 100644 --- a/packages/plugins/@nocobase/plugin-workflow/src/client/__e2e__/updateRecordNode/updateInABatch.test.ts +++ b/packages/plugins/@nocobase/plugin-workflow/src/client/__e2e__/updateRecordNode/updateInABatch.test.ts @@ -162,7 +162,7 @@ test('Collection event add data trigger, filter dropdown radio fields not null, const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); @@ -324,7 +324,7 @@ test('Collection event add data trigger, filter dropdown radio fields not empty, const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); @@ -489,7 +489,7 @@ test('Collection event add data trigger, filter date field not null, common tabl const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); @@ -651,7 +651,7 @@ test('Collection event add data trigger, filter date field not empty, common tab const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); diff --git a/packages/plugins/@nocobase/plugin-workflow/src/client/__e2e__/updateRecordNode/updateInABatch1.test.ts b/packages/plugins/@nocobase/plugin-workflow/src/client/__e2e__/updateRecordNode/updateInABatch1.test.ts index ced3c2908b..6ecfae13cb 100644 --- a/packages/plugins/@nocobase/plugin-workflow/src/client/__e2e__/updateRecordNode/updateInABatch1.test.ts +++ b/packages/plugins/@nocobase/plugin-workflow/src/client/__e2e__/updateRecordNode/updateInABatch1.test.ts @@ -168,7 +168,7 @@ test('Collection event add data trigger, filter single line text field not empty const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); @@ -332,7 +332,7 @@ test('Collection event add data trigger, filter single line text field not empty const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); @@ -492,7 +492,7 @@ test('Collection event add data trigger, filter multi-line text field not empty, const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); @@ -656,7 +656,7 @@ test('Collection event add data trigger, filter multiline text field not empty, const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); @@ -808,7 +808,7 @@ test('Collection event add data trigger, filter integer field not null, common t const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); diff --git a/packages/plugins/@nocobase/plugin-workflow/src/client/__e2e__/updateRecordNode/updateInABatch2.test.ts b/packages/plugins/@nocobase/plugin-workflow/src/client/__e2e__/updateRecordNode/updateInABatch2.test.ts index 65b0e24c63..4d9109ab4c 100644 --- a/packages/plugins/@nocobase/plugin-workflow/src/client/__e2e__/updateRecordNode/updateInABatch2.test.ts +++ b/packages/plugins/@nocobase/plugin-workflow/src/client/__e2e__/updateRecordNode/updateInABatch2.test.ts @@ -165,7 +165,7 @@ test('Collection event add data trigger, filter integer field not empty, common const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); @@ -318,7 +318,7 @@ test('Collection event add data trigger, filter numeric field not null, common t const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); @@ -475,7 +475,7 @@ test('Collection event add data trigger, filter numeric field not empty, common const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); @@ -628,7 +628,7 @@ test('Collection event add data trigger, filter dropdown radio field not null, c const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); @@ -787,7 +787,7 @@ test('Collection event add data trigger, filter dropdown radio field not empty, const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); diff --git a/packages/plugins/@nocobase/plugin-workflow/src/client/__e2e__/updateRecordNode/updateOneByOne.test.ts b/packages/plugins/@nocobase/plugin-workflow/src/client/__e2e__/updateRecordNode/updateOneByOne.test.ts index b9614ce069..5b1b4b3108 100644 --- a/packages/plugins/@nocobase/plugin-workflow/src/client/__e2e__/updateRecordNode/updateOneByOne.test.ts +++ b/packages/plugins/@nocobase/plugin-workflow/src/client/__e2e__/updateRecordNode/updateOneByOne.test.ts @@ -171,7 +171,7 @@ test('Collection event add data trigger, filter dropdown radio fields not empty, const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); @@ -337,7 +337,7 @@ test('Collection event add data trigger, filter date field not null, common tabl const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); @@ -500,7 +500,7 @@ test('Collection event add data trigger, filter date field not empty, common tab const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); diff --git a/packages/plugins/@nocobase/plugin-workflow/src/client/__e2e__/updateRecordNode/updateOneByOne1.test.ts b/packages/plugins/@nocobase/plugin-workflow/src/client/__e2e__/updateRecordNode/updateOneByOne1.test.ts index 4d92836d75..68a52289ac 100644 --- a/packages/plugins/@nocobase/plugin-workflow/src/client/__e2e__/updateRecordNode/updateOneByOne1.test.ts +++ b/packages/plugins/@nocobase/plugin-workflow/src/client/__e2e__/updateRecordNode/updateOneByOne1.test.ts @@ -169,7 +169,7 @@ test('Collection event add data trigger, filter single line text field not empty const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); @@ -334,7 +334,7 @@ test('Collection event add data trigger, filter single line text field not empty const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); @@ -495,7 +495,7 @@ test('Collection event add data trigger, filter multi-line text field not empty, const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); @@ -660,7 +660,7 @@ test('Collection event add data trigger, filter multiline text field not empty, const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); diff --git a/packages/plugins/@nocobase/plugin-workflow/src/client/__e2e__/updateRecordNode/updateOneByOne2.test.ts b/packages/plugins/@nocobase/plugin-workflow/src/client/__e2e__/updateRecordNode/updateOneByOne2.test.ts index 8d000752d0..38479e7921 100644 --- a/packages/plugins/@nocobase/plugin-workflow/src/client/__e2e__/updateRecordNode/updateOneByOne2.test.ts +++ b/packages/plugins/@nocobase/plugin-workflow/src/client/__e2e__/updateRecordNode/updateOneByOne2.test.ts @@ -162,7 +162,7 @@ test('Collection event add data trigger, filter integer field not null, common t const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); @@ -319,7 +319,7 @@ test('Collection event add data trigger, filter integer field not empty, common const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); @@ -473,7 +473,7 @@ test('Collection event add data trigger, filter numeric field not null, common t const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); @@ -631,7 +631,7 @@ test('Collection event add data trigger, filter numeric field not empty, common const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); diff --git a/packages/plugins/@nocobase/plugin-workflow/src/client/__e2e__/updateRecordNode/updateOneByOne3.test.ts b/packages/plugins/@nocobase/plugin-workflow/src/client/__e2e__/updateRecordNode/updateOneByOne3.test.ts index 212fdd75a4..f5162764f5 100644 --- a/packages/plugins/@nocobase/plugin-workflow/src/client/__e2e__/updateRecordNode/updateOneByOne3.test.ts +++ b/packages/plugins/@nocobase/plugin-workflow/src/client/__e2e__/updateRecordNode/updateOneByOne3.test.ts @@ -163,7 +163,7 @@ test('Collection event add data trigger, filter dropdown radio field not null, c const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); @@ -323,7 +323,7 @@ test('Collection event add data trigger, filter dropdown radio field not empty, const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); @@ -477,7 +477,7 @@ test('Collection event add data trigger, filter dropdown radio fields not null, const getWorkflow = await apiGetWorkflow(workflowId); const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); - const getWorkflowExecuted = getWorkflowObj.executed; + const getWorkflowExecuted = getWorkflowObj.versionStats.executed; expect(getWorkflowExecuted).toBe(1); const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); diff --git a/packages/plugins/@nocobase/plugin-workflow/src/client/components/AssignedFieldsFormSchemaConfig.tsx b/packages/plugins/@nocobase/plugin-workflow/src/client/components/AssignedFieldsFormSchemaConfig.tsx index 2faf440523..b875ed48cf 100644 --- a/packages/plugins/@nocobase/plugin-workflow/src/client/components/AssignedFieldsFormSchemaConfig.tsx +++ b/packages/plugins/@nocobase/plugin-workflow/src/client/components/AssignedFieldsFormSchemaConfig.tsx @@ -34,6 +34,7 @@ import { import { useFlowContext } from '../FlowContext'; import { useWorkflowVariableOptions } from '../variable'; import { Card } from 'antd'; +import { useWorkflowExecuted } from '../hooks'; function reduceSchema(s, fn) { fn(s); @@ -54,9 +55,8 @@ function createNewSchema() { } export function AssignedFieldsFormSchemaConfig(props) { - const { workflow } = useFlowContext(); + const executed = useWorkflowExecuted(); const { setFormValueChanged } = useActionContext(); - const api = useAPIClient(); const scope = useWorkflowVariableOptions(); const { values, setValuesIn, disabled } = useForm(); @@ -73,7 +73,7 @@ export function AssignedFieldsFormSchemaConfig(props) { () => createForm({ initialValues: params.values, - disabled: workflow.executed, + disabled: executed, effects() { onFormValuesChange((f) => { setValuesIn('params.values', toJS(f.values)); @@ -81,7 +81,7 @@ export function AssignedFieldsFormSchemaConfig(props) { }); }, }), - [workflow.executed], + [executed], ); useFormEffects(() => { diff --git a/packages/plugins/@nocobase/plugin-workflow/src/client/components/ExecutionStatus.tsx b/packages/plugins/@nocobase/plugin-workflow/src/client/components/ExecutionStatus.tsx index 7d2965b686..543b7310ef 100644 --- a/packages/plugins/@nocobase/plugin-workflow/src/client/components/ExecutionStatus.tsx +++ b/packages/plugins/@nocobase/plugin-workflow/src/client/components/ExecutionStatus.tsx @@ -20,13 +20,9 @@ import { lang } from '../locale'; function LabelTag(props) { const compile = useCompile(); const label = compile(props.label); - const onPreventMouseDown = useCallback((event: React.MouseEvent) => { - event.preventDefault(); - event.stopPropagation(); - }, []); const { color } = ExecutionStatusOptionsMap[props.value] ?? {}; return ( - + {label} ); diff --git a/packages/plugins/@nocobase/plugin-workflow/src/client/hooks/useWorkflowExecuted.ts b/packages/plugins/@nocobase/plugin-workflow/src/client/hooks/useWorkflowExecuted.ts index afeff2b607..a923deea02 100644 --- a/packages/plugins/@nocobase/plugin-workflow/src/client/hooks/useWorkflowExecuted.ts +++ b/packages/plugins/@nocobase/plugin-workflow/src/client/hooks/useWorkflowExecuted.ts @@ -11,10 +11,10 @@ import { useFlowContext } from '../FlowContext'; export function useWorkflowExecuted() { const { workflow } = useFlowContext(); - return Boolean(workflow?.executed); + return Boolean(workflow?.versionStats?.executed); } export function useWorkflowAnyExecuted() { const { workflow } = useFlowContext(); - return Boolean(workflow?.allExecuted); + return Boolean(workflow?.stats?.executed); } diff --git a/packages/plugins/@nocobase/plugin-workflow/src/client/locale/index.ts b/packages/plugins/@nocobase/plugin-workflow/src/client/locale/index.ts index b798eb0643..f94c3cd4b9 100644 --- a/packages/plugins/@nocobase/plugin-workflow/src/client/locale/index.ts +++ b/packages/plugins/@nocobase/plugin-workflow/src/client/locale/index.ts @@ -9,8 +9,9 @@ import { i18n } from '@nocobase/client'; import { useTranslation } from 'react-i18next'; +import { NAMESPACE } from '../../common/constants'; -export const NAMESPACE = 'workflow'; +export { NAMESPACE }; // i18n.addResources('zh-CN', NAMESPACE, zhCN); // i18n.addResources('en-US', NAMESPACE, enUS); diff --git a/packages/plugins/@nocobase/plugin-workflow/src/client/nodes/index.tsx b/packages/plugins/@nocobase/plugin-workflow/src/client/nodes/index.tsx index 5c1b676754..4a6324f78c 100644 --- a/packages/plugins/@nocobase/plugin-workflow/src/client/nodes/index.tsx +++ b/packages/plugins/@nocobase/plugin-workflow/src/client/nodes/index.tsx @@ -39,7 +39,7 @@ import { useFlowContext } from '../FlowContext'; import { DrawerDescription } from '../components/DrawerDescription'; import { StatusButton } from '../components/StatusButton'; import { JobStatusOptionsMap } from '../constants'; -import { useGetAriaLabelOfAddButton } from '../hooks/useGetAriaLabelOfAddButton'; +import { useGetAriaLabelOfAddButton, useWorkflowExecuted } from '../hooks'; import { lang } from '../locale'; import useStyles from '../style'; import { UseVariableOptions, VariableOption, WorkflowVariableInput } from '../variable'; @@ -105,10 +105,10 @@ function useUpdateAction() { const ctx = useActionContext(); const { refresh } = useResourceActionContext(); const data = useNodeContext(); - const { workflow } = useFlowContext(); + const executed = useWorkflowExecuted(); return { async run() { - if (workflow.executed) { + if (executed) { message.error(lang('Node in executed workflow cannot be modified')); return; } @@ -197,6 +197,7 @@ export function RemoveButton() { const { workflow, nodes, refresh } = useFlowContext() ?? {}; const current = useNodeContext(); const { modal } = App.useApp(); + const executed = useWorkflowExecuted(); const resource = api.resource('flow_nodes'); @@ -247,7 +248,7 @@ export function RemoveButton() { return null; } - return workflow.executed ? null : ( + return executed ? null : (
setEditingTitle(ev.target.value)} onBlur={(ev) => onChangeTitle(ev.target.value)} @@ -723,7 +724,7 @@ export function NodeDefaultView(props) { }, properties: instruction.fieldset, }, - footer: workflow.executed + footer: executed ? null : { type: 'void', diff --git a/packages/plugins/@nocobase/plugin-workflow/src/client/schemas/executions.tsx b/packages/plugins/@nocobase/plugin-workflow/src/client/schemas/executions.tsx index ef35b4a4cd..c3e42bf867 100644 --- a/packages/plugins/@nocobase/plugin-workflow/src/client/schemas/executions.tsx +++ b/packages/plugins/@nocobase/plugin-workflow/src/client/schemas/executions.tsx @@ -14,65 +14,58 @@ import { useTranslation } from 'react-i18next'; import { message } from 'antd'; import { useActionContext, useResourceActionContext, useResourceContext } from '@nocobase/client'; +import executionCollection from '../../common/collections/executions'; import { ExecutionStatusOptions, EXECUTION_STATUS } from '../constants'; import { NAMESPACE } from '../locale'; import { getWorkflowDetailPath } from '../utils'; -export const executionCollection = { - name: 'execution-executions', - fields: [ - { - interface: 'id', - type: 'bigInt', - name: 'id', - uiSchema: { - type: 'number', - title: '{{t("ID")}}', - 'x-component': 'Input', - 'x-component-props': {}, - 'x-read-pretty': true, - } as ISchema, - }, - { - interface: 'createdAt', - type: 'datetime', - name: 'createdAt', - uiSchema: { - type: 'datetime', - title: `{{t("Triggered at", { ns: "${NAMESPACE}" })}}`, - 'x-component': 'DatePicker', - 'x-component-props': {}, - 'x-read-pretty': true, - } as ISchema, - }, - { - interface: 'm2o', - type: 'belongsTo', - name: 'workflowId', - uiSchema: { - type: 'number', - title: `{{t("Version", { ns: "${NAMESPACE}" })}}`, - ['x-component']({ value }) { - const { setVisible } = useActionContext(); - return setVisible(false)}>{`#${value}`}; - }, - } as ISchema, - }, - { - type: 'number', - name: 'status', - interface: 'select', - uiSchema: { - title: `{{t("Status", { ns: "${NAMESPACE}" })}}`, - type: 'string', - 'x-component': 'Select', - 'x-decorator': 'FormItem', - enum: ExecutionStatusOptions, - } as ISchema, - }, - ], -}; +// export const executionCollection = { +// name: 'executions', +// fields: [ +// { +// interface: 'id', +// type: 'bigInt', +// name: 'id', +// uiSchema: { +// type: 'number', +// title: '{{t("ID")}}', +// 'x-component': 'Input', +// 'x-component-props': {}, +// 'x-read-pretty': true, +// } as ISchema, +// }, +// { +// interface: 'createdAt', +// type: 'datetime', +// name: 'createdAt', +// uiSchema: { +// type: 'datetime', +// title: `{{t("Triggered at", { ns: "${NAMESPACE}" })}}`, +// 'x-component': 'DatePicker', +// 'x-component-props': {}, +// 'x-read-pretty': true, +// } as ISchema, +// }, +// { +// interface: 'm2o', +// type: 'belongsTo', +// name: 'workflowId', +// uiSchema: { +// type: 'number', +// title: `{{t("Version", { ns: "${NAMESPACE}" })}}`, +// ['x-component']({ value }) { +// const { setVisible } = useActionContext(); +// return setVisible(false)}>{`#${value}`}; +// }, +// } as ISchema, +// }, +// { +// type: 'number', +// name: 'status', as ISchema, +// }, +// ], +// }; export const executionSchema = { type: 'void', @@ -185,7 +178,7 @@ export const executionSchema = { 'x-component': 'Table.Column', properties: { createdAt: { - type: 'datetime', + type: 'string', 'x-component': 'CollectionField', 'x-component-props': { showTime: true, @@ -198,10 +191,16 @@ export const executionSchema = { type: 'void', 'x-decorator': 'Table.Column.Decorator', 'x-component': 'Table.Column', + title: `{{t("Version", { ns: "${NAMESPACE}" })}}`, properties: { workflowId: { type: 'number', - 'x-component': 'CollectionField', + ['x-component']({ value }) { + const { setVisible } = useActionContext(); + return ( + setVisible(false)}>{`#${value}`} + ); + }, 'x-read-pretty': true, }, }, diff --git a/packages/plugins/@nocobase/plugin-workflow/src/client/schemas/workflows.ts b/packages/plugins/@nocobase/plugin-workflow/src/client/schemas/workflows.ts index a9ef697cb2..3f60af348d 100644 --- a/packages/plugins/@nocobase/plugin-workflow/src/client/schemas/workflows.ts +++ b/packages/plugins/@nocobase/plugin-workflow/src/client/schemas/workflows.ts @@ -7,113 +7,12 @@ * For more information, please refer to: https://www.nocobase.com/agreement. */ -import React from 'react'; import { ISchema } from '@formily/react'; -import { useRecord } from '@nocobase/client'; -import { NAMESPACE } from '../locale'; -// import { triggers } from '../triggers'; -import { executionSchema } from './executions'; -import { TriggerOptionRender } from '../components/TriggerOptionRender'; -const collection = { - name: 'workflows', - fields: [ - { - type: 'string', - name: 'title', - interface: 'input', - uiSchema: { - title: '{{t("Name")}}', - type: 'string', - 'x-component': 'Input', - required: true, - } as ISchema, - }, - { - type: 'string', - name: 'type', - interface: 'select', - uiSchema: { - title: `{{t("Trigger type", { ns: "${NAMESPACE}" })}}`, - type: 'string', - 'x-decorator': 'FormItem', - 'x-component': 'Select', - enum: '{{useTriggersOptions()}}', - 'x-component-props': { - optionRender: TriggerOptionRender, - popupMatchSelectWidth: true, - listHeight: 300, - }, - required: true, - } as ISchema, - }, - { - type: 'boolean', - name: 'sync', - interface: 'radioGroup', - uiSchema: { - title: `{{t("Mode", { ns: "${NAMESPACE}" })}}`, - type: 'boolean', - 'x-decorator': 'FormItem', - 'x-component': 'Radio.Group', - enum: [ - { - label: `{{ t("Asynchronously", { ns: "${NAMESPACE}" }) }}`, - value: false, - color: 'cyan', - }, - { - label: `{{ t("Synchronously", { ns: "${NAMESPACE}" }) }}`, - value: true, - color: 'orange', - }, - ], - required: true, - } as ISchema, - }, - { - type: 'string', - name: 'description', - interface: 'textarea', - uiSchema: { - title: '{{t("Description")}}', - type: 'string', - 'x-component': 'Input.TextArea', - } as ISchema, - }, - { - type: 'boolean', - name: 'enabled', - interface: 'radioGroup', - uiSchema: { - title: `{{t("Status", { ns: "${NAMESPACE}" })}}`, - type: 'string', - enum: [ - { label: `{{t("On", { ns: "${NAMESPACE}" })}}`, value: true, color: '#52c41a' }, - { label: `{{t("Off", { ns: "${NAMESPACE}" })}}`, value: false }, - ], - 'x-component': 'Radio.Group', - 'x-decorator': 'FormItem', - default: false, - } as ISchema, - }, - { - type: 'number', - name: 'allExecuted', - interface: 'integer', - uiSchema: { - title: `{{t("Executed", { ns: "${NAMESPACE}" })}}`, - type: 'number', - 'x-component': 'InputNumber', - 'x-decorator': 'FormItem', - } as ISchema, - }, - { - type: 'object', - name: 'options', - }, - ], -}; +import collection from '../../common/collections/workflows'; + +import { NAMESPACE } from '../locale'; +import { executionSchema } from './executions'; const workflowFieldset = { title: { @@ -176,6 +75,7 @@ const workflowFieldset = { 'x-component-props': { min: 1, precision: 0, + className: 'auto-width', }, }, }, @@ -201,6 +101,7 @@ export const workflowSchema: ISchema = { }, sort: ['-createdAt'], except: ['config'], + appends: ['stats'], }, }, }, @@ -380,24 +281,19 @@ export const workflowSchema: ISchema = { }, }, }, - allExecuted: { + 'stats.executed': { type: 'void', 'x-decorator': 'Table.Column.Decorator', 'x-component': 'Table.Column', + title: `{{ t("Executed", { ns: "${NAMESPACE}" }) }}`, properties: { - allExecuted: { + 'stats.executed': { type: 'number', 'x-decorator': 'OpenDrawer', 'x-decorator-props': { - component: function Com(props) { - const record = useRecord(); - return React.createElement('a', { - 'aria-label': `executed-${record.title}`, - ...props, - }); - }, + component: '{{ExecutedLink}}', }, - 'x-component': 'CollectionField', + 'x-component': 'InputNumber', 'x-read-pretty': true, properties: { drawer: executionSchema, diff --git a/packages/plugins/@nocobase/plugin-workflow/src/client/triggers/index.tsx b/packages/plugins/@nocobase/plugin-workflow/src/client/triggers/index.tsx index 91f8ffe5c3..ce91ab7918 100644 --- a/packages/plugins/@nocobase/plugin-workflow/src/client/triggers/index.tsx +++ b/packages/plugins/@nocobase/plugin-workflow/src/client/triggers/index.tsx @@ -28,7 +28,7 @@ import { useResourceActionContext, } from '@nocobase/client'; -import WorkflowPlugin from '..'; +import WorkflowPlugin, { useWorkflowExecuted } from '..'; import { useFlowContext } from '../FlowContext'; import { DrawerDescription } from '../components/DrawerDescription'; import { NAMESPACE, lang } from '../locale'; @@ -39,11 +39,12 @@ function useUpdateConfigAction() { const form = useForm(); const api = useAPIClient(); const { workflow } = useFlowContext() ?? {}; + const executed = useWorkflowExecuted(); const ctx = useActionContext(); const { refresh } = useResourceActionContext(); return { async run() { - if (workflow.executed) { + if (executed) { message.error(lang('Trigger in executed workflow cannot be modified')); return; } @@ -171,6 +172,7 @@ export const TriggerConfig = () => { const { styles } = useStyles(); const compile = useCompile(); const trigger = useTrigger(); + const executed = useWorkflowExecuted(); useEffect(() => { if (workflow) { @@ -182,7 +184,7 @@ export const TriggerConfig = () => { const values = cloneDeep(workflow.config); return createForm({ initialValues: values, - disabled: workflow.executed, + disabled: executed, }); }, [workflow]); @@ -229,7 +231,6 @@ export const TriggerConfig = () => { } }, []); - const detailText = workflow.executed ? '{{t("View")}}' : '{{t("Configure")}}'; const titleText = lang('Trigger'); if (!trigger) { @@ -284,7 +285,7 @@ export const TriggerConfig = () => { onChange={(ev) => setEditingTitle(ev.target.value)} onBlur={(ev) => onChangeTitle(ev.target.value)} autoSize - disabled={workflow.executed} + disabled={executed} />
{ properties: fieldset, }, actions: { - ...(workflow.executed + ...(executed ? {} : { type: 'void', diff --git a/packages/plugins/@nocobase/plugin-workflow/src/common/collections/executions.ts b/packages/plugins/@nocobase/plugin-workflow/src/common/collections/executions.ts new file mode 100644 index 0000000000..f73f794c56 --- /dev/null +++ b/packages/plugins/@nocobase/plugin-workflow/src/common/collections/executions.ts @@ -0,0 +1,104 @@ +/** + * This file is part of the NocoBase (R) project. + * Copyright (c) 2020-2024 NocoBase Co., Ltd. + * Authors: NocoBase Team. + * + * This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License. + * For more information, please refer to: https://www.nocobase.com/agreement. + */ + +import { NAMESPACE } from '../constants'; + +export default { + dumpRules: { + group: 'log', + }, + migrationRules: ['schema-only'], + name: 'executions', + shared: true, + fields: [ + { + type: 'bigInt', + name: 'id', + interface: 'id', + uiSchema: { + type: 'number', + title: '{{t("ID")}}', + 'x-component': 'Input', + 'x-component-props': {}, + 'x-read-pretty': true, + }, + primaryKey: true, + autoIncrement: true, + }, + { + type: 'belongsTo', + name: 'workflow', + target: 'workflows', + foreignKey: 'workflowId', + interface: 'm2o', + uiSchema: { + type: 'object', + title: `{{t("Version", { ns: "${NAMESPACE}" })}}`, + 'x-component': 'AssociationField', + 'x-component-props': { + fieldNames: { + label: 'id', + value: 'id', + }, + }, + 'x-read-pretty': true, + }, + }, + { + type: 'string', + name: 'key', + }, + { + type: 'string', + name: 'eventKey', + unique: true, + }, + { + type: 'hasMany', + name: 'jobs', + onDelete: 'CASCADE', + }, + { + type: 'json', + name: 'context', + }, + { + type: 'integer', + name: 'status', + interface: 'select', + uiSchema: { + title: `{{t("Status", { ns: "${NAMESPACE}" })}}`, + type: 'string', + 'x-component': 'Select', + 'x-decorator': 'FormItem', + enum: '{{ExecutionStatusOptions}}', + }, + }, + { + type: 'json', + name: 'stack', + }, + { + type: 'json', + name: 'output', + }, + { + interface: 'createdAt', + type: 'datetime', + name: 'createdAt', + uiSchema: { + type: 'datetime', + title: `{{t("Triggered at", { ns: "${NAMESPACE}" })}}`, + 'x-component': 'DatePicker', + 'x-component-props': {}, + 'x-read-pretty': true, + }, + }, + ], +}; diff --git a/packages/plugins/@nocobase/plugin-workflow/src/common/collections/flow_nodes.ts b/packages/plugins/@nocobase/plugin-workflow/src/common/collections/flow_nodes.ts new file mode 100644 index 0000000000..a864b05e26 --- /dev/null +++ b/packages/plugins/@nocobase/plugin-workflow/src/common/collections/flow_nodes.ts @@ -0,0 +1,66 @@ +/** + * This file is part of the NocoBase (R) project. + * Copyright (c) 2020-2024 NocoBase Co., Ltd. + * Authors: NocoBase Team. + * + * This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License. + * For more information, please refer to: https://www.nocobase.com/agreement. + */ + +export default { + dumpRules: 'required', + migrationRules: ['overwrite', 'schema-only'], + name: 'flow_nodes', + shared: true, + fields: [ + { + type: 'uid', + name: 'key', + }, + { + type: 'string', + name: 'title', + }, + // which workflow belongs to + { + name: 'workflow', + type: 'belongsTo', + }, + { + name: 'upstream', + type: 'belongsTo', + target: 'flow_nodes', + }, + { + name: 'branches', + type: 'hasMany', + target: 'flow_nodes', + sourceKey: 'id', + foreignKey: 'upstreamId', + }, + // only works when upstream node is branching type, such as condition and parallel. + // put here because the design of flow-links model is not really necessary for now. + // or it should be put into flow-links model. + { + name: 'branchIndex', + type: 'integer', + }, + // Note: for reasons: + // 1. redirect type node to solve cycle flow. + // 2. recognize as real next node after branches. + { + name: 'downstream', + type: 'belongsTo', + target: 'flow_nodes', + }, + { + type: 'string', + name: 'type', + }, + { + type: 'json', + name: 'config', + defaultValue: {}, + }, + ], +}; diff --git a/packages/plugins/@nocobase/plugin-workflow/src/common/collections/jobs.ts b/packages/plugins/@nocobase/plugin-workflow/src/common/collections/jobs.ts new file mode 100644 index 0000000000..4b961d6801 --- /dev/null +++ b/packages/plugins/@nocobase/plugin-workflow/src/common/collections/jobs.ts @@ -0,0 +1,45 @@ +/** + * This file is part of the NocoBase (R) project. + * Copyright (c) 2020-2024 NocoBase Co., Ltd. + * Authors: NocoBase Team. + * + * This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License. + * For more information, please refer to: https://www.nocobase.com/agreement. + */ + +export default { + dumpRules: { + group: 'log', + }, + migrationRules: ['schema-only'], + name: 'jobs', + shared: true, + fields: [ + { + type: 'belongsTo', + name: 'execution', + }, + { + type: 'belongsTo', + name: 'node', + target: 'flow_nodes', + }, + { + type: 'string', + name: 'nodeKey', + }, + { + type: 'belongsTo', + name: 'upstream', + target: 'jobs', + }, + { + type: 'integer', + name: 'status', + }, + { + type: 'json', + name: 'result', + }, + ], +}; diff --git a/packages/plugins/@nocobase/plugin-workflow/src/common/collections/workflowStats.ts b/packages/plugins/@nocobase/plugin-workflow/src/common/collections/workflowStats.ts new file mode 100644 index 0000000000..b2ceed0b4d --- /dev/null +++ b/packages/plugins/@nocobase/plugin-workflow/src/common/collections/workflowStats.ts @@ -0,0 +1,38 @@ +/** + * This file is part of the NocoBase (R) project. + * Copyright (c) 2020-2024 NocoBase Co., Ltd. + * Authors: NocoBase Team. + * + * This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License. + * For more information, please refer to: https://www.nocobase.com/agreement. + */ + +import { NAMESPACE } from '../constants'; + +export default { + dumpRules: { + group: 'log', + }, + migrationRules: ['schema-only'], + name: 'workflowStats', + shared: true, + autoGenId: false, + fields: [ + { + name: 'key', + type: 'uid', + primaryKey: true, + }, + { + type: 'bigInt', + name: 'executed', + defaultValue: 0, + interface: 'number', + uiSchema: { + title: `{{t("Executed", { ns: "${NAMESPACE}" })}}`, + 'x-component': 'InputNumber', + 'x-read-pretty': true, + }, + }, + ], +}; diff --git a/packages/plugins/@nocobase/plugin-workflow/src/common/collections/workflowTasks.ts b/packages/plugins/@nocobase/plugin-workflow/src/common/collections/workflowTasks.ts new file mode 100644 index 0000000000..24dd818799 --- /dev/null +++ b/packages/plugins/@nocobase/plugin-workflow/src/common/collections/workflowTasks.ts @@ -0,0 +1,44 @@ +/** + * This file is part of the NocoBase (R) project. + * Copyright (c) 2020-2024 NocoBase Co., Ltd. + * Authors: NocoBase Team. + * + * This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License. + * For more information, please refer to: https://www.nocobase.com/agreement. + */ + +import { CollectionOptions } from '@nocobase/database'; + +export default function () { + return { + dumpRules: 'required', + migrationRules: ['overwrite', 'schema-only'], + name: 'workflowTasks', + shared: true, + repository: 'WorkflowTasksRepository', + fields: [ + { + name: 'user', + type: 'belongsTo', + }, + { + name: 'workflow', + type: 'belongsTo', + }, + { + type: 'string', + name: 'type', + }, + { + type: 'string', + name: 'key', + }, + ], + indexes: [ + { + unique: true, + fields: ['type', 'key'], + }, + ], + } as CollectionOptions; +} diff --git a/packages/plugins/@nocobase/plugin-workflow/src/common/collections/workflowVersionStats.ts b/packages/plugins/@nocobase/plugin-workflow/src/common/collections/workflowVersionStats.ts new file mode 100644 index 0000000000..c50edfe3dc --- /dev/null +++ b/packages/plugins/@nocobase/plugin-workflow/src/common/collections/workflowVersionStats.ts @@ -0,0 +1,38 @@ +/** + * This file is part of the NocoBase (R) project. + * Copyright (c) 2020-2024 NocoBase Co., Ltd. + * Authors: NocoBase Team. + * + * This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License. + * For more information, please refer to: https://www.nocobase.com/agreement. + */ + +import { NAMESPACE } from '../constants'; + +export default { + dumpRules: { + group: 'log', + }, + migrationRules: ['schema-only'], + name: 'workflowVersionStats', + shared: true, + autoGenId: false, + fields: [ + { + name: 'id', + type: 'bigInt', + primaryKey: true, + }, + { + type: 'bigInt', + name: 'executed', + defaultValue: 0, + interface: 'number', + uiSchema: { + title: `{{t("Executed", { ns: "${NAMESPACE}" })}}`, + 'x-component': 'InputNumber', + 'x-read-pretty': true, + }, + }, + ], +}; diff --git a/packages/plugins/@nocobase/plugin-workflow/src/common/collections/workflows.ts b/packages/plugins/@nocobase/plugin-workflow/src/common/collections/workflows.ts new file mode 100644 index 0000000000..0cbe51028a --- /dev/null +++ b/packages/plugins/@nocobase/plugin-workflow/src/common/collections/workflows.ts @@ -0,0 +1,204 @@ +/** + * This file is part of the NocoBase (R) project. + * Copyright (c) 2020-2024 NocoBase Co., Ltd. + * Authors: NocoBase Team. + * + * This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License. + * For more information, please refer to: https://www.nocobase.com/agreement. + */ + +import { NAMESPACE } from '../constants'; + +export default { + dumpRules: 'required', + migrationRules: ['overwrite', 'schema-only'], + name: 'workflows', + shared: true, + repository: 'WorkflowRepository', + fields: [ + { + name: 'key', + type: 'uid', + }, + { + type: 'string', + name: 'title', + interface: 'input', + uiSchema: { + title: '{{t("Name")}}', + type: 'string', + 'x-component': 'Input', + required: true, + }, + }, + { + type: 'boolean', + name: 'enabled', + defaultValue: false, + interface: 'radioGroup', + uiSchema: { + title: `{{t("Status", { ns: "${NAMESPACE}" })}}`, + type: 'string', + enum: [ + { label: `{{t("On", { ns: "${NAMESPACE}" })}}`, value: true, color: '#52c41a' }, + { label: `{{t("Off", { ns: "${NAMESPACE}" })}}`, value: false }, + ], + 'x-component': 'Radio.Group', + 'x-decorator': 'FormItem', + default: false, + }, + }, + { + type: 'text', + name: 'description', + interface: 'textarea', + uiSchema: { + title: '{{t("Description")}}', + type: 'string', + 'x-component': 'Input.TextArea', + }, + }, + { + type: 'string', + name: 'type', + required: true, + interface: 'select', + uiSchema: { + title: `{{t("Trigger type", { ns: "${NAMESPACE}" })}}`, + type: 'string', + 'x-decorator': 'FormItem', + 'x-component': 'Select', + enum: '{{useTriggersOptions()}}', + 'x-component-props': { + optionRender: '{{TriggerOptionRender}}', + popupMatchSelectWidth: true, + listHeight: 300, + }, + required: true, + }, + }, + { + type: 'string', + name: 'triggerTitle', + }, + { + type: 'jsonb', + name: 'config', + required: true, + defaultValue: {}, + }, + { + type: 'hasMany', + name: 'nodes', + target: 'flow_nodes', + onDelete: 'CASCADE', + }, + { + type: 'hasMany', + name: 'executions', + }, + { + type: 'integer', + name: 'executed', + defaultValue: 0, + }, + { + type: 'integer', + name: 'allExecuted', + defaultValue: 0, + }, + { + type: 'boolean', + name: 'current', + }, + { + type: 'boolean', + name: 'sync', + defaultValue: false, + interface: 'radioGroup', + uiSchema: { + title: `{{t("Mode", { ns: "${NAMESPACE}" })}}`, + type: 'boolean', + 'x-decorator': 'FormItem', + 'x-component': 'Radio.Group', + enum: [ + { + label: `{{ t("Asynchronously", { ns: "${NAMESPACE}" }) }}`, + value: false, + color: 'cyan', + }, + { + label: `{{ t("Synchronously", { ns: "${NAMESPACE}" }) }}`, + value: true, + color: 'orange', + }, + ], + required: true, + }, + }, + { + type: 'hasMany', + name: 'revisions', + target: 'workflows', + foreignKey: 'key', + sourceKey: 'key', + // NOTE: no constraints needed here because tricky self-referencing + constraints: false, + onDelete: 'NO ACTION', + }, + { + type: 'jsonb', + name: 'options', + defaultValue: {}, + }, + { + type: 'hasOne', + name: 'stats', + target: 'workflowStats', + foreignKey: 'key', + sourceKey: 'key', + constraints: false, + onDelete: 'CASCADE', + interface: 'oho', + uiSchema: { + type: 'object', + 'x-component': 'AssociationField', + 'x-component-props': { + fieldNames: { + label: 'executed', + value: 'key', + }, + }, + 'x-read-pretty': true, + }, + }, + { + type: 'hasOne', + name: 'versionStats', + target: 'workflowVersionStats', + foreignKey: 'id', + sourceKey: 'id', + constraints: false, + onDelete: 'CASCADE', + interface: 'oho', + uiSchema: { + type: 'object', + 'x-component': 'AssociationField', + 'x-component-props': { + fieldNames: { + label: 'executed', + value: 'id', + }, + }, + 'x-read-pretty': true, + }, + }, + ], + // NOTE: use unique index for avoiding deadlock in mysql when setCurrent + indexes: [ + { + unique: true, + fields: ['key', 'current'], + }, + ], +}; diff --git a/packages/plugins/@nocobase/plugin-workflow/src/common/constants.ts b/packages/plugins/@nocobase/plugin-workflow/src/common/constants.ts new file mode 100644 index 0000000000..599c217ac8 --- /dev/null +++ b/packages/plugins/@nocobase/plugin-workflow/src/common/constants.ts @@ -0,0 +1,10 @@ +/** + * This file is part of the NocoBase (R) project. + * Copyright (c) 2020-2024 NocoBase Co., Ltd. + * Authors: NocoBase Team. + * + * This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License. + * For more information, please refer to: https://www.nocobase.com/agreement. + */ + +export const NAMESPACE = 'workflow'; diff --git a/packages/plugins/@nocobase/plugin-workflow/src/locale/zh-CN.json b/packages/plugins/@nocobase/plugin-workflow/src/locale/zh-CN.json index 9769d926aa..deabf7b6bf 100644 --- a/packages/plugins/@nocobase/plugin-workflow/src/locale/zh-CN.json +++ b/packages/plugins/@nocobase/plugin-workflow/src/locale/zh-CN.json @@ -33,6 +33,10 @@ "Auto delete history when execution is on end status": "执行结束后自动删除对应状态的历史记录", "Maximum number of cycling triggers": "最大循环触发次数", "The triggers of same workflow by some node (create, update and sub-flow etc.) more than this number will be ignored. Large number may cause performance issues. Please use with caution.": "由某个节点(创建、更新和子流程等)触发同一个工作流超过这个次数时将被忽略。设置过高的次数可能会导致性能问题,请谨慎使用。", + + "Continue when disabled or upgraded": "工作流被禁用或升级到新版本继续处理在途流程", + "If checked, all nodes in-progress could continue to be processed in execution of disabled workflow. Otherwise, all nodes in-progress will be aborted automatically.": "如果选中,在途的节点在禁用或升级到新版本的工作流中将继续处理。否则将自动取消执行。", + "Trigger": "触发器", "Unknown trigger": "未知触发器", "Workflow with unknown type will cause error. Please delete it or check plugin which provide this type.": "未知类型的工作流会导致错误,请删除或检查提供该类型的插件。", diff --git a/packages/plugins/@nocobase/plugin-workflow/src/server/Plugin.ts b/packages/plugins/@nocobase/plugin-workflow/src/server/Plugin.ts index a9abb48bee..d45449c56a 100644 --- a/packages/plugins/@nocobase/plugin-workflow/src/server/Plugin.ts +++ b/packages/plugins/@nocobase/plugin-workflow/src/server/Plugin.ts @@ -15,7 +15,7 @@ import LRUCache from 'lru-cache'; import { Op } from '@nocobase/database'; import { Plugin } from '@nocobase/server'; -import { Registry } from '@nocobase/utils'; +import { Registry, uid } from '@nocobase/utils'; import { SequelizeCollectionManager } from '@nocobase/data-source-manager'; import { Logger, LoggerOptions } from '@nocobase/logger'; @@ -75,6 +75,10 @@ export default class PluginWorkflowServer extends Plugin { private onBeforeSave = async (instance: WorkflowModel, { transaction }) => { const Model = instance.constructor; + if (!instance.key) { + instance.set('key', uid()); + } + if (instance.enabled) { instance.set('current', true); } @@ -275,14 +279,24 @@ export default class PluginWorkflowServer extends Plugin { }); db.on('workflows.beforeSave', this.onBeforeSave); - db.on('workflows.afterCreate', (model: WorkflowModel, { transaction }) => { + db.on('workflows.afterCreate', async (model: WorkflowModel, { transaction }) => { + const WorkflowStatsModel = this.db.getModel('workflowStats'); + const [stats, created] = await WorkflowStatsModel.findOrCreate({ + where: { key: model.key }, + defaults: { key: model.key }, + transaction, + }); + model.stats = stats; + model.versionStats = await model.createVersionStats({ id: model.id }, { transaction }); if (model.enabled) { this.toggle(model, true, { transaction }); } }); - db.on('workflows.afterUpdate', (model: WorkflowModel, { transaction }) => - this.toggle(model, model.enabled, { transaction }), - ); + db.on('workflows.afterUpdate', async (model: WorkflowModel, { transaction }) => { + model.stats = await model.getStats({ transaction }); + model.versionStats = await model.getVersionStats({ transaction }); + this.toggle(model, model.enabled, { transaction }); + }); db.on('workflows.afterDestroy', async (model: WorkflowModel, { transaction }) => { this.toggle(model, false, { transaction }); @@ -527,7 +541,7 @@ export default class PluginWorkflowServer extends Plugin { return Promise.reject(new Error('event is not valid')); } - let execution; + let execution: ExecutionModel; try { execution = await workflow.createExecution( { @@ -548,23 +562,21 @@ export default class PluginWorkflowServer extends Plugin { this.getLogger(workflow.id).info(`execution of workflow ${workflow.id} created as ${execution.id}`); - await workflow.increment(['executed', 'allExecuted'], { transaction }); + if (!workflow.stats) { + workflow.stats = await workflow.getStats({ transaction }); + } + await workflow.stats.increment('executed', { transaction }); // NOTE: https://sequelize.org/api/v6/class/src/model.js~model#instance-method-increment if (this.db.options.dialect !== 'postgres') { - await workflow.reload({ transaction }); + await workflow.stats.reload({ transaction }); + } + if (!workflow.versionStats) { + workflow.versionStats = await workflow.getVersionStats({ transaction }); + } + await workflow.versionStats.increment('executed', { transaction }); + if (this.db.options.dialect !== 'postgres') { + await workflow.versionStats.reload({ transaction }); } - - await (workflow.constructor).update( - { - allExecuted: workflow.allExecuted, - }, - { - where: { - key: workflow.key, - }, - transaction, - }, - ); if (!sameTransaction) { await transaction.commit(); diff --git a/packages/plugins/@nocobase/plugin-workflow/src/server/__tests__/actions/nodes.test.ts b/packages/plugins/@nocobase/plugin-workflow/src/server/__tests__/actions/nodes.test.ts index 0bb667c551..a799d9aeb9 100644 --- a/packages/plugins/@nocobase/plugin-workflow/src/server/__tests__/actions/nodes.test.ts +++ b/packages/plugins/@nocobase/plugin-workflow/src/server/__tests__/actions/nodes.test.ts @@ -54,9 +54,9 @@ describe('workflow > actions > workflows', () => { const workflow = await WorkflowModel.create({ enabled: true, type: 'asyncTrigger', - executed: 1, - allExecuted: 1, }); + await workflow.stats.update({ executed: 1 }); + await workflow.versionStats.update({ executed: 1 }); const { status } = await agent.resource('workflows.nodes', workflow.id).create({ values: { diff --git a/packages/plugins/@nocobase/plugin-workflow/src/server/__tests__/actions/workflows.test.ts b/packages/plugins/@nocobase/plugin-workflow/src/server/__tests__/actions/workflows.test.ts index aa87cc75ca..980f8892c9 100644 --- a/packages/plugins/@nocobase/plugin-workflow/src/server/__tests__/actions/workflows.test.ts +++ b/packages/plugins/@nocobase/plugin-workflow/src/server/__tests__/actions/workflows.test.ts @@ -19,6 +19,8 @@ describe('workflow > actions > workflows', () => { let PostRepo; let WorkflowModel; let ExecutionModel; + let WorkflowStatsRepo; + let WorkflowVersionStatsRepo; beforeEach(async () => { app = await getApp(); @@ -26,6 +28,8 @@ describe('workflow > actions > workflows', () => { db = app.db; WorkflowModel = db.getCollection('workflows').model; ExecutionModel = db.getCollection('executions').model; + WorkflowStatsRepo = db.getCollection('workflowStats').repository; + WorkflowVersionStatsRepo = db.getCollection('workflowVersionStats').repository; PostModel = db.getCollection('posts').model; PostRepo = db.getCollection('posts').repository; }); @@ -185,6 +189,12 @@ describe('workflow > actions > workflows', () => { const j2c = await JobModel.count(); expect(j2c).toBe(1); + + // NOTE: stats records should be deleted + const statsCount = await WorkflowStatsRepo.count(); + expect(statsCount).toBe(0); + const versionStatsCount = await WorkflowVersionStatsRepo.count(); + expect(versionStatsCount).toBe(0); }); }); @@ -211,13 +221,23 @@ describe('workflow > actions > workflows', () => { }); expect(status).toBe(200); - const { data: w2 } = body; + const w2 = await WorkflowModel.findOne({ + where: { + id: body.data.id, + }, + include: ['stats', 'versionStats'], + }); expect(w2.config).toMatchObject(w1.config); expect(w2.key).toBe(w1.key); expect(w2.current).toBeFalsy(); expect(w2.enabled).toBe(false); - expect(w2.executed).toBe(0); - expect(w2.allExecuted).toBe(1); + expect(w2.versionStats.executed).toBe(0); + expect(w2.stats.executed).toBe(1); + + const s1c = await WorkflowStatsRepo.count(); + expect(s1c).toBe(1); + const sv1c = await WorkflowVersionStatsRepo.count(); + expect(sv1c).toBe(2); await WorkflowModel.update( { @@ -237,15 +257,16 @@ describe('workflow > actions > workflows', () => { const [w1next, w2next] = await WorkflowModel.findAll({ order: [['id', 'ASC']], + include: ['stats', 'versionStats'], }); expect(w1next.enabled).toBe(false); expect(w1next.current).toBe(null); - expect(w1next.allExecuted).toBe(2); + expect(w1next.stats.executed).toBe(2); expect(w2next.enabled).toBe(true); expect(w2next.current).toBe(true); - expect(w2next.executed).toBe(1); - expect(w2next.allExecuted).toBe(2); + expect(w2next.versionStats.executed).toBe(1); + expect(w2next.stats.executed).toBe(2); const [e1] = await w1next.getExecutions(); const [e2] = await w2next.getExecutions(); @@ -330,12 +351,18 @@ describe('workflow > actions > workflows', () => { }); expect(status).toBe(200); - const { data: w2 } = body; + const w2 = await WorkflowModel.findOne({ + where: { + id: body.data.id, + }, + include: ['stats', 'versionStats'], + }); expect(w2.config).toMatchObject(w1.config); expect(w2.key).not.toBe(w1.key); expect(w2.current).toBeTruthy(); expect(w2.enabled).toBe(false); - expect(w2.allExecuted).toBe(0); + expect(w2.stats.executed).toBe(0); + expect(w2.versionStats.executed).toBe(0); // stop w1 await WorkflowModel.update( @@ -368,15 +395,16 @@ describe('workflow > actions > workflows', () => { const [w1next, w2next] = await WorkflowModel.findAll({ order: [['id', 'ASC']], + include: ['stats', 'versionStats'], }); expect(w1next.enabled).toBe(false); expect(w1next.current).toBe(true); - expect(w1next.executed).toBe(1); - expect(w1next.allExecuted).toBe(1); + expect(w1next.versionStats.executed).toBe(1); + expect(w1next.stats.executed).toBe(1); expect(w2next.enabled).toBe(true); - expect(w2next.executed).toBe(1); - expect(w2next.allExecuted).toBe(1); + expect(w2next.versionStats.executed).toBe(1); + expect(w2next.stats.executed).toBe(1); const [e1] = await w1next.getExecutions(); const [e2] = await w2next.getExecutions(); @@ -402,12 +430,17 @@ describe('workflow > actions > workflows', () => { }); expect(status).toBe(200); - const { data: w2 } = body; + const w2 = await WorkflowModel.findOne({ + where: { + id: body.data.id, + }, + include: ['stats', 'versionStats'], + }); expect(w2.config).toMatchObject(w1.config); expect(w2.key).not.toBe(w1.key); expect(w2.current).toBeTruthy(); expect(w2.enabled).toBe(false); - expect(w2.allExecuted).toBe(0); + expect(w2.stats.executed).toBe(0); expect(w2.sync).toBe(true); // stop w1 @@ -439,15 +472,16 @@ describe('workflow > actions > workflows', () => { const [w1next, w2next] = await WorkflowModel.findAll({ order: [['id', 'ASC']], + include: ['stats', 'versionStats'], }); expect(w1next.enabled).toBe(false); expect(w1next.current).toBe(true); - expect(w1next.executed).toBe(1); - expect(w1next.allExecuted).toBe(1); + expect(w1next.versionStats.executed).toBe(1); + expect(w1next.stats.executed).toBe(1); expect(w2next.enabled).toBe(true); - expect(w2next.executed).toBe(1); - expect(w2next.allExecuted).toBe(1); + expect(w2next.versionStats.executed).toBe(1); + expect(w2next.stats.executed).toBe(1); const [e1] = await w1next.getExecutions(); const [e2] = await w2next.getExecutions(); diff --git a/packages/plugins/@nocobase/plugin-workflow/src/server/__tests__/migrations/20250320223415-stats.test.ts b/packages/plugins/@nocobase/plugin-workflow/src/server/__tests__/migrations/20250320223415-stats.test.ts new file mode 100644 index 0000000000..9e373fc164 --- /dev/null +++ b/packages/plugins/@nocobase/plugin-workflow/src/server/__tests__/migrations/20250320223415-stats.test.ts @@ -0,0 +1,155 @@ +/** + * This file is part of the NocoBase (R) project. + * Copyright (c) 2020-2024 NocoBase Co., Ltd. + * Authors: NocoBase Team. + * + * This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License. + * For more information, please refer to: https://www.nocobase.com/agreement. + */ + +import { describe, test } from 'vitest'; + +import { MockServer } from '@nocobase/test'; +import { getApp } from '@nocobase/plugin-workflow-test'; + +import Migration from '../../migrations/20250320223415-stats'; +import PluginWorkflowServer from '../..'; + +describe('20250320223415-stats', () => { + let app: MockServer; + let workflow; + let plugin: PluginWorkflowServer; + let WorkflowRepo; + let WorkflowStatsRepo; + let WorkflowVersionStatsRepo; + + describe('legacy stats should be migrated', () => { + beforeEach(async () => { + app = await getApp(); + app.version.update('1.6.0'); + plugin = app.pm.get(PluginWorkflowServer) as PluginWorkflowServer; + WorkflowRepo = app.db.getRepository('workflows'); + WorkflowStatsRepo = app.db.getRepository('workflowStats'); + WorkflowVersionStatsRepo = app.db.getRepository('workflowVersionStats'); + }); + + afterEach(() => app.destroy()); + + test('only one version', async () => { + workflow = await WorkflowRepo.create({ + values: { + type: 'syncTrigger', + executed: 1, + allExecuted: 1, + key: 'abc', + }, + hooks: false, + }); + + const migration = new Migration({ app, db: app.db } as any); + await migration.up(); + + const stats = await WorkflowStatsRepo.findOne({ + filterByTk: workflow.get('key'), + }); + + expect(stats.get('executed')).toBe(1); + + const versionStats = await WorkflowVersionStatsRepo.findOne({ + filterByTk: workflow.get('id'), + }); + + expect(versionStats.get('executed')).toBe(1); + }); + + test('multiple versions', async () => { + const w1 = await WorkflowRepo.create({ + values: { + enabled: true, + type: 'syncTrigger', + executed: 1, + allExecuted: 2, + key: 'abc', + }, + hooks: false, + }); + + const w2 = await WorkflowRepo.create({ + values: { + enabled: true, + type: 'syncTrigger', + executed: 1, + allExecuted: 2, + key: 'abc', + }, + hooks: false, + }); + + const migration = new Migration({ app, db: app.db } as any); + await migration.up(); + + const stats = await WorkflowStatsRepo.findOne({ + filterByTk: w1.get('key'), + }); + + expect(stats.get('executed')).toBe(2); + + const v1Stats = await WorkflowVersionStatsRepo.findOne({ + filterByTk: w1.get('id'), + }); + + expect(v1Stats.get('executed')).toBe(1); + + const v2Stats = await WorkflowVersionStatsRepo.findOne({ + filterByTk: w2.get('id'), + }); + + expect(v2Stats.get('executed')).toBe(1); + }); + }); + + describe('executed field should works correctly after migrated', () => { + beforeEach(async () => { + app = await getApp(); + app.version.update('1.6.0'); + plugin = app.pm.get(PluginWorkflowServer) as PluginWorkflowServer; + WorkflowStatsRepo = app.db.getRepository('workflowStats'); + WorkflowVersionStatsRepo = app.db.getRepository('workflowVersionStats'); + const WorkflowRepo = app.db.getRepository('workflows'); + workflow = await WorkflowRepo.create({ + values: { + type: 'syncTrigger', + key: 'abc', + }, + hooks: false, + }); + }); + + afterEach(() => app.destroy()); + + test('trigger should get correct executed value', async () => { + const migration = new Migration({ app, db: app.db } as any); + await migration.up(); + + await workflow.update({ + enabled: true, + }); + workflow.stats = await workflow.getStats(); + workflow.versionStats = await workflow.getVersionStats(); + + await plugin.trigger(workflow, {}); + + const stats = await WorkflowStatsRepo.findOne({ + filterByTk: workflow.get('key'), + }); + + expect(stats.get('executed')).toBe(1); + + const versionStats = await WorkflowVersionStatsRepo.findOne({ + filterByTk: workflow.get('id'), + }); + + expect(versionStats.get('executed')).toBe(1); + }); + }); +}); diff --git a/packages/plugins/@nocobase/plugin-workflow/src/server/actions/nodes.ts b/packages/plugins/@nocobase/plugin-workflow/src/server/actions/nodes.ts index 1cffbd2dbd..daa709f332 100644 --- a/packages/plugins/@nocobase/plugin-workflow/src/server/actions/nodes.ts +++ b/packages/plugins/@nocobase/plugin-workflow/src/server/actions/nodes.ts @@ -19,7 +19,9 @@ export async function create(context: Context, next) { context.body = await db.sequelize.transaction(async (transaction) => { const workflow = (await repository.getSourceModel(transaction)) as WorkflowModel; - if (workflow.executed) { + workflow.versionStats = await workflow.getVersionStats({ transaction }); + const { executed } = workflow.versionStats; + if (executed) { context.throw(400, 'Node could not be created in executed workflow'); } @@ -126,9 +128,9 @@ export async function destroy(context: Context, next) { const instance = await repository.findOne({ filterByTk, fields: [...fields, 'workflowId'], - appends: ['upstream', 'downstream', 'workflow'], + appends: ['upstream', 'downstream', 'workflow.versionStats.executed'], }); - if (instance.workflow.executed) { + if (instance.workflow.versionStats.executed) { context.throw(400, 'Nodes in executed workflow could not be deleted'); } @@ -199,10 +201,10 @@ export async function update(context: Context, next) { // TODO(optimize): duplicated instance query const { workflow } = await repository.findOne({ filterByTk, - appends: ['workflow.executed'], + appends: ['workflow.versionStats.executed'], transaction, }); - if (workflow.executed) { + if (workflow.versionStats.executed) { context.throw(400, 'Nodes in executed workflow could not be reconfigured'); } diff --git a/packages/plugins/@nocobase/plugin-workflow/src/server/actions/workflows.ts b/packages/plugins/@nocobase/plugin-workflow/src/server/actions/workflows.ts index e80fc1d77b..02b714d8ef 100644 --- a/packages/plugins/@nocobase/plugin-workflow/src/server/actions/workflows.ts +++ b/packages/plugins/@nocobase/plugin-workflow/src/server/actions/workflows.ts @@ -22,8 +22,11 @@ export async function update(context: Context, next) { }); // only enable/disable if (Object.keys(values).includes('config')) { - const workflow = await repository.findById(filterByTk); - if (workflow.get('executed')) { + const workflow = await repository.findOne({ + filterByTk, + appends: ['versionStats'], + }); + if (workflow.versionStats.executed) { return context.throw(400, 'config of executed workflow can not be updated'); } } diff --git a/packages/plugins/@nocobase/plugin-workflow/src/server/collections/executions.ts b/packages/plugins/@nocobase/plugin-workflow/src/server/collections/executions.ts index 85c3a20b1d..1569e1800e 100644 --- a/packages/plugins/@nocobase/plugin-workflow/src/server/collections/executions.ts +++ b/packages/plugins/@nocobase/plugin-workflow/src/server/collections/executions.ts @@ -9,47 +9,6 @@ import { CollectionOptions } from '@nocobase/database'; -export default { - dumpRules: { - group: 'log', - }, - migrationRules: ['schema-only'], - name: 'executions', - shared: true, - fields: [ - { - type: 'belongsTo', - name: 'workflow', - }, - { - type: 'string', - name: 'key', - }, - { - type: 'string', - name: 'eventKey', - unique: true, - }, - { - type: 'hasMany', - name: 'jobs', - onDelete: 'CASCADE', - }, - { - type: 'json', - name: 'context', - }, - { - type: 'integer', - name: 'status', - }, - { - type: 'json', - name: 'stack', - }, - { - type: 'json', - name: 'output', - }, - ], -} as CollectionOptions; +import options from '../../common/collections/executions'; + +export default options as CollectionOptions; diff --git a/packages/plugins/@nocobase/plugin-workflow/src/server/collections/flow_nodes.ts b/packages/plugins/@nocobase/plugin-workflow/src/server/collections/flow_nodes.ts index 5c06802f0b..c4f409ae83 100644 --- a/packages/plugins/@nocobase/plugin-workflow/src/server/collections/flow_nodes.ts +++ b/packages/plugins/@nocobase/plugin-workflow/src/server/collections/flow_nodes.ts @@ -9,60 +9,6 @@ import { CollectionOptions } from '@nocobase/database'; -export default { - dumpRules: 'required', - migrationRules: ['overwrite', 'schema-only'], - name: 'flow_nodes', - shared: true, - fields: [ - { - type: 'uid', - name: 'key', - }, - { - type: 'string', - name: 'title', - }, - // which workflow belongs to - { - name: 'workflow', - type: 'belongsTo', - }, - { - name: 'upstream', - type: 'belongsTo', - target: 'flow_nodes', - }, - { - name: 'branches', - type: 'hasMany', - target: 'flow_nodes', - sourceKey: 'id', - foreignKey: 'upstreamId', - }, - // only works when upstream node is branching type, such as condition and parallel. - // put here because the design of flow-links model is not really necessary for now. - // or it should be put into flow-links model. - { - name: 'branchIndex', - type: 'integer', - }, - // Note: for reasons: - // 1. redirect type node to solve cycle flow. - // 2. recognize as real next node after branches. - { - name: 'downstream', - type: 'belongsTo', - target: 'flow_nodes', - }, - { - type: 'string', - name: 'type', - }, - { - type: 'json', - name: 'config', - defaultValue: {}, - }, - ], -} as CollectionOptions; +import options from '../../common/collections/flow_nodes'; + +export default options as CollectionOptions; diff --git a/packages/plugins/@nocobase/plugin-workflow/src/server/collections/jobs.ts b/packages/plugins/@nocobase/plugin-workflow/src/server/collections/jobs.ts index 86a5533cfd..f3d69c3de2 100644 --- a/packages/plugins/@nocobase/plugin-workflow/src/server/collections/jobs.ts +++ b/packages/plugins/@nocobase/plugin-workflow/src/server/collections/jobs.ts @@ -9,39 +9,6 @@ import { CollectionOptions } from '@nocobase/database'; -export default { - dumpRules: { - group: 'log', - }, - migrationRules: ['schema-only'], - name: 'jobs', - shared: true, - fields: [ - { - type: 'belongsTo', - name: 'execution', - }, - { - type: 'belongsTo', - name: 'node', - target: 'flow_nodes', - }, - { - type: 'string', - name: 'nodeKey', - }, - { - type: 'belongsTo', - name: 'upstream', - target: 'jobs', - }, - { - type: 'integer', - name: 'status', - }, - { - type: 'json', - name: 'result', - }, - ], -} as CollectionOptions; +import options from '../../common/collections/jobs'; + +export default options as CollectionOptions; diff --git a/packages/plugins/@nocobase/plugin-workflow/src/server/collections/workflowStats.ts b/packages/plugins/@nocobase/plugin-workflow/src/server/collections/workflowStats.ts new file mode 100644 index 0000000000..911e8ac922 --- /dev/null +++ b/packages/plugins/@nocobase/plugin-workflow/src/server/collections/workflowStats.ts @@ -0,0 +1,14 @@ +/** + * This file is part of the NocoBase (R) project. + * Copyright (c) 2020-2024 NocoBase Co., Ltd. + * Authors: NocoBase Team. + * + * This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License. + * For more information, please refer to: https://www.nocobase.com/agreement. + */ + +import { CollectionOptions } from '@nocobase/database'; + +import options from '../../common/collections/workflowStats'; + +export default options as CollectionOptions; diff --git a/packages/plugins/@nocobase/plugin-workflow/src/server/collections/workflowTasks.ts b/packages/plugins/@nocobase/plugin-workflow/src/server/collections/workflowTasks.ts index 24dd818799..32142412f6 100644 --- a/packages/plugins/@nocobase/plugin-workflow/src/server/collections/workflowTasks.ts +++ b/packages/plugins/@nocobase/plugin-workflow/src/server/collections/workflowTasks.ts @@ -9,36 +9,6 @@ import { CollectionOptions } from '@nocobase/database'; -export default function () { - return { - dumpRules: 'required', - migrationRules: ['overwrite', 'schema-only'], - name: 'workflowTasks', - shared: true, - repository: 'WorkflowTasksRepository', - fields: [ - { - name: 'user', - type: 'belongsTo', - }, - { - name: 'workflow', - type: 'belongsTo', - }, - { - type: 'string', - name: 'type', - }, - { - type: 'string', - name: 'key', - }, - ], - indexes: [ - { - unique: true, - fields: ['type', 'key'], - }, - ], - } as CollectionOptions; -} +import options from '../../common/collections/workflowTasks'; + +export default options as CollectionOptions; diff --git a/packages/plugins/@nocobase/plugin-workflow/src/server/collections/workflowVersionStats.ts b/packages/plugins/@nocobase/plugin-workflow/src/server/collections/workflowVersionStats.ts new file mode 100644 index 0000000000..3067755575 --- /dev/null +++ b/packages/plugins/@nocobase/plugin-workflow/src/server/collections/workflowVersionStats.ts @@ -0,0 +1,14 @@ +/** + * This file is part of the NocoBase (R) project. + * Copyright (c) 2020-2024 NocoBase Co., Ltd. + * Authors: NocoBase Team. + * + * This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License. + * For more information, please refer to: https://www.nocobase.com/agreement. + */ + +import { CollectionOptions } from '@nocobase/database'; + +import options from '../../common/collections/workflowVersionStats'; + +export default options as CollectionOptions; diff --git a/packages/plugins/@nocobase/plugin-workflow/src/server/collections/workflows.ts b/packages/plugins/@nocobase/plugin-workflow/src/server/collections/workflows.ts index 5af586e344..62961d431c 100644 --- a/packages/plugins/@nocobase/plugin-workflow/src/server/collections/workflows.ts +++ b/packages/plugins/@nocobase/plugin-workflow/src/server/collections/workflows.ts @@ -9,104 +9,6 @@ import { CollectionOptions } from '@nocobase/database'; -export default function () { - return { - dumpRules: 'required', - migrationRules: ['overwrite', 'schema-only'], - name: 'workflows', - shared: true, - repository: 'WorkflowRepository', - fields: [ - { - name: 'key', - type: 'uid', - }, - { - type: 'string', - name: 'title', - interface: 'input', - uiSchema: { - title: '{{t("Name")}}', - type: 'string', - 'x-component': 'Input', - required: true, - }, - }, - { - type: 'boolean', - name: 'enabled', - defaultValue: false, - }, - { - type: 'text', - name: 'description', - }, - { - type: 'string', - name: 'type', - required: true, - }, - { - type: 'string', - name: 'triggerTitle', - }, - { - type: 'jsonb', - name: 'config', - required: true, - defaultValue: {}, - }, - { - type: 'hasMany', - name: 'nodes', - target: 'flow_nodes', - onDelete: 'CASCADE', - }, - { - type: 'hasMany', - name: 'executions', - }, - { - type: 'integer', - name: 'executed', - defaultValue: 0, - }, - { - type: 'integer', - name: 'allExecuted', - defaultValue: 0, - }, - { - type: 'boolean', - name: 'current', - }, - { - type: 'boolean', - name: 'sync', - defaultValue: false, - }, - { - type: 'hasMany', - name: 'revisions', - target: 'workflows', - foreignKey: 'key', - sourceKey: 'key', - // NOTE: no constraints needed here because tricky self-referencing - constraints: false, - onDelete: 'NO ACTION', - }, - { - type: 'jsonb', - name: 'options', - defaultValue: {}, - }, - ], - // NOTE: use unique index for avoiding deadlock in mysql when setCurrent - indexes: [ - { - unique: true, - fields: ['key', 'current'], - }, - ], - } as CollectionOptions; -} +import options from '../../common/collections/workflows'; + +export default options as CollectionOptions; diff --git a/packages/plugins/@nocobase/plugin-workflow/src/server/migrations/20250320223415-stats.ts b/packages/plugins/@nocobase/plugin-workflow/src/server/migrations/20250320223415-stats.ts new file mode 100644 index 0000000000..0e0b787d09 --- /dev/null +++ b/packages/plugins/@nocobase/plugin-workflow/src/server/migrations/20250320223415-stats.ts @@ -0,0 +1,57 @@ +/** + * This file is part of the NocoBase (R) project. + * Copyright (c) 2020-2024 NocoBase Co., Ltd. + * Authors: NocoBase Team. + * + * This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License. + * For more information, please refer to: https://www.nocobase.com/agreement. + */ + +import { Migration } from '@nocobase/server'; + +export default class extends Migration { + appVersion = '<1.7.0'; + on = 'afterLoad'; + async up() { + const { db } = this.context; + + const WorkflowRepo = db.getRepository('workflows'); + const WorkflowStatsModel = db.getModel('workflowStats'); + const WorkflowVersionStatsModel = db.getModel('workflowVersionStats'); + await db.sequelize.transaction(async (transaction) => { + const workflows = await WorkflowRepo.find({ + fields: ['id', 'key', 'executed', 'allExecuted'], + transaction, + }); + + const groupCounts: { [key: string]: { key: string; executed: number } } = {}; + for (const workflow of workflows) { + await WorkflowVersionStatsModel.findOrCreate({ + where: { + id: workflow.id, + }, + defaults: { + id: workflow.id, + executed: workflow.get('executed'), + }, + transaction, + }); + + const key = workflow.get('key'); + groupCounts[key] = { + key, + executed: workflow.get('allExecuted') || 0, + }; + } + for (const values of Object.values(groupCounts)) { + await WorkflowStatsModel.findOrCreate({ + where: { + key: values.key, + }, + defaults: values, + transaction, + }); + } + }); + } +} diff --git a/packages/plugins/@nocobase/plugin-workflow/src/server/repositories/WorkflowRepository.ts b/packages/plugins/@nocobase/plugin-workflow/src/server/repositories/WorkflowRepository.ts index 3656c45f31..ac011952d4 100644 --- a/packages/plugins/@nocobase/plugin-workflow/src/server/repositories/WorkflowRepository.ts +++ b/packages/plugins/@nocobase/plugin-workflow/src/server/repositories/WorkflowRepository.ts @@ -18,7 +18,7 @@ export default class WorkflowRepository extends Repository { const origin = await this.findOne({ filterByTk, filter, - appends: ['nodes'], + appends: ['nodes', 'stats', 'versionStats'], context, transaction, }); @@ -30,7 +30,6 @@ export default class WorkflowRepository extends Repository { key: filter.key, title: origin.title, triggerTitle: origin.triggerTitle, - allExecuted: origin.allExecuted, current: null, ...values, } diff --git a/packages/plugins/@nocobase/plugin-workflow/src/server/triggers/ScheduleTrigger/DateFieldScheduleTrigger.ts b/packages/plugins/@nocobase/plugin-workflow/src/server/triggers/ScheduleTrigger/DateFieldScheduleTrigger.ts index c720e13eca..8e7d6eba9d 100644 --- a/packages/plugins/@nocobase/plugin-workflow/src/server/triggers/ScheduleTrigger/DateFieldScheduleTrigger.ts +++ b/packages/plugins/@nocobase/plugin-workflow/src/server/triggers/ScheduleTrigger/DateFieldScheduleTrigger.ts @@ -159,12 +159,12 @@ export default class DateFieldScheduleTrigger { // i. endsOn after now -> yes // ii. endsOn before now -> no async loadRecordsToSchedule( - { id, config: { collection, limit, startsOn, repeat, endsOn }, allExecuted }: WorkflowModel, + { id, config: { collection, limit, startsOn, repeat, endsOn }, stats }: WorkflowModel, currentDate: Date, ) { const { dataSourceManager } = this.workflow.app; - if (limit && allExecuted >= limit) { - this.workflow.getLogger(id).warn(`[Schedule on date field] limit reached (all executed ${allExecuted})`); + if (limit && stats.executed >= limit) { + this.workflow.getLogger(id).warn(`[Schedule on date field] limit reached (all executed ${stats.executed})`); return []; } if (!startsOn) { @@ -256,9 +256,9 @@ export default class DateFieldScheduleTrigger { getRecordNextTime(workflow: WorkflowModel, record, nextSecond = false) { const { config: { startsOn, endsOn, repeat, limit }, - allExecuted, + stats, } = workflow; - if (limit && allExecuted >= limit) { + if (limit && stats.executed >= limit) { return null; } const range = this.cacheCycle; @@ -356,7 +356,7 @@ export default class DateFieldScheduleTrigger { }, ); - if (!workflow.config.repeat || (workflow.config.limit && workflow.allExecuted >= workflow.config.limit - 1)) { + if (!workflow.config.repeat || (workflow.config.limit && workflow.stats.executed >= workflow.config.limit - 1)) { return; } diff --git a/packages/plugins/@nocobase/plugin-workflow/src/server/triggers/ScheduleTrigger/StaticScheduleTrigger.ts b/packages/plugins/@nocobase/plugin-workflow/src/server/triggers/ScheduleTrigger/StaticScheduleTrigger.ts index 9552ceae22..542746ed9a 100644 --- a/packages/plugins/@nocobase/plugin-workflow/src/server/triggers/ScheduleTrigger/StaticScheduleTrigger.ts +++ b/packages/plugins/@nocobase/plugin-workflow/src/server/triggers/ScheduleTrigger/StaticScheduleTrigger.ts @@ -50,8 +50,8 @@ export default class StaticScheduleTrigger { }); } - getNextTime({ config, allExecuted }: WorkflowModel, currentDate: Date, nextSecond = false) { - if (config.limit && allExecuted >= config.limit) { + getNextTime({ config, stats }: WorkflowModel, currentDate: Date, nextSecond = false) { + if (config.limit && stats.executed >= config.limit) { return null; } if (!config.startsOn) { @@ -119,7 +119,7 @@ export default class StaticScheduleTrigger { this.workflow.trigger(workflow, { date: new Date(time) }, { eventKey }); - if (!workflow.config.repeat || (workflow.config.limit && workflow.allExecuted >= workflow.config.limit - 1)) { + if (!workflow.config.repeat || (workflow.config.limit && workflow.stats.executed >= workflow.config.limit - 1)) { return; } diff --git a/packages/plugins/@nocobase/plugin-workflow/src/server/types/Workflow.ts b/packages/plugins/@nocobase/plugin-workflow/src/server/types/Workflow.ts index 4a184eff57..f5b637a0d6 100644 --- a/packages/plugins/@nocobase/plugin-workflow/src/server/types/Workflow.ts +++ b/packages/plugins/@nocobase/plugin-workflow/src/server/types/Workflow.ts @@ -29,8 +29,6 @@ export default class WorkflowModel extends Model { declare type: string; declare config: any; declare options: any; - declare executed: number; - declare allExecuted: number; declare sync: boolean; declare createdAt: Date; diff --git a/packages/plugins/@nocobase/plugin-workflow/src/swagger/index.ts b/packages/plugins/@nocobase/plugin-workflow/src/swagger/index.ts index ef4d4ceaf9..0114a7218f 100644 --- a/packages/plugins/@nocobase/plugin-workflow/src/swagger/index.ts +++ b/packages/plugins/@nocobase/plugin-workflow/src/swagger/index.ts @@ -579,14 +579,6 @@ export default { type: 'array', description: 'Revisions', }, - executed: { - type: 'integer', - description: 'Executed count for a single version', - }, - allExecuted: { - type: 'integer', - description: 'Executed count for all versions of the same workflow', - }, }, }, filterByTk: { @@ -623,12 +615,6 @@ export default { key: { $ref: '#/components/schemas/workflow/model/properties/key', }, - executed: { - $ref: '#/components/schemas/workflow/model/properties/executed', - }, - allExecuted: { - $ref: '#/components/schemas/workflow/model/properties/allExecuted', - }, }, }, }, diff --git a/packages/presets/nocobase/package.json b/packages/presets/nocobase/package.json index 208a462dab..5c4b3b0e31 100644 --- a/packages/presets/nocobase/package.json +++ b/packages/presets/nocobase/package.json @@ -1,81 +1,81 @@ { "name": "@nocobase/preset-nocobase", - "version": "1.7.0-beta.9", + "version": "1.7.0-alpha.10", "license": "AGPL-3.0", "main": "./lib/server/index.js", "dependencies": { "@formily/json-schema": "2.x", - "@nocobase/plugin-acl": "1.7.0-beta.9", - "@nocobase/plugin-action-bulk-edit": "1.7.0-beta.9", - "@nocobase/plugin-action-bulk-update": "1.7.0-beta.9", - "@nocobase/plugin-action-custom-request": "1.7.0-beta.9", - "@nocobase/plugin-action-duplicate": "1.7.0-beta.9", - "@nocobase/plugin-action-export": "1.7.0-beta.9", - "@nocobase/plugin-action-import": "1.7.0-beta.9", - "@nocobase/plugin-action-print": "1.7.0-beta.9", - "@nocobase/plugin-ai": "1.7.0-beta.9", - "@nocobase/plugin-api-doc": "1.7.0-beta.9", - "@nocobase/plugin-api-keys": "1.7.0-beta.9", - "@nocobase/plugin-async-task-manager": "1.7.0-beta.9", - "@nocobase/plugin-audit-logs": "1.7.0-beta.9", - "@nocobase/plugin-auth": "1.7.0-beta.9", - "@nocobase/plugin-auth-sms": "1.7.0-beta.9", - "@nocobase/plugin-backup-restore": "1.7.0-beta.9", - "@nocobase/plugin-block-iframe": "1.7.0-beta.9", - "@nocobase/plugin-block-template": "1.7.0-beta.9", - "@nocobase/plugin-block-workbench": "1.7.0-beta.9", - "@nocobase/plugin-calendar": "1.7.0-beta.9", - "@nocobase/plugin-charts": "1.7.0-beta.9", - "@nocobase/plugin-client": "1.7.0-beta.9", - "@nocobase/plugin-collection-sql": "1.7.0-beta.9", - "@nocobase/plugin-collection-tree": "1.7.0-beta.9", - "@nocobase/plugin-data-source-main": "1.7.0-beta.9", - "@nocobase/plugin-data-source-manager": "1.7.0-beta.9", - "@nocobase/plugin-data-visualization": "1.7.0-beta.9", - "@nocobase/plugin-environment-variables": "1.7.0-beta.9", - "@nocobase/plugin-error-handler": "1.7.0-beta.9", - "@nocobase/plugin-field-china-region": "1.7.0-beta.9", - "@nocobase/plugin-field-formula": "1.7.0-beta.9", - "@nocobase/plugin-field-m2m-array": "1.7.0-beta.9", - "@nocobase/plugin-field-markdown-vditor": "1.7.0-beta.9", - "@nocobase/plugin-field-sequence": "1.7.0-beta.9", - "@nocobase/plugin-field-sort": "1.7.0-beta.9", - "@nocobase/plugin-file-manager": "1.7.0-beta.9", - "@nocobase/plugin-gantt": "1.7.0-beta.9", - "@nocobase/plugin-graph-collection-manager": "1.7.0-beta.9", - "@nocobase/plugin-kanban": "1.7.0-beta.9", - "@nocobase/plugin-localization": "1.7.0-beta.9", - "@nocobase/plugin-logger": "1.7.0-beta.9", - "@nocobase/plugin-map": "1.7.0-beta.9", - "@nocobase/plugin-mobile": "1.7.0-beta.9", - "@nocobase/plugin-mobile-client": "1.7.0-beta.9", - "@nocobase/plugin-mock-collections": "1.7.0-beta.9", - "@nocobase/plugin-multi-app-manager": "1.7.0-beta.9", - "@nocobase/plugin-multi-app-share-collection": "1.7.0-beta.9", - "@nocobase/plugin-notification-email": "1.7.0-beta.9", - "@nocobase/plugin-notification-in-app-message": "1.7.0-beta.9", - "@nocobase/plugin-notification-manager": "1.7.0-beta.9", - "@nocobase/plugin-public-forms": "1.7.0-beta.9", - "@nocobase/plugin-snapshot-field": "1.7.0-beta.9", - "@nocobase/plugin-system-settings": "1.7.0-beta.9", - "@nocobase/plugin-theme-editor": "1.7.0-beta.9", - "@nocobase/plugin-ui-schema-storage": "1.7.0-beta.9", - "@nocobase/plugin-user-data-sync": "1.7.0-beta.9", - "@nocobase/plugin-users": "1.7.0-beta.9", - "@nocobase/plugin-verification": "1.7.0-beta.9", - "@nocobase/plugin-workflow": "1.7.0-beta.9", - "@nocobase/plugin-workflow-action-trigger": "1.7.0-beta.9", - "@nocobase/plugin-workflow-aggregate": "1.7.0-beta.9", - "@nocobase/plugin-workflow-delay": "1.7.0-beta.9", - "@nocobase/plugin-workflow-dynamic-calculation": "1.7.0-beta.9", - "@nocobase/plugin-workflow-loop": "1.7.0-beta.9", - "@nocobase/plugin-workflow-mailer": "1.7.0-beta.9", - "@nocobase/plugin-workflow-manual": "1.7.0-beta.9", - "@nocobase/plugin-workflow-notification": "1.7.0-beta.9", - "@nocobase/plugin-workflow-parallel": "1.7.0-beta.9", - "@nocobase/plugin-workflow-request": "1.7.0-beta.9", - "@nocobase/plugin-workflow-sql": "1.7.0-beta.9", - "@nocobase/server": "1.7.0-beta.9", + "@nocobase/plugin-acl": "1.7.0-alpha.10", + "@nocobase/plugin-action-bulk-edit": "1.7.0-alpha.10", + "@nocobase/plugin-action-bulk-update": "1.7.0-alpha.10", + "@nocobase/plugin-action-custom-request": "1.7.0-alpha.10", + "@nocobase/plugin-action-duplicate": "1.7.0-alpha.10", + "@nocobase/plugin-action-export": "1.7.0-alpha.10", + "@nocobase/plugin-action-import": "1.7.0-alpha.10", + "@nocobase/plugin-action-print": "1.7.0-alpha.10", + "@nocobase/plugin-ai": "1.7.0-alpha.10", + "@nocobase/plugin-api-doc": "1.7.0-alpha.10", + "@nocobase/plugin-api-keys": "1.7.0-alpha.10", + "@nocobase/plugin-async-task-manager": "1.7.0-alpha.10", + "@nocobase/plugin-audit-logs": "1.7.0-alpha.10", + "@nocobase/plugin-auth": "1.7.0-alpha.10", + "@nocobase/plugin-auth-sms": "1.7.0-alpha.10", + "@nocobase/plugin-backup-restore": "1.7.0-alpha.10", + "@nocobase/plugin-block-iframe": "1.7.0-alpha.10", + "@nocobase/plugin-block-template": "1.7.0-alpha.10", + "@nocobase/plugin-block-workbench": "1.7.0-alpha.10", + "@nocobase/plugin-calendar": "1.7.0-alpha.10", + "@nocobase/plugin-charts": "1.7.0-alpha.10", + "@nocobase/plugin-client": "1.7.0-alpha.10", + "@nocobase/plugin-collection-sql": "1.7.0-alpha.10", + "@nocobase/plugin-collection-tree": "1.7.0-alpha.10", + "@nocobase/plugin-data-source-main": "1.7.0-alpha.10", + "@nocobase/plugin-data-source-manager": "1.7.0-alpha.10", + "@nocobase/plugin-data-visualization": "1.7.0-alpha.10", + "@nocobase/plugin-environment-variables": "1.7.0-alpha.10", + "@nocobase/plugin-error-handler": "1.7.0-alpha.10", + "@nocobase/plugin-field-china-region": "1.7.0-alpha.10", + "@nocobase/plugin-field-formula": "1.7.0-alpha.10", + "@nocobase/plugin-field-m2m-array": "1.7.0-alpha.10", + "@nocobase/plugin-field-markdown-vditor": "1.7.0-alpha.10", + "@nocobase/plugin-field-sequence": "1.7.0-alpha.10", + "@nocobase/plugin-field-sort": "1.7.0-alpha.10", + "@nocobase/plugin-file-manager": "1.7.0-alpha.10", + "@nocobase/plugin-gantt": "1.7.0-alpha.10", + "@nocobase/plugin-graph-collection-manager": "1.7.0-alpha.10", + "@nocobase/plugin-kanban": "1.7.0-alpha.10", + "@nocobase/plugin-localization": "1.7.0-alpha.10", + "@nocobase/plugin-logger": "1.7.0-alpha.10", + "@nocobase/plugin-map": "1.7.0-alpha.10", + "@nocobase/plugin-mobile": "1.7.0-alpha.10", + "@nocobase/plugin-mobile-client": "1.7.0-alpha.10", + "@nocobase/plugin-mock-collections": "1.7.0-alpha.10", + "@nocobase/plugin-multi-app-manager": "1.7.0-alpha.10", + "@nocobase/plugin-multi-app-share-collection": "1.7.0-alpha.10", + "@nocobase/plugin-notification-email": "1.7.0-alpha.10", + "@nocobase/plugin-notification-in-app-message": "1.7.0-alpha.10", + "@nocobase/plugin-notification-manager": "1.7.0-alpha.10", + "@nocobase/plugin-public-forms": "1.7.0-alpha.10", + "@nocobase/plugin-snapshot-field": "1.7.0-alpha.10", + "@nocobase/plugin-system-settings": "1.7.0-alpha.10", + "@nocobase/plugin-theme-editor": "1.7.0-alpha.10", + "@nocobase/plugin-ui-schema-storage": "1.7.0-alpha.10", + "@nocobase/plugin-user-data-sync": "1.7.0-alpha.10", + "@nocobase/plugin-users": "1.7.0-alpha.10", + "@nocobase/plugin-verification": "1.7.0-alpha.10", + "@nocobase/plugin-workflow": "1.7.0-alpha.10", + "@nocobase/plugin-workflow-action-trigger": "1.7.0-alpha.10", + "@nocobase/plugin-workflow-aggregate": "1.7.0-alpha.10", + "@nocobase/plugin-workflow-delay": "1.7.0-alpha.10", + "@nocobase/plugin-workflow-dynamic-calculation": "1.7.0-alpha.10", + "@nocobase/plugin-workflow-loop": "1.7.0-alpha.10", + "@nocobase/plugin-workflow-mailer": "1.7.0-alpha.10", + "@nocobase/plugin-workflow-manual": "1.7.0-alpha.10", + "@nocobase/plugin-workflow-notification": "1.7.0-alpha.10", + "@nocobase/plugin-workflow-parallel": "1.7.0-alpha.10", + "@nocobase/plugin-workflow-request": "1.7.0-alpha.10", + "@nocobase/plugin-workflow-sql": "1.7.0-alpha.10", + "@nocobase/server": "1.7.0-alpha.10", "cronstrue": "^2.11.0", "fs-extra": "^11.1.1" },