Apply prettier rules

This commit is contained in:
2024-11-14 18:47:38 +01:00
parent 610227815a
commit aa0785fc71
291 changed files with 23646 additions and 22071 deletions

View File

@@ -1,57 +1,61 @@
<template>
<a :class="props.classes" @click="download_and_open($event)" ref="btn">
<i class="fa fa-file-pdf-o"></i>
Télécharger en pdf
</a>
<a :class="props.classes" @click="download_and_open($event)" ref="btn">
<i class="fa fa-file-pdf-o"></i>
Télécharger en pdf
</a>
</template>
<script lang="ts" setup>
import {build_convert_link, download_and_decrypt_doc, download_doc} from "./helpers";
import {
build_convert_link,
download_and_decrypt_doc,
download_doc,
} from "./helpers";
import mime from "mime";
import {reactive, ref} from "vue";
import {StoredObject, StoredObjectCreated} from "../../types";
import { reactive, ref } from "vue";
import { StoredObject, StoredObjectCreated } from "../../types";
interface ConvertButtonConfig {
storedObject: StoredObject,
classes: Record<string, boolean>,
filename?: string,
};
storedObject: StoredObject;
classes: Record<string, boolean>;
filename?: string;
}
interface DownloadButtonState {
content: null|string
content: null | string;
}
const props = defineProps<ConvertButtonConfig>();
const state: DownloadButtonState = reactive({content: null});
const state: DownloadButtonState = reactive({ content: null });
const btn = ref<HTMLAnchorElement | null>(null);
async function download_and_open(event: Event): Promise<void> {
const button = event.target as HTMLAnchorElement;
const button = event.target as HTMLAnchorElement;
if (null === state.content) {
event.preventDefault();
if (null === state.content) {
event.preventDefault();
const raw = await download_doc(build_convert_link(props.storedObject.uuid));
state.content = window.URL.createObjectURL(raw);
const raw = await download_doc(
build_convert_link(props.storedObject.uuid),
);
state.content = window.URL.createObjectURL(raw);
button.href = window.URL.createObjectURL(raw);
button.type = 'application/pdf';
button.href = window.URL.createObjectURL(raw);
button.type = "application/pdf";
button.download = (props.filename + '.pdf') || 'document.pdf';
}
button.download = props.filename + ".pdf" || "document.pdf";
}
button.click();
const reset_pending = setTimeout(reset_state, 45000);
button.click();
const reset_pending = setTimeout(reset_state, 45000);
}
function reset_state(): void {
state.content = null;
btn.value?.removeAttribute('download');
btn.value?.removeAttribute('href');
btn.value?.removeAttribute('type');
btn.value?.removeAttribute("download");
btn.value?.removeAttribute("href");
btn.value?.removeAttribute("type");
}
</script>
<style scoped lang="sass">

View File

