plugin-file-preview-auth 1.1.5 → 1.2.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 +14 -65
- package/dist/client/AIFilePreviewAction.d.ts +37 -0
- package/dist/client/index.js +1 -1
- package/dist/externalVersion.js +5 -4
- package/dist/locale/en-US.json +8 -5
- package/dist/locale/vi-VN.json +14 -11
- package/dist/locale/zh-CN.json +14 -11
- package/dist/server/excel-parser-handler.js +3 -3
- package/dist/server/plugin.d.ts +8 -0
- package/dist/server/plugin.js +257 -15
- package/package.json +43 -36
package/README.md
CHANGED
|
@@ -1,65 +1,14 @@
|
|
|
1
|
-
#
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
| **Excel** | `.xlsx` `.xls` | Rendered as HTML table using [SheetJS](https://sheetjs.com/) (bundled) with multi-sheet tabs |
|
|
16
|
-
|
|
17
|
-
All other file types show a download prompt with authenticated download.
|
|
18
|
-
|
|
19
|
-
### Authentication Flow
|
|
20
|
-
|
|
21
|
-
1. File URL is resolved from the attachment/file record
|
|
22
|
-
2. File is fetched from server with `Authorization: Bearer <token>` header
|
|
23
|
-
3. Response is converted to a Blob (binary) or text
|
|
24
|
-
4. Content is rendered client-side — no unauthenticated requests are made
|
|
25
|
-
|
|
26
|
-
### File Manager Integration
|
|
27
|
-
|
|
28
|
-
The plugin registers handlers in both NocoBase preview registries:
|
|
29
|
-
|
|
30
|
-
- **`attachmentFileTypes`** — Intercepts all file clicks in Upload/Attachment fields
|
|
31
|
-
- **`filePreviewTypes`** — Handles previews in File Manager plugin
|
|
32
|
-
|
|
33
|
-
### Additional Features
|
|
34
|
-
|
|
35
|
-
- **Authenticated download** — Download button in preview modal also uses Bearer token
|
|
36
|
-
- **Multi-sheet support** — Excel files with multiple sheets display tabs for navigation
|
|
37
|
-
- **Code-split bundles** — DOCX and XLSX libraries are lazy-loaded only when needed
|
|
38
|
-
- **i18n** — English, Vietnamese, Chinese translations included
|
|
39
|
-
- **Zero server-side processing** — All preview rendering happens in the browser
|
|
40
|
-
|
|
41
|
-
## Installation
|
|
42
|
-
|
|
43
|
-
```bash
|
|
44
|
-
# From .tgz file
|
|
45
|
-
yarn pm add /path/to/plugin-file-preview-auth-1.1.0.tgz
|
|
46
|
-
yarn pm enable plugin-file-preview-auth
|
|
47
|
-
```
|
|
48
|
-
|
|
49
|
-
## Compatibility
|
|
50
|
-
|
|
51
|
-
- NocoBase **2.x**
|
|
52
|
-
- Requires `plugin-file-manager` to be enabled
|
|
53
|
-
|
|
54
|
-
## Changelog
|
|
55
|
-
|
|
56
|
-
### v1.1.0
|
|
57
|
-
- Added DOCX preview (docx-preview, bundled)
|
|
58
|
-
- Added XLSX/XLS preview with multi-sheet tabs (SheetJS, bundled)
|
|
59
|
-
- Added YAML, YML, XAML to text preview
|
|
60
|
-
- Libraries are code-split and lazy-loaded
|
|
61
|
-
|
|
62
|
-
### v1.0.1
|
|
63
|
-
- Initial release
|
|
64
|
-
- PDF, Image, and Text preview with Bearer token auth
|
|
65
|
-
- Authenticated download for all file types
|
|
1
|
+
# plugin-file-preview-auth
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
Preview PDF, image, and text files with Bearer token authentication via blob URLs.
|
|
5
|
+
|
|
6
|
+
## Features
|
|
7
|
+
- **Secure Previews**: Prevents unauthorized access to sensitive attachments.
|
|
8
|
+
- **Blob URL Generation**: Creates short-lived, authenticated URLs for rendering documents in the browser.
|
|
9
|
+
- **Cross-Component Support**: Works seamlessly with tables, forms, and the AI chat interface.
|
|
10
|
+
|
|
11
|
+
## Usage
|
|
12
|
+
1. Enable the plugin.
|
|
13
|
+
2. Ensure your NocoBase roles are correctly configured for the `attachments` collection.
|
|
14
|
+
3. When users click on a file thumbnail in any NocoBase interface, the system securely fetches the file using their current session token and opens it in the secure previewer.
|
|
@@ -0,0 +1,37 @@
|
|
|
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
|
+
import React from 'react';
|
|
10
|
+
import type { Application } from '@nocobase/client';
|
|
11
|
+
export declare const FILE_PREVIEW_WORK_CONTEXT_TYPE = "file-preview";
|
|
12
|
+
export declare function createFilePreviewWorkContext(file: any): {
|
|
13
|
+
type: string;
|
|
14
|
+
uid: string;
|
|
15
|
+
title: string;
|
|
16
|
+
content: {
|
|
17
|
+
source: string;
|
|
18
|
+
file: {
|
|
19
|
+
id: any;
|
|
20
|
+
uid: any;
|
|
21
|
+
url: any;
|
|
22
|
+
preview: any;
|
|
23
|
+
filename: any;
|
|
24
|
+
name: any;
|
|
25
|
+
title: any;
|
|
26
|
+
extname: any;
|
|
27
|
+
mimetype: any;
|
|
28
|
+
size: any;
|
|
29
|
+
path: any;
|
|
30
|
+
storageId: any;
|
|
31
|
+
};
|
|
32
|
+
};
|
|
33
|
+
};
|
|
34
|
+
export declare const AIFilePreviewAction: React.FC<{
|
|
35
|
+
file: any;
|
|
36
|
+
}>;
|
|
37
|
+
export declare function registerFilePreviewAIWorkContext(app: Application): void;
|
package/dist/client/index.js
CHANGED
|
@@ -7,4 +7,4 @@
|
|
|
7
7
|
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
|
-
!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t(require("@nocobase/plugin-file-manager/client"),require("@nocobase/client"),require("react"),require("@ant-design/icons"),require("antd")):"function"==typeof define&&define.amd?define("plugin-file-preview-auth",["@nocobase/plugin-file-manager/client","@nocobase/client","react","@ant-design/icons","antd"],t):"object"==typeof exports?exports["plugin-file-preview-auth"]=t(require("@nocobase/plugin-file-manager/client"),require("@nocobase/client"),require("react"),require("@ant-design/icons"),require("antd")):e["plugin-file-preview-auth"]=t(e["@nocobase/plugin-file-manager/client"],e["@nocobase/client"],e.react,e["@ant-design/icons"],e.antd)}(self,function(e,t,n,r,i){return function(){var o,l,a,u,c,s,f={41: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},183:function(t){"use strict";t.exports=e},721:function(e){"use strict";e.exports=i},156:function(e){"use strict";e.exports=n}},p={};function d(e){var t=p[e];if(void 0!==t)return t.exports;var n=p[e]={exports:{}};return f[e](n,n.exports,d),n.exports}d.m=f,d.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return d.d(t,{a:t}),t},d.d=function(e,t){for(var n in t)d.o(t,n)&&!d.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:t[n]})},d.f={},d.e=function(e){return Promise.all(Object.keys(d.f).reduce(function(t,n){return d.f[n](e,t),t},[]))},d.u=function(e){return""+e+"."+({166:"17caa11c2ba40313",351:"0f0ce45c92425c8f",374:"96762d13b15e7467",514:"2a8b6aa0d2fcd4b2"})[e]+".js"},d.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||Function("return this")()}catch(e){if("object"==typeof window)return window}}(),d.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},o={},l="plugin-file-preview-auth:",d.l=function(e,t,n,r){if(o[e])return void o[e].push(t);if(void 0!==n)for(var i,a,u=document.getElementsByTagName("script"),c=0;c<u.length;c++){var s=u[c];if(s.getAttribute("src")==e||s.getAttribute("data-webpack")==l+n){i=s;break}}i||(a=!0,(i=document.createElement("script")).charset="utf-8",i.timeout=120,d.nc&&i.setAttribute("nonce",d.nc),i.setAttribute("data-webpack",l+n),i.src=e),o[e]=[t];var f=function(t,n){i.onerror=i.onload=null,clearTimeout(p);var r=o[e];if(delete o[e],i.parentNode&&i.parentNode.removeChild(i),r&&r.forEach(function(e){return e(n)}),t)return t(n)},p=setTimeout(f.bind(null,void 0,{type:"timeout",target:i}),12e4);i.onerror=f.bind(null,i.onerror),i.onload=f.bind(null,i.onload),a&&document.head.appendChild(i)},d.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},(a=window.__webpack_public_path__||"/").endsWith("/")||(a+="/"),d.p=a+"static/plugins/plugin-file-preview-auth/dist/client/",u={909:0},d.f.j=function(e,t){var n=d.o(u,e)?u[e]:void 0;if(0!==n)if(n)t.push(n[2]);else{var r=new Promise(function(t,r){n=u[e]=[t,r]});t.push(n[2]=r);var i=d.p+d.u(e),o=Error();d.l(i,function(t){if(d.o(u,e)&&(0!==(n=u[e])&&(u[e]=void 0),n)){var r=t&&("load"===t.type?"missing":t.type),i=t&&t.target&&t.target.src;o.message="Loading chunk "+e+" failed.\n("+r+": "+i+")",o.name="ChunkLoadError",o.type=r,o.request=i,n[1](o)}},"chunk-"+e,e)}},c=function(e,t){var n,r,i=t[0],o=t[1],l=t[2],a=0;if(i.some(function(e){return 0!==u[e]})){for(n in o)d.o(o,n)&&(d.m[n]=o[n]);l&&l(d)}for(e&&e(t);a<i.length;a++)r=i[a],d.o(u,r)&&u[r]&&u[r][0](),u[r]=0},(s=self.webpackChunkplugin_file_preview_auth=self.webpackChunkplugin_file_preview_auth||[]).forEach(c.bind(null,0)),s.push=c.bind(null,s.push.bind(s));var m={};return!function(){"use strict";d.r(m),d.d(m,{default:function(){return eu},PluginFilePreviewAuthClient:function(){return ea}});var e=d(156),t=d.n(e),n=d(482),r=d(721),i=d(772),o=d(183),l=JSON.parse('{"u2":"plugin-file-preview-auth"}');function a(){var e=(0,i.useApp)();return function(t){return e.i18n.t(t,{ns:[l.u2,"client"]})}}var u=d(41);function c(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 s(e,t,n,r,i,o,l){try{var a=e[o](l),u=a.value}catch(e){n(e);return}a.done?t(u):Promise.resolve(u).then(r,i)}function f(e){return function(){var t=this,n=arguments;return new Promise(function(r,i){var o=e.apply(t,n);function l(e){s(o,r,i,l,a,"next",e)}function a(e){s(o,r,i,l,a,"throw",e)}l(void 0)})}}function p(e,t,n){return(p=x()?Reflect.construct:function(e,t,n){var r=[null];r.push.apply(r,t);var i=new(Function.bind.apply(e,r));return n&&b(i,n.prototype),i}).apply(null,arguments)}function h(e){return(h=Object.setPrototypeOf?Object.getPrototypeOf:function(e){return e.__proto__||Object.getPrototypeOf(e)})(e)}function v(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{},r=Object.keys(n);"function"==typeof Object.getOwnPropertySymbols&&(r=r.concat(Object.getOwnPropertySymbols(n).filter(function(e){return Object.getOwnPropertyDescriptor(n,e).enumerable}))),r.forEach(function(t){var r;r=n[t],t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r})}return e}function y(e,t){return t=null!=t?t:{},Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(t)):(function(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);n.push.apply(n,r)}return n})(Object(t)).forEach(function(n){Object.defineProperty(e,n,Object.getOwnPropertyDescriptor(t,n))}),e}function b(e,t){return(b=Object.setPrototypeOf||function(e,t){return e.__proto__=t,e})(e,t)}function g(e,t){return function(e){if(Array.isArray(e))return e}(e)||function(e,t){var n,r,i=null==e?null:"undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(null!=i){var o=[],l=!0,a=!1;try{for(i=i.call(e);!(l=(n=i.next()).done)&&(o.push(n.value),!t||o.length!==t);l=!0);}catch(e){a=!0,r=e}finally{try{l||null==i.return||i.return()}finally{if(a)throw r}}return o}}(e,t)||function(e,t){if(e){if("string"==typeof e)return c(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 c(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 w(e){var t="function"==typeof Map?new Map:void 0;return(w=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 p(e,arguments,h(this).constructor)}return n.prototype=Object.create(e.prototype,{constructor:{value:n,enumerable:!1,writable:!0,configurable:!0}}),b(n,e)})(e)}function x(){try{var e=!Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],function(){}))}catch(e){}return(x=function(){return!!e})()}function E(e,t){var n,r,i,o,l={label:0,sent:function(){if(1&i[0])throw i[1];return i[1]},trys:[],ops:[]};return o={next:a(0),throw:a(1),return:a(2)},"function"==typeof Symbol&&(o[Symbol.iterator]=function(){return this}),o;function a(o){return function(a){var u=[o,a];if(n)throw TypeError("Generator is already executing.");for(;l;)try{if(n=1,r&&(i=2&u[0]?r.return:u[0]?r.throw||((i=r.return)&&i.call(r),0):r.next)&&!(i=i.call(r,u[1])).done)return i;switch(r=0,i&&(u=[2&u[0],i.value]),u[0]){case 0:case 1:i=u;break;case 4:return l.label++,{value:u[1],done:!1};case 5:l.label++,r=u[1],u=[0];continue;case 7:u=l.ops.pop(),l.trys.pop();continue;default:if(!(i=(i=l.trys).length>0&&i[i.length-1])&&(6===u[0]||2===u[0])){l=0;continue}if(3===u[0]&&(!i||u[1]>i[0]&&u[1]<i[3])){l.label=u[1];break}if(6===u[0]&&l.label<i[1]){l.label=i[1],i=u;break}if(i&&l.label<i[2]){l.label=i[2],l.ops.push(u);break}i[2]&&l.ops.pop(),l.trys.pop();continue}u=t.call(e,l)}catch(e){u=[6,e],r=0}finally{n=i=0}if(5&u[0])throw u[1];return{value:u[0]?u[1]:void 0,done:!0}}}}var k=["application/pdf"],P=["image/png","image/jpeg","image/gif","image/webp","image/svg+xml","image/bmp"],S=["text/plain","text/csv","text/html","text/css","text/javascript","application/json","application/xml","text/xml","text/yaml","application/x-yaml"],O=["application/vnd.openxmlformats-officedocument.wordprocessingml.document"],j=["application/vnd.openxmlformats-officedocument.spreadsheetml.sheet","application/vnd.ms-excel"],_=["pdf"],C=["png","jpg","jpeg","gif","webp","svg","bmp"],L=["txt","csv","html","css","js","json","xml","log","md","yaml","yml","xaml"],T=["docx"],F=["xlsx","xls"],A=["application/vnd.openxmlformats-officedocument.presentationml.presentation","application/vnd.ms-powerpoint"],R=["pptx","ppt"],I=function(e){var t=("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],n=t.lastIndexOf(".");return -1!==n?t.slice(n+1).toLowerCase().replace(/^\./,""):""},U=function(e){var t="string"==typeof e?e:null==e?void 0:e.url;return t?t.startsWith("https://")||t.startsWith("http://")?t:"".concat(location.origin,"/").concat(t.replace(/^\//,"")):""},D=function(e){if((null==e?void 0:e.mimetype)&&k.includes(e.mimetype))return!0;var t=I(e);return!!t&&_.includes(t)},B=function(e){if((null==e?void 0:e.mimetype)&&P.includes(e.mimetype)||(null==e?void 0:e.mimetype)&&(0,i.matchMimetype)(e,"image/*"))return!0;var t=I(e);return!!t&&C.includes(t)},M=function(e){if((null==e?void 0:e.mimetype)&&S.includes(e.mimetype))return!0;var t=I(e);return!!t&&L.includes(t)},q=function(e){if((null==e?void 0:e.mimetype)&&O.includes(e.mimetype))return!0;var t=I(e);return!!t&&T.includes(t)},N=function(e){if((null==e?void 0:e.mimetype)&&j.includes(e.mimetype))return!0;var t=I(e);return!!t&&F.includes(t)},z=function(e){if((null==e?void 0:e.mimetype)&&A.includes(e.mimetype))return!0;var t=I(e);return!!t&&R.includes(t)},W=function(e){return e?e.title&&e.extname?"".concat(e.title).concat(e.extname):e.filename||e.name||e.title||"download":"download"};function H(e,t){return X.apply(this,arguments)}function X(){return(X=f(function(e,t){var n,r;return E(this,function(i){switch(i.label){case 0:return n={},t&&(n.Authorization="Bearer ".concat(t)),[4,fetch(e,{method:"GET",headers:n,credentials:"include"})];case 1:if(!(r=i.sent()).ok)throw Error("Failed to fetch file: ".concat(r.status," ").concat(r.statusText));return[2,r.blob()]}})})).apply(this,arguments)}function G(){return(G=f(function(e,t){var n,r;return E(this,function(i){switch(i.label){case 0:return n={},t&&(n.Authorization="Bearer ".concat(t)),[4,fetch(e,{method:"GET",headers:n,credentials:"include"})];case 1:if(!(r=i.sent()).ok)throw Error("Failed to fetch file: ".concat(r.status," ").concat(r.statusText));return[2,r.text()]}})})).apply(this,arguments)}function Y(e,t){return J.apply(this,arguments)}function J(){return(J=f(function(e,t){var n,r,i,o,l;return E(this,function(a){switch(a.label){case 0:if(!(n=U(e)))return[2];return[4,H(n,t)];case 1:return r=a.sent(),i=W(e),(o=document.createElement("a")).href=l=URL.createObjectURL(r),o.download=i,document.body.appendChild(o),o.click(),document.body.removeChild(o),setTimeout(function(){return URL.revokeObjectURL(l)},1e3),[2]}})})).apply(this,arguments)}function $(t,n){var r=g((0,e.useState)(null),2),i=r[0],o=r[1],l=g((0,e.useState)(!0),2),a=l[0],u=l[1],c=g((0,e.useState)(null),2),s=c[0],f=c[1],p=(0,e.useRef)(null);return(0,e.useEffect)(function(){var e=!1,r=U(t);if(!r){u(!1),f("No file URL");return}return u(!0),f(null),H(r,n).then(function(t){if(!e){var n=URL.createObjectURL(t);p.current=n,o(n),u(!1)}}).catch(function(t){e||(f(t.message||"Failed to load"),u(!1))}),function(){e=!0,p.current&&(URL.revokeObjectURL(p.current),p.current=null)}},["string"==typeof t?t:null==t?void 0:t.url,n]),{blobUrl:i,loading:a,error:s}}function K(e){var n=e.message;return t().createElement("div",{style:{display:"flex",justifyContent:"center",alignItems:"center",height:"100%",width:"100%"}},t().createElement(r.Spin,{tip:n}))}function Q(e){var n=e.message;return t().createElement("div",{style:{padding:20,textAlign:"center",color:"#ff4d4f"}},n)}function V(e){var n,r=e.file,o=(0,i.useAPIClient)(),l=a(),u=$(r,(null==(n=o.auth)?void 0:n.token)||""),c=u.blobUrl,s=u.loading,f=u.error;return s?t().createElement(K,{message:l("Loading preview...")}):f||!c?t().createElement(Q,{message:l("Failed to load file preview")}):t().createElement("iframe",{src:c,width:"100%",height:"100%",style:{border:"none"}})}function Z(e){var n,r=e.file,o=(0,i.useAPIClient)(),l=a(),u=$(r,(null==(n=o.auth)?void 0:n.token)||""),c=u.blobUrl,s=u.loading,f=u.error;return s?t().createElement(K,{message:l("Loading preview...")}):f||!c?t().createElement(Q,{message:l("Failed to load file preview")}):t().createElement("img",{src:c,style:{maxWidth:"100%",maxHeight:"100%",objectFit:"contain"},alt:(null==r?void 0:r.title)||(null==r?void 0:r.filename)||""})}function ee(n){var r,o,l,u,c,s,f,p,d,m,h=n.file,v=(0,i.useAPIClient)(),y=a(),b=(null==(m=v.auth)?void 0:m.token)||"",w=(o=(r=g((0,e.useState)(null),2))[0],l=r[1],c=(u=g((0,e.useState)(!0),2))[0],s=u[1],p=(f=g((0,e.useState)(null),2))[0],d=f[1],(0,e.useEffect)(function(){var e=!1,t=U(h);if(!t){s(!1),d("No file URL");return}return s(!0),d(null),(function(e,t){return G.apply(this,arguments)})(t,b).then(function(t){e||(l(t),s(!1))}).catch(function(t){e||(d(t.message||"Failed to load"),s(!1))}),function(){e=!0}},["string"==typeof h?h:null==h?void 0:h.url,b]),{text:o,loading:c,error:p}),x=w.text,E=w.loading,k=w.error;return E?t().createElement(K,{message:y("Loading preview...")}):k||null===x?t().createElement(Q,{message:y("Failed to load file preview")}):t().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"}},x)}function et(n){var r,o=n.file,l=(0,i.useAPIClient)(),c=a(),s=(null==(r=l.auth)?void 0:r.token)||"",p=(0,e.useRef)(null),m=g((0,e.useState)(!0),2),h=m[0],v=m[1],y=g((0,e.useState)(null),2),b=y[0],w=y[1];return(0,e.useEffect)(function(){var e=!1,t=U(o);if(!t||!p.current){v(!1),w("No file URL");return}return v(!0),w(null),f(function(){var n,r,i;return E(this,function(o){switch(o.label){case 0:return o.trys.push([0,4,,5]),[4,H(t,s)];case 1:if(n=o.sent(),e)return[2];return[4,u("imported_-1dm6lbf_component",d.e("374").then(d.bind(d,335)))];case 2:if(r=o.sent(),e||!p.current)return[2];return p.current.innerHTML="",[4,r.renderAsync(n,p.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 3:return o.sent(),v(!1),[3,5];case 4:if(i=o.sent(),e)return[2];return w(i.message||"Failed to render DOCX"),v(!1),[3,5];case 5:return[2]}})})(),function(){e=!0}},["string"==typeof o?o:null==o?void 0:o.url,s]),t().createElement("div",{style:{width:"100%",height:"100%",position:"relative"}},h&&t().createElement(K,{message:c("Loading preview...")}),b&&t().createElement(Q,{message:c("Failed to load file preview")}),t().createElement("div",{ref:p,style:{width:"100%",height:"100%",overflow:"auto",display:h||b?"none":"block"}}))}function en(n){var r,o=n.file,l=(0,i.useAPIClient)(),c=a(),s=(null==(r=l.auth)?void 0:r.token)||"",p=(0,e.useRef)(null),m=g((0,e.useState)(!0),2),h=m[0],v=m[1],y=g((0,e.useState)(null),2),b=y[0],w=y[1],x=g((0,e.useState)([]),2),k=x[0],P=x[1],S=g((0,e.useState)(""),2),O=S[0],j=S[1],_=g((0,e.useState)({}),2),C=_[0],L=_[1];return(0,e.useEffect)(function(){var e=!1,t=U(o);if(!t){v(!1),w("No file URL");return}return v(!0),w(null),f(function(){var n,r,i,o,l,a,c,f,p,m,h,y,b,g;return E(this,function(x){switch(x.label){case 0:return x.trys.push([0,4,,5]),[4,H(t,s)];case 1:if(n=x.sent(),e)return[2];return[4,u("imported_-1lj2ifg_component",d.e("166").then(d.bind(d,907)))];case 2:if(r=x.sent(),e)return[2];return[4,n.arrayBuffer()];case 3:if(i=x.sent(),e)return[2];l=(o=r.read(i,{type:"array"})).SheetNames,a={},c=!0,f=!1,p=void 0;try{for(m=l[Symbol.iterator]();!(c=(h=m.next()).done);c=!0)y=h.value,b=o.Sheets[y],a[y]=r.utils.sheet_to_html(b,{id:"xlsx-preview-table"})}catch(e){f=!0,p=e}finally{try{c||null==m.return||m.return()}finally{if(f)throw p}}if(e)return[2];return P(l),j(l[0]||""),L(a),v(!1),[3,5];case 4:if(g=x.sent(),e)return[2];return w(g.message||"Failed to render XLSX"),v(!1),[3,5];case 5:return[2]}})})(),function(){e=!0}},["string"==typeof o?o:null==o?void 0:o.url,s]),t().createElement("div",{style:{width:"100%",height:"100%",display:"flex",flexDirection:"column"}},h&&t().createElement(K,{message:c("Loading preview...")}),b&&t().createElement(Q,{message:c("Failed to load file preview")}),!h&&!b&&t().createElement(t().Fragment,null,k.length>1&&t().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 t().createElement("button",{key:e,onClick:function(){return j(e)},style:{padding:"8px 16px",border:"none",borderBottom:O===e?"2px solid #1890ff":"2px solid transparent",background:O===e?"#fff":"transparent",color:O===e?"#1890ff":"#666",fontWeight:O===e?600:400,cursor:"pointer",fontSize:13,whiteSpace:"nowrap",transition:"all 0.2s"}},e)})),t().createElement("div",{ref:p,style:{flex:1,overflow:"auto",padding:0},dangerouslySetInnerHTML:{__html:C[O]||""}}),t().createElement("style",null,"\n #xlsx-preview-table {\n border-collapse: collapse;\n width: 100%;\n font-size: 13px;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n }\n #xlsx-preview-table td,\n #xlsx-preview-table th {\n border: 1px solid #e8e8e8;\n padding: 6px 10px;\n text-align: left;\n max-width: 33vw;\n white-space: normal;\n word-break: break-word;\n }\n #xlsx-preview-table tr:first-child td,\n #xlsx-preview-table tr:first-child th {\n background: #fafafa;\n font-weight: 600;\n position: sticky;\n top: 0;\n z-index: 1;\n }\n #xlsx-preview-table tr:nth-child(even) {\n background: #fafafa;\n }\n #xlsx-preview-table tr:hover {\n background: #f0f7ff;\n }\n ")))}function er(n){var r,o=n.file,l=(0,i.useAPIClient)(),c=a(),s=(null==(r=l.auth)?void 0:r.token)||"",p=g((0,e.useState)(!0),2),m=p[0],h=p[1],v=g((0,e.useState)(null),2),y=v[0],b=v[1],w=g((0,e.useState)(null),2),x=w[0],k=w[1],P=g((0,e.useState)(null),2),S=P[0],O=P[1];return(0,e.useEffect)(function(){var e=!1,t=U(o);if(!t){h(!1),b("No file URL");return}return h(!0),b(null),f(function(){var n,r,i,o,l;return E(this,function(a){switch(a.label){case 0:return a.trys.push([0,3,,4]),[4,Promise.all([H(t,s),u("imported_tpp3om_component",d.e("514").then(d.bind(d,581)))])];case 1:if(r=(n=g.apply(void 0,[a.sent(),2]))[0],i=n[1],e)return[2];return[4,r.arrayBuffer()];case 2:if(o=a.sent(),e)return[2];return k(o),O(function(){return i.PptxPreview}),h(!1),[3,4];case 3:if(l=a.sent(),e)return[2];return b(l.message||"Failed to render PPTX"),h(!1),[3,4];case 4:return[2]}})})(),function(){e=!0}},["string"==typeof o?o:null==o?void 0:o.url,s]),t().createElement("div",{style:{width:"100%",height:"100%",position:"relative"}},m&&t().createElement(K,{message:c("Loading preview...")}),y&&t().createElement(Q,{message:c("Failed to load file preview")}),!m&&!y&&S&&t().createElement("div",{style:{width:"100%",height:"100%",overflow:"auto"}},t().createElement(S,{file:x})))}var ei=function(o){return function(l){var u,c=l.open,s=l.onOpenChange,p=l.onClose,d=l.file,m=l.index,h=l.list,b=l.onSwitchIndex;l.onDownload;var g=(0,i.useAPIClient)(),w=a(),x=(0,e.useCallback)((u=f(function(e){var t,n,i;return E(this,function(o){switch(o.label){case 0:if(!(n=e||d))return[2];i=(null==(t=g.auth)?void 0:t.token)||"",o.label=1;case 1:return o.trys.push([1,3,,4]),[4,Y(n,i)];case 2:return o.sent(),[3,4];case 3:return o.sent(),r.message.error(w("Failed to download file")),[3,4];case 4:return[2]}})}),function(e){return u.apply(this,arguments)}),[d,g,w]);if("boolean"!=typeof c)return t().createElement(o,y(v({},l),{onDownload:x}));var k=W(d),P="number"==typeof m&&!!b&&m>0,S="number"==typeof m&&!!b&&m<h.length-1;return t().createElement(r.Modal,{open:c,title:k,onCancel:function(){null==s||s(!1),null==p||p()},footer:t().createElement(r.Space,{size:14,style:{fontSize:"20px"}},t().createElement(n.LeftOutlined,{style:{cursor:P?"pointer":"not-allowed"},onClick:function(){return P&&(null==b?void 0:b(m-1))}}),t().createElement(n.RightOutlined,{style:{cursor:S?"pointer":"not-allowed"},onClick:function(){return S&&(null==b?void 0:b(m+1))}}),t().createElement(n.DownloadOutlined,{onClick:function(){return x(d)}})),width:"90%",centered:!0},t().createElement("div",{style:{maxWidth:"100%",maxHeight:"calc(100vh - 256px)",height:"80vh",width:"100%",background:"white",display:"flex",flexDirection:"column",justifyContent:"center",alignItems:"center",overflowY:"auto"}},t().createElement(o,y(v({},l),{onDownload:x}))))}};function eo(n){var o,l,u=n.index,c=n.list,s=n.onSwitchIndex,p=a(),d=(0,i.useAPIClient)(),m=c[u],h=g((0,e.useState)(!1),2),v=h[0],y=h[1],b=(0,e.useCallback)((o=f(function(e){var t,n,i,o;return E(this,function(l){switch(l.label){case 0:null==e||null==(t=e.preventDefault)||t.call(e),null==e||null==(n=e.stopPropagation)||n.call(e),o=(null==(i=d.auth)?void 0:i.token)||"",y(!0),l.label=1;case 1:return l.trys.push([1,3,4,5]),[4,Y(m,o)];case 2:return l.sent(),[3,5];case 3:return l.sent(),r.message.error(p("Failed to download file")),[3,5];case 4:return y(!1),[7];case 5:return[2]}})}),function(e){return o.apply(this,arguments)}),[m,d,p]),w=(0,e.useCallback)((l=f(function(e){var t,n,i,o,l,a,u;return E(this,function(c){switch(c.label){case 0:if(null==e||null==(t=e.preventDefault)||t.call(e),null==e||null==(n=e.stopPropagation)||n.call(e),o=(null==(i=d.auth)?void 0:i.token)||"",!(l=U(m)))return[2];c.label=1;case 1:return c.trys.push([1,3,,4]),[4,H(l,o)];case 2:return a=c.sent(),u=URL.createObjectURL(a),window.open(u),[3,4];case 3:return c.sent(),r.message.error(p("Failed to load file preview")),[3,4];case 4:return[2]}})}),function(e){return l.apply(this,arguments)}),[m,d,p]),x=(0,e.useCallback)(function(){s(null)},[s]),k=(0,e.useMemo)(function(){return D(m)?V:B(m)?Z:M(m)?ee:q(m)?et:N(m)?en:z(m)?er:null},[m]),P=null!=k;return t().createElement(r.Modal,{open:null!=u,title:(null==m?void 0:m.title)||(null==m?void 0:m.filename)||(null==m?void 0:m.name)||"File",onCancel:x,footer:[P&&t().createElement(r.Button,{key:"open",onClick:w},p("Open in new window")),t().createElement(r.Button,{key:"download",onClick:b,loading:v},p("Download")),t().createElement(r.Button,{key:"close",onClick:x},p("Close"))].filter(Boolean),width:P?"90%":520,centered:!0},t().createElement("div",{style:{maxWidth:"100%",maxHeight:P?"calc(100vh - 256px)":"auto",height:P?"70vh":"auto",width:"100%",background:"white",display:"flex",flexDirection:"column",justifyContent:"center",alignItems:"center",overflowY:"auto"}},P?t().createElement(k,{file:m}):t().createElement(r.Alert,{type:"info",style:{width:"100%"},description:p("This file type cannot be previewed. Click Download to save the file."),showIcon:!0})))}function el(n){var o=n.file,l=(0,i.useAPIClient)(),u=a(),c=(0,e.useCallback)(f(function(){var e,t;return E(this,function(n){switch(n.label){case 0:t=(null==(e=l.auth)?void 0:e.token)||"",n.label=1;case 1:return n.trys.push([1,3,,4]),[4,Y(o,t)];case 2:return n.sent(),[3,4];case 3:return n.sent(),r.message.error(u("Failed to download file")),[3,4];case 4:return[2]}})}),[o,l,u]);return t().createElement(r.Alert,{type:"info",style:{width:"100%"},description:t().createElement("span",null,u("This file type cannot be previewed. ")," ",t().createElement("a",{onClick:c,style:{textDecoration:"underline",cursor:"pointer"}},u("Download"))),showIcon:!0})}var ea=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=h(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,x()?Reflect.construct(e,t||[],h(this).constructor):e.apply(this,t))}return n.prototype=Object.create(e&&e.prototype,{constructor:{value:n,writable:!0,configurable:!0}}),e&&b(n,e),t=[{key:"load",value:function(){return f(function(){return E(this,function(e){return i.attachmentFileTypes.add({match:function(){return!0},Previewer:eo}),o.filePreviewTypes.add({match:function(){return!0},Previewer:ei(el)}),o.filePreviewTypes.add({match:D,Previewer:ei(V)}),o.filePreviewTypes.add({match:B,getThumbnailURL:function(e){return(null==e?void 0:e.url)||(null==e?void 0:e.preview)||null},Previewer:ei(Z)}),o.filePreviewTypes.add({match:M,Previewer:ei(ee)}),o.filePreviewTypes.add({match:q,Previewer:ei(et)}),o.filePreviewTypes.add({match:N,Previewer:ei(en)}),o.filePreviewTypes.add({match:z,Previewer:ei(er)}),[2]})})()}}],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}(w(i.Plugin)),eu=ea}(),m}()});
|
|
10
|
+
!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t(require("@nocobase/plugin-ai/client"),require("@nocobase/plugin-file-manager/client"),require("@nocobase/client"),require("react"),require("@ant-design/icons"),require("antd")):"function"==typeof define&&define.amd?define("plugin-file-preview-auth",["@nocobase/plugin-ai/client","@nocobase/plugin-file-manager/client","@nocobase/client","react","@ant-design/icons","antd"],t):"object"==typeof exports?exports["plugin-file-preview-auth"]=t(require("@nocobase/plugin-ai/client"),require("@nocobase/plugin-file-manager/client"),require("@nocobase/client"),require("react"),require("@ant-design/icons"),require("antd")):e["plugin-file-preview-auth"]=t(e["@nocobase/plugin-ai/client"],e["@nocobase/plugin-file-manager/client"],e["@nocobase/client"],e.react,e["@ant-design/icons"],e.antd)}(self,function(e,t,n,r,i,o){return function(){var l,a,u,c,s,f,p={41:function(e){e.exports=function(e,t){return"undefined"!=typeof __deoptimization_sideEffect__&&__deoptimization_sideEffect__(e,t),t}},482:function(e){"use strict";e.exports=i},772:function(e){"use strict";e.exports=n},645:function(t){"use strict";t.exports=e},183:function(e){"use strict";e.exports=t},721:function(e){"use strict";e.exports=o},156:function(e){"use strict";e.exports=r}},d={};function m(e){var t=d[e];if(void 0!==t)return t.exports;var n=d[e]={exports:{}};return p[e](n,n.exports,m),n.exports}m.m=p,m.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return m.d(t,{a:t}),t},m.d=function(e,t){for(var n in t)m.o(t,n)&&!m.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:t[n]})},m.f={},m.e=function(e){return Promise.all(Object.keys(m.f).reduce(function(t,n){return m.f[n](e,t),t},[]))},m.u=function(e){return""+e+"."+({166:"17caa11c2ba40313",351:"0f0ce45c92425c8f",374:"96762d13b15e7467",514:"2a8b6aa0d2fcd4b2"})[e]+".js"},m.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||Function("return this")()}catch(e){if("object"==typeof window)return window}}(),m.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},l={},a="plugin-file-preview-auth:",m.l=function(e,t,n,r){if(l[e])return void l[e].push(t);if(void 0!==n)for(var i,o,u=document.getElementsByTagName("script"),c=0;c<u.length;c++){var s=u[c];if(s.getAttribute("src")==e||s.getAttribute("data-webpack")==a+n){i=s;break}}i||(o=!0,(i=document.createElement("script")).charset="utf-8",i.timeout=120,m.nc&&i.setAttribute("nonce",m.nc),i.setAttribute("data-webpack",a+n),i.src=e),l[e]=[t];var f=function(t,n){i.onerror=i.onload=null,clearTimeout(p);var r=l[e];if(delete l[e],i.parentNode&&i.parentNode.removeChild(i),r&&r.forEach(function(e){return e(n)}),t)return t(n)},p=setTimeout(f.bind(null,void 0,{type:"timeout",target:i}),12e4);i.onerror=f.bind(null,i.onerror),i.onload=f.bind(null,i.onload),o&&document.head.appendChild(i)},m.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+="/"),m.p=u+"static/plugins/plugin-file-preview-auth/dist/client/",c={909:0},m.f.j=function(e,t){var n=m.o(c,e)?c[e]:void 0;if(0!==n)if(n)t.push(n[2]);else{var r=new Promise(function(t,r){n=c[e]=[t,r]});t.push(n[2]=r);var i=m.p+m.u(e),o=Error();m.l(i,function(t){if(m.o(c,e)&&(0!==(n=c[e])&&(c[e]=void 0),n)){var r=t&&("load"===t.type?"missing":t.type),i=t&&t.target&&t.target.src;o.message="Loading chunk "+e+" failed.\n("+r+": "+i+")",o.name="ChunkLoadError",o.type=r,o.request=i,n[1](o)}},"chunk-"+e,e)}},s=function(e,t){var n,r,i=t[0],o=t[1],l=t[2],a=0;if(i.some(function(e){return 0!==c[e]})){for(n in o)m.o(o,n)&&(m.m[n]=o[n]);l&&l(m)}for(e&&e(t);a<i.length;a++)r=i[a],m.o(c,r)&&c[r]&&c[r][0](),c[r]=0},(f=self.webpackChunkplugin_file_preview_auth=self.webpackChunkplugin_file_preview_auth||[]).forEach(s.bind(null,0)),f.push=s.bind(null,f.push.bind(f));var v={};return!function(){"use strict";m.r(v),m.d(v,{default:function(){return eP},PluginFilePreviewAuthClient:function(){return eC}});var e=m(156),t=m.n(e),n=m(482),r=m(721),i=m(772),o=m(183),l=JSON.parse('{"u2":"plugin-file-preview-auth"}');function a(){var e=(0,i.useApp)();return function(t){return e.i18n.t(t,{ns:[l.u2,"client"]})}}var u=m(645);function c(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 s(e,t,n,r,i,o,l){try{var a=e[o](l),u=a.value}catch(e){n(e);return}a.done?t(u):Promise.resolve(u).then(r,i)}function f(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 p(e){return(p=Object.setPrototypeOf?Object.getPrototypeOf:function(e){return e.__proto__||Object.getPrototypeOf(e)})(e)}function d(e,t){return(d=Object.setPrototypeOf||function(e,t){return e.__proto__=t,e})(e,t)}function h(e,t){return function(e){if(Array.isArray(e))return e}(e)||function(e,t){var n,r,i=null==e?null:"undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(null!=i){var o=[],l=!0,a=!1;try{for(i=i.call(e);!(l=(n=i.next()).done)&&(o.push(n.value),!t||o.length!==t);l=!0);}catch(e){a=!0,r=e}finally{try{l||null==i.return||i.return()}finally{if(a)throw r}}return o}}(e,t)||b(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 y(e){return function(e){if(Array.isArray(e))return c(e)}(e)||function(e){if("undefined"!=typeof Symbol&&null!=e[Symbol.iterator]||null!=e["@@iterator"])return Array.from(e)}(e)||b(e)||function(){throw TypeError("Invalid attempt to spread non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function b(e,t){if(e){if("string"==typeof e)return c(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 c(e,t)}}function g(){try{var e=!Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],function(){}))}catch(e){}return(g=function(){return!!e})()}var w="file-preview",x="plugin-file-preview-auth.aiEmployee";function E(e){return e?e.title&&e.extname?"".concat(e.title).concat(e.extname):e.filename||e.name||e.title||"file":"file"}var k=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,i;if(!(this instanceof r))throw TypeError("Cannot call a class as a function");return n=r,i=[e],n=p(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,g()?Reflect.construct(n,i||[],p(this).constructor):n.apply(this,i))).state={hasError:!1},t}return r.prototype=Object.create(e&&e.prototype,{constructor:{value:r,writable:!0,configurable:!0}}),e&&d(r,e),n=[{key:"getDerivedStateFromError",value:function(){return{hasError:!0}}}],t=[{key:"render",value:function(){return this.state.hasError?null:this.props.children}}],f(r.prototype,t),n&&f(r,n),r}(t().Component),S=function(i){var o,l,c=i.file,f=a(),p=(0,u.useAIConfigRepository)(),d=(0,u.useChatBoxActions)().triggerTask,m=h((0,e.useState)([]),2),v=m[0],b=m[1],g=h((0,e.useState)(!1),2),k=g[0],S=g[1],C=h((0,e.useState)(!1),2),P=C[0],O=C[1];(0,e.useEffect)(function(){var e=!1;if(null==p?void 0:p.getAIEmployees){var t=p.aiEmployees||[];return t.length?void b(y(t)):(S(!0),p.getAIEmployees().then(function(t){e||b(y(t||[]))}).catch(function(){e||b([])}).finally(function(){e||S(!1)}),function(){e=!0})}},[p]);var j=(0,e.useMemo)(function(){var e=function(){try{return window.localStorage.getItem(x)||""}catch(e){return""}}();return e?y(v).sort(function(t,n){return t.username===e?-1:+(n.username===e)}):v},[v]),A=(0,e.useCallback)((o=function(e){return function(e,t){var n,r,i,o,l={label:0,sent:function(){if(1&i[0])throw i[1];return i[1]},trys:[],ops:[]};return o={next:a(0),throw:a(1),return:a(2)},"function"==typeof Symbol&&(o[Symbol.iterator]=function(){return this}),o;function a(o){return function(a){var u=[o,a];if(n)throw TypeError("Generator is already executing.");for(;l;)try{if(n=1,r&&(i=2&u[0]?r.return:u[0]?r.throw||((i=r.return)&&i.call(r),0):r.next)&&!(i=i.call(r,u[1])).done)return i;switch(r=0,i&&(u=[2&u[0],i.value]),u[0]){case 0:case 1:i=u;break;case 4:return l.label++,{value:u[1],done:!1};case 5:l.label++,r=u[1],u=[0];continue;case 7:u=l.ops.pop(),l.trys.pop();continue;default:if(!(i=(i=l.trys).length>0&&i[i.length-1])&&(6===u[0]||2===u[0])){l=0;continue}if(3===u[0]&&(!i||u[1]>i[0]&&u[1]<i[3])){l.label=u[1];break}if(6===u[0]&&l.label<i[1]){l.label=i[1],i=u;break}if(i&&l.label<i[2]){l.label=i[2],l.ops.push(u);break}i[2]&&l.ops.pop(),l.trys.pop();continue}u=t.call(e,l)}catch(e){u=[6,e],r=0}finally{n=i=0}if(5&u[0])throw u[1];return{value:u[0]?u[1]:void 0,done:!0}}}}(this,function(t){switch(t.label){case 0:if(!e||!c)return[2];O(!0),t.label=1;case 1:t.trys.push([1,3,4,5]);var n,i,o,l,a,u=e.username;try{window.localStorage.setItem(x,u)}catch(e){}return[4,d({aiEmployee:e,tasks:[{title:E(c),message:{user:f("Please help me analyze the file currently open in preview."),workContext:[{type:w,uid:(a=null!=(l=null!=(o=null!=(i=null!=(n=null==c?void 0:c.id)?n:null==c?void 0:c.uid)?i:null==c?void 0:c.url)?o:null==c?void 0:c.path)?l:E(c),"file-preview:".concat(String(a))),title:E(c),content:{source:"plugin-file-preview-auth",file:{id:null==c?void 0:c.id,uid:null==c?void 0:c.uid,url:null==c?void 0:c.url,preview:null==c?void 0:c.preview,filename:(null==c?void 0:c.filename)||(null==c?void 0:c.name),name:(null==c?void 0:c.name)||(null==c?void 0:c.filename),title:null==c?void 0:c.title,extname:null==c?void 0:c.extname,mimetype:null==c?void 0:c.mimetype,size:null==c?void 0:c.size,path:null==c?void 0:c.path,storageId:null==c?void 0:c.storageId}}}]},autoSend:!1}]})];case 2:return t.sent(),[3,5];case 3:return t.sent(),r.message.error(f("Failed to open AI chat")),[3,5];case 4:return O(!1),[7];case 5:return[2]}})},l=function(){var e=this,t=arguments;return new Promise(function(n,r){var i=o.apply(e,t);function l(e){s(i,n,r,l,a,"next",e)}function a(e){s(i,n,r,l,a,"throw",e)}l(void 0)})},function(e){return l.apply(this,arguments)}),[c,f,d]),_=j.map(function(e){return{key:e.username,label:(null==e?void 0:e.nickname)||(null==e?void 0:e.username)||"",onClick:function(){return A(e)}}});return k||j.length?1===j.length?t().createElement(r.Tooltip,{title:f("Ask AI")},t().createElement(r.Button,{type:"text",size:"small",icon:t().createElement(n.RobotOutlined,null),loading:P||k,onClick:function(e){e.stopPropagation(),A(j[0])}},f("Ask AI"))):t().createElement(r.Tooltip,{title:f("Ask AI")},t().createElement(r.Dropdown,{menu:{items:_},trigger:["click"],placement:"bottomRight",disabled:P||k},t().createElement(r.Button,{type:"text",size:"small",icon:t().createElement(n.RobotOutlined,null),loading:P||k,onClick:function(e){return e.stopPropagation()}},f("Ask AI")))):null},C=function(e){var n=e.file;return t().createElement(k,null,t().createElement(S,{file:n}))},P=m(41);function O(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 j(e,t,n,r,i,o,l){try{var a=e[o](l),u=a.value}catch(e){n(e);return}a.done?t(u):Promise.resolve(u).then(r,i)}function A(e){return function(){var t=this,n=arguments;return new Promise(function(r,i){var o=e.apply(t,n);function l(e){j(o,r,i,l,a,"next",e)}function a(e){j(o,r,i,l,a,"throw",e)}l(void 0)})}}function _(e,t,n){return(_=D()?Reflect.construct:function(e,t,n){var r=[null];r.push.apply(r,t);var i=new(Function.bind.apply(e,r));return n&&R(i,n.prototype),i}).apply(null,arguments)}function I(e){return(I=Object.setPrototypeOf?Object.getPrototypeOf:function(e){return e.__proto__||Object.getPrototypeOf(e)})(e)}function T(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{},r=Object.keys(n);"function"==typeof Object.getOwnPropertySymbols&&(r=r.concat(Object.getOwnPropertySymbols(n).filter(function(e){return Object.getOwnPropertyDescriptor(n,e).enumerable}))),r.forEach(function(t){var r;r=n[t],t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r})}return e}function F(e,t){return t=null!=t?t:{},Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(t)):(function(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);n.push.apply(n,r)}return n})(Object(t)).forEach(function(n){Object.defineProperty(e,n,Object.getOwnPropertyDescriptor(t,n))}),e}function R(e,t){return(R=Object.setPrototypeOf||function(e,t){return e.__proto__=t,e})(e,t)}function L(e,t){return function(e){if(Array.isArray(e))return e}(e)||function(e,t){var n,r,i=null==e?null:"undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(null!=i){var o=[],l=!0,a=!1;try{for(i=i.call(e);!(l=(n=i.next()).done)&&(o.push(n.value),!t||o.length!==t);l=!0);}catch(e){a=!0,r=e}finally{try{l||null==i.return||i.return()}finally{if(a)throw r}}return o}}(e,t)||function(e,t){if(e){if("string"==typeof e)return O(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 O(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 B(e){var t="function"==typeof Map?new Map:void 0;return(B=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 _(e,arguments,I(this).constructor)}return n.prototype=Object.create(e.prototype,{constructor:{value:n,enumerable:!1,writable:!0,configurable:!0}}),R(n,e)})(e)}function D(){try{var e=!Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],function(){}))}catch(e){}return(D=function(){return!!e})()}function U(e,t){var n,r,i,o,l={label:0,sent:function(){if(1&i[0])throw i[1];return i[1]},trys:[],ops:[]};return o={next:a(0),throw:a(1),return:a(2)},"function"==typeof Symbol&&(o[Symbol.iterator]=function(){return this}),o;function a(o){return function(a){var u=[o,a];if(n)throw TypeError("Generator is already executing.");for(;l;)try{if(n=1,r&&(i=2&u[0]?r.return:u[0]?r.throw||((i=r.return)&&i.call(r),0):r.next)&&!(i=i.call(r,u[1])).done)return i;switch(r=0,i&&(u=[2&u[0],i.value]),u[0]){case 0:case 1:i=u;break;case 4:return l.label++,{value:u[1],done:!1};case 5:l.label++,r=u[1],u=[0];continue;case 7:u=l.ops.pop(),l.trys.pop();continue;default:if(!(i=(i=l.trys).length>0&&i[i.length-1])&&(6===u[0]||2===u[0])){l=0;continue}if(3===u[0]&&(!i||u[1]>i[0]&&u[1]<i[3])){l.label=u[1];break}if(6===u[0]&&l.label<i[1]){l.label=i[1],i=u;break}if(i&&l.label<i[2]){l.label=i[2],l.ops.push(u);break}i[2]&&l.ops.pop(),l.trys.pop();continue}u=t.call(e,l)}catch(e){u=[6,e],r=0}finally{n=i=0}if(5&u[0])throw u[1];return{value:u[0]?u[1]:void 0,done:!0}}}}var z=["application/pdf"],M=["image/png","image/jpeg","image/gif","image/webp","image/svg+xml","image/bmp"],q=["text/plain","text/csv","text/html","text/css","text/javascript","application/json","application/xml","text/xml","text/yaml","application/x-yaml"],W=["application/vnd.openxmlformats-officedocument.wordprocessingml.document"],N=["application/vnd.openxmlformats-officedocument.spreadsheetml.sheet","application/vnd.ms-excel"],H=["pdf"],V=["png","jpg","jpeg","gif","webp","svg","bmp"],X=["txt","csv","html","css","js","json","xml","log","md","yaml","yml","xaml"],G=["docx"],Y=["xlsx","xls"],$=["application/vnd.openxmlformats-officedocument.presentationml.presentation","application/vnd.ms-powerpoint"],J=["pptx","ppt"],K=function(e){var t=("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],n=t.lastIndexOf(".");return -1!==n?t.slice(n+1).toLowerCase().replace(/^\./,""):""},Q=function(e){var t="string"==typeof e?e:null==e?void 0:e.url;return t?t.startsWith("https://")||t.startsWith("http://")?t:"".concat(location.origin,"/").concat(t.replace(/^\//,"")):""},Z=function(e){if((null==e?void 0:e.mimetype)&&z.includes(e.mimetype))return!0;var t=K(e);return!!t&&H.includes(t)},ee=function(e){if((null==e?void 0:e.mimetype)&&M.includes(e.mimetype)||(null==e?void 0:e.mimetype)&&(0,i.matchMimetype)(e,"image/*"))return!0;var t=K(e);return!!t&&V.includes(t)},et=function(e){if((null==e?void 0:e.mimetype)&&q.includes(e.mimetype))return!0;var t=K(e);return!!t&&X.includes(t)},en=function(e){if((null==e?void 0:e.mimetype)&&W.includes(e.mimetype))return!0;var t=K(e);return!!t&&G.includes(t)},er=function(e){if((null==e?void 0:e.mimetype)&&N.includes(e.mimetype))return!0;var t=K(e);return!!t&&Y.includes(t)},ei=function(e){if((null==e?void 0:e.mimetype)&&$.includes(e.mimetype))return!0;var t=K(e);return!!t&&J.includes(t)},eo=function(e){return e?e.title&&e.extname?"".concat(e.title).concat(e.extname):e.filename||e.name||e.title||"download":"download"};function el(e,t){return ea.apply(this,arguments)}function ea(){return(ea=A(function(e,t){var n,r;return U(this,function(i){switch(i.label){case 0:return n={},t&&(n.Authorization="Bearer ".concat(t)),[4,fetch(e,{method:"GET",headers:n,credentials:"include"})];case 1:if(!(r=i.sent()).ok)throw Error("Failed to fetch file: ".concat(r.status," ").concat(r.statusText));return[2,r.blob()]}})})).apply(this,arguments)}function eu(){return(eu=A(function(e,t){var n,r;return U(this,function(i){switch(i.label){case 0:return n={},t&&(n.Authorization="Bearer ".concat(t)),[4,fetch(e,{method:"GET",headers:n,credentials:"include"})];case 1:if(!(r=i.sent()).ok)throw Error("Failed to fetch file: ".concat(r.status," ").concat(r.statusText));return[2,r.text()]}})})).apply(this,arguments)}function ec(e,t){return es.apply(this,arguments)}function es(){return(es=A(function(e,t){var n,r,i,o,l;return U(this,function(a){switch(a.label){case 0:if(!(n=Q(e)))return[2];return[4,el(n,t)];case 1:return r=a.sent(),i=eo(e),(o=document.createElement("a")).href=l=URL.createObjectURL(r),o.download=i,document.body.appendChild(o),o.click(),document.body.removeChild(o),setTimeout(function(){return URL.revokeObjectURL(l)},1e3),[2]}})})).apply(this,arguments)}function ef(t,n){var r=L((0,e.useState)(null),2),i=r[0],o=r[1],l=L((0,e.useState)(!0),2),a=l[0],u=l[1],c=L((0,e.useState)(null),2),s=c[0],f=c[1],p=(0,e.useRef)(null);return(0,e.useEffect)(function(){var e=!1,r=Q(t);if(!r){u(!1),f("No file URL");return}return u(!0),f(null),el(r,n).then(function(t){if(!e){var n=URL.createObjectURL(t);p.current=n,o(n),u(!1)}}).catch(function(t){e||(f(t.message||"Failed to load"),u(!1))}),function(){e=!0,p.current&&(URL.revokeObjectURL(p.current),p.current=null)}},["string"==typeof t?t:null==t?void 0:t.url,n]),{blobUrl:i,loading:a,error:s}}function ep(e){var n=e.message;return t().createElement("div",{style:{display:"flex",justifyContent:"center",alignItems:"center",height:"100%",width:"100%"}},t().createElement(r.Spin,{tip:n}))}function ed(e){var n=e.message;return t().createElement("div",{style:{padding:20,textAlign:"center",color:"#ff4d4f"}},n)}function em(e){var n=e.file,r=e.title;return t().createElement("div",{style:{display:"flex",alignItems:"center",justifyContent:"space-between",gap:12,paddingRight:40}},t().createElement("span",{style:{minWidth:0,overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"},title:r},r),t().createElement(C,{file:n}))}function ev(e){var n,r=e.file,o=(0,i.useAPIClient)(),l=a(),u=ef(r,(null==(n=o.auth)?void 0:n.token)||""),c=u.blobUrl,s=u.loading,f=u.error;return s?t().createElement(ep,{message:l("Loading preview...")}):f||!c?t().createElement(ed,{message:l("Failed to load file preview")}):t().createElement("iframe",{src:c,width:"100%",height:"100%",style:{border:"none"}})}function eh(e){var n,r=e.file,o=(0,i.useAPIClient)(),l=a(),u=ef(r,(null==(n=o.auth)?void 0:n.token)||""),c=u.blobUrl,s=u.loading,f=u.error;return s?t().createElement(ep,{message:l("Loading preview...")}):f||!c?t().createElement(ed,{message:l("Failed to load file preview")}):t().createElement("img",{src:c,style:{maxWidth:"100%",maxHeight:"100%",objectFit:"contain"},alt:(null==r?void 0:r.title)||(null==r?void 0:r.filename)||""})}function ey(n){var r,o,l,u,c,s,f,p,d,m,v=n.file,h=(0,i.useAPIClient)(),y=a(),b=(null==(m=h.auth)?void 0:m.token)||"",g=(o=(r=L((0,e.useState)(null),2))[0],l=r[1],c=(u=L((0,e.useState)(!0),2))[0],s=u[1],p=(f=L((0,e.useState)(null),2))[0],d=f[1],(0,e.useEffect)(function(){var e=!1,t=Q(v);if(!t){s(!1),d("No file URL");return}return s(!0),d(null),(function(e,t){return eu.apply(this,arguments)})(t,b).then(function(t){e||(l(t),s(!1))}).catch(function(t){e||(d(t.message||"Failed to load"),s(!1))}),function(){e=!0}},["string"==typeof v?v:null==v?void 0:v.url,b]),{text:o,loading:c,error:p}),w=g.text,x=g.loading,E=g.error;return x?t().createElement(ep,{message:y("Loading preview...")}):E||null===w?t().createElement(ed,{message:y("Failed to load file preview")}):t().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"}},w)}function eb(n){var r,o=n.file,l=(0,i.useAPIClient)(),u=a(),c=(null==(r=l.auth)?void 0:r.token)||"",s=(0,e.useRef)(null),f=L((0,e.useState)(!0),2),p=f[0],d=f[1],v=L((0,e.useState)(null),2),h=v[0],y=v[1];return(0,e.useEffect)(function(){var e=!1,t=Q(o);if(!t||!s.current){d(!1),y("No file URL");return}return d(!0),y(null),A(function(){var n,r,i;return U(this,function(o){switch(o.label){case 0:return o.trys.push([0,4,,5]),[4,el(t,c)];case 1:if(n=o.sent(),e)return[2];return[4,P("imported_-1dm6lbf_component",m.e("374").then(m.bind(m,335)))];case 2:if(r=o.sent(),e||!s.current)return[2];return s.current.innerHTML="",[4,r.renderAsync(n,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 3:return o.sent(),d(!1),[3,5];case 4:if(i=o.sent(),e)return[2];return y(i.message||"Failed to render DOCX"),d(!1),[3,5];case 5:return[2]}})})(),function(){e=!0}},["string"==typeof o?o:null==o?void 0:o.url,c]),t().createElement("div",{style:{width:"100%",height:"100%",position:"relative"}},p&&t().createElement(ep,{message:u("Loading preview...")}),h&&t().createElement(ed,{message:u("Failed to load file preview")}),t().createElement("div",{ref:s,style:{width:"100%",height:"100%",overflow:"auto",display:p||h?"none":"block"}}))}function eg(n){var r,o=n.file,l=(0,i.useAPIClient)(),u=a(),c=(null==(r=l.auth)?void 0:r.token)||"",s=(0,e.useRef)(null),f=L((0,e.useState)(!0),2),p=f[0],d=f[1],v=L((0,e.useState)(null),2),h=v[0],y=v[1],b=L((0,e.useState)([]),2),g=b[0],w=b[1],x=L((0,e.useState)(""),2),E=x[0],k=x[1],S=L((0,e.useState)({}),2),C=S[0],O=S[1];return(0,e.useEffect)(function(){var e=!1,t=Q(o);if(!t){d(!1),y("No file URL");return}return d(!0),y(null),A(function(){var n,r,i,o,l,a,u,s,f,p,v,h,b,g;return U(this,function(x){switch(x.label){case 0:return x.trys.push([0,4,,5]),[4,el(t,c)];case 1:if(n=x.sent(),e)return[2];return[4,P("imported_-1lj2ifg_component",m.e("166").then(m.bind(m,907)))];case 2:if(r=x.sent(),e)return[2];return[4,n.arrayBuffer()];case 3:if(i=x.sent(),e)return[2];l=(o=r.read(i,{type:"array"})).SheetNames,a={},u=!0,s=!1,f=void 0;try{for(p=l[Symbol.iterator]();!(u=(v=p.next()).done);u=!0)h=v.value,b=o.Sheets[h],a[h]=r.utils.sheet_to_html(b,{id:"xlsx-preview-table"})}catch(e){s=!0,f=e}finally{try{u||null==p.return||p.return()}finally{if(s)throw f}}if(e)return[2];return w(l),k(l[0]||""),O(a),d(!1),[3,5];case 4:if(g=x.sent(),e)return[2];return y(g.message||"Failed to render XLSX"),d(!1),[3,5];case 5:return[2]}})})(),function(){e=!0}},["string"==typeof o?o:null==o?void 0:o.url,c]),t().createElement("div",{style:{width:"100%",height:"100%",display:"flex",flexDirection:"column"}},p&&t().createElement(ep,{message:u("Loading preview...")}),h&&t().createElement(ed,{message:u("Failed to load file preview")}),!p&&!h&&t().createElement(t().Fragment,null,g.length>1&&t().createElement("div",{style:{display:"flex",gap:0,borderBottom:"1px solid #e8e8e8",background:"#fafafa",padding:"0 8px",flexShrink:0,overflowX:"auto"}},g.map(function(e){return t().createElement("button",{key:e,onClick:function(){return k(e)},style:{padding:"8px 16px",border:"none",borderBottom:E===e?"2px solid #1890ff":"2px solid transparent",background:E===e?"#fff":"transparent",color:E===e?"#1890ff":"#666",fontWeight:E===e?600:400,cursor:"pointer",fontSize:13,whiteSpace:"nowrap",transition:"all 0.2s"}},e)})),t().createElement("div",{ref:s,style:{flex:1,overflow:"auto",padding:0},dangerouslySetInnerHTML:{__html:C[E]||""}}),t().createElement("style",null,"\n #xlsx-preview-table {\n border-collapse: collapse;\n width: 100%;\n font-size: 13px;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n }\n #xlsx-preview-table td,\n #xlsx-preview-table th {\n border: 1px solid #e8e8e8;\n padding: 6px 10px;\n text-align: left;\n max-width: 33vw;\n white-space: normal;\n word-break: break-word;\n }\n #xlsx-preview-table tr:first-child td,\n #xlsx-preview-table tr:first-child th {\n background: #fafafa;\n font-weight: 600;\n position: sticky;\n top: 0;\n z-index: 1;\n }\n #xlsx-preview-table tr:nth-child(even) {\n background: #fafafa;\n }\n #xlsx-preview-table tr:hover {\n background: #f0f7ff;\n }\n ")))}function ew(n){var r,o=n.file,l=(0,i.useAPIClient)(),u=a(),c=(null==(r=l.auth)?void 0:r.token)||"",s=L((0,e.useState)(!0),2),f=s[0],p=s[1],d=L((0,e.useState)(null),2),v=d[0],h=d[1],y=L((0,e.useState)(null),2),b=y[0],g=y[1],w=L((0,e.useState)(null),2),x=w[0],E=w[1];return(0,e.useEffect)(function(){var e=!1,t=Q(o);if(!t){p(!1),h("No file URL");return}return p(!0),h(null),A(function(){var n,r,i,o,l;return U(this,function(a){switch(a.label){case 0:return a.trys.push([0,3,,4]),[4,Promise.all([el(t,c),P("imported_tpp3om_component",m.e("514").then(m.bind(m,581)))])];case 1:if(r=(n=L.apply(void 0,[a.sent(),2]))[0],i=n[1],e)return[2];return[4,r.arrayBuffer()];case 2:if(o=a.sent(),e)return[2];return g(o),E(function(){return i.PptxPreview}),p(!1),[3,4];case 3:if(l=a.sent(),e)return[2];return h(l.message||"Failed to render PPTX"),p(!1),[3,4];case 4:return[2]}})})(),function(){e=!0}},["string"==typeof o?o:null==o?void 0:o.url,c]),t().createElement("div",{style:{width:"100%",height:"100%",position:"relative"}},f&&t().createElement(ep,{message:u("Loading preview...")}),v&&t().createElement(ed,{message:u("Failed to load file preview")}),!f&&!v&&x&&t().createElement("div",{style:{width:"100%",height:"100%",overflow:"auto"}},t().createElement(x,{file:b})))}var ex=function(o){return function(l){var u,c=l.open,s=l.onOpenChange,f=l.onClose,p=l.file,d=l.index,m=l.list,v=l.onSwitchIndex;l.onDownload;var h=(0,i.useAPIClient)(),y=a(),b=(0,e.useCallback)((u=A(function(e){var t,n,i;return U(this,function(o){switch(o.label){case 0:if(!(n=e||p))return[2];i=(null==(t=h.auth)?void 0:t.token)||"",o.label=1;case 1:return o.trys.push([1,3,,4]),[4,ec(n,i)];case 2:return o.sent(),[3,4];case 3:return o.sent(),r.message.error(y("Failed to download file")),[3,4];case 4:return[2]}})}),function(e){return u.apply(this,arguments)}),[p,h,y]);if("boolean"!=typeof c)return t().createElement(o,F(T({},l),{onDownload:b}));var g=eo(p),w="number"==typeof d&&!!v&&d>0,x="number"==typeof d&&!!v&&d<m.length-1,E=L((0,e.useState)("visual"),2),k=E[0],S=E[1];return t().createElement(r.Modal,{open:c,title:t().createElement(em,{file:p,title:g}),onCancel:function(){null==s||s(!1),null==f||f(),S("visual")},footer:t().createElement("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"center",width:"100%"}},t().createElement("div",{key:"left-actions"},t().createElement(r.Button,{onClick:function(){return S(function(e){return"visual"===e?"raw":"visual"})}},"visual"===k?y("View Raw Parsed Text"):y("View Visual Preview"))),t().createElement(r.Space,{size:14,style:{fontSize:"20px"}},t().createElement(n.LeftOutlined,{style:{cursor:w?"pointer":"not-allowed"},onClick:function(){return w&&(null==v?void 0:v(d-1))}}),t().createElement(n.RightOutlined,{style:{cursor:x?"pointer":"not-allowed"},onClick:function(){return x&&(null==v?void 0:v(d+1))}}),t().createElement(n.DownloadOutlined,{onClick:function(){return b(p)}}))),width:"90%",centered:!0},t().createElement("div",{style:{maxWidth:"100%",maxHeight:"calc(100vh - 256px)",height:"80vh",width:"100%",background:"white",display:"flex",flexDirection:"column",justifyContent:"center",alignItems:"center",overflowY:"auto"}},"raw"===k?t().createElement(eE,{file:p}):t().createElement(o,F(T({},l),{onDownload:b}))))}};function eE(o){var l=o.file,u=(0,i.useAPIClient)(),c=a(),s=L((0,e.useState)(""),2),f=s[0],p=s[1],d=L((0,e.useState)(!0),2),m=d[0],v=d[1],h=L((0,e.useState)(null),2),y=h[0],b=h[1],g=(0,i.useComponent)("MarkdownVditor"),w=(0,i.useComponent)("Markdown.Void");return((0,e.useEffect)(function(){var e=!1;return A(function(){var t,n,r,i,o,a,c;return U(this,function(s){switch(s.label){case 0:v(!0),b(null),s.label=1;case 1:return s.trys.push([1,3,,4]),[4,u.request({url:"filePreviewAuth:getContent",params:{file:l}})];case 2:if(r=s.sent(),e)return[2];return o=i=(null==r||null==(n=r.data)||null==(t=n.data)?void 0:t.content)||"",(a=i.match(/<file_preview[^>]*>([\s\S]*?)<\/file_preview>/i))&&(o=a[1].trim()),p(o),v(!1),[3,4];case 3:if(c=s.sent(),e)return[2];return b(c.message||"Failed to fetch raw text"),v(!1),[3,4];case 4:return[2]}})})(),function(){e=!0}},[l,u]),m)?t().createElement(r.Spin,{size:"large",tip:c("Extracting raw text..."),style:{marginTop:"40px"}}):y?t().createElement(r.Alert,{type:"error",message:y,style:{width:"100%",margin:"20px"}}):f?t().createElement("div",{style:{width:"100%",height:"100%",display:"flex",flexDirection:"column",position:"relative"}},t().createElement("span",{onClick:function(){if(navigator.clipboard&&navigator.clipboard.writeText)navigator.clipboard.writeText(f).then(function(){r.message.success(c("Copied to clipboard"))}).catch(function(e){r.message.error(c("Failed to copy")),console.error("Copy error",e)});else{var e=document.createElement("textarea");e.value=f,document.body.appendChild(e),e.select();try{document.execCommand("copy"),r.message.success(c("Copied to clipboard"))}catch(e){r.message.error(c("Failed to copy"))}document.body.removeChild(e)}},style:{position:"absolute",top:"20px",right:"25px",zIndex:10,cursor:"pointer",padding:"4px 10px",background:"rgba(255, 255, 255, 0.85)",border:"1px solid #e8e8e8",borderRadius:"4px",color:"#1890ff",display:"flex",alignItems:"center",gap:"6px",boxShadow:"0 2px 4px rgba(0,0,0,0.05)",fontSize:"13px"},title:c("Copy")},t().createElement(n.CopyOutlined,null),c("Copy")),t().createElement("div",{style:{flex:1,overflow:"auto",padding:"20px",textAlign:"left"}},t().createElement("style",null,"\n .hide-vditor-toolbar .vditor-toolbar {\n display: none !important;\n }\n .hide-vditor-toolbar .vditor {\n border: none !important;\n }\n "),t().createElement("div",{className:"hide-vditor-toolbar",style:{height:"100%"}},g?t().createElement(g,{value:f,disabled:!1}):w?t().createElement(w,{content:f}):t().createElement("pre",{style:{whiteSpace:"pre-wrap",wordBreak:"break-word",fontFamily:"monospace",fontSize:"13px"}},f)))):t().createElement(r.Alert,{type:"info",style:{width:"100%",margin:"20px"},description:c("No text content could be extracted from this file."),showIcon:!0})}function ek(n){var o,l=n.index,u=n.list,c=n.onSwitchIndex,s=a(),f=(0,i.useAPIClient)(),p=u[l],d=L((0,e.useState)(!1),2),m=d[0],v=d[1],h=L((0,e.useState)("visual"),2),y=h[0],b=h[1],g=(0,e.useCallback)((o=A(function(e){var t,n,i,o;return U(this,function(l){switch(l.label){case 0:null==e||null==(t=e.preventDefault)||t.call(e),null==e||null==(n=e.stopPropagation)||n.call(e),o=(null==(i=f.auth)?void 0:i.token)||"",v(!0),l.label=1;case 1:return l.trys.push([1,3,4,5]),[4,ec(p,o)];case 2:return l.sent(),[3,5];case 3:return l.sent(),r.message.error(s("Failed to download file")),[3,5];case 4:return v(!1),[7];case 5:return[2]}})}),function(e){return o.apply(this,arguments)}),[p,f,s]),w=(0,e.useCallback)(function(){c(null),b("visual")},[c]),x=(0,e.useMemo)(function(){return Z(p)?ev:ee(p)?eh:et(p)?ey:en(p)?eb:er(p)?eg:ei(p)?ew:null},[p]),E=null!=x||"raw"===y;return t().createElement(r.Modal,{open:null!=l,title:t().createElement(em,{file:p,title:(null==p?void 0:p.title)||(null==p?void 0:p.filename)||(null==p?void 0:p.name)||"File"}),onCancel:w,footer:t().createElement("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"center",width:"100%"}},t().createElement("div",{key:"left-actions"},t().createElement(r.Button,{onClick:function(){return b(function(e){return"visual"===e?"raw":"visual"})}},"visual"===y?s("View Raw Parsed Text"):s("View Visual Preview"))),t().createElement(r.Space,null,t().createElement(r.Button,{key:"download",onClick:g,loading:m},s("Download")),t().createElement(r.Button,{key:"close",onClick:w},s("Close")))),width:E?"90%":520,centered:!0},t().createElement("div",{style:{maxWidth:"100%",maxHeight:E?"calc(100vh - 256px)":"auto",height:E?"70vh":"auto",width:"100%",background:"white",display:"flex",flexDirection:"column",justifyContent:"center",alignItems:"center",overflowY:"auto"}},"raw"===y?t().createElement(eE,{file:p}):x?t().createElement(x,{file:p}):t().createElement(r.Alert,{type:"info",style:{width:"100%"},description:s("This file type cannot be previewed. Click Download to save the file."),showIcon:!0})))}function eS(n){var o=n.file,l=(0,i.useAPIClient)(),u=a(),c=(0,e.useCallback)(A(function(){var e,t;return U(this,function(n){switch(n.label){case 0:t=(null==(e=l.auth)?void 0:e.token)||"",n.label=1;case 1:return n.trys.push([1,3,,4]),[4,ec(o,t)];case 2:return n.sent(),[3,4];case 3:return n.sent(),r.message.error(u("Failed to download file")),[3,4];case 4:return[2]}})}),[o,l,u]);return t().createElement(r.Alert,{type:"info",style:{width:"100%"},description:t().createElement("span",null,u("This file type cannot be previewed. ")," ",t().createElement("a",{onClick:c,style:{textDecoration:"underline",cursor:"pointer"}},u("Download"))),showIcon:!0})}var eC=function(e){var l;if("function"!=typeof e&&null!==e)throw TypeError("Super expression must either be null or a function");function a(){var e,t;if(!(this instanceof a))throw TypeError("Cannot call a class as a function");return e=a,t=arguments,e=I(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,D()?Reflect.construct(e,t||[],I(this).constructor):e.apply(this,t))}return a.prototype=Object.create(e&&e.prototype,{constructor:{value:a,writable:!0,configurable:!0}}),e&&R(a,e),l=[{key:"load",value:function(){var e=this;return A(function(){return U(this,function(l){return!function(e){try{i=e.pm.get("ai")}catch(e){return}var i,o,l=null==i?void 0:i.aiManager;if(null==l?void 0:l.registerWorkContext)try{(null==(o=l.getWorkContext)?void 0:o.call(l,w))||l.registerWorkContext(w,{name:w,tag:{Component:function(e){var i=e.item;return t().createElement(r.Space,null,t().createElement(n.FileTextOutlined,null),t().createElement("span",null,(null==i?void 0:i.title)||""))}},chatbox:{Component:function(e){var i=e.item;return t().createElement(r.Space,null,t().createElement(n.FileTextOutlined,null),t().createElement("span",null,(null==i?void 0:i.title)||""))}}})}catch(e){}}(e.app),i.attachmentFileTypes.add({match:function(){return!0},Previewer:ek}),o.filePreviewTypes.add({match:function(){return!0},Previewer:ex(eS)}),o.filePreviewTypes.add({match:Z,Previewer:ex(ev)}),o.filePreviewTypes.add({match:ee,getThumbnailURL:function(e){return(null==e?void 0:e.url)||(null==e?void 0:e.preview)||null},Previewer:ex(eh)}),o.filePreviewTypes.add({match:et,Previewer:ex(ey)}),o.filePreviewTypes.add({match:en,Previewer:ex(eb)}),o.filePreviewTypes.add({match:er,Previewer:ex(eg)}),o.filePreviewTypes.add({match:ei,Previewer:ex(ew)}),[2]})})()}}],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)}}(a.prototype,l),a}(B(i.Plugin)),eP=eC}(),v}()});
|
package/dist/externalVersion.js
CHANGED
|
@@ -11,8 +11,9 @@ module.exports = {
|
|
|
11
11
|
"react": "18.2.0",
|
|
12
12
|
"@ant-design/icons": "5.6.1",
|
|
13
13
|
"antd": "5.24.2",
|
|
14
|
-
"@nocobase/client": "2.0.
|
|
15
|
-
"@nocobase/plugin-
|
|
16
|
-
"@nocobase/
|
|
17
|
-
"@nocobase/
|
|
14
|
+
"@nocobase/client": "2.0.46",
|
|
15
|
+
"@nocobase/plugin-ai": "2.0.46",
|
|
16
|
+
"@nocobase/plugin-file-manager": "2.0.46",
|
|
17
|
+
"@nocobase/actions": "2.0.46",
|
|
18
|
+
"@nocobase/server": "2.0.46"
|
|
18
19
|
};
|
package/dist/locale/en-US.json
CHANGED
|
@@ -4,8 +4,11 @@
|
|
|
4
4
|
"Download": "Download",
|
|
5
5
|
"Close": "Close",
|
|
6
6
|
"Loading preview...": "Loading preview...",
|
|
7
|
-
"Failed to load file preview": "Failed to load file preview",
|
|
8
|
-
"Failed to download file": "Failed to download file",
|
|
9
|
-
"
|
|
10
|
-
"
|
|
11
|
-
|
|
7
|
+
"Failed to load file preview": "Failed to load file preview",
|
|
8
|
+
"Failed to download file": "Failed to download file",
|
|
9
|
+
"Ask AI": "Ask AI",
|
|
10
|
+
"Please help me analyze the file currently open in preview.": "Please help me analyze the file currently open in preview.",
|
|
11
|
+
"Failed to open AI chat": "Failed to open AI chat",
|
|
12
|
+
"This file type cannot be previewed. Click Download to save the file.": "This file type cannot be previewed. Click Download to save the file.",
|
|
13
|
+
"This file type cannot be previewed. ": "This file type cannot be previewed. "
|
|
14
|
+
}
|
package/dist/locale/vi-VN.json
CHANGED
|
@@ -1,11 +1,14 @@
|
|
|
1
|
-
{
|
|
2
|
-
"Preview": "Xem trước",
|
|
3
|
-
"Open in new window": "Mở trong cửa sổ mới",
|
|
4
|
-
"Download": "Tải xuống",
|
|
5
|
-
"Close": "Đóng",
|
|
6
|
-
"Loading preview...": "Đang tải xem trước...",
|
|
7
|
-
"Failed to load file preview": "Không thể tải xem trước file",
|
|
8
|
-
"Failed to download file": "Không thể tải file",
|
|
9
|
-
"
|
|
10
|
-
"
|
|
11
|
-
|
|
1
|
+
{
|
|
2
|
+
"Preview": "Xem trước",
|
|
3
|
+
"Open in new window": "Mở trong cửa sổ mới",
|
|
4
|
+
"Download": "Tải xuống",
|
|
5
|
+
"Close": "Đóng",
|
|
6
|
+
"Loading preview...": "Đang tải xem trước...",
|
|
7
|
+
"Failed to load file preview": "Không thể tải xem trước file",
|
|
8
|
+
"Failed to download file": "Không thể tải file",
|
|
9
|
+
"Ask AI": "Hỏi AI",
|
|
10
|
+
"Please help me analyze the file currently open in preview.": "Hãy giúp tôi phân tích file đang được mở xem trước.",
|
|
11
|
+
"Failed to open AI chat": "Không thể mở chat AI",
|
|
12
|
+
"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.",
|
|
13
|
+
"This file type cannot be previewed. ": "Loại file này không thể xem trước. "
|
|
14
|
+
}
|
package/dist/locale/zh-CN.json
CHANGED
|
@@ -1,11 +1,14 @@
|
|
|
1
|
-
{
|
|
2
|
-
"Preview": "预览",
|
|
3
|
-
"Open in new window": "在新窗口中打开",
|
|
4
|
-
"Download": "下载",
|
|
5
|
-
"Close": "关闭",
|
|
6
|
-
"Loading preview...": "正在加载预览...",
|
|
7
|
-
"Failed to load file preview": "无法加载文件预览",
|
|
8
|
-
"Failed to download file": "无法下载文件",
|
|
9
|
-
"
|
|
10
|
-
"
|
|
11
|
-
|
|
1
|
+
{
|
|
2
|
+
"Preview": "预览",
|
|
3
|
+
"Open in new window": "在新窗口中打开",
|
|
4
|
+
"Download": "下载",
|
|
5
|
+
"Close": "关闭",
|
|
6
|
+
"Loading preview...": "正在加载预览...",
|
|
7
|
+
"Failed to load file preview": "无法加载文件预览",
|
|
8
|
+
"Failed to download file": "无法下载文件",
|
|
9
|
+
"Ask AI": "询问 AI",
|
|
10
|
+
"Please help me analyze the file currently open in preview.": "请帮我分析当前正在预览的文件。",
|
|
11
|
+
"Failed to open AI chat": "无法打开 AI 聊天",
|
|
12
|
+
"This file type cannot be previewed. Click Download to save the file.": "此文件类型不支持预览。请点击下载以保存文件。",
|
|
13
|
+
"This file type cannot be previewed. ": "此文件类型不支持预览。"
|
|
14
|
+
}
|
|
@@ -58,10 +58,10 @@ class ExcelParserHandler {
|
|
|
58
58
|
return XLSX_EXTNAMES.has(resolveExtname(attachment));
|
|
59
59
|
}
|
|
60
60
|
async parse(attachment, ctx) {
|
|
61
|
-
var _a, _b, _c;
|
|
62
|
-
const docParserPlugin = (_a = ctx.app.pm) == null ? void 0 : _a.get("@nocobase/plugin-document-parser");
|
|
61
|
+
var _a, _b, _c, _d;
|
|
62
|
+
const docParserPlugin = ((_a = ctx.app.pm) == null ? void 0 : _a.get("@nocobase/plugin-document-parser")) || ((_b = ctx.app.pm) == null ? void 0 : _b.get("plugin-document-parser"));
|
|
63
63
|
if (!(docParserPlugin == null ? void 0 : docParserPlugin.fetchFileBuffer)) {
|
|
64
|
-
(
|
|
64
|
+
(_d = (_c = ctx.log) == null ? void 0 : _c.warn) == null ? void 0 : _d.call(_c, "[ExcelParser] plugin-document-parser not available \u2014 cannot fetch file bytes");
|
|
65
65
|
return { text: "", handled: false };
|
|
66
66
|
}
|
|
67
67
|
const { buffer } = await docParserPlugin.fetchFileBuffer(ctx, attachment);
|
package/dist/server/plugin.d.ts
CHANGED
|
@@ -8,8 +8,16 @@
|
|
|
8
8
|
*/
|
|
9
9
|
import { Plugin } from '@nocobase/server';
|
|
10
10
|
export declare class PluginFilePreviewAuthServer extends Plugin {
|
|
11
|
+
private cache;
|
|
11
12
|
load(): Promise<void>;
|
|
12
13
|
private registerDownloadApi;
|
|
14
|
+
private registerAIWorkContext;
|
|
15
|
+
private resolveAttachment;
|
|
16
|
+
private assertCanAccessAttachment;
|
|
17
|
+
private assertAuthenticated;
|
|
18
|
+
private extractAttachmentText;
|
|
19
|
+
private readAttachmentAsText;
|
|
20
|
+
private formatAttachmentWorkContext;
|
|
13
21
|
/**
|
|
14
22
|
* Register Excel handler into plugin-document-parser's InternalParserRegistry.
|
|
15
23
|
* Uses prepend:true so SheetJS takes priority over the AI-loader fallback.
|
package/dist/server/plugin.js
CHANGED
|
@@ -32,40 +32,96 @@ __export(plugin_exports, {
|
|
|
32
32
|
module.exports = __toCommonJS(plugin_exports);
|
|
33
33
|
var import_server = require("@nocobase/server");
|
|
34
34
|
var import_excel_parser_handler = require("./excel-parser-handler");
|
|
35
|
+
const FILE_PREVIEW_WORK_CONTEXT_TYPE = "file-preview";
|
|
36
|
+
const MAX_AI_CONTEXT_CHARS = 5e4;
|
|
35
37
|
class PluginFilePreviewAuthServer extends import_server.Plugin {
|
|
38
|
+
cache;
|
|
36
39
|
async load() {
|
|
40
|
+
this.cache = await this.app.cacheManager.createCache({ name: "file-preview-auth" });
|
|
37
41
|
this.registerExcelParser();
|
|
42
|
+
this.registerAIWorkContext();
|
|
38
43
|
this.registerDownloadApi();
|
|
39
44
|
}
|
|
40
45
|
registerDownloadApi() {
|
|
41
46
|
this.app.resourcer.define({
|
|
42
47
|
name: "filePreviewAuth",
|
|
43
48
|
actions: {
|
|
49
|
+
getContent: async (ctx, next) => {
|
|
50
|
+
const params = ctx.action.params || {};
|
|
51
|
+
const values = params.values || {};
|
|
52
|
+
const reqQuery = ctx.request.query || {};
|
|
53
|
+
const reqBody = ctx.request.body || {};
|
|
54
|
+
const fileInput = values.file || params.file || reqQuery.file || reqBody.file || params;
|
|
55
|
+
const attachment = await this.resolveAttachment(ctx, fileInput);
|
|
56
|
+
this.assertAuthenticated(ctx);
|
|
57
|
+
const cacheKey = `parsed_text:${attachment.id || attachment.key || attachment.url || attachment.path}`;
|
|
58
|
+
let text = await this.cache.get(cacheKey);
|
|
59
|
+
if (text == null) {
|
|
60
|
+
text = await this.extractAttachmentText(ctx, attachment);
|
|
61
|
+
await this.cache.set(cacheKey, text, 864e5);
|
|
62
|
+
}
|
|
63
|
+
ctx.body = {
|
|
64
|
+
filename: getAttachmentDisplayName(attachment),
|
|
65
|
+
mimetype: getAttachmentValue(attachment, "mimetype") || "",
|
|
66
|
+
content: this.formatAttachmentWorkContext(attachment, text)
|
|
67
|
+
};
|
|
68
|
+
await next();
|
|
69
|
+
},
|
|
44
70
|
download: async (ctx, next) => {
|
|
45
|
-
|
|
46
|
-
const
|
|
47
|
-
|
|
71
|
+
const params = ctx.action.params || {};
|
|
72
|
+
const reqQuery = ctx.request.query || {};
|
|
73
|
+
const reqBody = ctx.request.body || {};
|
|
74
|
+
let rawUrl = params.url || reqQuery.url || reqBody.url;
|
|
75
|
+
if (!rawUrl) {
|
|
48
76
|
ctx.throw(400, "url is required");
|
|
49
77
|
}
|
|
78
|
+
let url = rawUrl;
|
|
79
|
+
try {
|
|
80
|
+
url = decodeURIComponent(rawUrl);
|
|
81
|
+
} catch (e) {
|
|
82
|
+
}
|
|
83
|
+
const collection = params.collection || reqQuery.collection || reqBody.collection;
|
|
84
|
+
const storageIdInput = params.storageId || reqQuery.storageId || reqBody.storageId;
|
|
85
|
+
let storageId = storageIdInput;
|
|
50
86
|
const fileManager = this.pm.get("@nocobase/plugin-file-manager");
|
|
51
87
|
if (!fileManager) {
|
|
52
88
|
ctx.throw(500, "File manager plugin not found");
|
|
53
89
|
}
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
90
|
+
let filterByTk = null;
|
|
91
|
+
try {
|
|
92
|
+
const parsedUrl = new URL(url, "http://local");
|
|
93
|
+
filterByTk = parsedUrl.searchParams.get("filterByTk");
|
|
94
|
+
if (!storageId) {
|
|
95
|
+
storageId = parsedUrl.searchParams.get("storageId") || parsedUrl.searchParams.get("storage_id");
|
|
96
|
+
}
|
|
97
|
+
} catch (e) {
|
|
98
|
+
}
|
|
99
|
+
let attachment = null;
|
|
100
|
+
let isVirtual = false;
|
|
101
|
+
const collectionsToTry = Array.from(new Set([collection, "aiFiles", "attachments"].filter(Boolean)));
|
|
102
|
+
for (const colName of collectionsToTry) {
|
|
103
|
+
const repo = this.db.getRepository(colName);
|
|
104
|
+
if (repo) {
|
|
105
|
+
if (filterByTk) {
|
|
106
|
+
attachment = await repo.findOne({ filterByTk });
|
|
107
|
+
}
|
|
108
|
+
if (!attachment) {
|
|
109
|
+
attachment = await repo.findOne({ filter: { url } });
|
|
110
|
+
}
|
|
111
|
+
if (attachment) {
|
|
112
|
+
break;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
if (!attachment && storageId) {
|
|
117
|
+
attachment = { url, storageId, filename: reqQuery.filename || "file" };
|
|
118
|
+
isVirtual = true;
|
|
57
119
|
}
|
|
58
|
-
const attachmentRepo = this.db.getRepository("attachments");
|
|
59
|
-
const attachment = await attachmentRepo.findOne({
|
|
60
|
-
filter: { url }
|
|
61
|
-
});
|
|
62
120
|
if (!attachment) {
|
|
63
121
|
ctx.throw(404, "Attachment not found for this URL");
|
|
64
122
|
}
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
if (!isOwner && !isAdmin) {
|
|
68
|
-
ctx.throw(403, "Permission denied: you cannot view other users' files");
|
|
123
|
+
if (!isVirtual) {
|
|
124
|
+
await this.assertCanAccessAttachment(ctx, attachment);
|
|
69
125
|
}
|
|
70
126
|
try {
|
|
71
127
|
const storageModel = fileManager.storagesCache.get(attachment.storageId);
|
|
@@ -99,15 +155,142 @@ class PluginFilePreviewAuthServer extends import_server.Plugin {
|
|
|
99
155
|
}
|
|
100
156
|
}
|
|
101
157
|
});
|
|
158
|
+
this.app.acl.allow("filePreviewAuth", ["download", "getContent"], "loggedIn");
|
|
102
159
|
this.log.info("[FilePreviewAuth] Registered /api/filePreviewAuth:download endpoint");
|
|
103
160
|
}
|
|
161
|
+
registerAIWorkContext() {
|
|
162
|
+
var _a;
|
|
163
|
+
let aiPlugin;
|
|
164
|
+
try {
|
|
165
|
+
aiPlugin = this.pm.get("ai") || this.pm.get("@nocobase/plugin-ai");
|
|
166
|
+
} catch {
|
|
167
|
+
aiPlugin = null;
|
|
168
|
+
}
|
|
169
|
+
if (!((_a = aiPlugin == null ? void 0 : aiPlugin.workContextHandler) == null ? void 0 : _a.registerStrategy)) {
|
|
170
|
+
this.log.debug("[FilePreviewAuth] plugin-ai not found - file preview AI context skipped");
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
173
|
+
try {
|
|
174
|
+
aiPlugin.workContextHandler.registerStrategy(FILE_PREVIEW_WORK_CONTEXT_TYPE, {
|
|
175
|
+
resolve: async (ctx, contextItem) => {
|
|
176
|
+
var _a2;
|
|
177
|
+
const file = ((_a2 = contextItem == null ? void 0 : contextItem.content) == null ? void 0 : _a2.file) || (contextItem == null ? void 0 : contextItem.content) || contextItem;
|
|
178
|
+
const attachment = await this.resolveAttachment(ctx, file);
|
|
179
|
+
this.assertAuthenticated(ctx);
|
|
180
|
+
const text = await this.extractAttachmentText(ctx, attachment);
|
|
181
|
+
return this.formatAttachmentWorkContext(attachment, text);
|
|
182
|
+
}
|
|
183
|
+
});
|
|
184
|
+
this.log.info("[FilePreviewAuth] AI file-preview work context registered");
|
|
185
|
+
} catch (err) {
|
|
186
|
+
this.log.warn(`[FilePreviewAuth] AI file-preview work context registration skipped: ${err}`);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
async resolveAttachment(ctx, input) {
|
|
190
|
+
var _a;
|
|
191
|
+
const file = (input == null ? void 0 : input.file) || input || {};
|
|
192
|
+
const collectionNames = [
|
|
193
|
+
file.collectionName,
|
|
194
|
+
"attachments",
|
|
195
|
+
"aiFiles"
|
|
196
|
+
].filter(Boolean);
|
|
197
|
+
const ids = [file.id, file.uid].filter((value) => isLikelyRecordId(value));
|
|
198
|
+
for (const collectionName of collectionNames) {
|
|
199
|
+
if (!ctx.db.getCollection(collectionName)) continue;
|
|
200
|
+
const repo = ctx.db.getRepository(collectionName);
|
|
201
|
+
for (const id of ids) {
|
|
202
|
+
const record = await repo.findOne({ filter: { id } });
|
|
203
|
+
if (record) return record;
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
const urlCandidates = getUrlCandidates(file.url || file.preview || file.path);
|
|
207
|
+
for (const collectionName of collectionNames) {
|
|
208
|
+
if (!ctx.db.getCollection(collectionName)) continue;
|
|
209
|
+
const repo = ctx.db.getRepository(collectionName);
|
|
210
|
+
for (const url of urlCandidates) {
|
|
211
|
+
const record = await repo.findOne({ filter: { url } });
|
|
212
|
+
if (record) return record;
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
if ((file.storageId || ((_a = file.url) == null ? void 0 : _a.includes("extStorage:download"))) && (file.url || file.path || file.key)) {
|
|
216
|
+
return file;
|
|
217
|
+
}
|
|
218
|
+
ctx.throw(404, "Attachment not found for this preview file");
|
|
219
|
+
}
|
|
220
|
+
async assertCanAccessAttachment(ctx, attachment) {
|
|
221
|
+
const currentUser = this.assertAuthenticated(ctx);
|
|
222
|
+
const createdById = getAttachmentValue(attachment, "createdById");
|
|
223
|
+
const currentRoles = ctx.state.currentRoles || [];
|
|
224
|
+
const userRoles = currentUser.roles || [];
|
|
225
|
+
const isOwner = createdById != null && String(createdById) === String(currentUser.id);
|
|
226
|
+
const isAdmin = currentRoles.includes("root") || currentRoles.includes("admin") || userRoles.some((role) => role === "root" || role === "admin" || (role == null ? void 0 : role.name) === "root" || (role == null ? void 0 : role.name) === "admin");
|
|
227
|
+
if (!isOwner && !isAdmin) {
|
|
228
|
+
ctx.throw(403, "Permission denied: you cannot view other users' files");
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
assertAuthenticated(ctx) {
|
|
232
|
+
const currentUser = ctx.state.currentUser;
|
|
233
|
+
if (!currentUser) {
|
|
234
|
+
ctx.throw(401, "Unauthorized");
|
|
235
|
+
}
|
|
236
|
+
return currentUser;
|
|
237
|
+
}
|
|
238
|
+
async extractAttachmentText(ctx, attachment) {
|
|
239
|
+
var _a;
|
|
240
|
+
const docParserPlugin = this.pm.get("@nocobase/plugin-document-parser") || this.pm.get("plugin-document-parser");
|
|
241
|
+
if (docParserPlugin == null ? void 0 : docParserPlugin.internalParserRegistry) {
|
|
242
|
+
try {
|
|
243
|
+
const result = await docParserPlugin.internalParserRegistry.parse(attachment, ctx);
|
|
244
|
+
if ((result == null ? void 0 : result.handled) && ((_a = result.text) == null ? void 0 : _a.trim())) {
|
|
245
|
+
return result.text;
|
|
246
|
+
}
|
|
247
|
+
} catch (err) {
|
|
248
|
+
this.log.warn(`[FilePreviewAuth] Document parser failed: ${err}`);
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
if (isPlainTextAttachment(attachment)) {
|
|
252
|
+
return await this.readAttachmentAsText(attachment);
|
|
253
|
+
}
|
|
254
|
+
return "";
|
|
255
|
+
}
|
|
256
|
+
async readAttachmentAsText(attachment) {
|
|
257
|
+
const fileManager = this.pm.get("@nocobase/plugin-file-manager") || this.pm.get("file-manager");
|
|
258
|
+
if (!(fileManager == null ? void 0 : fileManager.getFileStream)) {
|
|
259
|
+
return "";
|
|
260
|
+
}
|
|
261
|
+
const { stream } = await fileManager.getFileStream(attachment);
|
|
262
|
+
const chunks = [];
|
|
263
|
+
for await (const chunk of stream) {
|
|
264
|
+
chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
|
|
265
|
+
}
|
|
266
|
+
return Buffer.concat(chunks).toString("utf-8");
|
|
267
|
+
}
|
|
268
|
+
formatAttachmentWorkContext(attachment, text) {
|
|
269
|
+
const filename = sanitizeXmlAttr(getAttachmentDisplayName(attachment));
|
|
270
|
+
const mimetype = sanitizeXmlAttr(getAttachmentValue(attachment, "mimetype") || "");
|
|
271
|
+
const extname = sanitizeXmlAttr(getAttachmentValue(attachment, "extname") || "");
|
|
272
|
+
const size = sanitizeXmlAttr(getAttachmentValue(attachment, "size") || "");
|
|
273
|
+
const content = truncateForContext((text == null ? void 0 : text.trim()) || "");
|
|
274
|
+
if (!content) {
|
|
275
|
+
return [
|
|
276
|
+
`<file_preview filename="${filename}" type="${mimetype}" extname="${extname}" size="${size}">`,
|
|
277
|
+
"The user is previewing this file, but no extractable text content was found by the server parser.",
|
|
278
|
+
"</file_preview>"
|
|
279
|
+
].join("\n");
|
|
280
|
+
}
|
|
281
|
+
return [
|
|
282
|
+
`<file_preview filename="${filename}" type="${mimetype}" extname="${extname}" size="${size}">`,
|
|
283
|
+
content,
|
|
284
|
+
"</file_preview>"
|
|
285
|
+
].join("\n");
|
|
286
|
+
}
|
|
104
287
|
/**
|
|
105
288
|
* Register Excel handler into plugin-document-parser's InternalParserRegistry.
|
|
106
289
|
* Uses prepend:true so SheetJS takes priority over the AI-loader fallback.
|
|
107
290
|
* Silent no-op when plugin-document-parser is not loaded.
|
|
108
291
|
*/
|
|
109
292
|
registerExcelParser() {
|
|
110
|
-
const docParserPlugin = this.pm.get("@nocobase/plugin-document-parser");
|
|
293
|
+
const docParserPlugin = this.pm.get("@nocobase/plugin-document-parser") || this.pm.get("plugin-document-parser");
|
|
111
294
|
if (!(docParserPlugin == null ? void 0 : docParserPlugin.internalParserRegistry)) {
|
|
112
295
|
this.log.debug("[FilePreviewAuth] plugin-document-parser not found \u2014 Excel parser registration skipped");
|
|
113
296
|
return;
|
|
@@ -121,6 +304,65 @@ class PluginFilePreviewAuthServer extends import_server.Plugin {
|
|
|
121
304
|
}
|
|
122
305
|
}
|
|
123
306
|
var plugin_default = PluginFilePreviewAuthServer;
|
|
307
|
+
function getAttachmentValue(attachment, key) {
|
|
308
|
+
if (!attachment) return void 0;
|
|
309
|
+
if (typeof attachment.get === "function") return attachment.get(key);
|
|
310
|
+
return attachment[key];
|
|
311
|
+
}
|
|
312
|
+
function getAttachmentDisplayName(attachment) {
|
|
313
|
+
const title = getAttachmentValue(attachment, "title");
|
|
314
|
+
const extname = getAttachmentValue(attachment, "extname");
|
|
315
|
+
if (title && extname) return `${title}${extname}`;
|
|
316
|
+
return getAttachmentValue(attachment, "filename") || getAttachmentValue(attachment, "name") || "file";
|
|
317
|
+
}
|
|
318
|
+
function isLikelyRecordId(value) {
|
|
319
|
+
if (value === void 0 || value === null || value === "") return false;
|
|
320
|
+
const text = String(value);
|
|
321
|
+
return !text.includes("/") && !text.startsWith("http://") && !text.startsWith("https://");
|
|
322
|
+
}
|
|
323
|
+
function getUrlCandidates(value) {
|
|
324
|
+
if (!value) return [];
|
|
325
|
+
const original = decodePossiblyEncodedUrl(String(value));
|
|
326
|
+
const candidates = /* @__PURE__ */ new Set();
|
|
327
|
+
const add = (url) => {
|
|
328
|
+
if (!url) return;
|
|
329
|
+
candidates.add(url);
|
|
330
|
+
candidates.add(url.split("?")[0]);
|
|
331
|
+
candidates.add(url.replace(/^\//, ""));
|
|
332
|
+
candidates.add(`/${url.replace(/^\//, "")}`);
|
|
333
|
+
};
|
|
334
|
+
add(original);
|
|
335
|
+
try {
|
|
336
|
+
const parsed = new URL(original, "http://local");
|
|
337
|
+
if (parsed.pathname.includes("/api/filePreviewAuth:download")) {
|
|
338
|
+
add(decodePossiblyEncodedUrl(parsed.searchParams.get("url") || ""));
|
|
339
|
+
} else if (parsed.origin !== "http://local") {
|
|
340
|
+
add(`${parsed.pathname}${parsed.search}`);
|
|
341
|
+
}
|
|
342
|
+
} catch {
|
|
343
|
+
}
|
|
344
|
+
return [...candidates].filter(Boolean);
|
|
345
|
+
}
|
|
346
|
+
function decodePossiblyEncodedUrl(value) {
|
|
347
|
+
try {
|
|
348
|
+
return decodeURIComponent(value);
|
|
349
|
+
} catch {
|
|
350
|
+
return value;
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
function isPlainTextAttachment(attachment) {
|
|
354
|
+
const mimetype = String(getAttachmentValue(attachment, "mimetype") || "").toLowerCase();
|
|
355
|
+
const extname = String(getAttachmentValue(attachment, "extname") || "").toLowerCase();
|
|
356
|
+
return mimetype.startsWith("text/") || ["application/json", "application/xml", "application/x-yaml"].includes(mimetype) || [".txt", ".md", ".csv", ".json", ".xml", ".yaml", ".yml", ".log"].includes(extname);
|
|
357
|
+
}
|
|
358
|
+
function truncateForContext(text) {
|
|
359
|
+
if (!text || text.length <= MAX_AI_CONTEXT_CHARS) return text;
|
|
360
|
+
return `${text.slice(0, MAX_AI_CONTEXT_CHARS)}
|
|
361
|
+
...[truncated]`;
|
|
362
|
+
}
|
|
363
|
+
function sanitizeXmlAttr(value) {
|
|
364
|
+
return String(value ?? "").replace(/&/g, "&").replace(/"/g, """).replace(/</g, "<").replace(/>/g, ">");
|
|
365
|
+
}
|
|
124
366
|
// Annotate the CommonJS export names for ESM import in node:
|
|
125
367
|
0 && (module.exports = {
|
|
126
368
|
PluginFilePreviewAuthServer
|
package/package.json
CHANGED
|
@@ -1,36 +1,43 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "plugin-file-preview-auth",
|
|
3
|
-
"displayName": "Authenticated File Previewer",
|
|
4
|
-
"displayName.vi-VN": "Xem trước file có xác thực",
|
|
5
|
-
"displayName.zh-CN": "认证文件预览",
|
|
6
|
-
"description": "Preview PDF, image, and text files with Bearer token authentication via blob URLs.",
|
|
7
|
-
"description.vi-VN": "Xem trước file PDF, hình ảnh và văn bản với xác thực Bearer token qua blob URL.",
|
|
8
|
-
"description.zh-CN": "通过 Bearer 令牌认证和 Blob URL 预览 PDF、图片和文本文件。",
|
|
9
|
-
"version": "1.
|
|
10
|
-
"main": "dist/server/index.js",
|
|
11
|
-
"files": [
|
|
12
|
-
"dist",
|
|
13
|
-
"public",
|
|
14
|
-
"client.js",
|
|
15
|
-
"client.d.ts",
|
|
16
|
-
"server.js",
|
|
17
|
-
"server.d.ts",
|
|
18
|
-
"README.md"
|
|
19
|
-
],
|
|
20
|
-
"peerDependencies": {
|
|
21
|
-
"@nocobase/client": "2.x",
|
|
22
|
-
"@nocobase/plugin-
|
|
23
|
-
"@nocobase/
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
"
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
"
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
1
|
+
{
|
|
2
|
+
"name": "plugin-file-preview-auth",
|
|
3
|
+
"displayName": "Authenticated File Previewer",
|
|
4
|
+
"displayName.vi-VN": "Xem trước file có xác thực",
|
|
5
|
+
"displayName.zh-CN": "认证文件预览",
|
|
6
|
+
"description": "Preview PDF, image, and text files with Bearer token authentication via blob URLs.",
|
|
7
|
+
"description.vi-VN": "Xem trước file PDF, hình ảnh và văn bản với xác thực Bearer token qua blob URL.",
|
|
8
|
+
"description.zh-CN": "通过 Bearer 令牌认证和 Blob URL 预览 PDF、图片和文本文件。",
|
|
9
|
+
"version": "1.2.0",
|
|
10
|
+
"main": "dist/server/index.js",
|
|
11
|
+
"files": [
|
|
12
|
+
"dist",
|
|
13
|
+
"public",
|
|
14
|
+
"client.js",
|
|
15
|
+
"client.d.ts",
|
|
16
|
+
"server.js",
|
|
17
|
+
"server.d.ts",
|
|
18
|
+
"README.md"
|
|
19
|
+
],
|
|
20
|
+
"peerDependencies": {
|
|
21
|
+
"@nocobase/client": "2.x",
|
|
22
|
+
"@nocobase/plugin-ai": "2.x",
|
|
23
|
+
"@nocobase/plugin-file-manager": "2.x",
|
|
24
|
+
"@nocobase/server": "2.x"
|
|
25
|
+
},
|
|
26
|
+
"peerDependenciesMeta": {
|
|
27
|
+
"@nocobase/plugin-ai": {
|
|
28
|
+
"optional": true
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
"devDependencies": {},
|
|
32
|
+
"keywords": [
|
|
33
|
+
"File manager",
|
|
34
|
+
"File preview",
|
|
35
|
+
"Authentication"
|
|
36
|
+
],
|
|
37
|
+
"license": "Apache-2.0",
|
|
38
|
+
"dependencies": {
|
|
39
|
+
"docx-preview": "^0.3.3",
|
|
40
|
+
"react-pptx-preview-kit": "^0.1.9",
|
|
41
|
+
"xlsx": "^0.18.5"
|
|
42
|
+
}
|
|
43
|
+
}
|