plugin-ai-chat-file-preview 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +44 -0
- package/client.d.ts +2 -0
- package/client.js +1 -0
- package/dist/client/0ef9cbd6bccd7aff.js +30 -0
- package/dist/client/7e04271656f34237.js +10 -0
- package/dist/client/index.js +10 -0
- package/dist/externalVersion.js +17 -0
- package/dist/index.js +48 -0
- package/dist/locale/en-US.json +10 -0
- package/dist/locale/vi-VN.json +10 -0
- package/dist/locale/zh-CN.json +10 -0
- package/dist/server/index.js +42 -0
- package/dist/server/plugin.js +42 -0
- package/package.json +30 -0
- package/server.d.ts +2 -0
- package/server.js +1 -0
- package/src/client/ChatFilePreviewProvider.tsx +235 -0
- package/src/client/PreviewModal.tsx +634 -0
- package/src/client/SessionBlobCache.ts +96 -0
- package/src/client/index.tsx +19 -0
- package/src/client/locale.ts +17 -0
- package/src/index.ts +11 -0
- package/src/locale/en-US.json +10 -0
- package/src/locale/vi-VN.json +10 -0
- package/src/locale/zh-CN.json +10 -0
- package/src/server/index.ts +10 -0
- package/src/server/plugin.ts +18 -0
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file is part of the NocoBase (R) project.
|
|
3
|
+
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
|
4
|
+
* Authors: NocoBase Team.
|
|
5
|
+
*
|
|
6
|
+
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
|
+
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t(require("@nocobase/plugin-ai/client"),require("@nocobase/client"),require("react"),require("@ant-design/icons"),require("antd")):"function"==typeof define&&define.amd?define("plugin-ai-chat-file-preview",["@nocobase/plugin-ai/client","@nocobase/client","react","@ant-design/icons","antd"],t):"object"==typeof exports?exports["plugin-ai-chat-file-preview"]=t(require("@nocobase/plugin-ai/client"),require("@nocobase/client"),require("react"),require("@ant-design/icons"),require("antd")):e["plugin-ai-chat-file-preview"]=t(e["@nocobase/plugin-ai/client"],e["@nocobase/client"],e.react,e["@ant-design/icons"],e.antd)}(self,function(e,t,n,r,o){return function(){var i,a,u,l,c,s,f={581:function(e){e.exports=function(e,t){return"undefined"!=typeof __deoptimization_sideEffect__&&__deoptimization_sideEffect__(e,t),t}},482:function(e){"use strict";e.exports=r},772:function(e){"use strict";e.exports=t},645:function(t){"use strict";t.exports=e},721:function(e){"use strict";e.exports=o},156:function(e){"use strict";e.exports=n}},d={};function p(e){var t=d[e];if(void 0!==t)return t.exports;var n=d[e]={exports:{}};return f[e](n,n.exports,p),n.exports}p.m=f,p.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return p.d(t,{a:t}),t},p.d=function(e,t){for(var n in t)p.o(t,n)&&!p.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:t[n]})},p.f={},p.e=function(e){return Promise.all(Object.keys(p.f).reduce(function(t,n){return p.f[n](e,t),t},[]))},p.u=function(e){return""+({395:"0ef9cbd6bccd7aff",463:"7e04271656f34237"})[e]+".js"},p.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||Function("return this")()}catch(e){if("object"==typeof window)return window}}(),p.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},i={},a="plugin-ai-chat-file-preview:",p.l=function(e,t,n,r){if(i[e])return void i[e].push(t);if(void 0!==n)for(var o,u,l=document.getElementsByTagName("script"),c=0;c<l.length;c++){var s=l[c];if(s.getAttribute("src")==e||s.getAttribute("data-webpack")==a+n){o=s;break}}o||(u=!0,(o=document.createElement("script")).charset="utf-8",o.timeout=120,p.nc&&o.setAttribute("nonce",p.nc),o.setAttribute("data-webpack",a+n),o.src=e),i[e]=[t];var f=function(t,n){o.onerror=o.onload=null,clearTimeout(d);var r=i[e];if(delete i[e],o.parentNode&&o.parentNode.removeChild(o),r&&r.forEach(function(e){return e(n)}),t)return t(n)},d=setTimeout(f.bind(null,void 0,{type:"timeout",target:o}),12e4);o.onerror=f.bind(null,o.onerror),o.onload=f.bind(null,o.onload),u&&document.head.appendChild(o)},p.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},(u=window.__webpack_public_path__||"/").endsWith("/")||(u+="/"),p.p=u+"static/plugins/plugin-ai-chat-file-preview/dist/client/",l={909:0},p.f.j=function(e,t){var n=p.o(l,e)?l[e]:void 0;if(0!==n)if(n)t.push(n[2]);else{var r=new Promise(function(t,r){n=l[e]=[t,r]});t.push(n[2]=r);var o=p.p+p.u(e),i=Error();p.l(o,function(t){if(p.o(l,e)&&(0!==(n=l[e])&&(l[e]=void 0),n)){var r=t&&("load"===t.type?"missing":t.type),o=t&&t.target&&t.target.src;i.message="Loading chunk "+e+" failed.\n("+r+": "+o+")",i.name="ChunkLoadError",i.type=r,i.request=o,n[1](i)}},"chunk-"+e,e)}},c=function(e,t){var n,r,o=t[0],i=t[1],a=t[2],u=0;if(o.some(function(e){return 0!==l[e]})){for(n in i)p.o(i,n)&&(p.m[n]=i[n]);a&&a(p)}for(e&&e(t);u<o.length;u++)r=o[u],p.o(l,r)&&l[r]&&l[r][0](),l[r]=0},(s=self.webpackChunkplugin_ai_chat_file_preview=self.webpackChunkplugin_ai_chat_file_preview||[]).forEach(c.bind(null,0)),s.push=c.bind(null,s.push.bind(s));var h={};return!function(){"use strict";p.r(h),p.d(h,{PluginAIChatFilePreviewClient:function(){return eh},default:function(){return ev}});var e=p(772),t=p(156),n=p.n(t),r=p(645),o=p(721),i=p(482);function a(e,t,n,r,o,i,a){try{var u=e[i](a),l=u.value}catch(e){n(e);return}u.done?t(l):Promise.resolve(l).then(r,o)}function u(e){return function(){var t=this,n=arguments;return new Promise(function(r,o){var i=e.apply(t,n);function u(e){a(i,r,o,u,l,"next",e)}function l(e){a(i,r,o,u,l,"throw",e)}u(void 0)})}}function l(e,t){var n,r,o,i,a={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]};return i={next:u(0),throw:u(1),return:u(2)},"function"==typeof Symbol&&(i[Symbol.iterator]=function(){return this}),i;function u(i){return function(u){var l=[i,u];if(n)throw TypeError("Generator is already executing.");for(;a;)try{if(n=1,r&&(o=2&l[0]?r.return:l[0]?r.throw||((o=r.return)&&o.call(r),0):r.next)&&!(o=o.call(r,l[1])).done)return o;switch(r=0,o&&(l=[2&l[0],o.value]),l[0]){case 0:case 1:o=l;break;case 4:return a.label++,{value:l[1],done:!1};case 5:a.label++,r=l[1],l=[0];continue;case 7:l=a.ops.pop(),a.trys.pop();continue;default:if(!(o=(o=a.trys).length>0&&o[o.length-1])&&(6===l[0]||2===l[0])){a=0;continue}if(3===l[0]&&(!o||l[1]>o[0]&&l[1]<o[3])){a.label=l[1];break}if(6===l[0]&&a.label<o[1]){a.label=o[1],o=l;break}if(o&&a.label<o[2]){a.label=o[2],a.ops.push(l);break}o[2]&&a.ops.pop(),a.trys.pop();continue}l=t.call(e,a)}catch(e){l=[6,e],r=0}finally{n=o=0}if(5&l[0])throw l[1];return{value:l[0]?l[1]:void 0,done:!0}}}}var c="blobs";function s(){return new Promise(function(e,t){var n=indexedDB.open("nb-ai-chat-file-preview",1);n.onupgradeneeded=function(){var e=n.result;e.objectStoreNames.contains(c)||e.createObjectStore(c)},n.onsuccess=function(){return e(n.result)},n.onerror=function(){return t(n.error)}})}function f(e,t){return"".concat(e,":").concat(t)}var d={get:function(e,t){return u(function(){var n;return l(this,function(r){switch(r.label){case 0:return[4,s()];case 1:return n=r.sent(),[2,new Promise(function(r,o){var i=n.transaction(c,"readonly").objectStore(c).get(f(e,t));i.onsuccess=function(){return r(i.result||null)},i.onerror=function(){return o(i.error)}})]}})})()},put:function(e,t,n){return u(function(){var r;return l(this,function(o){switch(o.label){case 0:return[4,s()];case 1:return r=o.sent(),[2,new Promise(function(o,i){var a=r.transaction(c,"readwrite");a.objectStore(c).put(n,f(e,t)),a.oncomplete=function(){return o()},a.onerror=function(){return i(a.error)}})]}})})()},delete:function(e,t){return u(function(){var n;return l(this,function(r){switch(r.label){case 0:return[4,s()];case 1:return n=r.sent(),[2,new Promise(function(r,o){var i=n.transaction(c,"readwrite");i.objectStore(c).delete(f(e,t)),i.oncomplete=function(){return r()},i.onerror=function(){return o(i.error)}})]}})})()},clearSession:function(e){return u(function(){var t;return l(this,function(n){switch(n.label){case 0:return[4,s()];case 1:return t=n.sent(),[2,new Promise(function(n,r){var o=t.transaction(c,"readwrite"),i=o.objectStore(c).openCursor();i.onsuccess=function(){var t=i.result;t&&("string"==typeof t.key&&t.key.startsWith("".concat(e,":"))&&t.delete(),t.continue())},o.oncomplete=function(){return n()},o.onerror=function(){return r(o.error)}})]}})})()},clearAll:function(){return u(function(){var e;return l(this,function(t){switch(t.label){case 0:return[4,s()];case 1:return e=t.sent(),[2,new Promise(function(t,n){var r=e.transaction(c,"readwrite");r.objectStore(c).clear(),r.oncomplete=function(){return t()},r.onerror=function(){return n(r.error)}})]}})})()}};function v(){var t=(0,e.useApp)();return{t:function(e){return t.i18n.t(e,{ns:"@nocobase/plugin-ai-chat-file-preview"})}}}var m=p(581);function y(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n<t;n++)r[n]=e[n];return r}function b(e,t,n,r,o,i,a){try{var u=e[i](a),l=u.value}catch(e){n(e);return}u.done?t(l):Promise.resolve(l).then(r,o)}function g(e){return function(){var t=this,n=arguments;return new Promise(function(r,o){var i=e.apply(t,n);function a(e){b(i,r,o,a,u,"next",e)}function u(e){b(i,r,o,a,u,"throw",e)}a(void 0)})}}function w(e,t){return function(e){if(Array.isArray(e))return e}(e)||function(e,t){var n,r,o=null==e?null:"undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(null!=o){var i=[],a=!0,u=!1;try{for(o=o.call(e);!(a=(n=o.next()).done)&&(i.push(n.value),!t||i.length!==t);a=!0);}catch(e){u=!0,r=e}finally{try{a||null==o.return||o.return()}finally{if(u)throw r}}return i}}(e,t)||function(e,t){if(e){if("string"==typeof e)return y(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);if("Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n)return Array.from(n);if("Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))return y(e,t)}}(e,t)||function(){throw TypeError("Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function x(e,t){var n,r,o,i,a={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]};return i={next:u(0),throw:u(1),return:u(2)},"function"==typeof Symbol&&(i[Symbol.iterator]=function(){return this}),i;function u(i){return function(u){var l=[i,u];if(n)throw TypeError("Generator is already executing.");for(;a;)try{if(n=1,r&&(o=2&l[0]?r.return:l[0]?r.throw||((o=r.return)&&o.call(r),0):r.next)&&!(o=o.call(r,l[1])).done)return o;switch(r=0,o&&(l=[2&l[0],o.value]),l[0]){case 0:case 1:o=l;break;case 4:return a.label++,{value:l[1],done:!1};case 5:a.label++,r=l[1],l=[0];continue;case 7:l=a.ops.pop(),a.trys.pop();continue;default:if(!(o=(o=a.trys).length>0&&o[o.length-1])&&(6===l[0]||2===l[0])){a=0;continue}if(3===l[0]&&(!o||l[1]>o[0]&&l[1]<o[3])){a.label=l[1];break}if(6===l[0]&&a.label<o[1]){a.label=o[1],o=l;break}if(o&&a.label<o[2]){a.label=o[2],a.ops.push(l);break}o[2]&&a.ops.pop(),a.trys.pop();continue}l=t.call(e,a)}catch(e){l=[6,e],r=0}finally{n=o=0}if(5&l[0])throw l[1];return{value:l[0]?l[1]:void 0,done:!0}}}}var S=["application/pdf"],E=["image/png","image/jpeg","image/gif","image/webp","image/svg+xml","image/bmp"],k=["text/plain","text/csv","text/html","text/css","text/javascript","application/json","application/xml","text/xml","text/yaml","application/x-yaml"],j=["application/vnd.openxmlformats-officedocument.wordprocessingml.document"],_=["application/vnd.openxmlformats-officedocument.spreadsheetml.sheet","application/vnd.ms-excel"],C=["pdf"],O=["png","jpg","jpeg","gif","webp","svg","bmp"],P=["txt","csv","html","css","js","json","xml","log","md","yaml","yml","xaml"],I=["docx"],A=["xlsx","xls"];function L(e){var t="string"==typeof e?e:null==e?void 0:e.url;return t?t.startsWith("http://")||t.startsWith("https://")?t:"".concat(location.origin,"/").concat(t.replace(/^\//,"")):""}function R(e,t,n){if((null==e?void 0:e.mimetype)&&t.includes(e.mimetype))return!0;var r,o,i=-1!==(o=(r=("string"==typeof e?e:(null==e?void 0:e.extname)||(null==e?void 0:e.name)||(null==e?void 0:e.filename)||(null==e?void 0:e.url)||"").split("?")[0].split("#")[0]).lastIndexOf("."))?r.slice(o+1).toLowerCase().replace(/^\./,""):"";return!!i&&n.includes(i)}var F=function(e){return R(e,S,C)},T=function(e){return R(e,E,O)},U=function(e){return R(e,k,P)},B=function(e){return R(e,j,I)},q=function(e){return R(e,_,A)};function M(e,t){return D.apply(this,arguments)}function D(){return(D=g(function(e,t){var n,r;return x(this,function(o){switch(o.label){case 0:return n={},t&&(n.Authorization="Bearer ".concat(t)),[4,fetch(e,{method:"GET",headers:n,credentials:"include"})];case 1:if(!(r=o.sent()).ok)throw Error("Failed to fetch file: ".concat(r.status));return[2,r.blob()]}})})).apply(this,arguments)}function N(){return(N=g(function(e,t){var n,r;return x(this,function(o){switch(o.label){case 0:return n={},t&&(n.Authorization="Bearer ".concat(t)),[4,fetch(e,{method:"GET",headers:n,credentials:"include"})];case 1:if(!(r=o.sent()).ok)throw Error("Failed to fetch file: ".concat(r.status));return[2,r.text()]}})})).apply(this,arguments)}function z(){return(z=g(function(e,t){var n,r,o,i,a;return x(this,function(u){switch(u.label){case 0:if(!(n=L(e)))return[2];return[4,M(n,t)];case 1:return r=u.sent(),o=(null==e?void 0:e.title)&&(null==e?void 0:e.extname)?"".concat(e.title).concat(e.extname):(null==e?void 0:e.filename)||(null==e?void 0:e.name)||"download",(i=document.createElement("a")).href=a=URL.createObjectURL(r),i.download=o,document.body.appendChild(i),i.click(),document.body.removeChild(i),setTimeout(function(){return URL.revokeObjectURL(a)},1e3),[2]}})})).apply(this,arguments)}function W(e){var t=e.msg;return n().createElement("div",{style:{display:"flex",justifyContent:"center",alignItems:"center",height:"100%",width:"100%"}},n().createElement(o.Spin,{tip:t}))}function H(e){var t=e.msg;return n().createElement("div",{style:{padding:20,textAlign:"center",color:"#ff4d4f"}},t)}function G(e,n,r){var o=w((0,t.useState)(null),2),i=o[0],a=o[1],u=w((0,t.useState)(!0),2),l=u[0],c=u[1],s=w((0,t.useState)(null),2),f=s[0],p=s[1],h=(0,t.useRef)(null),v=(null==e?void 0:e.id)||(null==e?void 0:e.uid)||"",m=L(e);return(0,t.useEffect)(function(){var e=!1;if(!m){c(!1),p("No file URL");return}return c(!0),p(null),g(function(){var t,o,i,u,l;return x(this,function(s){switch(s.label){case 0:if(s.trys.push([0,4,,5]),!(r&&v))return[3,2];return[4,d.get(r,String(v))];case 1:if((t=s.sent())&&!e)return h.current=o=URL.createObjectURL(t),a(o),c(!1),[2];s.label=2;case 2:return[4,M(m,n)];case 3:if(i=s.sent(),e)return[2];return r&&v&&d.put(r,String(v),i).catch(function(){}),h.current=u=URL.createObjectURL(i),a(u),c(!1),[3,5];case 4:if(l=s.sent(),e)return[2];return p(l.message||"Failed to load"),c(!1),[3,5];case 5:return[2]}})})(),function(){e=!0,h.current&&(URL.revokeObjectURL(h.current),h.current=null)}},[m,n,r,v]),{blobUrl:i,loading:l,error:f}}function X(t){var r,o=t.file,i=t.sessionId,a=(0,e.useAPIClient)(),u=v().t,l=G(o,(null==(r=a.auth)?void 0:r.token)||"",i),c=l.blobUrl,s=l.loading,f=l.error;return s?n().createElement(W,{msg:u("Loading preview...")}):f||!c?n().createElement(H,{msg:u("Failed to load file preview")}):n().createElement("iframe",{src:c,width:"100%",height:"100%",style:{border:"none"}})}function $(t){var r,o=t.file,i=t.sessionId,a=(0,e.useAPIClient)(),u=v().t,l=G(o,(null==(r=a.auth)?void 0:r.token)||"",i),c=l.blobUrl,s=l.loading,f=l.error;return s?n().createElement(W,{msg:u("Loading preview...")}):f||!c?n().createElement(H,{msg:u("Failed to load file preview")}):n().createElement("img",{src:c,style:{maxWidth:"100%",maxHeight:"100%",objectFit:"contain"},alt:(null==o?void 0:o.filename)||""})}function J(r){var o,i,a,u,l,c,s,f,p,h,m,y,b=r.file,S=r.sessionId,E=(0,e.useAPIClient)(),k=v().t,j=(null==(y=E.auth)?void 0:y.token)||"",_=(i=(o=w((0,t.useState)(null),2))[0],a=o[1],l=(u=w((0,t.useState)(!0),2))[0],c=u[1],f=(s=w((0,t.useState)(null),2))[0],p=s[1],h=(null==b?void 0:b.id)||(null==b?void 0:b.uid)||"",m=L(b),(0,t.useEffect)(function(){var e=!1;if(!m){c(!1),p("No file URL");return}return c(!0),p(null),g(function(){var t,n,r,o;return x(this,function(i){switch(i.label){case 0:if(i.trys.push([0,5,,6]),!(S&&h))return[3,3];return[4,d.get(S,String(h))];case 1:if(!((t=i.sent())&&!e))return[3,3];return[4,t.text()];case 2:return a(i.sent()),c(!1),[2];case 3:return[4,function(e,t){return N.apply(this,arguments)}(m,j)];case 4:if(n=i.sent(),e)return[2];return S&&h&&(r=new Blob([n],{type:"text/plain"}),d.put(S,String(h),r).catch(function(){})),a(n),c(!1),[3,6];case 5:if(o=i.sent(),e)return[2];return p(o.message||"Failed to load"),c(!1),[3,6];case 6:return[2]}})})(),function(){e=!0}},[m,j,S,h]),{text:i,loading:l,error:f}),C=_.text,O=_.loading,P=_.error;return O?n().createElement(W,{msg:k("Loading preview...")}):P||null===C?n().createElement(H,{msg:k("Failed to load file preview")}):n().createElement("pre",{style:{width:"100%",height:"100%",overflow:"auto",padding:16,margin:0,fontSize:13,lineHeight:1.6,whiteSpace:"pre-wrap",wordWrap:"break-word",background:"#f5f5f5",border:"none"}},C)}function Y(r){var o,i=r.file,a=r.sessionId,u=(0,e.useAPIClient)(),l=v().t,c=(null==(o=u.auth)?void 0:o.token)||"",s=(0,t.useRef)(null),f=w((0,t.useState)(!0),2),h=f[0],y=f[1],b=w((0,t.useState)(null),2),S=b[0],E=b[1],k=L(i),j=(null==i?void 0:i.id)||(null==i?void 0:i.uid)||"";return(0,t.useEffect)(function(){var e=!1;if(!k||!s.current){y(!1),E("No file URL");return}return y(!0),E(null),g(function(){var t,n,r,o;return x(this,function(i){switch(i.label){case 0:if(i.trys.push([0,10,,11]),!(a&&j))return[3,5];return[4,d.get(a,String(j))];case 1:if(!((n=i.sent())&&!e))return[3,2];return t=n,[3,4];case 2:return[4,M(k,c)];case 3:if(t=i.sent(),e)return[2];d.put(a,String(j),t).catch(function(){}),i.label=4;case 4:return[3,7];case 5:return[4,M(k,c)];case 6:t=i.sent(),i.label=7;case 7:if(e||!s.current)return[2];return[4,m("imported_-1dm6lbf_component",p.e("395").then(p.bind(p,835)))];case 8:if(r=i.sent(),e||!s.current)return[2];return s.current.innerHTML="",[4,r.renderAsync(t,s.current,void 0,{className:"docx-preview-wrapper",inWrapper:!0,ignoreWidth:!1,ignoreHeight:!1,ignoreFonts:!1,breakPages:!0,ignoreLastRenderedPageBreak:!0,experimental:!1,trimXmlDeclaration:!0,useBase64URL:!0,renderHeaders:!0,renderFooters:!0,renderFootnotes:!0,renderEndnotes:!0})];case 9:return i.sent(),y(!1),[3,11];case 10:if(o=i.sent(),e)return[2];return E(o.message||"Failed to render DOCX"),y(!1),[3,11];case 11:return[2]}})})(),function(){e=!0}},[k,c,a,j]),n().createElement("div",{style:{width:"100%",height:"100%",position:"relative"}},h&&n().createElement(W,{msg:l("Loading preview...")}),S&&n().createElement(H,{msg:l("Failed to load file preview")}),n().createElement("div",{ref:s,style:{width:"100%",height:"100%",overflow:"auto",display:h||S?"none":"block"}}))}function K(r){var o,i=r.file,a=r.sessionId,u=(0,e.useAPIClient)(),l=v().t,c=(null==(o=u.auth)?void 0:o.token)||"",s=w((0,t.useState)(!0),2),f=s[0],h=s[1],y=w((0,t.useState)(null),2),b=y[0],S=y[1],E=w((0,t.useState)([]),2),k=E[0],j=E[1],_=w((0,t.useState)(""),2),C=_[0],O=_[1],P=w((0,t.useState)({}),2),I=P[0],A=P[1],R=L(i),F=(null==i?void 0:i.id)||(null==i?void 0:i.uid)||"";return(0,t.useEffect)(function(){var e=!1;if(!R){h(!1),S("No file URL");return}return h(!0),S(null),g(function(){var t,n,r,o,i,u,l,s,f,v,y,b,g,w;return x(this,function(x){switch(x.label){case 0:if(x.trys.push([0,10,,11]),!(a&&F))return[3,5];return[4,d.get(a,String(F))];case 1:if(!((n=x.sent())&&!e))return[3,2];return t=n,[3,4];case 2:return[4,M(R,c)];case 3:if(t=x.sent(),e)return[2];d.put(a,String(F),t).catch(function(){}),x.label=4;case 4:return[3,7];case 5:return[4,M(R,c)];case 6:t=x.sent(),x.label=7;case 7:if(e)return[2];return[4,m("imported_-1lj2ifg_component",p.e("463").then(p.bind(p,312)))];case 8:if(r=x.sent(),e)return[2];return[4,t.arrayBuffer()];case 9:if(o=x.sent(),e)return[2];u=(i=r.read(o,{type:"array"})).SheetNames,l={},s=!0,f=!1,v=void 0;try{for(y=u[Symbol.iterator]();!(s=(b=y.next()).done);s=!0)l[g=b.value]=r.utils.sheet_to_html(i.Sheets[g],{id:"xlsx-preview-table"})}catch(e){f=!0,v=e}finally{try{s||null==y.return||y.return()}finally{if(f)throw v}}if(e)return[2];return j(u),O(u[0]||""),A(l),h(!1),[3,11];case 10:if(w=x.sent(),e)return[2];return S(w.message||"Failed to render XLSX"),h(!1),[3,11];case 11:return[2]}})})(),function(){e=!0}},[R,c,a,F]),n().createElement("div",{style:{width:"100%",height:"100%",display:"flex",flexDirection:"column"}},f&&n().createElement(W,{msg:l("Loading preview...")}),b&&n().createElement(H,{msg:l("Failed to load file preview")}),!f&&!b&&n().createElement(n().Fragment,null,k.length>1&&n().createElement("div",{style:{display:"flex",gap:0,borderBottom:"1px solid #e8e8e8",background:"#fafafa",padding:"0 8px",flexShrink:0,overflowX:"auto"}},k.map(function(e){return n().createElement("button",{key:e,onClick:function(){return O(e)},style:{padding:"8px 16px",border:"none",borderBottom:C===e?"2px solid #1890ff":"2px solid transparent",background:C===e?"#fff":"transparent",color:C===e?"#1890ff":"#666",fontWeight:C===e?600:400,cursor:"pointer",fontSize:13,whiteSpace:"nowrap",transition:"all 0.2s"}},e)})),n().createElement("div",{style:{flex:1,overflow:"auto",padding:0},dangerouslySetInnerHTML:{__html:I[C]||""}}),n().createElement("style",null,"\n #xlsx-preview-table { border-collapse: collapse; width: 100%; font-size: 13px; }\n #xlsx-preview-table td, #xlsx-preview-table th {\n border: 1px solid #e8e8e8; padding: 6px 10px; text-align: left;\n max-width: 33vw; white-space: normal; word-break: break-word;\n }\n #xlsx-preview-table tr:first-child td, #xlsx-preview-table tr:first-child th {\n background: #fafafa; font-weight: 600; position: sticky; top: 0; z-index: 1;\n }\n #xlsx-preview-table tr:nth-child(even) { background: #fafafa; }\n #xlsx-preview-table tr:hover { background: #f0f7ff; }\n ")))}var Q=function(r){var a=r.open,u=r.file,l=r.sessionId,c=r.onClose,s=(0,e.useAPIClient)(),f=v().t,p=w((0,t.useState)(!1),2),h=p[0],m=p[1],y=(null==u?void 0:u.id)||(null==u?void 0:u.uid)||"",b=(0,t.useCallback)(g(function(){var e,t;return x(this,function(n){switch(n.label){case 0:if(!u)return[2];t=(null==(e=s.auth)?void 0:e.token)||"",m(!0),n.label=1;case 1:return n.trys.push([1,3,4,5]),[4,function(e,t){return z.apply(this,arguments)}(u,t)];case 2:return n.sent(),[3,5];case 3:return n.sent(),o.message.error(f("Failed to download file")),[3,5];case 4:return m(!1),[7];case 5:return[2]}})}),[u,s,f]),S=(0,t.useCallback)(g(function(){return x(this,function(e){switch(e.label){case 0:if(!l||!y)return[2];return[4,d.delete(l,String(y))];case 1:return e.sent(),o.message.success(f("Cache cleared")),[2]}})}),[l,y,f]),E=(0,t.useMemo)(function(){return u?F(u)?X:T(u)?$:U(u)?J:B(u)?Y:q(u)?K:null:null},[u]),k=null!=E,j=(null==u?void 0:u.title)&&(null==u?void 0:u.extname)?"".concat(u.title).concat(u.extname):(null==u?void 0:u.filename)||(null==u?void 0:u.name)||"File";return n().createElement(o.Modal,{open:a,title:j,onCancel:c,destroyOnClose:!0,footer:[l&&y?n().createElement(o.Button,{key:"clear-cache",icon:n().createElement(i.DeleteOutlined,null),onClick:S},f("Clear cache")):null,n().createElement(o.Button,{key:"download",icon:n().createElement(i.DownloadOutlined,null),onClick:b,loading:h},f("Download")),n().createElement(o.Button,{key:"close",onClick:c},f("Close"))].filter(Boolean),width:k?"85vw":520,centered:!0},n().createElement("div",{style:{maxWidth:"100%",maxHeight:k?"calc(100vh - 256px)":"auto",height:k?"70vh":"auto",width:"100%",background:"white",display:"flex",flexDirection:"column",justifyContent:"center",alignItems:"center",overflowY:"auto"}},k&&u?n().createElement(E,{file:u,sessionId:l}):n().createElement(o.Alert,{type:"info",style:{width:"100%"},description:f("This file type cannot be previewed. Click Download to save the file."),showIcon:!0})))};function V(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n<t;n++)r[n]=e[n];return r}function Z(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}function ee(e){return(ee=Object.setPrototypeOf?Object.getPrototypeOf:function(e){return e.__proto__||Object.getPrototypeOf(e)})(e)}function et(e,t){return(et=Object.setPrototypeOf||function(e,t){return e.__proto__=t,e})(e,t)}function en(e,t){return function(e){if(Array.isArray(e))return e}(e)||function(e,t){var n,r,o=null==e?null:"undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(null!=o){var i=[],a=!0,u=!1;try{for(o=o.call(e);!(a=(n=o.next()).done)&&(i.push(n.value),!t||i.length!==t);a=!0);}catch(e){u=!0,r=e}finally{try{a||null==o.return||o.return()}finally{if(u)throw r}}return i}}(e,t)||function(e,t){if(e){if("string"==typeof e)return V(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);if("Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n)return Array.from(n);if("Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))return V(e,t)}}(e,t)||function(){throw TypeError("Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function er(){try{var e=!Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],function(){}))}catch(e){}return(er=function(){return!!e})()}function eo(e){return{id:e.id,uid:e.uid,url:e.url,filename:e.filename||e.name,name:e.name||e.filename,title:e.title,extname:e.extname,mimetype:e.mimetype,size:e.size}}var ei=function(o){var i=o.children,a=en((0,t.useState)(!1),2),u=a[0],l=a[1],c=en((0,t.useState)(null),2),s=c[0],f=c[1],p=en((0,t.useState)(""),2),h=p[0],v=p[1],m=(0,e.useAPIClient)(),y=r.useChatMessagesStore.use.messages(),b=r.useChatMessagesStore.use.attachments(),g=(0,t.useRef)(y),w=(0,t.useRef)(b);g.current=y,w.current=b;var x=(0,t.useRef)("");(0,t.useEffect)(function(){var e=m.axios.interceptors.request.use(function(e){var t=e.url||"";if(t.includes("aiConversations:getMessages")){var n=t.match(/sessionId=([^&]+)/);n&&(x.current=decodeURIComponent(n[1]))}if(t.includes("aiConversations:sendMessages")&&e.data)try{var r="string"==typeof e.data?JSON.parse(e.data):e.data;(null==r?void 0:r.sessionId)&&(x.current=r.sessionId)}catch(e){}return e});return function(){m.axios.interceptors.request.eject(e)}},[m]),(0,t.useEffect)(function(){var e=function(e){var t,n,r,o=e.target;if(!o)return;var i=o.closest('[class*="attachment-list-card"]');if(!(!i||!i.closest(".ant-layout")||i.classList.toString().includes("type-preview")||o.closest('[class*="-remove"]'))){var a=function(e,t,n){if(!e)return null;var r=!0,o=!1,i=void 0;try{for(var a,u=t[Symbol.iterator]();!(r=(a=u.next()).done);r=!0){var l=a.value,c=l.content||l,s=null==c?void 0:c.attachments;if(null==s?void 0:s.length){var f=!0,d=!1,p=void 0;try{for(var h,v=s[Symbol.iterator]();!(f=(h=v.next()).done);f=!0){var m=h.value;if((m.filename||m.name||"")===e||"".concat(m.title||"").concat(m.extname||"")===e)return eo(m)}}catch(e){d=!0,p=e}finally{try{f||null==v.return||v.return()}finally{if(d)throw p}}}}}catch(e){o=!0,i=e}finally{try{r||null==u.return||u.return()}finally{if(o)throw i}}var y=!0,b=!1,g=void 0;try{for(var w,x=(n||[])[Symbol.iterator]();!(y=(w=x.next()).done);y=!0){var S=w.value;if((S.filename||S.name||"")===e||"".concat(S.title||"").concat(S.extname||"")===e)return eo(S)}}catch(e){b=!0,g=e}finally{try{y||null==x.return||x.return()}finally{if(b)throw g}}return null}((n=i.querySelector('[class*="ellipsis-prefix"]'),r=i.querySelector('[class*="ellipsis-suffix"]'),n&&r?(n.textContent||"")+(r.textContent||""):(null==(t=i.textContent)?void 0:t.trim())||""),g.current,w.current);a&&(F(a)||T(a)||U(a)||B(a)||q(a))&&(e.preventDefault(),e.stopPropagation(),v(x.current||""),f(a),l(!0))}};return document.addEventListener("click",e,{capture:!0}),function(){return document.removeEventListener("click",e,{capture:!0})}},[]),(0,t.useEffect)(function(){var e=m.axios.interceptors.response.use(function(e){try{var t,n=(null==(t=e.config)?void 0:t.url)||"";if(n.includes("aiConversations:destroy")){var r=n.match(/filterByTk=([^&]+)/);r&&d.clearSession(decodeURIComponent(r[1])).catch(function(){})}}catch(e){}return e});return function(){m.axios.interceptors.response.eject(e)}},[m]);var S=(0,t.useCallback)(function(){l(!1),f(null)},[]);return n().createElement(n().Fragment,null,i,n().createElement(Q,{open:u,file:s,sessionId:h,onClose:S}))},ea=function(e){var t,n;if("function"!=typeof e&&null!==e)throw TypeError("Super expression must either be null or a function");function r(e){var t,n,o;if(!(this instanceof r))throw TypeError("Cannot call a class as a function");return n=r,o=[e],n=ee(n),(t=function(e,t){var n;if(t&&("object"==((n=t)&&"undefined"!=typeof Symbol&&n.constructor===Symbol?"symbol":typeof n)||"function"==typeof t))return t;if(void 0===e)throw ReferenceError("this hasn't been initialised - super() hasn't been called");return e}(this,er()?Reflect.construct(n,o||[],ee(this).constructor):n.apply(this,o))).state={hasError:!1},t}return r.prototype=Object.create(e&&e.prototype,{constructor:{value:r,writable:!0,configurable:!0}}),e&&et(r,e),n=[{key:"getDerivedStateFromError",value:function(){return{hasError:!0}}}],t=[{key:"render",value:function(){return this.state.hasError,this.props.children}}],Z(r.prototype,t),n&&Z(r,n),r}(n().Component),eu=function(e){var t=e.children;return n().createElement(ea,null,n().createElement(ei,null,t))};function el(e,t,n,r,o,i,a){try{var u=e[i](a),l=u.value}catch(e){n(e);return}u.done?t(l):Promise.resolve(l).then(r,o)}function ec(e,t,n){return(ec=ep()?Reflect.construct:function(e,t,n){var r=[null];r.push.apply(r,t);var o=new(Function.bind.apply(e,r));return n&&ef(o,n.prototype),o}).apply(null,arguments)}function es(e){return(es=Object.setPrototypeOf?Object.getPrototypeOf:function(e){return e.__proto__||Object.getPrototypeOf(e)})(e)}function ef(e,t){return(ef=Object.setPrototypeOf||function(e,t){return e.__proto__=t,e})(e,t)}function ed(e){var t="function"==typeof Map?new Map:void 0;return(ed=function(e){if(null===e||-1===Function.toString.call(e).indexOf("[native code]"))return e;if("function"!=typeof e)throw TypeError("Super expression must either be null or a function");if(void 0!==t){if(t.has(e))return t.get(e);t.set(e,n)}function n(){return ec(e,arguments,es(this).constructor)}return n.prototype=Object.create(e.prototype,{constructor:{value:n,enumerable:!1,writable:!0,configurable:!0}}),ef(n,e)})(e)}function ep(){try{var e=!Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],function(){}))}catch(e){}return(ep=function(){return!!e})()}var eh=function(e){var t;if("function"!=typeof e&&null!==e)throw TypeError("Super expression must either be null or a function");function n(){var e,t;if(!(this instanceof n))throw TypeError("Cannot call a class as a function");return e=n,t=arguments,e=es(e),function(e,t){var n;if(t&&("object"==((n=t)&&"undefined"!=typeof Symbol&&n.constructor===Symbol?"symbol":typeof n)||"function"==typeof t))return t;if(void 0===e)throw ReferenceError("this hasn't been initialised - super() hasn't been called");return e}(this,ep()?Reflect.construct(e,t||[],es(this).constructor):e.apply(this,t))}return n.prototype=Object.create(e&&e.prototype,{constructor:{value:n,writable:!0,configurable:!0}}),e&&ef(n,e),t=[{key:"load",value:function(){var e,t=this;return(e=function(){return function(e,t){var n,r,o,i,a={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]};return i={next:u(0),throw:u(1),return:u(2)},"function"==typeof Symbol&&(i[Symbol.iterator]=function(){return this}),i;function u(i){return function(u){var l=[i,u];if(n)throw TypeError("Generator is already executing.");for(;a;)try{if(n=1,r&&(o=2&l[0]?r.return:l[0]?r.throw||((o=r.return)&&o.call(r),0):r.next)&&!(o=o.call(r,l[1])).done)return o;switch(r=0,o&&(l=[2&l[0],o.value]),l[0]){case 0:case 1:o=l;break;case 4:return a.label++,{value:l[1],done:!1};case 5:a.label++,r=l[1],l=[0];continue;case 7:l=a.ops.pop(),a.trys.pop();continue;default:if(!(o=(o=a.trys).length>0&&o[o.length-1])&&(6===l[0]||2===l[0])){a=0;continue}if(3===l[0]&&(!o||l[1]>o[0]&&l[1]<o[3])){a.label=l[1];break}if(6===l[0]&&a.label<o[1]){a.label=o[1],o=l;break}if(o&&a.label<o[2]){a.label=o[2],a.ops.push(l);break}o[2]&&a.ops.pop(),a.trys.pop();continue}l=t.call(e,a)}catch(e){l=[6,e],r=0}finally{n=o=0}if(5&l[0])throw l[1];return{value:l[0]?l[1]:void 0,done:!0}}}}(this,function(e){return t.app.use(eu),[2]})},function(){var t=this,n=arguments;return new Promise(function(r,o){var i=e.apply(t,n);function a(e){el(i,r,o,a,u,"next",e)}function u(e){el(i,r,o,a,u,"throw",e)}a(void 0)})})()}}],function(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}(n.prototype,t),n}(ed(e.Plugin)),ev=eh}(),h}()});
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file is part of the NocoBase (R) project.
|
|
3
|
+
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
|
4
|
+
* Authors: NocoBase Team.
|
|
5
|
+
*
|
|
6
|
+
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
|
+
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
module.exports = {
|
|
11
|
+
"react": "18.2.0",
|
|
12
|
+
"@nocobase/client": "2.0.32",
|
|
13
|
+
"@nocobase/plugin-ai": "2.0.32",
|
|
14
|
+
"antd": "5.24.2",
|
|
15
|
+
"@ant-design/icons": "5.6.1",
|
|
16
|
+
"@nocobase/server": "2.0.32"
|
|
17
|
+
};
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file is part of the NocoBase (R) project.
|
|
3
|
+
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
|
4
|
+
* Authors: NocoBase Team.
|
|
5
|
+
*
|
|
6
|
+
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
|
+
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
var __create = Object.create;
|
|
11
|
+
var __defProp = Object.defineProperty;
|
|
12
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
13
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
14
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
15
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
16
|
+
var __export = (target, all) => {
|
|
17
|
+
for (var name in all)
|
|
18
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
19
|
+
};
|
|
20
|
+
var __copyProps = (to, from, except, desc) => {
|
|
21
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
22
|
+
for (let key of __getOwnPropNames(from))
|
|
23
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
24
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
25
|
+
}
|
|
26
|
+
return to;
|
|
27
|
+
};
|
|
28
|
+
var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default"));
|
|
29
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
30
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
31
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
32
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
33
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
34
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
35
|
+
mod
|
|
36
|
+
));
|
|
37
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
38
|
+
var src_exports = {};
|
|
39
|
+
__export(src_exports, {
|
|
40
|
+
default: () => import_server.default
|
|
41
|
+
});
|
|
42
|
+
module.exports = __toCommonJS(src_exports);
|
|
43
|
+
__reExport(src_exports, require("./server"), module.exports);
|
|
44
|
+
var import_server = __toESM(require("./server"));
|
|
45
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
46
|
+
0 && (module.exports = {
|
|
47
|
+
...require("./server")
|
|
48
|
+
});
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"Loading preview...": "Loading preview...",
|
|
3
|
+
"Failed to load file preview": "Failed to load file preview",
|
|
4
|
+
"Failed to download file": "Failed to download file",
|
|
5
|
+
"Download": "Download",
|
|
6
|
+
"Close": "Close",
|
|
7
|
+
"Clear cache": "Clear cache",
|
|
8
|
+
"Cache cleared": "Cache cleared",
|
|
9
|
+
"This file type cannot be previewed. Click Download to save the file.": "This file type cannot be previewed. Click Download to save the file."
|
|
10
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"Loading preview...": "Đang tải xem trước...",
|
|
3
|
+
"Failed to load file preview": "Không thể tải xem trước file",
|
|
4
|
+
"Failed to download file": "Không thể tải file",
|
|
5
|
+
"Download": "Tải xuống",
|
|
6
|
+
"Close": "Đóng",
|
|
7
|
+
"Clear cache": "Xóa bộ nhớ đệm",
|
|
8
|
+
"Cache cleared": "Đã xóa bộ nhớ đệm",
|
|
9
|
+
"This file type cannot be previewed. Click Download to save the file.": "Loại file này không thể xem trước. Nhấn Tải xuống để lưu file."
|
|
10
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"Loading preview...": "加载预览中...",
|
|
3
|
+
"Failed to load file preview": "加载文件预览失败",
|
|
4
|
+
"Failed to download file": "下载文件失败",
|
|
5
|
+
"Download": "下载",
|
|
6
|
+
"Close": "关闭",
|
|
7
|
+
"Clear cache": "清除缓存",
|
|
8
|
+
"Cache cleared": "缓存已清除",
|
|
9
|
+
"This file type cannot be previewed. Click Download to save the file.": "此文件类型无法预览。点击下载保存文件。"
|
|
10
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file is part of the NocoBase (R) project.
|
|
3
|
+
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
|
4
|
+
* Authors: NocoBase Team.
|
|
5
|
+
*
|
|
6
|
+
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
|
+
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
var __create = Object.create;
|
|
11
|
+
var __defProp = Object.defineProperty;
|
|
12
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
13
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
14
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
15
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
16
|
+
var __export = (target, all) => {
|
|
17
|
+
for (var name in all)
|
|
18
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
19
|
+
};
|
|
20
|
+
var __copyProps = (to, from, except, desc) => {
|
|
21
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
22
|
+
for (let key of __getOwnPropNames(from))
|
|
23
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
24
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
25
|
+
}
|
|
26
|
+
return to;
|
|
27
|
+
};
|
|
28
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
29
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
30
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
31
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
32
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
33
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
34
|
+
mod
|
|
35
|
+
));
|
|
36
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
37
|
+
var server_exports = {};
|
|
38
|
+
__export(server_exports, {
|
|
39
|
+
default: () => import_plugin.default
|
|
40
|
+
});
|
|
41
|
+
module.exports = __toCommonJS(server_exports);
|
|
42
|
+
var import_plugin = __toESM(require("./plugin"));
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file is part of the NocoBase (R) project.
|
|
3
|
+
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
|
4
|
+
* Authors: NocoBase Team.
|
|
5
|
+
*
|
|
6
|
+
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
|
+
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
var __defProp = Object.defineProperty;
|
|
11
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
12
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
13
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
14
|
+
var __export = (target, all) => {
|
|
15
|
+
for (var name in all)
|
|
16
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
17
|
+
};
|
|
18
|
+
var __copyProps = (to, from, except, desc) => {
|
|
19
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
20
|
+
for (let key of __getOwnPropNames(from))
|
|
21
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
22
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
23
|
+
}
|
|
24
|
+
return to;
|
|
25
|
+
};
|
|
26
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
27
|
+
var plugin_exports = {};
|
|
28
|
+
__export(plugin_exports, {
|
|
29
|
+
PluginAIChatFilePreviewServer: () => PluginAIChatFilePreviewServer,
|
|
30
|
+
default: () => plugin_default
|
|
31
|
+
});
|
|
32
|
+
module.exports = __toCommonJS(plugin_exports);
|
|
33
|
+
var import_server = require("@nocobase/server");
|
|
34
|
+
class PluginAIChatFilePreviewServer extends import_server.Plugin {
|
|
35
|
+
async load() {
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
var plugin_default = PluginAIChatFilePreviewServer;
|
|
39
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
40
|
+
0 && (module.exports = {
|
|
41
|
+
PluginAIChatFilePreviewServer
|
|
42
|
+
});
|
package/package.json
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "plugin-ai-chat-file-preview",
|
|
3
|
+
"displayName": "AI Chat File Preview",
|
|
4
|
+
"displayName.vi-VN": "Xem trước file trong Chat AI",
|
|
5
|
+
"displayName.zh-CN": "AI聊天文件预览",
|
|
6
|
+
"description": "Preview uploaded file attachments directly in AI Employee chat with in-browser caching.",
|
|
7
|
+
"description.vi-VN": "Xem trước file đính kèm đã tải lên trực tiếp trong chat AI Employee với bộ nhớ đệm trình duyệt.",
|
|
8
|
+
"description.zh-CN": "在AI员工聊天中直接预览上传的文件附件,支持浏览器缓存。",
|
|
9
|
+
"version": "1.0.0",
|
|
10
|
+
"main": "dist/server/index.js",
|
|
11
|
+
"dependencies": {
|
|
12
|
+
"xlsx": "^0.18.5",
|
|
13
|
+
"docx-preview": "^0.3.3"
|
|
14
|
+
},
|
|
15
|
+
"peerDependencies": {
|
|
16
|
+
"@nocobase/client": "2.x",
|
|
17
|
+
"@nocobase/server": "2.x",
|
|
18
|
+
"@nocobase/database": "2.x",
|
|
19
|
+
"@nocobase/plugin-ai": "2.x",
|
|
20
|
+
"@nocobase/plugin-file-manager": "2.x"
|
|
21
|
+
},
|
|
22
|
+
"devDependencies": {},
|
|
23
|
+
"keywords": [
|
|
24
|
+
"AI",
|
|
25
|
+
"Chat",
|
|
26
|
+
"File preview",
|
|
27
|
+
"Cache"
|
|
28
|
+
],
|
|
29
|
+
"license": "Apache-2.0"
|
|
30
|
+
}
|
package/server.d.ts
ADDED
package/server.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
module.exports = require('./dist/server');
|
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file is part of the NocoBase (R) project.
|
|
3
|
+
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
|
4
|
+
* Authors: NocoBase Team.
|
|
5
|
+
*
|
|
6
|
+
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
|
+
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import React, { useCallback, useEffect, useRef, useState } from 'react';
|
|
11
|
+
import { useAPIClient } from '@nocobase/client';
|
|
12
|
+
import { useChatMessagesStore } from '@nocobase/plugin-ai/client';
|
|
13
|
+
import { PreviewModal, PreviewFile, isPreviewableFile } from './PreviewModal';
|
|
14
|
+
import { SessionBlobCache } from './SessionBlobCache';
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Extract displayed filename from a FileListCard DOM element.
|
|
18
|
+
* FileListCard renders: ellipsis-prefix (name without ext) + ellipsis-suffix (.ext)
|
|
19
|
+
*/
|
|
20
|
+
function getDisplayNameFromCard(cardEl: HTMLElement): string {
|
|
21
|
+
const prefixEl = cardEl.querySelector('[class*="ellipsis-prefix"]');
|
|
22
|
+
const suffixEl = cardEl.querySelector('[class*="ellipsis-suffix"]');
|
|
23
|
+
|
|
24
|
+
if (prefixEl && suffixEl) {
|
|
25
|
+
return (prefixEl.textContent || '') + (suffixEl.textContent || '');
|
|
26
|
+
}
|
|
27
|
+
return cardEl.textContent?.trim() || '';
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function attToPreviewFile(att: any): PreviewFile {
|
|
31
|
+
return {
|
|
32
|
+
id: att.id,
|
|
33
|
+
uid: att.uid,
|
|
34
|
+
url: att.url,
|
|
35
|
+
filename: att.filename || att.name,
|
|
36
|
+
name: att.name || att.filename,
|
|
37
|
+
title: att.title,
|
|
38
|
+
extname: att.extname,
|
|
39
|
+
mimetype: att.mimetype,
|
|
40
|
+
size: att.size,
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Find file metadata matching the displayed filename across all message attachments.
|
|
46
|
+
*/
|
|
47
|
+
function findFileByDisplayName(displayName: string, messages: any[], pendingAttachments: any[]): PreviewFile | null {
|
|
48
|
+
if (!displayName) return null;
|
|
49
|
+
|
|
50
|
+
// Search sent messages
|
|
51
|
+
for (const msg of messages) {
|
|
52
|
+
const content = msg.content || msg;
|
|
53
|
+
const attachments = content?.attachments;
|
|
54
|
+
if (!attachments?.length) continue;
|
|
55
|
+
|
|
56
|
+
for (const att of attachments) {
|
|
57
|
+
const attName = att.filename || att.name || '';
|
|
58
|
+
if (attName === displayName || `${att.title || ''}${att.extname || ''}` === displayName) {
|
|
59
|
+
return attToPreviewFile(att);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// Search pending (not yet sent) attachments
|
|
65
|
+
for (const att of pendingAttachments || []) {
|
|
66
|
+
const attName = att.filename || att.name || '';
|
|
67
|
+
if (attName === displayName || `${att.title || ''}${att.extname || ''}` === displayName) {
|
|
68
|
+
return attToPreviewFile(att);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
return null;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Inner component that reads from plugin-ai's zustand stores via hooks.
|
|
77
|
+
* Uses refs to make latest state available inside the DOM click handler.
|
|
78
|
+
*/
|
|
79
|
+
const ChatFilePreviewInner: React.FC<{ children: React.ReactNode }> = ({ children }) => {
|
|
80
|
+
const [previewOpen, setPreviewOpen] = useState(false);
|
|
81
|
+
const [previewFile, setPreviewFile] = useState<PreviewFile | null>(null);
|
|
82
|
+
const [sessionId, setSessionId] = useState('');
|
|
83
|
+
const apiClient = useAPIClient();
|
|
84
|
+
|
|
85
|
+
// Read zustand stores via hooks — these re-render on changes
|
|
86
|
+
const messages = useChatMessagesStore.use.messages();
|
|
87
|
+
const pendingAttachments = useChatMessagesStore.use.attachments();
|
|
88
|
+
|
|
89
|
+
// Keep latest values in refs for the click handler (avoids stale closures)
|
|
90
|
+
const messagesRef = useRef(messages);
|
|
91
|
+
const pendingAttachmentsRef = useRef(pendingAttachments);
|
|
92
|
+
messagesRef.current = messages;
|
|
93
|
+
pendingAttachmentsRef.current = pendingAttachments;
|
|
94
|
+
|
|
95
|
+
// We don't have direct access to useChatConversationsStore (not exported).
|
|
96
|
+
// Instead, we'll extract sessionId from the URL or from a data attribute on the DOM.
|
|
97
|
+
// A simpler approach: use a global ref that gets populated via the axios interceptor.
|
|
98
|
+
const currentSessionIdRef = useRef<string>('');
|
|
99
|
+
|
|
100
|
+
// Track the current sessionId by intercepting the getMessages API call
|
|
101
|
+
useEffect(() => {
|
|
102
|
+
const reqInterceptor = apiClient.axios.interceptors.request.use((config) => {
|
|
103
|
+
const url = config.url || '';
|
|
104
|
+
// When loadMessages is called, the sessionId appears in the URL
|
|
105
|
+
if (url.includes('aiConversations:getMessages')) {
|
|
106
|
+
const match = url.match(/sessionId=([^&]+)/);
|
|
107
|
+
if (match) {
|
|
108
|
+
currentSessionIdRef.current = decodeURIComponent(match[1]);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
// When sendMessages is called, sessionId is in the request body
|
|
112
|
+
if (url.includes('aiConversations:sendMessages') && config.data) {
|
|
113
|
+
try {
|
|
114
|
+
const data = typeof config.data === 'string' ? JSON.parse(config.data) : config.data;
|
|
115
|
+
if (data?.sessionId) {
|
|
116
|
+
currentSessionIdRef.current = data.sessionId;
|
|
117
|
+
}
|
|
118
|
+
} catch {
|
|
119
|
+
// ignore
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
return config;
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
return () => {
|
|
126
|
+
apiClient.axios.interceptors.request.eject(reqInterceptor);
|
|
127
|
+
};
|
|
128
|
+
}, [apiClient]);
|
|
129
|
+
|
|
130
|
+
// Click interceptor: capture clicks on FileCard elements
|
|
131
|
+
useEffect(() => {
|
|
132
|
+
const handler = (e: MouseEvent) => {
|
|
133
|
+
const target = e.target as HTMLElement;
|
|
134
|
+
if (!target) return;
|
|
135
|
+
|
|
136
|
+
// Find closest FileCard element — uses ant-design/x class pattern
|
|
137
|
+
const cardEl = target.closest('[class*="attachment-list-card"]') as HTMLElement;
|
|
138
|
+
if (!cardEl) return;
|
|
139
|
+
|
|
140
|
+
// Ensure it's within a chatbox-like container
|
|
141
|
+
const chatContainer = cardEl.closest('.ant-layout');
|
|
142
|
+
if (!chatContainer) return;
|
|
143
|
+
|
|
144
|
+
// Skip image cards (antd Image component handles its own preview)
|
|
145
|
+
if (cardEl.classList.toString().includes('type-preview')) return;
|
|
146
|
+
|
|
147
|
+
// Skip remove button clicks
|
|
148
|
+
if (target.closest('[class*="-remove"]')) return;
|
|
149
|
+
|
|
150
|
+
const displayName = getDisplayNameFromCard(cardEl);
|
|
151
|
+
const file = findFileByDisplayName(displayName, messagesRef.current, pendingAttachmentsRef.current);
|
|
152
|
+
|
|
153
|
+
if (!file) return;
|
|
154
|
+
if (!isPreviewableFile(file)) return;
|
|
155
|
+
|
|
156
|
+
e.preventDefault();
|
|
157
|
+
e.stopPropagation();
|
|
158
|
+
|
|
159
|
+
setSessionId(currentSessionIdRef.current || '');
|
|
160
|
+
setPreviewFile(file);
|
|
161
|
+
setPreviewOpen(true);
|
|
162
|
+
};
|
|
163
|
+
|
|
164
|
+
document.addEventListener('click', handler, { capture: true });
|
|
165
|
+
return () => document.removeEventListener('click', handler, { capture: true });
|
|
166
|
+
}, []);
|
|
167
|
+
|
|
168
|
+
// Cleanup cache when conversations are deleted
|
|
169
|
+
useEffect(() => {
|
|
170
|
+
const interceptor = apiClient.axios.interceptors.response.use((response) => {
|
|
171
|
+
try {
|
|
172
|
+
const url = response.config?.url || '';
|
|
173
|
+
if (url.includes('aiConversations:destroy')) {
|
|
174
|
+
const match = url.match(/filterByTk=([^&]+)/);
|
|
175
|
+
if (match) {
|
|
176
|
+
SessionBlobCache.clearSession(decodeURIComponent(match[1])).catch(() => {});
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
} catch {
|
|
180
|
+
// ignore
|
|
181
|
+
}
|
|
182
|
+
return response;
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
return () => {
|
|
186
|
+
apiClient.axios.interceptors.response.eject(interceptor);
|
|
187
|
+
};
|
|
188
|
+
}, [apiClient]);
|
|
189
|
+
|
|
190
|
+
const handleClose = useCallback(() => {
|
|
191
|
+
setPreviewOpen(false);
|
|
192
|
+
setPreviewFile(null);
|
|
193
|
+
}, []);
|
|
194
|
+
|
|
195
|
+
return (
|
|
196
|
+
<>
|
|
197
|
+
{children}
|
|
198
|
+
<PreviewModal open={previewOpen} file={previewFile} sessionId={sessionId} onClose={handleClose} />
|
|
199
|
+
</>
|
|
200
|
+
);
|
|
201
|
+
};
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* Top-level provider that wraps the app.
|
|
205
|
+
* Wrapped in try/catch ErrorBoundary so that if plugin-ai isn't loaded,
|
|
206
|
+
* the app still works normally without preview functionality.
|
|
207
|
+
*/
|
|
208
|
+
export class ChatFilePreviewErrorBoundary extends React.Component<
|
|
209
|
+
{ children: React.ReactNode },
|
|
210
|
+
{ hasError: boolean }
|
|
211
|
+
> {
|
|
212
|
+
constructor(props: { children: React.ReactNode }) {
|
|
213
|
+
super(props);
|
|
214
|
+
this.state = { hasError: false };
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
static getDerivedStateFromError() {
|
|
218
|
+
return { hasError: true };
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
render() {
|
|
222
|
+
if (this.state.hasError) {
|
|
223
|
+
return this.props.children;
|
|
224
|
+
}
|
|
225
|
+
return this.props.children;
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
export const ChatFilePreviewProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => {
|
|
230
|
+
return (
|
|
231
|
+
<ChatFilePreviewErrorBoundary>
|
|
232
|
+
<ChatFilePreviewInner>{children}</ChatFilePreviewInner>
|
|
233
|
+
</ChatFilePreviewErrorBoundary>
|
|
234
|
+
);
|
|
235
|
+
};
|