@@ -1,23 +1,24 @@
<script setup lang="ts">
import Modal from "ChillMainAssets/vuejs/_components/Modal.vue";
import {computed, reactive} from "vue";
import { computed, reactive } from "vue";
export interface DesktopEditButtonConfig {
editLink: null,
classes: Record<string, boolean>,
expirationLink: number|Date,
editLink: null;
classes: Record<string, boolean>;
expirationLink: number | Date;
}
interface DesktopEditButtonState {
modalOpened: boolean
};
modalOpened: boolean;
}
const state: DesktopEditButtonState = reactive({modalOpened: false});
const state: DesktopEditButtonState = reactive({ modalOpened: false });
const props = defineProps<DesktopEditButtonConfig>();
const buildCommand = computed<string>(() => 'vnd.libreoffice.command:ofe|u|' + props.editLink);
const buildCommand = computed<string>(
() => "vnd.libreoffice.command:ofe|u|" + props.editLink,
);
const editionUntilFormatted = computed<string>(() => {
let d;
@@ -29,26 +30,52 @@ const editionUntilFormatted = computed<string>(() => {
}
console.log(props.expirationLink);
return (new Intl.DateTimeFormat(undefined, {'dateStyle': 'long', 'timeStyle': 'medium'})).format(d);
return new Intl.DateTimeFormat(undefined, {
dateStyle: "long",
timeStyle: "medium",
}).format(d);
});
</script>
<template>
<teleport to="body">
<modal v-if="state.modalOpened" @close="state.modalOpened=false">
<modal v-if="state.modalOpened" @close="state.modalOpened = false">
<template v-slot:body>
<div class="desktop-edit">
<p class="center">Veuillez enregistrer vos modifications avant le</p>
<p><strong>{{ editionUntilFormatted }}</strong></p>
<p class="center">
Veuillez enregistrer vos modifications avant le
</p>
<p>
<strong>{{ editionUntilFormatted }}</strong>
</p>
<p><a class="btn btn-primary" :href="buildCommand">Ouvrir le document pour édition</a></p>
<p>
<a class="btn btn-primary" :href="buildCommand"
>Ouvrir le document pour édition</a
>
</p>
<p><small>Le document peut être édité uniquement en utilisant Libre Office.</small></p>
<p>
<small
>Le document peut être édité uniquement en utilisant
Libre Office.</small
>
</p>
<p><small>En cas d'échec lors de l'enregistrement, sauver le document sur le poste de travail avant de le déposer à nouveau ici.</small></p>
<p>
<small
>En cas d'échec lors de l'enregistrement, sauver le
document sur le poste de travail avant de le déposer
à nouveau ici.</small
>
</p>
<p><small>Vous pouvez naviguez sur d'autres pages pendant l'édition.</small></p>
<p>
<small
>Vous pouvez naviguez sur d'autres pages pendant
l'édition.</small
>
</p>
</div>
</template>
</modal>

View File

@@ -1,43 +1,59 @@
<template>
<a v-if="!state.is_ready" :class="props.classes" @click="download_and_open($event)">
<a
v-if="!state.is_ready"
:class="props.classes"
@click="download_and_open($event)"
>
<i class="fa fa-download"></i>
Télécharger
</a>
<a v-else :class="props.classes" target="_blank" :type="props.storedObject.type" :download="buildDocumentName()" :href="state.href_url" ref="open_button">
<a
v-else
:class="props.classes"
target="_blank"
:type="props.storedObject.type"
:download="buildDocumentName()"
:href="state.href_url"
ref="open_button"
>
<i class="fa fa-external-link"></i>
Ouvrir
</a>
</template>
<script lang="ts" setup>
import {reactive, ref, nextTick, onMounted} from "vue";
import {build_download_info_link, download_and_decrypt_doc} from "./helpers";
import { reactive, ref, nextTick, onMounted } from "vue";
import { build_download_info_link, download_and_decrypt_doc } from "./helpers";
import mime from "mime";
import {StoredObject, StoredObjectCreated} from "../../types";
import { StoredObject, StoredObjectCreated } from "../../types";
interface DownloadButtonConfig {
storedObject: StoredObject|StoredObjectCreated,
classes: Record<string, boolean>,
filename?: string,
storedObject: StoredObject | StoredObjectCreated;
classes: Record<string, boolean>;
filename?: string;
}
interface DownloadButtonState {
is_ready: boolean,
is_running: boolean,
href_url: string,
is_ready: boolean;
is_running: boolean;
href_url: string;
}
const props = defineProps<DownloadButtonConfig>();
const state: DownloadButtonState = reactive({is_ready: false, is_running: false, href_url: "#"});
const state: DownloadButtonState = reactive({
is_ready: false,
is_running: false,
href_url: "#",
});
const open_button = ref<HTMLAnchorElement | null>(null);
function buildDocumentName(): string {
const document_name = props.filename || 'document';
const document_name = props.filename || "document";
const ext = mime.getExtension(props.storedObject.type);
if (null !== ext) {
return document_name + '.' + ext;
return document_name + "." + ext;
}
return document_name;
@@ -47,14 +63,14 @@ async function download_and_open(event: Event): Promise<void> {
const button = event.target as HTMLAnchorElement;
if (state.is_running) {
console.log('state is running, aborting');
console.log("state is running, aborting");
return;
}
state.is_running = true;
if (state.is_ready) {
console.log('state is ready. This should not happens');
console.log("state is ready. This should not happens");
return;
}
@@ -62,36 +78,40 @@ async function download_and_open(event: Event): Promise<void> {
let raw;
try {
raw = await download_and_decrypt_doc(urlInfo, props.storedObject.keyInfos, new Uint8Array(props.storedObject.iv));
raw = await download_and_decrypt_doc(
urlInfo,
props.storedObject.keyInfos,
new Uint8Array(props.storedObject.iv),
);
} catch (e) {
console.error("error while downloading and decrypting document");
console.error(e);
throw e;
}
console.log('document downloading (and decrypting) successfully');
console.log("document downloading (and decrypting) successfully");
console.log('creating the url')
console.log("creating the url");
state.href_url = window.URL.createObjectURL(raw);
console.log('url created', state.href_url);
console.log("url created", state.href_url);
state.is_running = false;
state.is_ready = true;
console.log('new button marked as ready');
console.log('will click on button');
console.log("new button marked as ready");
console.log("will click on button");
console.log('openbutton is now', open_button.value);
console.log("openbutton is now", open_button.value);
await nextTick();
console.log('next tick actions');
console.log('openbutton after next tick', open_button.value);
console.log("next tick actions");
console.log("openbutton after next tick", open_button.value);
open_button.value?.click();
console.log('open button should have been clicked');
console.log("open button should have been clicked");
const timer = setTimeout(reset_state, 45000);
}
function reset_state(): void {
state.href_url = '#';
state.href_url = "#";
state.is_ready = false;
state.is_running = false;
}

View File

@@ -1,20 +1,30 @@
<template>
<a :class="Object.assign(props.classes, {'btn': true})" @click="beforeLeave($event)" :href="build_wopi_editor_link(props.storedObject.uuid, props.returnPath)">
<i class="fa fa-paragraph"></i>
Editer en ligne
</a>
<a
:class="Object.assign(props.classes, { btn: true })"
@click="beforeLeave($event)"
:href="
build_wopi_editor_link(props.storedObject.uuid, props.returnPath)
"
>
<i class="fa fa-paragraph"></i>
Editer en ligne
</a>
</template>
<script lang="ts" setup>
import WopiEditButton from "./WopiEditButton.vue";
import {build_wopi_editor_link} from "./helpers";
import {StoredObject, StoredObjectCreated, WopiEditButtonExecutableBeforeLeaveFunction} from "../../types";
import { build_wopi_editor_link } from "./helpers";
import {
StoredObject,
StoredObjectCreated,
WopiEditButtonExecutableBeforeLeaveFunction,
} from "../../types";
interface WopiEditButtonConfig {
storedObject: StoredObject,
returnPath?: string,
classes: Record<string, boolean>,
executeBeforeLeave?: WopiEditButtonExecutableBeforeLeaveFunction,
storedObject: StoredObject;
returnPath?: string;
classes: Record<string, boolean>;
executeBeforeLeave?: WopiEditButtonExecutableBeforeLeaveFunction;
}
const props = defineProps<WopiEditButtonConfig>();
@@ -22,20 +32,20 @@ const props = defineProps<WopiEditButtonConfig>();
let executed = false;
async function beforeLeave(event: Event): Promise<true> {
console.log(executed);
if (props.executeBeforeLeave === undefined || executed === true) {
console.log(executed);
if (props.executeBeforeLeave === undefined || executed === true) {
return Promise.resolve(true);
}
event.preventDefault();
await props.executeBeforeLeave();
executed = true;
const link = event.target as HTMLAnchorElement;
link.click();
return Promise.resolve(true);
}
event.preventDefault();
await props.executeBeforeLeave();
executed = true;
const link = event.target as HTMLAnchorElement;
link.click();
return Promise.resolve(true);
}
</script>
@@ -44,4 +54,3 @@ i.fa::before {
color: var(--bs-dropdown-link-hover-color);
}
</style>

View File

@@ -1,198 +1,228 @@
import {StoredObject, StoredObjectStatus, StoredObjectStatusChange} from "../../types";
import {
StoredObject,
StoredObjectStatus,
StoredObjectStatusChange,
} from "../../types";
const MIMES_EDIT = new Set([
'application/vnd.ms-powerpoint',
'application/vnd.ms-excel',
'application/vnd.oasis.opendocument.text',
'application/vnd.oasis.opendocument.text-flat-xml',
'application/vnd.oasis.opendocument.spreadsheet',
'application/vnd.oasis.opendocument.spreadsheet-flat-xml',
'application/vnd.oasis.opendocument.presentation',
'application/vnd.oasis.opendocument.presentation-flat-xml',
'application/vnd.oasis.opendocument.graphics',
'application/vnd.oasis.opendocument.graphics-flat-xml',
'application/vnd.oasis.opendocument.chart',
'application/msword',
'application/vnd.ms-excel',
'application/vnd.ms-powerpoint',
'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
'application/vnd.ms-word.document.macroEnabled.12',
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
'application/vnd.ms-excel.sheet.binary.macroEnabled.12',
'application/vnd.ms-excel.sheet.macroEnabled.12',
'application/vnd.openxmlformats-officedocument.presentationml.presentation',
'application/vnd.ms-powerpoint.presentation.macroEnabled.12',
'application/x-dif-document',
'text/spreadsheet',
'text/csv',
'application/x-dbase',
'text/rtf',
'text/plain',
'application/vnd.openxmlformats-officedocument.presentationml.slideshow',
"application/vnd.ms-powerpoint",
"application/vnd.ms-excel",
"application/vnd.oasis.opendocument.text",
"application/vnd.oasis.opendocument.text-flat-xml",
"application/vnd.oasis.opendocument.spreadsheet",
"application/vnd.oasis.opendocument.spreadsheet-flat-xml",
"application/vnd.oasis.opendocument.presentation",
"application/vnd.oasis.opendocument.presentation-flat-xml",
"application/vnd.oasis.opendocument.graphics",
"application/vnd.oasis.opendocument.graphics-flat-xml",
"application/vnd.oasis.opendocument.chart",
"application/msword",
"application/vnd.ms-excel",
"application/vnd.ms-powerpoint",
"application/vnd.openxmlformats-officedocument.wordprocessingml.document",
"application/vnd.ms-word.document.macroEnabled.12",
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
"application/vnd.ms-excel.sheet.binary.macroEnabled.12",
"application/vnd.ms-excel.sheet.macroEnabled.12",
"application/vnd.openxmlformats-officedocument.presentationml.presentation",
"application/vnd.ms-powerpoint.presentation.macroEnabled.12",
"application/x-dif-document",
"text/spreadsheet",
"text/csv",
"application/x-dbase",
"text/rtf",
"text/plain",
"application/vnd.openxmlformats-officedocument.presentationml.slideshow",
]);
const MIMES_VIEW = new Set([
...MIMES_EDIT,
[
'image/svg+xml',
'application/vnd.sun.xml.writer',
'application/vnd.sun.xml.calc',
'application/vnd.sun.xml.impress',
'application/vnd.sun.xml.draw',
'application/vnd.sun.xml.writer.global',
'application/vnd.sun.xml.writer.template',
'application/vnd.sun.xml.calc.template',
'application/vnd.sun.xml.impress.template',
'application/vnd.sun.xml.draw.template',
'application/vnd.oasis.opendocument.text-master',
'application/vnd.oasis.opendocument.text-template',
'application/vnd.oasis.opendocument.text-master-template',
'application/vnd.oasis.opendocument.spreadsheet-template',
'application/vnd.oasis.opendocument.presentation-template',
'application/vnd.oasis.opendocument.graphics-template',
'application/vnd.ms-word.template.macroEnabled.12',
'application/vnd.openxmlformats-officedocument.spreadsheetml.template',
'application/vnd.ms-excel.template.macroEnabled.12',
'application/vnd.openxmlformats-officedocument.presentationml.template',
'application/vnd.ms-powerpoint.template.macroEnabled.12',
'application/vnd.wordperfect',
'application/x-aportisdoc',
'application/x-hwp',
'application/vnd.ms-works',
'application/x-mswrite',
'application/vnd.lotus-1-2-3',
'image/cgm',
'image/vnd.dxf',
'image/x-emf',
'image/x-wmf',
'application/coreldraw',
'application/vnd.visio2013',
'application/vnd.visio',
'application/vnd.ms-visio.drawing',
'application/x-mspublisher',
'application/x-sony-bbeb',
'application/x-gnumeric',
'application/macwriteii',
'application/x-iwork-numbers-sffnumbers',
'application/vnd.oasis.opendocument.text-web',
'application/x-pagemaker',
'application/x-fictionbook+xml',
'application/clarisworks',
'image/x-wpg',
'application/x-iwork-pages-sffpages',
'application/x-iwork-keynote-sffkey',
'application/x-abiword',
'image/x-freehand',
'application/vnd.sun.xml.chart',
'application/x-t602',
'image/bmp',
'image/png',
'image/gif',
'image/tiff',
'image/jpg',
'image/jpeg',
'application/pdf',
]
])
...MIMES_EDIT,
[
"image/svg+xml",
"application/vnd.sun.xml.writer",
"application/vnd.sun.xml.calc",
"application/vnd.sun.xml.impress",
"application/vnd.sun.xml.draw",
"application/vnd.sun.xml.writer.global",
"application/vnd.sun.xml.writer.template",
"application/vnd.sun.xml.calc.template",
"application/vnd.sun.xml.impress.template",
"application/vnd.sun.xml.draw.template",
"application/vnd.oasis.opendocument.text-master",
"application/vnd.oasis.opendocument.text-template",
"application/vnd.oasis.opendocument.text-master-template",
"application/vnd.oasis.opendocument.spreadsheet-template",
"application/vnd.oasis.opendocument.presentation-template",
"application/vnd.oasis.opendocument.graphics-template",
"application/vnd.ms-word.template.macroEnabled.12",
"application/vnd.openxmlformats-officedocument.spreadsheetml.template",
"application/vnd.ms-excel.template.macroEnabled.12",
"application/vnd.openxmlformats-officedocument.presentationml.template",
"application/vnd.ms-powerpoint.template.macroEnabled.12",
"application/vnd.wordperfect",
"application/x-aportisdoc",
"application/x-hwp",
"application/vnd.ms-works",
"application/x-mswrite",
"application/vnd.lotus-1-2-3",
"image/cgm",
"image/vnd.dxf",
"image/x-emf",
"image/x-wmf",
"application/coreldraw",
"application/vnd.visio2013",
"application/vnd.visio",
"application/vnd.ms-visio.drawing",
"application/x-mspublisher",
"application/x-sony-bbeb",
"application/x-gnumeric",
"application/macwriteii",
"application/x-iwork-numbers-sffnumbers",
"application/vnd.oasis.opendocument.text-web",
"application/x-pagemaker",
"application/x-fictionbook+xml",
"application/clarisworks",
"image/x-wpg",
"application/x-iwork-pages-sffpages",
"application/x-iwork-keynote-sffkey",
"application/x-abiword",
"image/x-freehand",
"application/vnd.sun.xml.chart",
"application/x-t602",
"image/bmp",
"image/png",
"image/gif",
"image/tiff",
"image/jpg",
"image/jpeg",
"application/pdf",
],
]);
function is_extension_editable(mimeType: string): boolean {
return MIMES_EDIT.has(mimeType);
return MIMES_EDIT.has(mimeType);
}
function is_extension_viewable(mimeType: string): boolean {
return MIMES_VIEW.has(mimeType);
return MIMES_VIEW.has(mimeType);
}
function build_convert_link(uuid: string) {
return `/chill/wopi/convert/${uuid}`;
return `/chill/wopi/convert/${uuid}`;
}
function build_download_info_link(object_name: string) {
return `/asyncupload/temp_url/generate/GET?object_name=${object_name}`;
return `/asyncupload/temp_url/generate/GET?object_name=${object_name}`;
}
function build_wopi_editor_link(uuid: string, returnPath?: string) {
if (returnPath === undefined) {
returnPath = window.location.pathname + window.location.search + window.location.hash;
}
if (returnPath === undefined) {
returnPath =
window.location.pathname +
window.location.search +
window.location.hash;
}
return `/chill/wopi/edit/${uuid}?returnPath=` + encodeURIComponent(returnPath);
return (
`/chill/wopi/edit/${uuid}?returnPath=` + encodeURIComponent(returnPath)
);
}
function download_doc(url: string): Promise<Blob> {
return window.fetch(url).then(r => {
if (r.ok) {
return r.blob()
return window.fetch(url).then((r) => {
if (r.ok) {
return r.blob();
}
throw new Error("Could not download document");
});
}
async function download_and_decrypt_doc(
urlGenerator: string,
keyData: JsonWebKey,
iv: Uint8Array,
): Promise<Blob> {
const algo = "AES-CBC";
// get an url to download the object
const downloadInfoResponse = await window.fetch(urlGenerator);
if (!downloadInfoResponse.ok) {
throw new Error(
"error while downloading url " +
downloadInfoResponse.status +
" " +
downloadInfoResponse.statusText,
);
}
throw new Error('Could not download document');
});
const downloadInfo = (await downloadInfoResponse.json()) as { url: string };
const rawResponse = await window.fetch(downloadInfo.url);
if (!rawResponse.ok) {
throw new Error(
"error while downloading raw file " +
rawResponse.status +
" " +
rawResponse.statusText,
);
}
if (iv.length === 0) {
console.log("returning document immediatly");
return rawResponse.blob();
}
console.log("start decrypting doc");
const rawBuffer = await rawResponse.arrayBuffer();
try {
const key = await window.crypto.subtle.importKey(
"jwk",
keyData,
{ name: algo },
false,
["decrypt"],
);
console.log("key created");
const decrypted = await window.crypto.subtle.decrypt(
{ name: algo, iv: iv },
key,
rawBuffer,
);
console.log("doc decrypted");
return Promise.resolve(new Blob([decrypted]));
} catch (e) {
console.error("get error while keys and decrypt operations");
console.error(e);
throw e;
}
}
async function download_and_decrypt_doc(urlGenerator: string, keyData: JsonWebKey, iv: Uint8Array): Promise<Blob>
{
const algo = 'AES-CBC';
// get an url to download the object
const downloadInfoResponse = await window.fetch(urlGenerator);
if (!downloadInfoResponse.ok) {
throw new Error("error while downloading url " + downloadInfoResponse.status + " " + downloadInfoResponse.statusText);
}
const downloadInfo = await downloadInfoResponse.json() as {url: string};
const rawResponse = await window.fetch(downloadInfo.url);
if (!rawResponse.ok) {
throw new Error("error while downloading raw file " + rawResponse.status + " " + rawResponse.statusText);
}
if (iv.length === 0) {
console.log('returning document immediatly');
return rawResponse.blob();
}
console.log('start decrypting doc');
const rawBuffer = await rawResponse.arrayBuffer();
try {
const key = await window.crypto.subtle
.importKey('jwk', keyData, { name: algo }, false, ['decrypt']);
console.log('key created');
const decrypted = await window.crypto.subtle
.decrypt({ name: algo, iv: iv }, key, rawBuffer);
console.log('doc decrypted');
return Promise.resolve(new Blob([decrypted]));
} catch (e) {
console.error('get error while keys and decrypt operations');
console.error(e);
throw e;
}
}
async function is_object_ready(storedObject: StoredObject): Promise<StoredObjectStatusChange>
{
const new_status_response = await window
.fetch( `/api/1.0/doc-store/stored-object/${storedObject.uuid}/is-ready`);
async function is_object_ready(
storedObject: StoredObject,
): Promise<StoredObjectStatusChange> {
const new_status_response = await window.fetch(
`/api/1.0/doc-store/stored-object/${storedObject.uuid}/is-ready`,
);
if (!new_status_response.ok) {
throw new Error("could not fetch the new status");
throw new Error("could not fetch the new status");
}
return await new_status_response.json();
}
export {
build_convert_link,
build_download_info_link,
build_wopi_editor_link,
download_and_decrypt_doc,
download_doc,
is_extension_editable,
is_extension_viewable,
is_object_ready,
build_convert_link,
build_download_info_link,
build_wopi_editor_link,
download_and_decrypt_doc,
download_doc,
is_extension_editable,
is_extension_viewable,
is_object_ready,
};