feat: load prompts from database (#17)

* feat: load prompts from database

* chore: bump editor version

* fix: dropdown disable state

* fix: revert dropdown menu changes

* chore: bump ai chat

* fix: duplicated fields not immediately usable

* chore: bump ai chat version

* chore: move hook usage upwards

* chore: export type
This commit is contained in:
Richard Shiue
2025-07-04 13:39:58 +08:00
committed by GitHub
parent 7ddbd094ec
commit d951ac32c2
13 changed files with 626 additions and 90 deletions

View File

@@ -24,8 +24,8 @@
"generate-tokens": "node scripts/system-token/convert-tokens.cjs"
},
"dependencies": {
"@appflowyinc/ai-chat": "0.1.30",
"@appflowyinc/editor": "^0.1.10",
"@appflowyinc/ai-chat": "0.1.33",
"@appflowyinc/editor": "^0.1.13",
"@atlaskit/pragmatic-drag-and-drop": "1.5.2",
"@atlaskit/pragmatic-drag-and-drop-auto-scroll": "2.1.0",
"@atlaskit/pragmatic-drag-and-drop-flourish": "2.0.2",

297
pnpm-lock.yaml generated
View File

@@ -9,11 +9,11 @@ importers:
.:
dependencies:
'@appflowyinc/ai-chat':
specifier: 0.1.30
version: 0.1.30(@appflowyinc/editor@0.1.10(@types/react-dom@18.3.7(@types/react@18.3.21))(@types/react@18.3.21)(i18next-resources-to-backend@1.2.1)(i18next@22.5.1)(react-dom@18.3.1(react@18.3.1))(react-i18next@14.1.3(i18next@22.5.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1)(slate-history@0.100.0(slate@0.101.5))(slate-react@0.101.6(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(slate@0.101.5))(slate@0.101.5)(ts-node@10.9.2(@types/node@20.17.47)(typescript@4.9.5)))(@emotion/is-prop-valid@1.3.1)(@types/react-dom@18.3.7(@types/react@18.3.21))(@types/react@18.3.21)(axios@1.9.0)(dompurify@3.2.5)(i18next-resources-to-backend@1.2.1)(i18next@22.5.1)(react-dom@18.3.1(react@18.3.1))(react-i18next@14.1.3(i18next@22.5.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1)(ts-node@10.9.2(@types/node@20.17.47)(typescript@4.9.5))
specifier: 0.1.33
version: 0.1.33(@appflowyinc/editor@0.1.13(@types/react-dom@18.3.7(@types/react@18.3.21))(@types/react@18.3.21)(i18next-resources-to-backend@1.2.1)(i18next@22.5.1)(react-dom@18.3.1(react@18.3.1))(react-i18next@14.1.3(i18next@22.5.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1)(slate-history@0.100.0(slate@0.101.5))(slate-react@0.101.6(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(slate@0.101.5))(slate@0.101.5)(ts-node@10.9.2(@types/node@20.17.47)(typescript@4.9.5)))(@emotion/is-prop-valid@1.3.1)(@types/react-dom@18.3.7(@types/react@18.3.21))(@types/react@18.3.21)(axios@1.9.0)(dompurify@3.2.5)(i18next-resources-to-backend@1.2.1)(i18next@22.5.1)(react-dom@18.3.1(react@18.3.1))(react-i18next@14.1.3(i18next@22.5.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1)(ts-node@10.9.2(@types/node@20.17.47)(typescript@4.9.5))
'@appflowyinc/editor':
specifier: ^0.1.10
version: 0.1.10(@types/react-dom@18.3.7(@types/react@18.3.21))(@types/react@18.3.21)(i18next-resources-to-backend@1.2.1)(i18next@22.5.1)(react-dom@18.3.1(react@18.3.1))(react-i18next@14.1.3(i18next@22.5.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1)(slate-history@0.100.0(slate@0.101.5))(slate-react@0.101.6(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(slate@0.101.5))(slate@0.101.5)(ts-node@10.9.2(@types/node@20.17.47)(typescript@4.9.5))
specifier: ^0.1.13
version: 0.1.13(@types/react-dom@18.3.7(@types/react@18.3.21))(@types/react@18.3.21)(i18next-resources-to-backend@1.2.1)(i18next@22.5.1)(react-dom@18.3.1(react@18.3.1))(react-i18next@14.1.3(i18next@22.5.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1)(slate-history@0.100.0(slate@0.101.5))(slate-react@0.101.6(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(slate@0.101.5))(slate@0.101.5)(ts-node@10.9.2(@types/node@20.17.47)(typescript@4.9.5))
'@atlaskit/pragmatic-drag-and-drop':
specifier: 1.5.2
version: 1.5.2
@@ -632,10 +632,10 @@ packages:
'@antfu/utils@8.1.1':
resolution: {integrity: sha512-Mex9nXf9vR6AhcXmMrlz/HVgYYZpVGJ6YlPgwl7UnaFpnshXs6EK/oa5Gpf3CzENMjkvEx2tQtntGnb7UtSTOQ==}
'@appflowyinc/ai-chat@0.1.30':
resolution: {integrity: sha512-hSZk/q4g7pOWS3oAA8np+a2WMWmiQgEGUtLJGyj1hbUv6Y/rv4qHvvSz+yTzPOz9YFoypMgfryOGSaxMTr8F0w==}
'@appflowyinc/ai-chat@0.1.33':
resolution: {integrity: sha512-tLq49wxg5XUqc7S3TllH7nlRI7cLzsdF4EviioNkRWxOdIhoyenLQ2FEvAsY2UiP7qtzR9ehm9lrmijOsf+2nA==}
peerDependencies:
'@appflowyinc/editor': ^0.1.7
'@appflowyinc/editor': ^0.1.13
axios: ^1.7.9
dompurify: ^3.2.4
i18next: ^22.4.10
@@ -644,8 +644,8 @@ packages:
react-dom: ^18.2.0
react-i18next: ^14.1.0
'@appflowyinc/editor@0.1.10':
resolution: {integrity: sha512-2/IcZ1FTIEhv9DzVdCu+9WvOnjSLENU3j08Uu2Pep52EsoYQpEHpdeKaYKqBpwESFGwI0vc2sOXFyKOel8UgTg==}
'@appflowyinc/editor@0.1.13':
resolution: {integrity: sha512-iMN+BgNF9bAXjrpqstakC4q/vsW4A37INBlATyEoC04dsMHvbKlZL8k/eA9DjHU6MEk+BijSpbN6oUTKlxIpdA==}
peerDependencies:
i18next: ^22.4.10
i18next-resources-to-backend: ^1.2.1
@@ -2328,6 +2328,19 @@ packages:
'@types/react-dom':
optional: true
'@radix-ui/react-arrow@1.1.7':
resolution: {integrity: sha512-F+M1tLhO+mlQaOWspE8Wstg+z6PwxwRd8oQ8IXceWz92kfAmalTRf0EjrouQeo7QssEPfCn05B4Ihs1K9WQ/7w==}
peerDependencies:
'@types/react': '*'
'@types/react-dom': '*'
react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
peerDependenciesMeta:
'@types/react':
optional: true
'@types/react-dom':
optional: true
'@radix-ui/react-avatar@1.1.9':
resolution: {integrity: sha512-10tQokfvZdFvnvDkcOJPjm2pWiP8A0R4T83MoD7tb15bC/k2GU7B1YBuzJi8lNQ8V1QqhP8ocNqp27ByZaNagQ==}
peerDependencies:
@@ -2398,6 +2411,19 @@ packages:
'@types/react-dom':
optional: true
'@radix-ui/react-dialog@1.1.14':
resolution: {integrity: sha512-+CpweKjqpzTmwRwcYECQcNYbI8V9VSQt0SNFKeEBLgfucbsLssU6Ppq7wUdNXEGb573bMjFhVjKVll8rmV6zMw==}
peerDependencies:
'@types/react': '*'
'@types/react-dom': '*'
react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
peerDependenciesMeta:
'@types/react':
optional: true
'@types/react-dom':
optional: true
'@radix-ui/react-direction@1.1.1':
resolution: {integrity: sha512-1UEWRX6jnOA2y4H5WczZ44gOOjTEmlqv1uNW4GAJEO5+bauCBhv8snY65Iw5/VOS/ghKN9gr2KjnLKxrsvoMVw==}
peerDependencies:
@@ -2407,6 +2433,19 @@ packages:
'@types/react':
optional: true
'@radix-ui/react-dismissable-layer@1.1.10':
resolution: {integrity: sha512-IM1zzRV4W3HtVgftdQiiOmA0AdJlCtMLe00FXaHwgt3rAnNsIyDqshvkIW3hj/iu5hu8ERP7KIYki6NkqDxAwQ==}
peerDependencies:
'@types/react': '*'
'@types/react-dom': '*'
react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
peerDependenciesMeta:
'@types/react':
optional: true
'@types/react-dom':
optional: true
'@radix-ui/react-dismissable-layer@1.1.9':
resolution: {integrity: sha512-way197PiTvNp+WBP7svMJasHl+vibhWGQDb6Mgf5mhEWJkgb85z7Lfl9TUdkqpWsf8GRNmoopx9ZxCyDzmgRMQ==}
peerDependencies:
@@ -2433,6 +2472,19 @@ packages:
'@types/react-dom':
optional: true
'@radix-ui/react-dropdown-menu@2.1.15':
resolution: {integrity: sha512-mIBnOjgwo9AH3FyKaSWoSu/dYj6VdhJ7frEPiGTeXCdUFHjl9h3mFh2wwhEtINOmYXWhdpf1rY2minFsmaNgVQ==}
peerDependencies:
'@types/react': '*'
'@types/react-dom': '*'
react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
peerDependenciesMeta:
'@types/react':
optional: true
'@types/react-dom':
optional: true
'@radix-ui/react-focus-guards@1.1.2':
resolution: {integrity: sha512-fyjAACV62oPV925xFCrH8DR5xWhg9KYtJT4s3u54jxp+L/hbpTY2kIeEFFbFe+a/HCE94zGQMZLIpVTPVZDhaA==}
peerDependencies:
@@ -2455,6 +2507,19 @@ packages:
'@types/react-dom':
optional: true
'@radix-ui/react-focus-scope@1.1.7':
resolution: {integrity: sha512-t2ODlkXBQyn7jkl6TNaw/MtVEVvIGelJDCG41Okq/KwUsJBwQ4XVZsHAVUkK4mBv3ewiAS3PGuUWuY2BoK4ZUw==}
peerDependencies:
'@types/react': '*'
'@types/react-dom': '*'
react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
peerDependenciesMeta:
'@types/react':
optional: true
'@types/react-dom':
optional: true
'@radix-ui/react-id@1.1.1':
resolution: {integrity: sha512-kGkGegYIdQsOb4XjsfM97rXsiHaBwco+hFI66oO4s9LU+PLAC5oJ7khdOVFxkhsmlbpUqDAvXw11CluXP+jkHg==}
peerDependencies:
@@ -2490,6 +2555,19 @@ packages:
'@types/react-dom':
optional: true
'@radix-ui/react-menu@2.1.15':
resolution: {integrity: sha512-tVlmA3Vb9n8SZSd+YSbuFR66l87Wiy4du+YE+0hzKQEANA+7cWKH1WgqcEX4pXqxUFQKrWQGHdvEfw00TjFiew==}
peerDependencies:
'@types/react': '*'
'@types/react-dom': '*'
react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
peerDependenciesMeta:
'@types/react':
optional: true
'@types/react-dom':
optional: true
'@radix-ui/react-popover@1.1.13':
resolution: {integrity: sha512-84uqQV3omKDR076izYgcha6gdpN8m3z6w/AeJ83MSBJYVG/AbOHdLjAgsPZkeC/kt+k64moXFCnio8BbqXszlw==}
peerDependencies:
@@ -2503,6 +2581,19 @@ packages:
'@types/react-dom':
optional: true
'@radix-ui/react-popover@1.1.14':
resolution: {integrity: sha512-ODz16+1iIbGUfFEfKx2HTPKizg2MN39uIOV8MXeHnmdd3i/N9Wt7vU46wbHsqA0xoaQyXVcs0KIlBdOA2Y95bw==}
peerDependencies:
'@types/react': '*'
'@types/react-dom': '*'
react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
peerDependenciesMeta:
'@types/react':
optional: true
'@types/react-dom':
optional: true
'@radix-ui/react-popper@1.2.6':
resolution: {integrity: sha512-7iqXaOWIjDBfIG7aq8CUEeCSsQMLFdn7VEE8TaFz704DtEzpPHR7w/uuzRflvKgltqSAImgcmxQ7fFX3X7wasg==}
peerDependencies:
@@ -2516,6 +2607,19 @@ packages:
'@types/react-dom':
optional: true
'@radix-ui/react-popper@1.2.7':
resolution: {integrity: sha512-IUFAccz1JyKcf/RjB552PlWwxjeCJB8/4KxT7EhBHOJM+mN7LdW+B3kacJXILm32xawcMMjb2i0cIZpo+f9kiQ==}
peerDependencies:
'@types/react': '*'
'@types/react-dom': '*'
react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
peerDependenciesMeta:
'@types/react':
optional: true
'@types/react-dom':
optional: true
'@radix-ui/react-portal@1.1.8':
resolution: {integrity: sha512-hQsTUIn7p7fxCPvao/q6wpbxmCwgLrlz+nOrJgC+RwfZqWY/WN+UMqkXzrtKbPrF82P43eCTl3ekeKuyAQbFeg==}
peerDependencies:
@@ -2529,6 +2633,19 @@ packages:
'@types/react-dom':
optional: true
'@radix-ui/react-portal@1.1.9':
resolution: {integrity: sha512-bpIxvq03if6UNwXZ+HTK71JLh4APvnXntDc6XOX8UVq4XQOVl7lwok0AvIl+b8zgCw3fSaVTZMpAPPagXbKmHQ==}
peerDependencies:
'@types/react': '*'
'@types/react-dom': '*'
react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
peerDependenciesMeta:
'@types/react':
optional: true
'@types/react-dom':
optional: true
'@radix-ui/react-presence@1.1.4':
resolution: {integrity: sha512-ueDqRbdc4/bkaQT3GIpLQssRlFgWaL/U2z/S31qRwwLWoxHLgry3SIfCwhxeQNbirEUXFa+lq3RL3oBYXtcmIA==}
peerDependencies:
@@ -8718,14 +8835,15 @@ snapshots:
'@antfu/utils@8.1.1': {}
'@appflowyinc/ai-chat@0.1.30(@appflowyinc/editor@0.1.10(@types/react-dom@18.3.7(@types/react@18.3.21))(@types/react@18.3.21)(i18next-resources-to-backend@1.2.1)(i18next@22.5.1)(react-dom@18.3.1(react@18.3.1))(react-i18next@14.1.3(i18next@22.5.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1)(slate-history@0.100.0(slate@0.101.5))(slate-react@0.101.6(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(slate@0.101.5))(slate@0.101.5)(ts-node@10.9.2(@types/node@20.17.47)(typescript@4.9.5)))(@emotion/is-prop-valid@1.3.1)(@types/react-dom@18.3.7(@types/react@18.3.21))(@types/react@18.3.21)(axios@1.9.0)(dompurify@3.2.5)(i18next-resources-to-backend@1.2.1)(i18next@22.5.1)(react-dom@18.3.1(react@18.3.1))(react-i18next@14.1.3(i18next@22.5.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1)(ts-node@10.9.2(@types/node@20.17.47)(typescript@4.9.5))':
'@appflowyinc/ai-chat@0.1.33(@appflowyinc/editor@0.1.13(@types/react-dom@18.3.7(@types/react@18.3.21))(@types/react@18.3.21)(i18next-resources-to-backend@1.2.1)(i18next@22.5.1)(react-dom@18.3.1(react@18.3.1))(react-i18next@14.1.3(i18next@22.5.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1)(slate-history@0.100.0(slate@0.101.5))(slate-react@0.101.6(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(slate@0.101.5))(slate@0.101.5)(ts-node@10.9.2(@types/node@20.17.47)(typescript@4.9.5)))(@emotion/is-prop-valid@1.3.1)(@types/react-dom@18.3.7(@types/react@18.3.21))(@types/react@18.3.21)(axios@1.9.0)(dompurify@3.2.5)(i18next-resources-to-backend@1.2.1)(i18next@22.5.1)(react-dom@18.3.1(react@18.3.1))(react-i18next@14.1.3(i18next@22.5.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1)(ts-node@10.9.2(@types/node@20.17.47)(typescript@4.9.5))':
dependencies:
'@appflowyinc/editor': 0.1.10(@types/react-dom@18.3.7(@types/react@18.3.21))(@types/react@18.3.21)(i18next-resources-to-backend@1.2.1)(i18next@22.5.1)(react-dom@18.3.1(react@18.3.1))(react-i18next@14.1.3(i18next@22.5.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1)(slate-history@0.100.0(slate@0.101.5))(slate-react@0.101.6(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(slate@0.101.5))(slate@0.101.5)(ts-node@10.9.2(@types/node@20.17.47)(typescript@4.9.5))
'@appflowyinc/editor': 0.1.13(@types/react-dom@18.3.7(@types/react@18.3.21))(@types/react@18.3.21)(i18next-resources-to-backend@1.2.1)(i18next@22.5.1)(react-dom@18.3.1(react@18.3.1))(react-i18next@14.1.3(i18next@22.5.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1)(slate-history@0.100.0(slate@0.101.5))(slate-react@0.101.6(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(slate@0.101.5))(slate@0.101.5)(ts-node@10.9.2(@types/node@20.17.47)(typescript@4.9.5))
'@jest/globals': 29.7.0
'@radix-ui/react-avatar': 1.1.9(@types/react-dom@18.3.7(@types/react@18.3.21))(@types/react@18.3.21)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@radix-ui/react-dialog': 1.1.13(@types/react-dom@18.3.7(@types/react@18.3.21))(@types/react@18.3.21)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@radix-ui/react-dialog': 1.1.14(@types/react-dom@18.3.7(@types/react@18.3.21))(@types/react@18.3.21)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@radix-ui/react-dropdown-menu': 2.1.15(@types/react-dom@18.3.7(@types/react@18.3.21))(@types/react@18.3.21)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@radix-ui/react-label': 2.1.6(@types/react-dom@18.3.7(@types/react@18.3.21))(@types/react@18.3.21)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@radix-ui/react-popover': 1.1.13(@types/react-dom@18.3.7(@types/react@18.3.21))(@types/react@18.3.21)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@radix-ui/react-popover': 1.1.14(@types/react-dom@18.3.7(@types/react@18.3.21))(@types/react@18.3.21)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@radix-ui/react-radio-group': 1.3.6(@types/react-dom@18.3.7(@types/react@18.3.21))(@types/react@18.3.21)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@radix-ui/react-select': 2.2.4(@types/react-dom@18.3.7(@types/react@18.3.21))(@types/react@18.3.21)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@radix-ui/react-separator': 1.1.6(@types/react-dom@18.3.7(@types/react@18.3.21))(@types/react@18.3.21)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
@@ -8761,13 +8879,13 @@ snapshots:
- supports-color
- ts-node
'@appflowyinc/editor@0.1.10(@types/react-dom@18.3.7(@types/react@18.3.21))(@types/react@18.3.21)(i18next-resources-to-backend@1.2.1)(i18next@22.5.1)(react-dom@18.3.1(react@18.3.1))(react-i18next@14.1.3(i18next@22.5.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1)(slate-history@0.100.0(slate@0.101.5))(slate-react@0.101.6(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(slate@0.101.5))(slate@0.101.5)(ts-node@10.9.2(@types/node@20.17.47)(typescript@4.9.5))':
'@appflowyinc/editor@0.1.13(@types/react-dom@18.3.7(@types/react@18.3.21))(@types/react@18.3.21)(i18next-resources-to-backend@1.2.1)(i18next@22.5.1)(react-dom@18.3.1(react@18.3.1))(react-i18next@14.1.3(i18next@22.5.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1)(slate-history@0.100.0(slate@0.101.5))(slate-react@0.101.6(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(slate@0.101.5))(slate@0.101.5)(ts-node@10.9.2(@types/node@20.17.47)(typescript@4.9.5))':
dependencies:
'@radix-ui/react-label': 2.1.6(@types/react-dom@18.3.7(@types/react@18.3.21))(@types/react@18.3.21)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@radix-ui/react-popover': 1.1.13(@types/react-dom@18.3.7(@types/react@18.3.21))(@types/react@18.3.21)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@radix-ui/react-popover': 1.1.14(@types/react-dom@18.3.7(@types/react@18.3.21))(@types/react@18.3.21)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@radix-ui/react-select': 2.2.4(@types/react-dom@18.3.7(@types/react@18.3.21))(@types/react@18.3.21)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@radix-ui/react-separator': 1.1.6(@types/react-dom@18.3.7(@types/react@18.3.21))(@types/react@18.3.21)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@radix-ui/react-slot': 1.2.2(@types/react@18.3.21)(react@18.3.1)
'@radix-ui/react-slot': 1.2.3(@types/react@18.3.21)(react@18.3.1)
'@radix-ui/react-switch': 1.2.4(@types/react-dom@18.3.7(@types/react@18.3.21))(@types/react@18.3.21)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@radix-ui/react-tooltip': 1.2.6(@types/react-dom@18.3.7(@types/react@18.3.21))(@types/react@18.3.21)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
class-variance-authority: 0.7.1
@@ -10843,6 +10961,15 @@ snapshots:
'@types/react': 18.3.21
'@types/react-dom': 18.3.7(@types/react@18.3.21)
'@radix-ui/react-arrow@1.1.7(@types/react-dom@18.3.7(@types/react@18.3.21))(@types/react@18.3.21)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
dependencies:
'@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.7(@types/react@18.3.21))(@types/react@18.3.21)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
react: 18.3.1
react-dom: 18.3.1(react@18.3.1)
optionalDependencies:
'@types/react': 18.3.21
'@types/react-dom': 18.3.7(@types/react@18.3.21)
'@radix-ui/react-avatar@1.1.9(@types/react-dom@18.3.7(@types/react@18.3.21))(@types/react@18.3.21)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
dependencies:
'@radix-ui/react-context': 1.1.2(@types/react@18.3.21)(react@18.3.1)
@@ -10914,12 +11041,47 @@ snapshots:
'@types/react': 18.3.21
'@types/react-dom': 18.3.7(@types/react@18.3.21)
'@radix-ui/react-dialog@1.1.14(@types/react-dom@18.3.7(@types/react@18.3.21))(@types/react@18.3.21)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
dependencies:
'@radix-ui/primitive': 1.1.2
'@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.21)(react@18.3.1)
'@radix-ui/react-context': 1.1.2(@types/react@18.3.21)(react@18.3.1)
'@radix-ui/react-dismissable-layer': 1.1.10(@types/react-dom@18.3.7(@types/react@18.3.21))(@types/react@18.3.21)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@radix-ui/react-focus-guards': 1.1.2(@types/react@18.3.21)(react@18.3.1)
'@radix-ui/react-focus-scope': 1.1.7(@types/react-dom@18.3.7(@types/react@18.3.21))(@types/react@18.3.21)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@radix-ui/react-id': 1.1.1(@types/react@18.3.21)(react@18.3.1)
'@radix-ui/react-portal': 1.1.9(@types/react-dom@18.3.7(@types/react@18.3.21))(@types/react@18.3.21)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@radix-ui/react-presence': 1.1.4(@types/react-dom@18.3.7(@types/react@18.3.21))(@types/react@18.3.21)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.7(@types/react@18.3.21))(@types/react@18.3.21)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@radix-ui/react-slot': 1.2.3(@types/react@18.3.21)(react@18.3.1)
'@radix-ui/react-use-controllable-state': 1.2.2(@types/react@18.3.21)(react@18.3.1)
aria-hidden: 1.2.4
react: 18.3.1
react-dom: 18.3.1(react@18.3.1)
react-remove-scroll: 2.6.3(@types/react@18.3.21)(react@18.3.1)
optionalDependencies:
'@types/react': 18.3.21
'@types/react-dom': 18.3.7(@types/react@18.3.21)
'@radix-ui/react-direction@1.1.1(@types/react@18.3.21)(react@18.3.1)':
dependencies:
react: 18.3.1
optionalDependencies:
'@types/react': 18.3.21
'@radix-ui/react-dismissable-layer@1.1.10(@types/react-dom@18.3.7(@types/react@18.3.21))(@types/react@18.3.21)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
dependencies:
'@radix-ui/primitive': 1.1.2
'@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.21)(react@18.3.1)
'@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.7(@types/react@18.3.21))(@types/react@18.3.21)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@radix-ui/react-use-callback-ref': 1.1.1(@types/react@18.3.21)(react@18.3.1)
'@radix-ui/react-use-escape-keydown': 1.1.1(@types/react@18.3.21)(react@18.3.1)
react: 18.3.1
react-dom: 18.3.1(react@18.3.1)
optionalDependencies:
'@types/react': 18.3.21
'@types/react-dom': 18.3.7(@types/react@18.3.21)
'@radix-ui/react-dismissable-layer@1.1.9(@types/react-dom@18.3.7(@types/react@18.3.21))(@types/react@18.3.21)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
dependencies:
'@radix-ui/primitive': 1.1.2
@@ -10948,6 +11110,21 @@ snapshots:
'@types/react': 18.3.21
'@types/react-dom': 18.3.7(@types/react@18.3.21)
'@radix-ui/react-dropdown-menu@2.1.15(@types/react-dom@18.3.7(@types/react@18.3.21))(@types/react@18.3.21)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
dependencies:
'@radix-ui/primitive': 1.1.2
'@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.21)(react@18.3.1)
'@radix-ui/react-context': 1.1.2(@types/react@18.3.21)(react@18.3.1)
'@radix-ui/react-id': 1.1.1(@types/react@18.3.21)(react@18.3.1)
'@radix-ui/react-menu': 2.1.15(@types/react-dom@18.3.7(@types/react@18.3.21))(@types/react@18.3.21)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.7(@types/react@18.3.21))(@types/react@18.3.21)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@radix-ui/react-use-controllable-state': 1.2.2(@types/react@18.3.21)(react@18.3.1)
react: 18.3.1
react-dom: 18.3.1(react@18.3.1)
optionalDependencies:
'@types/react': 18.3.21
'@types/react-dom': 18.3.7(@types/react@18.3.21)
'@radix-ui/react-focus-guards@1.1.2(@types/react@18.3.21)(react@18.3.1)':
dependencies:
react: 18.3.1
@@ -10965,6 +11142,17 @@ snapshots:
'@types/react': 18.3.21
'@types/react-dom': 18.3.7(@types/react@18.3.21)
'@radix-ui/react-focus-scope@1.1.7(@types/react-dom@18.3.7(@types/react@18.3.21))(@types/react@18.3.21)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
dependencies:
'@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.21)(react@18.3.1)
'@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.7(@types/react@18.3.21))(@types/react@18.3.21)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@radix-ui/react-use-callback-ref': 1.1.1(@types/react@18.3.21)(react@18.3.1)
react: 18.3.1
react-dom: 18.3.1(react@18.3.1)
optionalDependencies:
'@types/react': 18.3.21
'@types/react-dom': 18.3.7(@types/react@18.3.21)
'@radix-ui/react-id@1.1.1(@types/react@18.3.21)(react@18.3.1)':
dependencies:
'@radix-ui/react-use-layout-effect': 1.1.1(@types/react@18.3.21)(react@18.3.1)
@@ -11007,6 +11195,32 @@ snapshots:
'@types/react': 18.3.21
'@types/react-dom': 18.3.7(@types/react@18.3.21)
'@radix-ui/react-menu@2.1.15(@types/react-dom@18.3.7(@types/react@18.3.21))(@types/react@18.3.21)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
dependencies:
'@radix-ui/primitive': 1.1.2
'@radix-ui/react-collection': 1.1.7(@types/react-dom@18.3.7(@types/react@18.3.21))(@types/react@18.3.21)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.21)(react@18.3.1)
'@radix-ui/react-context': 1.1.2(@types/react@18.3.21)(react@18.3.1)
'@radix-ui/react-direction': 1.1.1(@types/react@18.3.21)(react@18.3.1)
'@radix-ui/react-dismissable-layer': 1.1.10(@types/react-dom@18.3.7(@types/react@18.3.21))(@types/react@18.3.21)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@radix-ui/react-focus-guards': 1.1.2(@types/react@18.3.21)(react@18.3.1)
'@radix-ui/react-focus-scope': 1.1.7(@types/react-dom@18.3.7(@types/react@18.3.21))(@types/react@18.3.21)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@radix-ui/react-id': 1.1.1(@types/react@18.3.21)(react@18.3.1)
'@radix-ui/react-popper': 1.2.7(@types/react-dom@18.3.7(@types/react@18.3.21))(@types/react@18.3.21)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@radix-ui/react-portal': 1.1.9(@types/react-dom@18.3.7(@types/react@18.3.21))(@types/react@18.3.21)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@radix-ui/react-presence': 1.1.4(@types/react-dom@18.3.7(@types/react@18.3.21))(@types/react@18.3.21)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.7(@types/react@18.3.21))(@types/react@18.3.21)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@radix-ui/react-roving-focus': 1.1.10(@types/react-dom@18.3.7(@types/react@18.3.21))(@types/react@18.3.21)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@radix-ui/react-slot': 1.2.3(@types/react@18.3.21)(react@18.3.1)
'@radix-ui/react-use-callback-ref': 1.1.1(@types/react@18.3.21)(react@18.3.1)
aria-hidden: 1.2.4
react: 18.3.1
react-dom: 18.3.1(react@18.3.1)
react-remove-scroll: 2.6.3(@types/react@18.3.21)(react@18.3.1)
optionalDependencies:
'@types/react': 18.3.21
'@types/react-dom': 18.3.7(@types/react@18.3.21)
'@radix-ui/react-popover@1.1.13(@types/react-dom@18.3.7(@types/react@18.3.21))(@types/react@18.3.21)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
dependencies:
'@radix-ui/primitive': 1.1.2
@@ -11030,6 +11244,29 @@ snapshots:
'@types/react': 18.3.21
'@types/react-dom': 18.3.7(@types/react@18.3.21)
'@radix-ui/react-popover@1.1.14(@types/react-dom@18.3.7(@types/react@18.3.21))(@types/react@18.3.21)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
dependencies:
'@radix-ui/primitive': 1.1.2
'@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.21)(react@18.3.1)
'@radix-ui/react-context': 1.1.2(@types/react@18.3.21)(react@18.3.1)
'@radix-ui/react-dismissable-layer': 1.1.10(@types/react-dom@18.3.7(@types/react@18.3.21))(@types/react@18.3.21)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@radix-ui/react-focus-guards': 1.1.2(@types/react@18.3.21)(react@18.3.1)
'@radix-ui/react-focus-scope': 1.1.7(@types/react-dom@18.3.7(@types/react@18.3.21))(@types/react@18.3.21)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@radix-ui/react-id': 1.1.1(@types/react@18.3.21)(react@18.3.1)
'@radix-ui/react-popper': 1.2.7(@types/react-dom@18.3.7(@types/react@18.3.21))(@types/react@18.3.21)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@radix-ui/react-portal': 1.1.9(@types/react-dom@18.3.7(@types/react@18.3.21))(@types/react@18.3.21)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@radix-ui/react-presence': 1.1.4(@types/react-dom@18.3.7(@types/react@18.3.21))(@types/react@18.3.21)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.7(@types/react@18.3.21))(@types/react@18.3.21)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@radix-ui/react-slot': 1.2.3(@types/react@18.3.21)(react@18.3.1)
'@radix-ui/react-use-controllable-state': 1.2.2(@types/react@18.3.21)(react@18.3.1)
aria-hidden: 1.2.4
react: 18.3.1
react-dom: 18.3.1(react@18.3.1)
react-remove-scroll: 2.6.3(@types/react@18.3.21)(react@18.3.1)
optionalDependencies:
'@types/react': 18.3.21
'@types/react-dom': 18.3.7(@types/react@18.3.21)
'@radix-ui/react-popper@1.2.6(@types/react-dom@18.3.7(@types/react@18.3.21))(@types/react@18.3.21)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
dependencies:
'@floating-ui/react-dom': 2.1.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
@@ -11048,6 +11285,24 @@ snapshots:
'@types/react': 18.3.21
'@types/react-dom': 18.3.7(@types/react@18.3.21)
'@radix-ui/react-popper@1.2.7(@types/react-dom@18.3.7(@types/react@18.3.21))(@types/react@18.3.21)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
dependencies:
'@floating-ui/react-dom': 2.1.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@radix-ui/react-arrow': 1.1.7(@types/react-dom@18.3.7(@types/react@18.3.21))(@types/react@18.3.21)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.21)(react@18.3.1)
'@radix-ui/react-context': 1.1.2(@types/react@18.3.21)(react@18.3.1)
'@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.7(@types/react@18.3.21))(@types/react@18.3.21)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@radix-ui/react-use-callback-ref': 1.1.1(@types/react@18.3.21)(react@18.3.1)
'@radix-ui/react-use-layout-effect': 1.1.1(@types/react@18.3.21)(react@18.3.1)
'@radix-ui/react-use-rect': 1.1.1(@types/react@18.3.21)(react@18.3.1)
'@radix-ui/react-use-size': 1.1.1(@types/react@18.3.21)(react@18.3.1)
'@radix-ui/rect': 1.1.1
react: 18.3.1
react-dom: 18.3.1(react@18.3.1)
optionalDependencies:
'@types/react': 18.3.21
'@types/react-dom': 18.3.7(@types/react@18.3.21)
'@radix-ui/react-portal@1.1.8(@types/react-dom@18.3.7(@types/react@18.3.21))(@types/react@18.3.21)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
dependencies:
'@radix-ui/react-primitive': 2.1.2(@types/react-dom@18.3.7(@types/react@18.3.21))(@types/react@18.3.21)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
@@ -11058,6 +11313,16 @@ snapshots:
'@types/react': 18.3.21
'@types/react-dom': 18.3.7(@types/react@18.3.21)
'@radix-ui/react-portal@1.1.9(@types/react-dom@18.3.7(@types/react@18.3.21))(@types/react@18.3.21)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
dependencies:
'@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.7(@types/react@18.3.21))(@types/react@18.3.21)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@radix-ui/react-use-layout-effect': 1.1.1(@types/react@18.3.21)(react@18.3.1)
react: 18.3.1
react-dom: 18.3.1(react@18.3.1)
optionalDependencies:
'@types/react': 18.3.21
'@types/react-dom': 18.3.7(@types/react@18.3.21)
'@radix-ui/react-presence@1.1.4(@types/react-dom@18.3.7(@types/react@18.3.21))(@types/react@18.3.21)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
dependencies:
'@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.21)(react@18.3.1)

View File

@@ -7,9 +7,11 @@ import {
DatabaseRelations,
GenerateAISummaryRowPayload,
GenerateAITranslateRowPayload,
LoadDatabasePrompts,
LoadView,
LoadViewMeta,
RowId,
TestDatabasePromptConfig,
UpdatePagePayload,
View,
YDatabase,
@@ -48,6 +50,8 @@ export interface DatabaseContextState {
loadViews?: () => Promise<View[]>;
uploadFile?: (file: File) => Promise<string>;
createOrphanedView?: (payload: { document_id: string }) => Promise<void>;
loadDatabasePrompts?: LoadDatabasePrompts;
testDatabasePromptConfig?: TestDatabasePromptConfig;
requestInstance?: AxiosInstance | null;
}

View File

@@ -1,3 +1,4 @@
import { PromptDatabaseConfiguration } from '@appflowyinc/ai-chat';
import { AxiosInstance } from 'axios';
import * as Y from 'yjs';
@@ -1068,6 +1069,14 @@ export interface ViewComponentProps {
createFolderView?: (payload: CreateFolderViewPayload) => Promise<string>;
generateAISummaryForRow?: (payload: GenerateAISummaryRowPayload) => Promise<string>;
generateAITranslateForRow?: (payload: GenerateAITranslateRowPayload) => Promise<string>;
loadDatabasePrompts?: (config: PromptDatabaseConfiguration) => Promise<{
rawDatabasePrompts: DatabasePrompt[];
fields: DatabasePromptField[];
}>;
testDatabasePromptConfig?: (viewId: string) => Promise<{
config: PromptDatabaseConfiguration;
fields: DatabasePromptField[];
}>;
}
export interface CreatePagePayload {
@@ -1142,3 +1151,35 @@ export interface GenerateAITranslateRowPayload {
include_header?: boolean
}
export type LoadDatabasePrompts = (config: PromptDatabaseConfiguration) => Promise<{
rawDatabasePrompts: DatabasePrompt[];
fields: DatabasePromptField[];
}>;
export type TestDatabasePromptConfig = (viewId: string) => Promise<{
config: PromptDatabaseConfiguration;
fields: DatabasePromptField[];
}>;
export interface DatabasePrompt {
id: string;
name: string;
content: string;
example: string;
category: string;
}
export interface DatabasePromptField {
id: string;
name: string;
isPrimary: boolean;
isSelect: boolean;
}
export interface DatabasePromptRow {
id: string;
data: {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
[fieldId: string]: any;
};
}

View File

@@ -17,7 +17,7 @@ export function AIChat({ chatId, onRendered }: { chatId: string; onRendered?: ()
const isMobile = getPlatform().isMobile;
const [openMobilePrompt, setOpenMobilePrompt] = React.useState(isMobile);
const { refreshOutline, updatePage } = useAppHandlers();
const { refreshOutline, updatePage, loadDatabasePrompts, testDatabasePromptConfig } = useAppHandlers();
const {
selectionMode,
@@ -77,7 +77,7 @@ export function AIChat({ chatId, onRendered }: { chatId: string; onRendered?: ()
}
}, [onRendered]);
if (!requestInstance) return null;
if (!requestInstance || !workspaceId) return null;
return (
<div
@@ -88,6 +88,7 @@ export function AIChat({ chatId, onRendered }: { chatId: string; onRendered?: ()
>
<div className={'w-[952px] max-w-full px-24 max-sm:px-6'}>
<Chat
workspaceId={workspaceId}
requestInstance={requestInstance}
chatId={chatId}
currentUser={
@@ -106,6 +107,8 @@ export function AIChat({ chatId, onRendered }: { chatId: string; onRendered?: ()
openingViewId={(drawerOpen && openViewId) || undefined}
onCloseView={onCloseView}
onOpenView={onOpenView}
loadDatabasePrompts={loadDatabasePrompts}
testDatabasePromptConfig={testDatabasePromptConfig}
/>
</div>

View File

@@ -13,12 +13,17 @@ import {
CreatePagePayload,
CreateRowDoc,
CreateSpacePayload,
DatabasePrompt,
DatabasePromptField,
DatabasePromptRow,
DatabaseRelations,
GenerateAISummaryRowPayload,
GenerateAITranslateRowPayload,
LoadDatabasePrompts,
LoadView,
LoadViewMeta,
Subscription,
TestDatabasePromptConfig,
TextCount,
Types,
UIVariant,
@@ -27,6 +32,7 @@ import {
UserWorkspaceInfo,
View,
ViewLayout,
YDatabase,
YjsDatabaseKey,
YjsEditorKey,
YSharedRoot,
@@ -36,6 +42,9 @@ import { AppOverlayProvider } from '@/components/app/app-overlay/AppOverlayProvi
import RequestAccess from '@/components/app/landing-pages/RequestAccess';
import { AFConfigContext, useService } from '@/components/main/app.hooks';
import { findAncestors, findView, findViewByLayout } from '@/components/_shared/outline/utils';
import { PromptDatabaseConfiguration } from '@appflowyinc/ai-chat';
import { FieldType } from '@/application/database-yjs';
import { getCellDataText } from '@/application/database-yjs/cell.parse';
const ViewModal = React.lazy(() => import('@/components/app/ViewModal'));
@@ -84,6 +93,8 @@ export interface AppContextType {
generateAITranslateForRow?: (payload: GenerateAITranslateRowPayload) => Promise<string>;
loadDatabaseRelations?: () => Promise<DatabaseRelations | undefined>;
createOrphanedView?: (payload: { document_id: string }) => Promise<void>;
loadDatabasePrompts?: LoadDatabasePrompts;
testDatabasePromptConfig?: TestDatabasePromptConfig;
eventEmitter?: EventEmitter;
}
@@ -832,6 +843,203 @@ export const AppProvider = ({ children }: { children: React.ReactNode }) => {
[currentWorkspaceId, service]
);
const rowDocsRef = useRef<Map<string, DatabasePromptRow>>(new Map());
const getRows = useCallback(
async (viewId: string) => {
if (!currentWorkspaceId) return [];
const doc = await loadView(viewId);
const database = doc?.getMap(YjsEditorKey.data_section)?.get(YjsEditorKey.database) as YDatabase;
const view = database.get(YjsDatabaseKey.views).get(viewId);
const rowOrders = view?.get(YjsDatabaseKey.row_orders) || [];
const rowPromises = rowOrders
.map(async (row: { id: string }) => {
if (rowDocsRef.current.has(row.id)) {
return rowDocsRef.current.get(row.id);
}
if (!createRowDoc) return;
const rowKey = `${doc.guid}_rows_${row.id}`;
const rowDoc = await createRowDoc(rowKey);
const rowSharedRoot = rowDoc?.getMap(YjsEditorKey.data_section);
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const data = rowSharedRoot?.get(YjsEditorKey.database_row) as { [fieldId: string]: any };
const databaseRow = {
id: row.id,
data,
};
rowDocsRef.current.set(row.id, databaseRow);
return databaseRow;
})
.filter((p): p is Promise<DatabasePromptRow> => p !== undefined);
return Promise.all(rowPromises);
},
[createRowDoc, currentWorkspaceId, loadView]
);
const getFields = useCallback(
async (viewId: string) => {
if (!currentWorkspaceId) return [];
const doc = await loadView(viewId);
const database = doc?.getMap(YjsEditorKey.data_section)?.get(YjsEditorKey.database) as YDatabase;
const fields = database.get(YjsDatabaseKey.fields);
return Array.from(fields.entries())
.map(([id, field]) => {
const isPrimary = field.get(YjsDatabaseKey.is_primary) || false;
const name = field.get(YjsDatabaseKey.name) || '';
const fieldType = Number(field.get(YjsDatabaseKey.type));
const isSelect = fieldType === FieldType.SingleSelect || fieldType === FieldType.MultiSelect;
return {
id,
name,
fieldType,
isPrimary,
isSelect,
data: field,
};
})
.filter((f) => [FieldType.RichText, FieldType.SingleSelect, FieldType.MultiSelect].includes(f.fieldType));
},
[currentWorkspaceId, loadView]
);
const loadDatabasePromptsWithFields = useCallback(
async (
config: PromptDatabaseConfiguration,
fields: {
id: string;
name: string;
isPrimary: boolean;
fieldType: FieldType;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
data: any;
}[]
) => {
const titleField = fields.find((field) => field.id === config.titleFieldId);
if (!titleField) {
throw new Error('Cannot find title field');
}
const contentField = fields.find((field) => field.id === config.contentFieldId);
if (!contentField) {
throw new Error('Cannot find content field');
}
const exampleField = config.exampleFieldId
? fields.find((field) => field.id === config.exampleFieldId)
: undefined;
const categoryField = config.categoryFieldId
? fields.find((field) => field.id === config.categoryFieldId)
: undefined;
const rows = await getRows(config.databaseViewId);
return rows
.map((row) => {
const cells = row?.data.get(YjsDatabaseKey.cells);
const nameCell = cells?.get(titleField.id);
const name = nameCell && titleField ? getCellDataText(nameCell, titleField.data) : '';
const contentCell = cells?.get(contentField.id);
const content = contentCell && contentField ? getCellDataText(contentCell, contentField.data) : '';
if (!name || !content) return null;
const exampleCell = exampleField ? cells?.get(exampleField.id) : null;
const example = exampleCell && exampleField ? getCellDataText(exampleCell, exampleField.data) : '';
const categoryCell = categoryField ? cells?.get(categoryField.id) : null;
const category = categoryCell && categoryField ? getCellDataText(categoryCell, categoryField.data) : '';
return {
id: row.id,
name,
content,
example,
category,
};
})
.filter((prompt): prompt is DatabasePrompt => prompt !== null);
},
[getRows]
);
const loadDatabasePrompts = async (
config: PromptDatabaseConfiguration
): Promise<{
rawDatabasePrompts: DatabasePrompt[];
fields: DatabasePromptField[];
}> => {
const fields = await getFields(config.databaseViewId);
const rawDatabasePrompts = await loadDatabasePromptsWithFields(config, fields);
return {
rawDatabasePrompts,
fields: fields.map((field) => ({
id: field.id,
name: field.name,
isPrimary: field.isPrimary,
isSelect: field.fieldType === FieldType.SingleSelect || field.fieldType === FieldType.MultiSelect,
})),
};
};
const testDatabasePromptConfig = useCallback(
async (viewId: string) => {
const fields = await getFields(viewId);
const titleField = fields.find((field) => field.isPrimary);
if (!titleField) {
throw new Error('Cannot find primary field');
}
const contentField = fields.find(
(field) =>
!field.isPrimary &&
((field.name.toLowerCase() === 'content' && field.fieldType === FieldType.RichText) ||
field.fieldType === FieldType.RichText)
);
if (!contentField) {
throw new Error('Cannot find content field');
}
const exampleField = fields.find(
(field) => field.name.toLowerCase() === 'example' && field.fieldType === FieldType.RichText
);
const categoryField = fields.find(
(field) => field.name.toLowerCase() === 'category' && field.fieldType === FieldType.RichText
);
const config: PromptDatabaseConfiguration = {
databaseViewId: viewId,
titleFieldId: titleField.id,
contentFieldId: contentField.id,
exampleFieldId: exampleField?.id || null,
categoryFieldId: categoryField?.id || null,
};
return { config, fields };
},
[getFields]
);
return (
<AppContext.Provider
value={{
@@ -879,6 +1087,8 @@ export const AppProvider = ({ children }: { children: React.ReactNode }) => {
generateAITranslateForRow,
loadDatabaseRelations,
createOrphanedView,
loadDatabasePrompts,
testDatabasePromptConfig,
eventEmitter: eventEmitterRef.current,
}}
>
@@ -1035,6 +1245,8 @@ export function useAppHandlers() {
generateAITranslateForRow: context.generateAITranslateForRow,
loadDatabaseRelations: context.loadDatabaseRelations,
createOrphanedView: context.createOrphanedView,
loadDatabasePrompts: context.loadDatabasePrompts,
testDatabasePromptConfig: context.testDatabasePromptConfig,
eventEmitter: context.eventEmitter,
};
}

View File

@@ -7,7 +7,9 @@ import { Button } from '@/components/ui/button';
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuGroup, DropdownMenuSeparator,
DropdownMenuGroup,
DropdownMenuItem,
DropdownMenuSeparator,
DropdownMenuTrigger,
} from '@/components/ui/dropdown-menu';
import React, { useCallback, useEffect, useMemo, useState } from 'react';
@@ -15,15 +17,17 @@ import { useTranslation } from 'react-i18next';
import MoreActionsContent from './MoreActionsContent';
import { ReactComponent as AddToPageIcon } from '@/assets/icons/add_to_page.svg';
import { useService } from '@/components/main/app.hooks';
import { Tooltip, TooltipContent } from '@/components/ui/tooltip';
import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip';
function MoreActions ({ viewId, onDeleted, menuContentProps }:
{
viewId: string;
onDeleted?: () => void;
menuContentProps?: React.ComponentProps<typeof DropdownMenuContent>
} & React.ComponentProps<typeof DropdownMenu>,
) {
function MoreActions({
viewId,
onDeleted,
menuContentProps,
}: {
viewId: string;
onDeleted?: () => void;
menuContentProps?: React.ComponentProps<typeof DropdownMenuContent>;
} & React.ComponentProps<typeof DropdownMenu>) {
const workspaceId = useCurrentWorkspaceId();
const service = useService();
const { selectionMode, onOpenSelectionMode } = useAIChatContext();
@@ -59,21 +63,21 @@ function MoreActions ({ viewId, onDeleted, menuContentProps }:
return view?.layout === ViewLayout.AIChat ? (
<>
<Tooltip>
<div>
<Button
disabled={!hasMessages}
<TooltipTrigger asChild>
<DropdownMenuItem
onClick={() => {
onOpenSelectionMode();
handleClose();
if (hasMessages) {
onOpenSelectionMode();
handleClose();
}
}}
className={hasMessages ? '' : '!cursor-default !text-text-tertiary hover:!bg-fill-content'}
>
<AddToPageIcon />
{t('web.addMessagesToPage')}
</Button>
</div>
<TooltipContent>
{hasMessages ? '' : t('web.addMessagesToPageDisabled')}
</TooltipContent>
</DropdownMenuItem>
</TooltipTrigger>
{!hasMessages && <TooltipContent>{t('web.addMessagesToPageDisabled')}</TooltipContent>}
</Tooltip>
<DropdownMenuSeparator />
</>
@@ -85,23 +89,14 @@ function MoreActions ({ viewId, onDeleted, menuContentProps }:
}
return (
<DropdownMenu
open={open}
onOpenChange={setOpen}
>
<DropdownMenu open={open} onOpenChange={setOpen}>
<DropdownMenuTrigger asChild>
<Button
size={'icon'}
variant={'ghost'}
className={'text-icon-secondary'}
>
<Button size={'icon'} variant={'ghost'} className={'text-icon-secondary'}>
<MoreIcon />
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent {...menuContentProps}>
<DropdownMenuGroup>
{ChatOptions}
</DropdownMenuGroup>
<DropdownMenuGroup>{ChatOptions}</DropdownMenuGroup>
<MoreActionsContent
itemClicked={() => {
@@ -113,7 +108,6 @@ function MoreActions ({ viewId, onDeleted, menuContentProps }:
<DropdownMenuSeparator />
<DocumentInfo viewId={viewId} />
</DropdownMenuContent>
</DropdownMenu>
);
}

View File

@@ -26,6 +26,7 @@ export const DatabaseRowSubDocument = memo(({ rowId }: { rowId: string }) => {
const context = useDatabaseContext();
const database = useDatabase();
const row = useRowData(rowId);
const getCellData = useCallback(
(cell: YDatabaseCell, field: YDatabaseField) => {
const type = Number(field?.get(YjsDatabaseKey.type));

View File

@@ -13,9 +13,12 @@ import { clipboardFormatKey } from '@/components/editor/plugins/withCopy';
const defaultInitialValue: Descendant[] = [];
function CollaborativeEditor({ doc, onEditorConnected }: {
doc: Y.Doc,
onEditorConnected?: (editor: YjsEditor) => void
function CollaborativeEditor({
doc,
onEditorConnected,
}: {
doc: Y.Doc;
onEditorConnected?: (editor: YjsEditor) => void;
}) {
const context = useEditorContext();
const readSummary = context.readSummary;
@@ -25,13 +28,16 @@ function CollaborativeEditor({ doc, onEditorConnected }: {
const viewId = context.viewId;
const onWordCountChange = context.onWordCountChange;
const [, setClock] = useState(0);
const onContentChange = useCallback((content: Descendant[]) => {
const wordCount = getTextCount(content);
const onContentChange = useCallback(
(content: Descendant[]) => {
const wordCount = getTextCount(content);
onWordCountChange?.(viewId, wordCount);
setClock((prev) => prev + 1);
onRendered?.();
}, [onWordCountChange, viewId, onRendered]);
onWordCountChange?.(viewId, wordCount);
setClock((prev) => prev + 1);
onRendered?.();
},
[onWordCountChange, viewId, onRendered]
);
const editor = useMemo(
() =>
@@ -46,18 +52,18 @@ function CollaborativeEditor({ doc, onEditorConnected }: {
onContentChange,
uploadFile,
id: viewId,
}),
})
),
clipboardFormatKey,
),
clipboardFormatKey
)
) as YjsEditor),
// eslint-disable-next-line react-hooks/exhaustive-deps
[viewId, doc],
[viewId, doc]
);
const [, setIsConnected] = useState(false);
useEffect(() => {
if(!editor) return;
if (!editor) return;
editor.connect();
setIsConnected(true);
@@ -71,13 +77,9 @@ function CollaborativeEditor({ doc, onEditorConnected }: {
}, [editor]);
return (
<Slate
editor={editor}
initialValue={defaultInitialValue}
>
<Slate editor={editor} initialValue={defaultInitialValue}>
<EditorEditable />
</Slate>
);
}

View File

@@ -24,10 +24,7 @@ export const Editor = memo(({ doc, onEditorConnected, layoutStyle = defaultLayou
addCodeGrammars={handleAddCodeGrammars}
layoutStyle={layoutStyle}
>
<CollaborativeEditor
doc={doc}
onEditorConnected={onEditorConnected}
/>
<CollaborativeEditor doc={doc} onEditorConnected={onEditorConnected} />
</EditorContextProvider>
);
});

View File

@@ -3,7 +3,13 @@ import {
FontLayout,
LineHeightLayout,
LoadView,
LoadViewMeta, UIVariant, View, CreatePagePayload, TextCount,
LoadViewMeta,
UIVariant,
View,
CreatePagePayload,
TextCount,
LoadDatabasePrompts,
TestDatabasePromptConfig,
} from '@/application/types';
import { AxiosInstance } from 'axios';
import EventEmitter from 'events';
@@ -57,6 +63,8 @@ export interface EditorContextState {
uploadFile?: (file: File) => Promise<string>;
requestInstance?: AxiosInstance | null;
getMoreAIContext?: () => string;
loadDatabasePrompts?: LoadDatabasePrompts;
testDatabasePromptConfig?: TestDatabasePromptConfig;
eventEmitter?: EventEmitter;
}
@@ -76,7 +84,7 @@ export const EditorContextProvider = ({ children, ...props }: EditorContextState
setDecorateState((prev) => {
const oldValue = prev[type];
if(oldValue && Range.equals(oldValue.range, range) && oldValue.class_name === class_name) {
if (oldValue && Range.equals(oldValue.range, range) && oldValue.class_name === class_name) {
return prev;
}
@@ -92,7 +100,7 @@ export const EditorContextProvider = ({ children, ...props }: EditorContextState
const removeDecorate = useCallback((type: string) => {
setDecorateState((prev) => {
if(prev[type] === undefined) {
if (prev[type] === undefined) {
return prev;
}
@@ -103,16 +111,20 @@ export const EditorContextProvider = ({ children, ...props }: EditorContextState
});
}, []);
return <EditorContext.Provider
value={{
...props,
decorateState,
addDecorate,
removeDecorate,
setSelectedBlockIds,
selectedBlockIds,
}}
>{children}</EditorContext.Provider>;
return (
<EditorContext.Provider
value={{
...props,
decorateState,
addDecorate,
removeDecorate,
setSelectedBlockIds,
selectedBlockIds,
}}
>
{children}
</EditorContext.Provider>
);
};
export function useEditorContext() {

View File

@@ -23,7 +23,7 @@ import Panels from './components/panels';
import Toolbars from './components/toolbar';
function EditorOverlay({ viewId, workspaceId }: { viewId: string; workspaceId: string }) {
const { requestInstance } = useEditorContext();
const { requestInstance, loadDatabasePrompts, testDatabasePromptConfig } = useEditorContext();
const editor = useSlate() as YjsEditor;
const selection = editor.selection;
const isRange = selection ? Range.isExpanded(selection) : false;
@@ -172,7 +172,11 @@ function EditorOverlay({ viewId, workspaceId }: { viewId: string; workspaceId: s
return (
<ErrorBoundary fallbackRender={() => null}>
<PromptModalProvider>
<PromptModalProvider
workspaceId={workspaceId}
loadDatabasePrompts={loadDatabasePrompts}
testDatabasePromptConfig={testDatabasePromptConfig}
>
<AIAssistantProvider
isGlobalDocument={!isRange}
onInsertBelow={handleInsertBelow}

View File

@@ -94,6 +94,7 @@ const dropdownMenuItemVariants = cva(
const DropdownMenuItem = forwardRef<
HTMLDivElement,
React.ComponentProps<typeof DropdownMenuPrimitive.Item> & {
className?: string;
inset?: boolean;
variant?: 'default' | 'destructive';
}