diff --git a/lib/RoadizRozierBundle/src/Controller/Document/DocumentAdjustController.php b/lib/RoadizRozierBundle/src/Controller/Document/DocumentAdjustController.php index 2db074a6c..07ef91547 100644 --- a/lib/RoadizRozierBundle/src/Controller/Document/DocumentAdjustController.php +++ b/lib/RoadizRozierBundle/src/Controller/Document/DocumentAdjustController.php @@ -82,6 +82,20 @@ public function adjustAction(Request $request, int $documentId): Response /** @var UploadedFile $uploadedFile */ $uploadedFile = $fileForm->get('editDocument')->getData(); + + $uploadedFileMimeType = $uploadedFile->getMimeType(); + if ( + \is_string($uploadedFileMimeType) + && \str_starts_with($uploadedFileMimeType, 'image/') + && 'image/svg+xml' !== $uploadedFileMimeType + ) { + $imageSize = \getimagesize($uploadedFile->getPathname()); + if (\is_array($imageSize)) { + $document->setImageWidth((int) $imageSize[0]); + $document->setImageHeight((int) $imageSize[1]); + } + } + $this->documentFactory->setFile($uploadedFile); $this->documentFactory->updateDocument($document); $em->flush(); @@ -103,6 +117,8 @@ public function adjustAction(Request $request, int $documentId): Response return new JsonResponse([ 'message' => $msg, 'path' => $this->documentsStorage->publicUrl($mountPath).'?'.\random_int(10, 999), + 'imageWidth' => $document->getImageWidth(), + 'imageHeight' => $document->getImageHeight(), ]); } diff --git a/lib/RoadizRozierBundle/src/TwigExtension/RozierExtension.php b/lib/RoadizRozierBundle/src/TwigExtension/RozierExtension.php index 1a5b5f7d4..00a3117e3 100644 --- a/lib/RoadizRozierBundle/src/TwigExtension/RozierExtension.php +++ b/lib/RoadizRozierBundle/src/TwigExtension/RozierExtension.php @@ -180,8 +180,6 @@ public function getNodeSourceHref(mixed $node, ?TranslationInterface $translatio return null; } - /** @var NodeInterface&object{isHidingChildren(): bool} $node */ - if ($node->isHidingChildren()) { return $this->urlGenerator->generate('nodesTreePage', [ 'nodeId' => $node->getId(), diff --git a/lib/RoadizRozierBundle/templates/documents/adjust.html.twig b/lib/RoadizRozierBundle/templates/documents/adjust.html.twig index aa5d8bf5b..def90ede7 100644 --- a/lib/RoadizRozierBundle/templates/documents/adjust.html.twig +++ b/lib/RoadizRozierBundle/templates/documents/adjust.html.twig @@ -18,6 +18,7 @@ data-vuejs src-url="{{ document|url({ 'noProcess': true }) }}" filename="{{ document.filename }}" + mime-type="{{ document.mimeType }}" width="{{ document.imageWidth }}" height="{{ document.imageHeight }}" > diff --git a/lib/Rozier/app/containers/BlanchetteEditorContainer.vue b/lib/Rozier/app/containers/BlanchetteEditorContainer.vue index 465f8d234..e135c0cec 100644 --- a/lib/Rozier/app/containers/BlanchetteEditorContainer.vue +++ b/lib/Rozier/app/containers/BlanchetteEditorContainer.vue @@ -34,8 +34,8 @@ :alt="name" @load="load" ref="image" - :width="width ? width : ''" - :height="height ? height : ''" + :width="currentWidth ? currentWidth : ''" + :height="currentHeight ? currentHeight : ''" /> @@ -94,6 +94,10 @@ export default { required: true, type: String, }, + mimeType: { + type: String, + default: '', + }, width: { type: [Number, String], }, @@ -110,14 +114,20 @@ export default { canvasData: null, cropBoxData: null, image: null, - type: '', + type: 'image/png', + originalMimeType: '', name: '', url: this.srcUrl, cropped: false, aspectRatio: null, + currentWidth: this.width ? Number(this.width) : null, + currentHeight: this.height ? Number(this.height) : null, } }, mounted() { + this.originalMimeType = this.normalizeMimeType(this.mimeType) + this.type = this.resolveOutputMimeType(this.originalMimeType) + this.blanchetteEditorInit({ url: this.url, editor: this.$refs.blanchetteEditor, @@ -133,11 +143,50 @@ export default { methods: { ...mapActions(['blanchetteEditorInit', 'blanchetteEditorLoaded', 'blanchetteEditorSave']), overwrite() { - console.log(this) this.blanchetteEditorSave({ url: this.url, - filename: this.filename, - }).then(() => this.restore()) + filename: this.getOverwriteFilename(), + }).then((data) => { + if ( + data && + typeof data.imageWidth !== 'undefined' && + typeof data.imageHeight !== 'undefined' + ) { + this.currentWidth = Number(data.imageWidth) + this.currentHeight = Number(data.imageHeight) + } + this.restore() + }) + }, + normalizeMimeType(mimeType) { + if (!mimeType || typeof mimeType !== 'string') { + return '' + } + + return mimeType.toLowerCase() + }, + resolveOutputMimeType(mimeType) { + switch (mimeType) { + case 'image/jpeg': + case 'image/png': + case 'image/webp': + return mimeType + case 'image/gif': + default: + return 'image/png' + } + }, + getOverwriteFilename() { + if (this.type !== 'image/png' || this.originalMimeType === 'image/png') { + return this.filename + } + + const extensionPosition = this.filename.lastIndexOf('.') + if (extensionPosition > 0) { + return `${this.filename.slice(0, extensionPosition)}.png` + } + + return `${this.filename}.png` }, async load() { await sleep(1000) @@ -246,15 +295,15 @@ export default { this.data = cropper.getData() this.canvasData = cropper.getCanvasData() this.cropBoxData = cropper.getCropBoxData() - this.url = cropper - .getCroppedCanvas( - type === 'image/png' - ? null - : { - fillColor: '#fff', - } - ) - .toDataURL(type) + if (type === 'image/png') { + this.url = cropper.getCroppedCanvas().toDataURL(type) + } else { + this.url = cropper + .getCroppedCanvas({ + fillColor: '#fff', + }) + .toDataURL(type) + } this.cropped = true this.stop() diff --git a/lib/Rozier/app/store/modules/BlanchetteEditorStoreModule.js b/lib/Rozier/app/store/modules/BlanchetteEditorStoreModule.js index b4f3fea09..2073c659c 100644 --- a/lib/Rozier/app/store/modules/BlanchetteEditorStoreModule.js +++ b/lib/Rozier/app/store/modules/BlanchetteEditorStoreModule.js @@ -41,10 +41,17 @@ const actions = { commit(BLANCHETTE_EDITOR_IS_LOADING) - // TODO: update document width and height return DocumentApi.setDocument(formData) .then(async (response) => { - const data = await response.json() + const data = await response.json().catch(() => null) + + if (!response.ok) { + throw ( + data ?? + new Error(response.statusText || 'Request failed') + ) + } + commit(BLANCHETTE_EDITOR_LOADED) if (data && data.path) { window.dispatchEvent( @@ -56,13 +63,36 @@ const actions = { }), ) commit(BLANCHETTE_EDITOR_SAVE_SUCCESS, { path: data.path }) + return data } else { throw new Error('No path found') } }) .catch(async (error) => { + let parsedError = null + + if ( + error?.response && + typeof error.response.json === 'function' + ) { + parsedError = await error.response.json().catch(() => null) + } else if ( + error && + typeof error === 'object' && + !(error instanceof Error) + ) { + parsedError = error + } + + const errorMessage = + parsedError?.humanMessage || + parsedError?.message || + (error instanceof Error ? error.message : 'Request failed') + commit(BLANCHETTE_EDITOR_ERROR, { - error: await error.response.json(), + error: { + message: errorMessage, + }, }) commit(BLANCHETTE_EDITOR_LOADED) })