diff --git a/server/plugin/plg_application_docxjs/Makefile b/server/plugin/plg_application_docxjs/Makefile new file mode 100644 index 00000000..546104ca --- /dev/null +++ b/server/plugin/plg_application_docxjs/Makefile @@ -0,0 +1,15 @@ +all: + make setup + make build + make install + +setup: + [ -d lib/vendor ] || mkdir -p lib/vendor + curl -L https://raw.githubusercontent.com/VolodymyrBaydalka/docxjs/refs/heads/master/dist/docx-preview.js > lib/vendor/docx-preview.js + curl -L https://unpkg.com/jszip/dist/jszip.min.js > lib/vendor/jszip.min.js + +build: + zip -r application_docx.zip . + +install: + mv application_docx.zip ../../../dist/data/state/plugins/ diff --git a/server/plugin/plg_application_docxjs/loader_docx.css b/server/plugin/plg_application_docxjs/loader_docx.css new file mode 100644 index 00000000..7cf990ce --- /dev/null +++ b/server/plugin/plg_application_docxjs/loader_docx.css @@ -0,0 +1,16 @@ +.component_docx { + width: 100%; +} + +.component_docx .docx-wrapper { + background: #f5f5f5; +} +.component_docx .docx-wrapper > section.docx { + box-shadow: 0 0 3px rgba(0, 0, 0, 0.1); + border-radius: 4px; +} + +.component_filedownloader { + width: 100%; + margin: 0 auto; +} diff --git a/server/plugin/plg_application_docxjs/loader_docx.js b/server/plugin/plg_application_docxjs/loader_docx.js new file mode 100644 index 00000000..664830f2 --- /dev/null +++ b/server/plugin/plg_application_docxjs/loader_docx.js @@ -0,0 +1,55 @@ +import { createElement } from "../../lib/skeleton/index.js"; +import rxjs, { effect } from "../../lib/rx.js"; +import ajax from "../../lib/ajax.js"; +import { loadJS, loadCSS } from "../../helpers/loader.js"; +import ctrlError from "../../pages/ctrl_error.js"; +import { transition } from "../../pages/viewerpage/common.js"; +import ctrlDownloader, { init as initDownloader } from "../../pages/viewerpage/application_downloader.js"; +import { createLoader } from "../../components/loader.js"; + +await init(); + +/* + * This viewer application is for rendering a docx onto an HTML document. To get a smooth UI, the whole + * flow is broken down to these steps: + * 1) show a loading spinner => `... = createLoader($page);` + * 2) fetch the docx file => effect(ajax({ xxxx })).pipe( + * 3) remove the spinner => cancelLoader, + * 4) render + transition => ... renderDocx ... + * 5) fallback on error => ... catchError ... ctrlDownloader(...) + * + * note: you don't have to use rxjs if you don't like it, the same code could be written with plain + * promises instead. We just happen to be rxjs fanboys who enjoy the automatic resource cleanup it + * enforces. In this example, if the user navigates away before the docx is loaded, the ajax call + * is cancelled automatically. Additionally, we prefer thinking in terms of streams rather than + * the classical state management approach used by most frameworks. + */ +export default async function(render, { getDownloadUrl, getFilename, $menubar, acl$ }) { + const $page = createElement(` +
+ `); + render($page); + + const cancelLoader = createLoader($page); + effect(ajax({ url: getDownloadUrl(), responseType: "arraybuffer" }).pipe( + cancelLoader, + rxjs.mergeMap(async ({ response }) => renderDocx(response, $page)), + rxjs.catchError(() => ctrlDownloader(render, { acl$, getFilename, getDownloadUrl, hasMenubar: false })), + )); +} + +async function renderDocx(response, $page) { + $page.classList.add("hidden"); + await window.docx.renderAsync(response, $page) + $page.classList.remove("hidden"); + $page.parentElement.classList.add("scroll-y"); + transition($page); +} + +function init() { + return Promise.all([ + loadCSS(import.meta.url, "./loader_docx.css"), + initDownloader(), + loadJS(import.meta.url, "./lib/vendor/jszip.min.js").then(() => loadJS(import.meta.url, "./lib/vendor/docx-preview.js")), + ]); +} diff --git a/server/plugin/plg_application_docxjs/manifest.json b/server/plugin/plg_application_docxjs/manifest.json new file mode 100644 index 00000000..1fbde257 --- /dev/null +++ b/server/plugin/plg_application_docxjs/manifest.json @@ -0,0 +1,12 @@ +{ + "author": "Filestash Pty Ltd", + "version": "v0.0", + "modules": [ + { + "type": "xdg-open", + "mime": "application/word", + "entrypoint": "loader_docx.js", + "application": "skeleton" + } + ] +}