More automatic eslint fixes, update baseline and eslint docs

This commit is contained in:
Julie Lenaerts 2024-12-11 11:32:29 +01:00
parent e8962782ed
commit 16fe07cce7
14 changed files with 591 additions and 418 deletions

View File

@ -13,6 +13,18 @@ Interesting options are:
- ``--quiet`` to only get errors and silence the warnings - ``--quiet`` to only get errors and silence the warnings
- ``--fix`` to have ESLint fix what it can, automatically. This will not fix everything. - ``--fix`` to have ESLint fix what it can, automatically. This will not fix everything.
Baseline
--------
To allow us the time to fix linting errors/warnings a baseline has been created using the following command
- ``npx eslint-baseline "**/*.{js,vue}"``
The baseline has been commited and the gitlab CI setup to only fail upon new errors/warnings being created.
When fixing errors/warnings manually, please update the baseline.
1. Delete the current baseline file
2. Run the above command locally, this will automatically create a new baseline that should be commited
Rules Rules
----- -----

View File

@ -1,18 +1,19 @@
import {makeFetch} from "../../../../../ChillMainBundle/Resources/public/lib/api/apiMethods"; import { makeFetch } from "../../../../../ChillMainBundle/Resources/public/lib/api/apiMethods";
import {PostStoreObjectSignature, StoredObject} from "../../types"; import { PostStoreObjectSignature, StoredObject } from "../../types";
const algo = 'AES-CBC'; const algo = "AES-CBC";
const URL_POST = '/asyncupload/temp_url/generate/post'; const URL_POST = "/asyncupload/temp_url/generate/post";
const keyDefinition = { const keyDefinition = {
name: algo, name: algo,
length: 256 length: 256,
}; };
const createFilename = (): string => { const createFilename = (): string => {
var text = ""; let text = "";
var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; const possible =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
for (let i = 0; i < 7; i++) { for (let i = 0; i < 7; i++) {
text += possible.charAt(Math.floor(Math.random() * possible.length)); text += possible.charAt(Math.floor(Math.random() * possible.length));
@ -29,14 +30,22 @@ const createFilename = (): string => {
* @returns {Promise<StoredObject>} A Promise that resolves to the newly created StoredObject. * @returns {Promise<StoredObject>} A Promise that resolves to the newly created StoredObject.
*/ */
export const fetchNewStoredObject = async (): Promise<StoredObject> => { export const fetchNewStoredObject = async (): Promise<StoredObject> => {
return makeFetch("POST", '/api/1.0/doc-store/stored-object/create', null); return makeFetch("POST", "/api/1.0/doc-store/stored-object/create", null);
} };
export const uploadVersion = async (uploadFile: ArrayBuffer, storedObject: StoredObject): Promise<string> => { export const uploadVersion = async (
uploadFile: ArrayBuffer,
storedObject: StoredObject,
): Promise<string> => {
const params = new URLSearchParams(); const params = new URLSearchParams();
params.append('expires_delay', "180"); params.append("expires_delay", "180");
params.append('submit_delay', "180"); params.append("submit_delay", "180");
const asyncData: PostStoreObjectSignature = await makeFetch("GET", `/api/1.0/doc-store/async-upload/temp_url/${storedObject.uuid}/generate/post` + "?" + params.toString()); const asyncData: PostStoreObjectSignature = await makeFetch(
"GET",
`/api/1.0/doc-store/async-upload/temp_url/${storedObject.uuid}/generate/post` +
"?" +
params.toString(),
);
const suffix = createFilename(); const suffix = createFilename();
const filename = asyncData.prefix + suffix; const filename = asyncData.prefix + suffix;
const formData = new FormData(); const formData = new FormData();
@ -50,7 +59,7 @@ export const uploadVersion = async (uploadFile: ArrayBuffer, storedObject: Store
const response = await window.fetch(asyncData.url, { const response = await window.fetch(asyncData.url, {
method: "POST", method: "POST",
body: formData, body: formData,
}) });
if (!response.ok) { if (!response.ok) {
console.error("Error while sending file to store", response); console.error("Error while sending file to store", response);
@ -58,13 +67,22 @@ export const uploadVersion = async (uploadFile: ArrayBuffer, storedObject: Store
} }
return Promise.resolve(filename); return Promise.resolve(filename);
} };
export const encryptFile = async (originalFile: ArrayBuffer): Promise<[ArrayBuffer, Uint8Array, JsonWebKey]> => { export const encryptFile = async (
originalFile: ArrayBuffer,
): Promise<[ArrayBuffer, Uint8Array, JsonWebKey]> => {
const iv = crypto.getRandomValues(new Uint8Array(16)); const iv = crypto.getRandomValues(new Uint8Array(16));
const key = await window.crypto.subtle.generateKey(keyDefinition, true, [ "encrypt", "decrypt" ]); const key = await window.crypto.subtle.generateKey(keyDefinition, true, [
const exportedKey = await window.crypto.subtle.exportKey('jwk', key); "encrypt",
const encrypted = await window.crypto.subtle.encrypt({ name: algo, iv: iv}, key, originalFile); "decrypt",
]);
const exportedKey = await window.crypto.subtle.exportKey("jwk", key);
const encrypted = await window.crypto.subtle.encrypt(
{ name: algo, iv: iv },
key,
originalFile,
);
return Promise.resolve([encrypted, iv, exportedKey]); return Promise.resolve([encrypted, iv, exportedKey]);
}; };

View File

@ -1,18 +1,22 @@
import {CollectionEventPayload} from "../../../../../ChillMainBundle/Resources/public/module/collection"; import { CollectionEventPayload } from "../../../../../ChillMainBundle/Resources/public/module/collection";
import {createApp} from "vue"; import { createApp } from "vue";
import DropFileWidget from "../../vuejs/DropFileWidget/DropFileWidget.vue" import DropFileWidget from "../../vuejs/DropFileWidget/DropFileWidget.vue";
import {StoredObject, StoredObjectVersion} from "../../types"; import { StoredObject, StoredObjectVersion } from "../../types";
import {_createI18n} from "../../../../../ChillMainBundle/Resources/public/vuejs/_js/i18n"; import { _createI18n } from "../../../../../ChillMainBundle/Resources/public/vuejs/_js/i18n";
const i18n = _createI18n({}); const i18n = _createI18n({});
const startApp = (divElement: HTMLDivElement, collectionEntry: null|HTMLLIElement): void => { const startApp = (
console.log('app started', divElement); divElement: HTMLDivElement,
const input_stored_object: HTMLInputElement|null = divElement.querySelector("input[data-stored-object]"); collectionEntry: null | HTMLLIElement,
): void => {
console.log("app started", divElement);
const input_stored_object: HTMLInputElement | null =
divElement.querySelector("input[data-stored-object]");
if (null === input_stored_object) { if (null === input_stored_object) {
throw new Error('input to stored object not found'); throw new Error("input to stored object not found");
} }
let existingDoc: StoredObject|null = null; let existingDoc: StoredObject | null = null;
if (input_stored_object.value !== "") { if (input_stored_object.value !== "") {
existingDoc = JSON.parse(input_stored_object.value); existingDoc = JSON.parse(input_stored_object.value);
} }
@ -20,69 +24,87 @@ const startApp = (divElement: HTMLDivElement, collectionEntry: null|HTMLLIElemen
divElement.appendChild(app_container); divElement.appendChild(app_container);
const app = createApp({ const app = createApp({
template: '<drop-file-widget :existingDoc="this.$data.existingDoc" :allowRemove="true" @addDocument="this.addDocument" @removeDocument="removeDocument"></drop-file-widget>', template:
'<drop-file-widget :existingDoc="this.$data.existingDoc" :allowRemove="true" @addDocument="this.addDocument" @removeDocument="removeDocument"></drop-file-widget>',
data(vm) { data(vm) {
return { return {
existingDoc: existingDoc, existingDoc: existingDoc,
} };
}, },
components: { components: {
DropFileWidget, DropFileWidget,
}, },
methods: { methods: {
addDocument: function({stored_object, stored_object_version}: {stored_object: StoredObject, stored_object_version: StoredObjectVersion}): void { addDocument: function ({
console.log('object added', stored_object); stored_object,
console.log('version added', stored_object_version); stored_object_version,
}: {
stored_object: StoredObject;
stored_object_version: StoredObjectVersion;
}): void {
console.log("object added", stored_object);
console.log("version added", stored_object_version);
this.$data.existingDoc = stored_object; this.$data.existingDoc = stored_object;
this.$data.existingDoc.currentVersion = stored_object_version; this.$data.existingDoc.currentVersion = stored_object_version;
input_stored_object.value = JSON.stringify(this.$data.existingDoc); input_stored_object.value = JSON.stringify(
this.$data.existingDoc,
);
}, },
removeDocument: function(object: StoredObject): void { removeDocument: function (object: StoredObject): void {
console.log('catch remove document', object); console.log("catch remove document", object);
input_stored_object.value = ""; input_stored_object.value = "";
this.$data.existingDoc = undefined; this.$data.existingDoc = undefined;
console.log('collectionEntry', collectionEntry); console.log("collectionEntry", collectionEntry);
if (null !== collectionEntry) { if (null !== collectionEntry) {
console.log('will remove collection'); console.log("will remove collection");
collectionEntry.remove(); collectionEntry.remove();
} }
} },
} },
}); });
app.use(i18n).mount(app_container); app.use(i18n).mount(app_container);
} };
window.addEventListener('collection-add-entry', ((e: CustomEvent<CollectionEventPayload>) => { window.addEventListener("collection-add-entry", ((
e: CustomEvent<CollectionEventPayload>,
) => {
const detail = e.detail; const detail = e.detail;
const divElement: null|HTMLDivElement = detail.entry.querySelector('div[data-stored-object]'); const divElement: null | HTMLDivElement = detail.entry.querySelector(
"div[data-stored-object]",
);
if (null === divElement) { if (null === divElement) {
throw new Error('div[data-stored-object] not found'); throw new Error("div[data-stored-object] not found");
} }
startApp(divElement, detail.entry); startApp(divElement, detail.entry);
}) as EventListener); }) as EventListener);
window.addEventListener('DOMContentLoaded', () => { window.addEventListener("DOMContentLoaded", () => {
const upload_inputs: NodeListOf<HTMLDivElement> = document.querySelectorAll('div[data-stored-object]'); const upload_inputs: NodeListOf<HTMLDivElement> = document.querySelectorAll(
"div[data-stored-object]",
);
upload_inputs.forEach((input: HTMLDivElement): void => { upload_inputs.forEach((input: HTMLDivElement): void => {
// test for a parent to check if this is a collection entry // test for a parent to check if this is a collection entry
let collectionEntry: null|HTMLLIElement = null; let collectionEntry: null | HTMLLIElement = null;
let parent = input.parentElement; const parent = input.parentElement;
console.log('parent', parent); console.log("parent", parent);
if (null !== parent) { if (null !== parent) {
let grandParent = parent.parentElement; const grandParent = parent.parentElement;
console.log('grandParent', grandParent); console.log("grandParent", grandParent);
if (null !== grandParent) { if (null !== grandParent) {
if (grandParent.tagName.toLowerCase() === 'li' && grandParent.classList.contains('entry')) { if (
grandParent.tagName.toLowerCase() === "li" &&
grandParent.classList.contains("entry")
) {
collectionEntry = grandParent as HTMLLIElement; collectionEntry = grandParent as HTMLLIElement;
} }
} }
} }
startApp(input, collectionEntry); startApp(input, collectionEntry);
}) });
}); });
export {} export {};

View File

@ -1,27 +1,34 @@
import {_createI18n} from "../../../../../ChillMainBundle/Resources/public/vuejs/_js/i18n"; import { _createI18n } from "../../../../../ChillMainBundle/Resources/public/vuejs/_js/i18n";
import {createApp} from "vue"; import { createApp } from "vue";
import DocumentActionButtonsGroup from "../../vuejs/DocumentActionButtonsGroup.vue"; import DocumentActionButtonsGroup from "../../vuejs/DocumentActionButtonsGroup.vue";
import {StoredObject, StoredObjectStatusChange} from "../../types"; import { StoredObject, StoredObjectStatusChange } from "../../types";
import {defineComponent} from "vue"; import { defineComponent } from "vue";
import DownloadButton from "../../vuejs/StoredObjectButton/DownloadButton.vue"; import DownloadButton from "../../vuejs/StoredObjectButton/DownloadButton.vue";
import ToastPlugin from "vue-toast-notification"; import ToastPlugin from "vue-toast-notification";
const i18n = _createI18n({}); const i18n = _createI18n({});
window.addEventListener('DOMContentLoaded', function (e) { window.addEventListener("DOMContentLoaded", function (e) {
document.querySelectorAll<HTMLDivElement>('div[data-download-button-single]').forEach((el) => { document
const storedObject = JSON.parse(el.dataset.storedObject as string) as StoredObject; .querySelectorAll<HTMLDivElement>("div[data-download-button-single]")
const title = el.dataset.title as string; .forEach((el) => {
const app = createApp({ const storedObject = JSON.parse(
components: {DownloadButton}, el.dataset.storedObject as string,
data() { ) as StoredObject;
return {storedObject, title, classes: {btn: true, "btn-outline-primary": true}}; const title = el.dataset.title as string;
}, const app = createApp({
template: '<download-button :stored-object="storedObject" :at-version="storedObject.currentVersion" :classes="classes" :filename="title" :direct-download="true"></download-button>', components: { DownloadButton },
}); data() {
return {
storedObject,
title,
classes: { btn: true, "btn-outline-primary": true },
};
},
template:
'<download-button :stored-object="storedObject" :at-version="storedObject.currentVersion" :classes="classes" :filename="title" :direct-download="true"></download-button>',
});
app.use(i18n).use(ToastPlugin).mount(el); app.use(i18n).use(ToastPlugin).mount(el);
}); });
}); });

View File

@ -1,54 +1,73 @@
import {_createI18n} from "../../../../../ChillMainBundle/Resources/public/vuejs/_js/i18n"; import { _createI18n } from "../../../../../ChillMainBundle/Resources/public/vuejs/_js/i18n";
import DocumentActionButtonsGroup from "../../vuejs/DocumentActionButtonsGroup.vue"; import DocumentActionButtonsGroup from "../../vuejs/DocumentActionButtonsGroup.vue";
import {createApp} from "vue"; import { createApp } from "vue";
import {StoredObject, StoredObjectStatusChange} from "../../types"; import { StoredObject, StoredObjectStatusChange } from "../../types";
import {is_object_ready} from "../../vuejs/StoredObjectButton/helpers"; import { is_object_ready } from "../../vuejs/StoredObjectButton/helpers";
import ToastPlugin from "vue-toast-notification"; import ToastPlugin from "vue-toast-notification";
const i18n = _createI18n({}); const i18n = _createI18n({});
window.addEventListener('DOMContentLoaded', function (e) { window.addEventListener("DOMContentLoaded", function (e) {
document.querySelectorAll<HTMLDivElement>('div[data-download-buttons]').forEach((el) => { document
const app = createApp({ .querySelectorAll<HTMLDivElement>("div[data-download-buttons]")
components: {DocumentActionButtonsGroup}, .forEach((el) => {
data() { const app = createApp({
components: { DocumentActionButtonsGroup },
data() {
const datasets = el.dataset as {
filename: string;
canEdit: string;
storedObject: string;
buttonSmall: string;
davLink: string;
davLinkExpiration: string;
};
const datasets = el.dataset as { const storedObject = JSON.parse(
filename: string, datasets.storedObject,
canEdit: string, ) as StoredObject,
storedObject: string, filename = datasets.filename,
buttonSmall: string, canEdit = datasets.canEdit === "1",
davLink: string, small = datasets.buttonSmall === "1",
davLinkExpiration: string, davLink =
}; "davLink" in datasets && datasets.davLink !== ""
? datasets.davLink
: null,
davLinkExpiration =
"davLinkExpiration" in datasets
? Number.parseInt(datasets.davLinkExpiration)
: null;
return {
storedObject,
filename,
canEdit,
small,
davLink,
davLinkExpiration,
};
},
template:
'<document-action-buttons-group :can-edit="canEdit" :filename="filename" :stored-object="storedObject" :small="small" :dav-link="davLink" :dav-link-expiration="davLinkExpiration" @on-stored-object-status-change="onStoredObjectStatusChange"></document-action-buttons-group>',
methods: {
onStoredObjectStatusChange: function (
newStatus: StoredObjectStatusChange,
): void {
this.$data.storedObject.status = newStatus.status;
this.$data.storedObject.filename = newStatus.filename;
this.$data.storedObject.type = newStatus.type;
const // remove eventual div which inform pending status
storedObject = JSON.parse(datasets.storedObject) as StoredObject, document
filename = datasets.filename, .querySelectorAll(
canEdit = datasets.canEdit === '1', `[data-docgen-is-pending="${this.$data.storedObject.id}"]`,
small = datasets.buttonSmall === '1', )
davLink = 'davLink' in datasets && datasets.davLink !== '' ? datasets.davLink : null, .forEach(function (el) {
davLinkExpiration = 'davLinkExpiration' in datasets ? Number.parseInt(datasets.davLinkExpiration) : null el.remove();
; });
},
},
});
return { storedObject, filename, canEdit, small, davLink, davLinkExpiration }; app.use(i18n).use(ToastPlugin).mount(el);
}, });
template: '<document-action-buttons-group :can-edit="canEdit" :filename="filename" :stored-object="storedObject" :small="small" :dav-link="davLink" :dav-link-expiration="davLinkExpiration" @on-stored-object-status-change="onStoredObjectStatusChange"></document-action-buttons-group>',
methods: {
onStoredObjectStatusChange: function(newStatus: StoredObjectStatusChange): void {
this.$data.storedObject.status = newStatus.status;
this.$data.storedObject.filename = newStatus.filename;
this.$data.storedObject.type = newStatus.type;
// remove eventual div which inform pending status
document.querySelectorAll(`[data-docgen-is-pending="${this.$data.storedObject.id}"]`)
.forEach(function(el) {
el.remove();
});
}
}
});
app.use(i18n).use(ToastPlugin).mount(el);
})
}); });

View File

@ -2,7 +2,7 @@ import {
DateTime, DateTime,
User, User,
} from "../../../ChillMainBundle/Resources/public/types"; } from "../../../ChillMainBundle/Resources/public/types";
import {SignedUrlGet} from "./vuejs/StoredObjectButton/helpers"; import { SignedUrlGet } from "./vuejs/StoredObjectButton/helpers";
export type StoredObjectStatus = "empty" | "ready" | "failure" | "pending"; export type StoredObjectStatus = "empty" | "ready" | "failure" | "pending";
@ -64,23 +64,22 @@ export interface StoredObjectStatusChange {
type: string; type: string;
} }
export interface StoredObjectVersionWithPointInTime extends StoredObjectVersionPersisted { export interface StoredObjectVersionWithPointInTime
extends StoredObjectVersionPersisted {
"point-in-times": StoredObjectPointInTime[]; "point-in-times": StoredObjectPointInTime[];
"from-restored": StoredObjectVersionPersisted|null; "from-restored": StoredObjectVersionPersisted | null;
} }
export interface StoredObjectPointInTime { export interface StoredObjectPointInTime {
id: number; id: number;
byUser: User | null; byUser: User | null;
reason: 'keep-before-conversion'|'keep-by-user'; reason: "keep-before-conversion" | "keep-by-user";
} }
/** /**
* Function executed by the WopiEditButton component. * Function executed by the WopiEditButton component.
*/ */
export type WopiEditButtonExecutableBeforeLeaveFunction = { export type WopiEditButtonExecutableBeforeLeaveFunction = () => Promise<void>;
(): Promise<void>;
};
/** /**
* Object containing information for performering a POST request to a swift object store * Object containing information for performering a POST request to a swift object store
@ -135,7 +134,7 @@ export interface ZoomLevel {
id: number; id: number;
zoom: number; zoom: number;
label: { label: {
fr?: string, fr?: string;
nl?: string nl?: string;
}; };
} }

View File

@ -5,29 +5,29 @@ import App from "./App.vue";
const appMessages = { const appMessages = {
fr: { fr: {
yes: 'Oui', yes: "Oui",
are_you_sure: 'Êtes-vous sûr·e?', are_you_sure: "Êtes-vous sûr·e?",
you_are_going_to_sign: 'Vous allez signer le document', you_are_going_to_sign: "Vous allez signer le document",
signature_confirmation: 'Confirmation de la signature', signature_confirmation: "Confirmation de la signature",
sign: 'Signer', sign: "Signer",
choose_another_signature: 'Choisir une autre zone', choose_another_signature: "Choisir une autre zone",
cancel: 'Annuler', cancel: "Annuler",
last_sign_zone: 'Zone de signature précédente', last_sign_zone: "Zone de signature précédente",
next_sign_zone: 'Zone de signature suivante', next_sign_zone: "Zone de signature suivante",
add_sign_zone: 'Ajouter une zone de signature', add_sign_zone: "Ajouter une zone de signature",
click_on_document: 'Cliquer sur le document', click_on_document: "Cliquer sur le document",
last_zone: 'Zone précédente', last_zone: "Zone précédente",
next_zone: 'Zone suivante', next_zone: "Zone suivante",
add_zone: 'Ajouter une zone', add_zone: "Ajouter une zone",
another_zone: 'Autre zone', another_zone: "Autre zone",
electronic_signature_in_progress: 'Signature électronique en cours...', electronic_signature_in_progress: "Signature électronique en cours...",
loading: 'Chargement...', loading: "Chargement...",
remove_sign_zone: 'Enlever la zone', remove_sign_zone: "Enlever la zone",
return: 'Retour', return: "Retour",
see_all_pages: 'Voir toutes les pages', see_all_pages: "Voir toutes les pages",
all_pages: 'Toutes les pages', all_pages: "Toutes les pages",
} },
} };
const i18n = _createI18n(appMessages); const i18n = _createI18n(appMessages);

View File

@ -1,12 +1,33 @@
import {StoredObject, StoredObjectVersionPersisted, StoredObjectVersionWithPointInTime} from "../../../types"; import {
import {fetchResults, makeFetch} from "../../../../../../ChillMainBundle/Resources/public/lib/api/apiMethods"; StoredObject,
StoredObjectVersionPersisted,
StoredObjectVersionWithPointInTime,
} from "../../../types";
import {
fetchResults,
makeFetch,
} from "../../../../../../ChillMainBundle/Resources/public/lib/api/apiMethods";
export const get_versions = async (storedObject: StoredObject): Promise<StoredObjectVersionWithPointInTime[]> => { export const get_versions = async (
const versions = await fetchResults<StoredObjectVersionWithPointInTime>(`/api/1.0/doc-store/stored-object/${storedObject.uuid}/versions`); storedObject: StoredObject,
): Promise<StoredObjectVersionWithPointInTime[]> => {
const versions = await fetchResults<StoredObjectVersionWithPointInTime>(
`/api/1.0/doc-store/stored-object/${storedObject.uuid}/versions`,
);
return versions.sort((a: StoredObjectVersionWithPointInTime, b: StoredObjectVersionWithPointInTime) => b.version - a.version); return versions.sort(
} (
a: StoredObjectVersionWithPointInTime,
b: StoredObjectVersionWithPointInTime,
) => b.version - a.version,
);
};
export const restore_version = async (version: StoredObjectVersionPersisted): Promise<StoredObjectVersionWithPointInTime> => { export const restore_version = async (
return await makeFetch<null, StoredObjectVersionWithPointInTime>("POST", `/api/1.0/doc-store/stored-object/restore-from-version/${version.id}`); version: StoredObjectVersionPersisted,
} ): Promise<StoredObjectVersionWithPointInTime> => {
return await makeFetch<null, StoredObjectVersionWithPointInTime>(
"POST",
`/api/1.0/doc-store/stored-object/restore-from-version/${version.id}`,
);
};

View File

@ -1,200 +1,235 @@
import {StoredObject, StoredObjectStatus, StoredObjectStatusChange, StoredObjectVersion} from "../../types"; import {
import {makeFetch} from "../../../../../ChillMainBundle/Resources/public/lib/api/apiMethods"; StoredObject,
StoredObjectStatus,
StoredObjectStatusChange,
StoredObjectVersion,
} from "../../types";
import { makeFetch } from "../../../../../ChillMainBundle/Resources/public/lib/api/apiMethods";
const MIMES_EDIT = new Set([ const MIMES_EDIT = new Set([
'application/vnd.ms-powerpoint', "application/vnd.ms-powerpoint",
'application/vnd.ms-excel', "application/vnd.ms-excel",
'application/vnd.oasis.opendocument.text', "application/vnd.oasis.opendocument.text",
'application/vnd.oasis.opendocument.text-flat-xml', "application/vnd.oasis.opendocument.text-flat-xml",
'application/vnd.oasis.opendocument.spreadsheet', "application/vnd.oasis.opendocument.spreadsheet",
'application/vnd.oasis.opendocument.spreadsheet-flat-xml', "application/vnd.oasis.opendocument.spreadsheet-flat-xml",
'application/vnd.oasis.opendocument.presentation', "application/vnd.oasis.opendocument.presentation",
'application/vnd.oasis.opendocument.presentation-flat-xml', "application/vnd.oasis.opendocument.presentation-flat-xml",
'application/vnd.oasis.opendocument.graphics', "application/vnd.oasis.opendocument.graphics",
'application/vnd.oasis.opendocument.graphics-flat-xml', "application/vnd.oasis.opendocument.graphics-flat-xml",
'application/vnd.oasis.opendocument.chart', "application/vnd.oasis.opendocument.chart",
'application/msword', "application/msword",
'application/vnd.ms-excel', "application/vnd.ms-excel",
'application/vnd.ms-powerpoint', "application/vnd.ms-powerpoint",
'application/vnd.openxmlformats-officedocument.wordprocessingml.document', "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
'application/vnd.ms-word.document.macroEnabled.12', "application/vnd.ms-word.document.macroEnabled.12",
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
'application/vnd.ms-excel.sheet.binary.macroEnabled.12', "application/vnd.ms-excel.sheet.binary.macroEnabled.12",
'application/vnd.ms-excel.sheet.macroEnabled.12', "application/vnd.ms-excel.sheet.macroEnabled.12",
'application/vnd.openxmlformats-officedocument.presentationml.presentation', "application/vnd.openxmlformats-officedocument.presentationml.presentation",
'application/vnd.ms-powerpoint.presentation.macroEnabled.12', "application/vnd.ms-powerpoint.presentation.macroEnabled.12",
'application/x-dif-document', "application/x-dif-document",
'text/spreadsheet', "text/spreadsheet",
'text/csv', "text/csv",
'application/x-dbase', "application/x-dbase",
'text/rtf', "text/rtf",
'text/plain', "text/plain",
'application/vnd.openxmlformats-officedocument.presentationml.slideshow', "application/vnd.openxmlformats-officedocument.presentationml.slideshow",
]); ]);
const MIMES_VIEW = new Set([ const MIMES_VIEW = new Set([
...MIMES_EDIT, ...MIMES_EDIT,
[ [
'image/svg+xml', "image/svg+xml",
'application/vnd.sun.xml.writer', "application/vnd.sun.xml.writer",
'application/vnd.sun.xml.calc', "application/vnd.sun.xml.calc",
'application/vnd.sun.xml.impress', "application/vnd.sun.xml.impress",
'application/vnd.sun.xml.draw', "application/vnd.sun.xml.draw",
'application/vnd.sun.xml.writer.global', "application/vnd.sun.xml.writer.global",
'application/vnd.sun.xml.writer.template', "application/vnd.sun.xml.writer.template",
'application/vnd.sun.xml.calc.template', "application/vnd.sun.xml.calc.template",
'application/vnd.sun.xml.impress.template', "application/vnd.sun.xml.impress.template",
'application/vnd.sun.xml.draw.template', "application/vnd.sun.xml.draw.template",
'application/vnd.oasis.opendocument.text-master', "application/vnd.oasis.opendocument.text-master",
'application/vnd.oasis.opendocument.text-template', "application/vnd.oasis.opendocument.text-template",
'application/vnd.oasis.opendocument.text-master-template', "application/vnd.oasis.opendocument.text-master-template",
'application/vnd.oasis.opendocument.spreadsheet-template', "application/vnd.oasis.opendocument.spreadsheet-template",
'application/vnd.oasis.opendocument.presentation-template', "application/vnd.oasis.opendocument.presentation-template",
'application/vnd.oasis.opendocument.graphics-template', "application/vnd.oasis.opendocument.graphics-template",
'application/vnd.ms-word.template.macroEnabled.12', "application/vnd.ms-word.template.macroEnabled.12",
'application/vnd.openxmlformats-officedocument.spreadsheetml.template', "application/vnd.openxmlformats-officedocument.spreadsheetml.template",
'application/vnd.ms-excel.template.macroEnabled.12', "application/vnd.ms-excel.template.macroEnabled.12",
'application/vnd.openxmlformats-officedocument.presentationml.template', "application/vnd.openxmlformats-officedocument.presentationml.template",
'application/vnd.ms-powerpoint.template.macroEnabled.12', "application/vnd.ms-powerpoint.template.macroEnabled.12",
'application/vnd.wordperfect', "application/vnd.wordperfect",
'application/x-aportisdoc', "application/x-aportisdoc",
'application/x-hwp', "application/x-hwp",
'application/vnd.ms-works', "application/vnd.ms-works",
'application/x-mswrite', "application/x-mswrite",
'application/vnd.lotus-1-2-3', "application/vnd.lotus-1-2-3",
'image/cgm', "image/cgm",
'image/vnd.dxf', "image/vnd.dxf",
'image/x-emf', "image/x-emf",
'image/x-wmf', "image/x-wmf",
'application/coreldraw', "application/coreldraw",
'application/vnd.visio2013', "application/vnd.visio2013",
'application/vnd.visio', "application/vnd.visio",
'application/vnd.ms-visio.drawing', "application/vnd.ms-visio.drawing",
'application/x-mspublisher', "application/x-mspublisher",
'application/x-sony-bbeb', "application/x-sony-bbeb",
'application/x-gnumeric', "application/x-gnumeric",
'application/macwriteii', "application/macwriteii",
'application/x-iwork-numbers-sffnumbers', "application/x-iwork-numbers-sffnumbers",
'application/vnd.oasis.opendocument.text-web', "application/vnd.oasis.opendocument.text-web",
'application/x-pagemaker', "application/x-pagemaker",
'application/x-fictionbook+xml', "application/x-fictionbook+xml",
'application/clarisworks', "application/clarisworks",
'image/x-wpg', "image/x-wpg",
'application/x-iwork-pages-sffpages', "application/x-iwork-pages-sffpages",
'application/x-iwork-keynote-sffkey', "application/x-iwork-keynote-sffkey",
'application/x-abiword', "application/x-abiword",
'image/x-freehand', "image/x-freehand",
'application/vnd.sun.xml.chart', "application/vnd.sun.xml.chart",
'application/x-t602', "application/x-t602",
'image/bmp', "image/bmp",
'image/png', "image/png",
'image/gif', "image/gif",
'image/tiff', "image/tiff",
'image/jpg', "image/jpg",
'image/jpeg', "image/jpeg",
'application/pdf', "application/pdf",
] ],
]) ]);
export interface SignedUrlGet { export interface SignedUrlGet {
method: 'GET'|'HEAD', method: "GET" | "HEAD";
url: string, url: string;
expires: number, expires: number;
object_name: string, object_name: string;
} }
function is_extension_editable(mimeType: string): boolean { function is_extension_editable(mimeType: string): boolean {
return MIMES_EDIT.has(mimeType); return MIMES_EDIT.has(mimeType);
} }
function is_extension_viewable(mimeType: string): boolean { function is_extension_viewable(mimeType: string): boolean {
return MIMES_VIEW.has(mimeType); return MIMES_VIEW.has(mimeType);
} }
function build_convert_link(uuid: string) { function build_convert_link(uuid: string) {
return `/chill/wopi/convert/${uuid}`; return `/chill/wopi/convert/${uuid}`;
} }
function build_download_info_link(storedObject: StoredObject, atVersion: null|StoredObjectVersion): string { function build_download_info_link(
storedObject: StoredObject,
atVersion: null | StoredObjectVersion,
): string {
const url = `/api/1.0/doc-store/async-upload/temp_url/${storedObject.uuid}/generate/get`; const url = `/api/1.0/doc-store/async-upload/temp_url/${storedObject.uuid}/generate/get`;
if (null !== atVersion) { if (null !== atVersion) {
const params = new URLSearchParams({version: atVersion.filename}); const params = new URLSearchParams({ version: atVersion.filename });
return url + '?' + params.toString(); return url + "?" + params.toString();
} }
return url; return url;
} }
async function download_info_link(storedObject: StoredObject, atVersion: null|StoredObjectVersion): Promise<SignedUrlGet> { async function download_info_link(
return makeFetch('GET', build_download_info_link(storedObject, atVersion)); storedObject: StoredObject,
atVersion: null | StoredObjectVersion,
): Promise<SignedUrlGet> {
return makeFetch("GET", build_download_info_link(storedObject, atVersion));
} }
function build_wopi_editor_link(uuid: string, returnPath?: string) { function build_wopi_editor_link(uuid: string, returnPath?: string) {
if (returnPath === undefined) { if (returnPath === undefined) {
returnPath = window.location.pathname + window.location.search + window.location.hash; 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> { function download_doc(url: string): Promise<Blob> {
return window.fetch(url).then(r => { return window.fetch(url).then((r) => {
if (r.ok) { if (r.ok) {
return r.blob() return r.blob();
} }
throw new Error('Could not download document'); throw new Error("Could not download document");
}); });
} }
async function download_and_decrypt_doc(storedObject: StoredObject, atVersion: null|StoredObjectVersion): Promise<Blob> async function download_and_decrypt_doc(
{ storedObject: StoredObject,
const algo = 'AES-CBC'; atVersion: null | StoredObjectVersion,
): Promise<Blob> {
const algo = "AES-CBC";
const atVersionToDownload = atVersion ?? storedObject.currentVersion; const atVersionToDownload = atVersion ?? storedObject.currentVersion;
if (null === atVersionToDownload) { if (null === atVersionToDownload) {
throw new Error("no version associated to stored object"); throw new Error("no version associated to stored object");
}
// sometimes, the downloadInfo may be embedded into the storedObject
console.log('storedObject', storedObject);
let downloadInfo;
if (typeof storedObject._links !== 'undefined' && typeof storedObject._links.downloadLink !== 'undefined') {
downloadInfo = storedObject._links.downloadLink;
} else {
downloadInfo = await download_info_link(storedObject, atVersionToDownload);
} }
const rawResponse = await window.fetch(downloadInfo.url); // sometimes, the downloadInfo may be embedded into the storedObject
console.log("storedObject", storedObject);
let downloadInfo;
if (
typeof storedObject._links !== "undefined" &&
typeof storedObject._links.downloadLink !== "undefined"
) {
downloadInfo = storedObject._links.downloadLink;
} else {
downloadInfo = await download_info_link(
storedObject,
atVersionToDownload,
);
}
if (!rawResponse.ok) { const rawResponse = await window.fetch(downloadInfo.url);
throw new Error("error while downloading raw file " + rawResponse.status + " " + rawResponse.statusText);
}
if (atVersionToDownload.iv.length === 0) { if (!rawResponse.ok) {
return rawResponse.blob(); throw new Error(
} "error while downloading raw file " +
rawResponse.status +
" " +
rawResponse.statusText,
);
}
const rawBuffer = await rawResponse.arrayBuffer(); if (atVersionToDownload.iv.length === 0) {
try { return rawResponse.blob();
const key = await window.crypto.subtle }
.importKey('jwk', atVersionToDownload.keyInfos, { name: algo }, false, ['decrypt']);
const iv = Uint8Array.from(atVersionToDownload.iv);
const decrypted = await window.crypto.subtle
.decrypt({ name: algo, iv: iv }, key, rawBuffer);
return Promise.resolve(new Blob([decrypted])); const rawBuffer = await rawResponse.arrayBuffer();
} catch (e) { try {
console.error('encounter error while keys and decrypt operations'); const key = await window.crypto.subtle.importKey(
console.error(e); "jwk",
atVersionToDownload.keyInfos,
{ name: algo },
false,
["decrypt"],
);
const iv = Uint8Array.from(atVersionToDownload.iv);
const decrypted = await window.crypto.subtle.decrypt(
{ name: algo, iv: iv },
key,
rawBuffer,
);
throw e; return Promise.resolve(new Blob([decrypted]));
} } catch (e) {
console.error("encounter error while keys and decrypt operations");
console.error(e);
throw e;
}
} }
/** /**
@ -203,14 +238,16 @@ async function download_and_decrypt_doc(storedObject: StoredObject, atVersion: n
* If the document is already in a pdf on the server side, the document is retrieved "as is" from the usual * If the document is already in a pdf on the server side, the document is retrieved "as is" from the usual
* storage. * storage.
*/ */
async function download_doc_as_pdf(storedObject: StoredObject): Promise<Blob> async function download_doc_as_pdf(storedObject: StoredObject): Promise<Blob> {
{
if (null === storedObject.currentVersion) { if (null === storedObject.currentVersion) {
throw new Error("the stored object does not count any version"); throw new Error("the stored object does not count any version");
} }
if (storedObject.currentVersion?.type === 'application/pdf') { if (storedObject.currentVersion?.type === "application/pdf") {
return download_and_decrypt_doc(storedObject, storedObject.currentVersion); return download_and_decrypt_doc(
storedObject,
storedObject.currentVersion,
);
} }
const convertLink = build_convert_link(storedObject.uuid); const convertLink = build_convert_link(storedObject.uuid);
@ -223,25 +260,27 @@ async function download_doc_as_pdf(storedObject: StoredObject): Promise<Blob>
return response.blob(); return response.blob();
} }
async function is_object_ready(storedObject: StoredObject): Promise<StoredObjectStatusChange> async function is_object_ready(
{ storedObject: StoredObject,
const new_status_response = await window ): Promise<StoredObjectStatusChange> {
.fetch( `/api/1.0/doc-store/stored-object/${storedObject.uuid}/is-ready`); const new_status_response = await window.fetch(
`/api/1.0/doc-store/stored-object/${storedObject.uuid}/is-ready`,
);
if (!new_status_response.ok) { 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(); return await new_status_response.json();
} }
export { export {
build_convert_link, build_convert_link,
build_wopi_editor_link, build_wopi_editor_link,
download_and_decrypt_doc, download_and_decrypt_doc,
download_doc, download_doc,
download_doc_as_pdf, download_doc_as_pdf,
is_extension_editable, is_extension_editable,
is_extension_viewable, is_extension_viewable,
is_object_ready, is_object_ready,
}; };

View File

@ -9,14 +9,18 @@
* *
* @throws {Error} If the related entity ID is undefined. * @throws {Error} If the related entity ID is undefined.
*/ */
export const buildLinkCreate = (workflowName: string, relatedEntityClass: string, relatedEntityId: number|undefined): string => { export const buildLinkCreate = (
if (typeof (relatedEntityId) === 'undefined') { workflowName: string,
relatedEntityClass: string,
relatedEntityId: number | undefined,
): string => {
if (typeof relatedEntityId === "undefined") {
throw new Error("the related entity id is not set"); throw new Error("the related entity id is not set");
} }
let params = new URLSearchParams(); const params = new URLSearchParams();
params.set('entityClass', relatedEntityClass); params.set("entityClass", relatedEntityClass);
params.set('entityId', relatedEntityId.toString(10)); params.set("entityId", relatedEntityId.toString(10));
params.set('workflow', workflowName); params.set("workflow", workflowName);
return `/fr/main/workflow/create?`+params.toString(); return `/fr/main/workflow/create?` + params.toString();
}; };

View File

@ -28,11 +28,15 @@
* }); * });
* ``` * ```
*/ */
import './collection.scss'; import "./collection.scss";
declare global { declare global {
interface GlobalEventHandlersEventMap { interface GlobalEventHandlersEventMap {
'show-hide-show': CustomEvent<{id: number, froms: HTMLElement[], container: HTMLElement}>, "show-hide-show": CustomEvent<{
id: number;
froms: HTMLElement[];
container: HTMLElement;
}>;
} }
} }
@ -47,27 +51,31 @@ export class CollectionEventPayload {
} }
export const handleAdd = (button: any): void => { export const handleAdd = (button: any): void => {
let const form_name = button.dataset.collectionAddTarget,
form_name = button.dataset.collectionAddTarget,
prototype = button.dataset.formPrototype, prototype = button.dataset.formPrototype,
collection: HTMLUListElement | null = document.querySelector('ul[data-collection-name="' + form_name + '"]'); collection: HTMLUListElement | null = document.querySelector(
'ul[data-collection-name="' + form_name + '"]',
);
if (collection === null) { if (collection === null) {
return; return;
} }
let const empty_explain: HTMLLIElement | null = collection.querySelector(
empty_explain: HTMLLIElement | null = collection.querySelector('li[data-collection-empty-explain]'), "li[data-collection-empty-explain]",
entry = document.createElement('li'), ),
counter = collection.querySelectorAll('li.entry').length, // Updated counter logic entry = document.createElement("li"),
counter = collection.querySelectorAll("li.entry").length, // Updated counter logic
content = prototype.replace(/__name__/g, counter.toString()), content = prototype.replace(/__name__/g, counter.toString()),
event = new CustomEvent('collection-add-entry', {detail: new CollectionEventPayload(collection, entry)}); event = new CustomEvent("collection-add-entry", {
detail: new CollectionEventPayload(collection, entry),
});
console.log(counter) console.log(counter);
console.log(content) console.log(content);
entry.innerHTML = content; entry.innerHTML = content;
entry.classList.add('entry'); entry.classList.add("entry");
if ("collectionRegular" in collection.dataset) { if ("collectionRegular" in collection.dataset) {
initializeRemove(collection, entry); initializeRemove(collection, entry);
@ -81,7 +89,10 @@ export const handleAdd = (button: any): void => {
window.dispatchEvent(event); window.dispatchEvent(event);
}; };
const initializeRemove = (collection: HTMLUListElement, entry: HTMLLIElement): void => { const initializeRemove = (
collection: HTMLUListElement,
entry: HTMLLIElement,
): void => {
const button = buildRemoveButton(collection, entry); const button = buildRemoveButton(collection, entry);
if (null === button) { if (null === button) {
return; return;
@ -89,21 +100,24 @@ const initializeRemove = (collection: HTMLUListElement, entry: HTMLLIElement): v
entry.appendChild(button); entry.appendChild(button);
}; };
export const buildRemoveButton = (collection: HTMLUListElement, entry: HTMLLIElement): HTMLButtonElement|null => { export const buildRemoveButton = (
collection: HTMLUListElement,
entry: HTMLLIElement,
): HTMLButtonElement | null => {
const button = document.createElement("button"),
isPersisted = entry.dataset.collectionIsPersisted || "",
content = collection.dataset.collectionButtonRemoveLabel || "",
allowDelete = collection.dataset.collectionAllowDelete || "",
event = new CustomEvent("collection-remove-entry", {
detail: new CollectionEventPayload(collection, entry),
});
let if (allowDelete === "0" && isPersisted === "1") {
button = document.createElement('button'),
isPersisted = entry.dataset.collectionIsPersisted || '',
content = collection.dataset.collectionButtonRemoveLabel || '',
allowDelete = collection.dataset.collectionAllowDelete || '',
event = new CustomEvent('collection-remove-entry', {detail: new CollectionEventPayload(collection, entry)});
if (allowDelete === '0' && isPersisted === '1') {
return null; return null;
} }
button.classList.add('btn', 'btn-delete', 'remove-entry'); button.classList.add("btn", "btn-delete", "remove-entry");
button.textContent = content; button.textContent = content;
button.addEventListener('click', (e: Event) => { button.addEventListener("click", (e: Event) => {
e.preventDefault(); e.preventDefault();
entry.remove(); entry.remove();
collection.dispatchEvent(event); collection.dispatchEvent(event);
@ -111,15 +125,18 @@ export const buildRemoveButton = (collection: HTMLUListElement, entry: HTMLLIEle
}); });
return button; return button;
} };
const collectionsInit = new Set<string>; const collectionsInit = new Set<string>();
const buttonsInit = new Set<string>(); const buttonsInit = new Set<string>();
const initialize = function (target: Document|Element): void { const initialize = function (target: Document | Element): void {
let const addButtons: NodeListOf<HTMLButtonElement> = document.querySelectorAll(
addButtons: NodeListOf<HTMLButtonElement> = document.querySelectorAll("button[data-collection-add-target]"), "button[data-collection-add-target]",
collections: NodeListOf<HTMLUListElement> = document.querySelectorAll("ul[data-collection-regular]"); ),
collections: NodeListOf<HTMLUListElement> = document.querySelectorAll(
"ul[data-collection-regular]",
);
for (let i = 0; i < addButtons.length; i++) { for (let i = 0; i < addButtons.length; i++) {
const addButton = addButtons[i]; const addButton = addButtons[i];
@ -128,7 +145,7 @@ const initialize = function (target: Document|Element): void {
continue; continue;
} }
buttonsInit.add(uniqid); buttonsInit.add(uniqid);
addButton.addEventListener('click', (e: Event) => { addButton.addEventListener("click", (e: Event) => {
e.preventDefault(); e.preventDefault();
handleAdd(e.target); handleAdd(e.target);
}); });
@ -140,7 +157,8 @@ const initialize = function (target: Document|Element): void {
continue; continue;
} }
collectionsInit.add(uniqid); collectionsInit.add(uniqid);
let entries: NodeListOf<HTMLLIElement> = collection.querySelectorAll(':scope > li'); const entries: NodeListOf<HTMLLIElement> =
collection.querySelectorAll(":scope > li");
for (let j = 0; j < entries.length; j++) { for (let j = 0; j < entries.length; j++) {
if (entries[j].dataset.collectionEmptyExplain === "1") { if (entries[j].dataset.collectionEmptyExplain === "1") {
continue; continue;
@ -150,11 +168,20 @@ const initialize = function (target: Document|Element): void {
} }
}; };
window.addEventListener('DOMContentLoaded', () => { window.addEventListener("DOMContentLoaded", () => {
initialize(document); initialize(document);
}); });
window.addEventListener('show-hide-show', (event: CustomEvent<{id: number; container: HTMLElement; froms: HTMLElement[]}>) => { window.addEventListener(
const container = event.detail.container as HTMLElement; "show-hide-show",
initialize(container); (
}) event: CustomEvent<{
id: number;
container: HTMLElement;
froms: HTMLElement[];
}>,
) => {
const container = event.detail.container as HTMLElement;
initialize(container);
},
);

View File

@ -64,10 +64,10 @@ export interface UserAssociatedInterface {
id: number; id: number;
} }
export type TranslatableString = { export interface TranslatableString {
fr?: string; fr?: string;
nl?: string; nl?: string;
}; }
export interface Postcode { export interface Postcode {
id: number; id: number;
@ -76,10 +76,10 @@ export interface Postcode {
center: Point; center: Point;
} }
export type Point = { export interface Point {
type: "Point"; type: "Point";
coordinates: [lat: number, lon: number]; coordinates: [lat: number, lon: number];
}; }
export interface Country { export interface Country {
id: number; id: number;

View File

@ -1,43 +1,43 @@
import { import {
Address, Address,
Center, Center,
Civility, Civility,
DateTime, DateTime,
User, User,
WorkflowAvailable WorkflowAvailable,
} from "../../../ChillMainBundle/Resources/public/types"; } from "../../../ChillMainBundle/Resources/public/types";
import {StoredObject} from "../../../ChillDocStoreBundle/Resources/public/types"; import { StoredObject } from "../../../ChillDocStoreBundle/Resources/public/types";
export interface Person { export interface Person {
id: number; id: number;
type: "person"; type: "person";
text: string; text: string;
textAge: string; textAge: string;
firstName: string; firstName: string;
lastName: string; lastName: string;
current_household_address: Address | null; current_household_address: Address | null;
birthdate: DateTime | null; birthdate: DateTime | null;
deathdate: DateTime | null; deathdate: DateTime | null;
age: number; age: number;
phonenumber: string; phonenumber: string;
mobilenumber: string; mobilenumber: string;
email: string; email: string;
gender: "woman" | "man" | "other"; gender: "woman" | "man" | "other";
centers: Center[]; centers: Center[];
civility: Civility | null; civility: Civility | null;
current_household_id: number; current_household_id: number;
current_residential_addresses: Address[]; current_residential_addresses: Address[];
} }
export interface AccompanyingPeriodWorkEvaluationDocument { export interface AccompanyingPeriodWorkEvaluationDocument {
id: number; id: number;
type: "accompanying_period_work_evaluation_document" type: "accompanying_period_work_evaluation_document";
storedObject: StoredObject; storedObject: StoredObject;
title: string; title: string;
createdAt: DateTime | null; createdAt: DateTime | null;
createdBy: User | null; createdBy: User | null;
updatedAt: DateTime | null; updatedAt: DateTime | null;
updatedBy: User | null; updatedBy: User | null;
workflows_availables: WorkflowAvailable[]; workflows_availables: WorkflowAvailable[];
workflows: object[]; workflows: object[];
} }

View File

@ -1,6 +1,11 @@
import {AccompanyingPeriodWorkEvaluationDocument} from "../../types"; import { AccompanyingPeriodWorkEvaluationDocument } from "../../types";
import {makeFetch} from "../../../../../ChillMainBundle/Resources/public/lib/api/apiMethods"; import { makeFetch } from "../../../../../ChillMainBundle/Resources/public/lib/api/apiMethods";
export const duplicate = async (id: number): Promise<AccompanyingPeriodWorkEvaluationDocument> => { export const duplicate = async (
return makeFetch<null, AccompanyingPeriodWorkEvaluationDocument>("POST", `/api/1.0/person/accompanying-course-work-evaluation-document/${id}/duplicate`); id: number,
} ): Promise<AccompanyingPeriodWorkEvaluationDocument> => {
return makeFetch<null, AccompanyingPeriodWorkEvaluationDocument>(
"POST",
`/api/1.0/person/accompanying-course-work-evaluation-document/${id}/duplicate`,
);
};