|
|
@@ -1,6 +1,8 @@
|
|
|
import ApiRequestService from './apiRequestService'
|
|
|
import FileUtils from '~/services/utils/fileUtils'
|
|
|
-import { FILE_TYPE, FILE_VISIBILITY } from '~/types/enum/enums'
|
|
|
+import { FILE_TYPE, FILE_VISIBILITY, IMAGE_SIZE } from '~/types/enum/enums'
|
|
|
+import type { AssociativeArray } from '~/types/data'
|
|
|
+import UrlUtils from '~/services/utils/urlUtils'
|
|
|
|
|
|
/**
|
|
|
* Permet le requêtage, l'upload et la manipulation des images via l'API Opentalent
|
|
|
@@ -14,50 +16,97 @@ class ImageManager {
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * Retourne l'image correspondante sous forme d'un blob encodé au format base64,
|
|
|
- * ou l'url d'une image par défaut si l'image est introuvable ou si l'id passé en paramètre est null
|
|
|
+ * Retourne l'image correspondante sous forme soit d'une URL, soit d'un blob encodé au format base64.
|
|
|
*
|
|
|
- * Attention, les dimensions (hauteur / largeur) ne s'appliqueront pas à l'image par défaut, il est nécessaire de
|
|
|
- * les redéfinir dans le composant lui-même.
|
|
|
+ * Retourne l'url de l'image par défaut si l'image est introuvable
|
|
|
+ * ou si l'id passé en paramètre est null.
|
|
|
*
|
|
|
* @param id The id of the image; if null, the url to the default image is returned
|
|
|
+ * @param size
|
|
|
* @param defaultImage The path of an image in the 'public' folder, default: '/images/default/picture.jpeg'
|
|
|
- * @param height Height of the image (does not apply to default image)
|
|
|
- * @param width Width of the image (does not apply to default image)
|
|
|
*/
|
|
|
public async get(
|
|
|
- id: number | null,
|
|
|
+ id: number | string | null,
|
|
|
+ size: IMAGE_SIZE = IMAGE_SIZE.MD,
|
|
|
defaultImage: string | null = null,
|
|
|
- height: number = 0,
|
|
|
- width: number = 0,
|
|
|
- ): Promise<string | ArrayBuffer> {
|
|
|
+ ): Promise<string> {
|
|
|
const defaultUrl = defaultImage ?? ImageManager.defaultImage
|
|
|
|
|
|
if (id === null) {
|
|
|
return defaultUrl
|
|
|
}
|
|
|
|
|
|
- const imageUrl = `api/file/download/${id}`
|
|
|
+ const matches = id.toString().match(/\/api\/files\/(\d+)(?:\/\w+)?/)
|
|
|
+ if (matches) {
|
|
|
+ // Lors de l'enregistrement d'une entité, les ids des objets liés sont
|
|
|
+ // temporairement convertis en IRI. Avec la réactivité, ceci peut
|
|
|
+ // générer une erreur temporaire avec les liens des images, d'où ce patch.
|
|
|
+ id = parseInt(matches[1])
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!(typeof id === 'number' && Number.isInteger(id))) {
|
|
|
+ throw new Error('Error: image ' + id + ' is invalid')
|
|
|
+ }
|
|
|
+
|
|
|
+ try {
|
|
|
+ return size === IMAGE_SIZE.RAW ?
|
|
|
+ this.getRaw(id) :
|
|
|
+ this.getProcessed(id, size)
|
|
|
|
|
|
- // Set requested size if needed
|
|
|
- if (height > 0 || width > 0) {
|
|
|
- // @see https://thumbor.readthedocs.io/en/latest/crop_and_resize_algorithms.html
|
|
|
- // TODO: ajouter le support de ces options dans ap2i
|
|
|
- // url = UrlUtils.join(url, `${height}x${width}`)
|
|
|
+ } catch (error) {
|
|
|
+ console.error(error)
|
|
|
+ return defaultUrl
|
|
|
}
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Retourne une image dimensionnée et cropped depuis le cache Liip.
|
|
|
+ *
|
|
|
+ * @param id The id of the image; if null, the url to the default image is returned
|
|
|
+ * @param size
|
|
|
+ */
|
|
|
+ private async getProcessed(
|
|
|
+ id: number | null,
|
|
|
+ size: IMAGE_SIZE = IMAGE_SIZE.MD
|
|
|
+ ): Promise<string> {
|
|
|
+
|
|
|
+ let imageUrl = `api/image/download/${id}/${size}`
|
|
|
+
|
|
|
+ // Une image doit toujours avoir le time en options pour éviter les problèmes de cache
|
|
|
+ const query: AssociativeArray = {0: this.getCacheKey()}
|
|
|
+
|
|
|
+ const response = await this.apiRequestService.get(imageUrl, query);
|
|
|
+
|
|
|
+ const cachedImageUrl = response.toString()
|
|
|
+
|
|
|
+ if (!cachedImageUrl) {
|
|
|
+ throw new Error('Error: image ' + id + ' not found');
|
|
|
+ }
|
|
|
+
|
|
|
+ return UrlUtils.addQuery(cachedImageUrl, query)
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Retourne l'image non traitée. Utilisé entre autres pour le
|
|
|
+ * cropper du UiInputImage.
|
|
|
+ *
|
|
|
+ * @param id
|
|
|
+ * @private
|
|
|
+ */
|
|
|
+ private async getRaw(id: number | null): Promise<string> {
|
|
|
+
|
|
|
+ const imageUrl = `api/file/download/${id}`
|
|
|
|
|
|
// Une image doit toujours avoir le time en options pour éviter les problèmes de cache
|
|
|
const query = [this.getCacheKey()]
|
|
|
|
|
|
const blobPart = await this.apiRequestService.get(imageUrl, query)
|
|
|
if (!blobPart) {
|
|
|
- console.error('Error: image ' + id + ' not found')
|
|
|
- return defaultUrl
|
|
|
+ throw new Error('Error: image ' + id + ' not found');
|
|
|
}
|
|
|
|
|
|
if (!(blobPart instanceof Blob) || blobPart.size === 0) {
|
|
|
- console.error('Error: image ' + id + ' is invalid')
|
|
|
- return defaultUrl
|
|
|
+ throw new Error('Error: image ' + id + ' is invalid');
|
|
|
}
|
|
|
|
|
|
return await this.toBase64(blobPart)
|