@widergy/mobile-ui 1.26.0 → 1.26.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,3 +1,10 @@
1
+ ## [1.26.1](https://github.com/widergy/mobile-ui/compare/v1.26.0...v1.26.1) (2024-09-26)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * preview and validations attachment list ([#361](https://github.com/widergy/mobile-ui/issues/361)) ([7fa7c2b](https://github.com/widergy/mobile-ui/commit/7fa7c2b7ff95bd916d7f44804c4afc8055936a50))
7
+
1
8
  # [1.26.0](https://github.com/widergy/mobile-ui/compare/v1.25.1...v1.26.0) (2024-09-25)
2
9
 
3
10
 
@@ -2,30 +2,50 @@ import React, { Component } from 'react';
2
2
  import { View } from 'react-native';
3
3
  // eslint-disable-next-line import/no-unresolved
4
4
  import DocumentPicker from 'react-native-document-picker';
5
- import { isEmpty } from '@widergy/web-utils/lib/array';
5
+ import { isArray, isEmpty } from 'lodash';
6
6
 
7
- import { retrieveFile, isImageByUri, blobToFile } from '../../utils/fileUtils.js';
7
+ import { retrieveFile, blobToFile } from '../../utils/fileUtils.js';
8
8
 
9
9
  import Picker from './components/Picker';
10
10
  import UploadedFiles from './components/UploadedFiles';
11
11
  import { UPLOAD_ICON, DEFAULT_MAX_SIZE } from './constants';
12
12
  import filePickerPropTypes from './propTypes';
13
- import { onlyPDFAllowed, pdfAspectRatioValidation } from './utils';
13
+ import {
14
+ getInitialValuesFrom,
15
+ isInvalidFileSize,
16
+ onlyPDFAllowed,
17
+ validateFileFormat,
18
+ validateFileQuantity,
19
+ validateFileType,
20
+ validateOnlyPDFAllowed
21
+ } from './utils';
14
22
 
15
23
  class MultipleFilePicker extends Component {
16
24
  constructor(props) {
17
25
  super(props);
26
+ const { files } = props?.value || [];
27
+
18
28
  this.state = {
19
- uploadedFiles: []
29
+ uploadedFiles: isArray(files) ? getInitialValuesFrom(files) : [],
30
+ rawFiles: isArray(files) ? files : []
20
31
  };
21
32
  }
22
33
 
34
+ componentDidUpdate(_, prevState) {
35
+ const { rawFiles } = this.state;
36
+ const { onChange } = this.props;
37
+
38
+ if (prevState.rawFiles !== rawFiles && onChange) {
39
+ const payloadOnChange = isEmpty(rawFiles) ? null : { files: rawFiles };
40
+ onChange(payloadOnChange);
41
+ }
42
+ }
43
+
23
44
  handleShowPicker = async () => {
24
45
  const {
25
46
  allowedTypes,
26
47
  onMaxSizeError,
27
48
  onError,
28
- onChange,
29
49
  maxFileByteSize,
30
50
  maxFiles,
31
51
  minFiles,
@@ -41,47 +61,34 @@ class MultipleFilePicker extends Component {
41
61
  });
42
62
  const { uploadedFiles } = this.state;
43
63
 
44
- if (uploadedFiles.length + documents.length > maxFiles) {
45
- throw new Error(fileTypeError || 'La cantidad de archivos supera al máximo permitido');
46
- }
47
- if (uploadedFiles.length + documents.length < minFiles) {
48
- throw new Error(fileTypeError || 'La cantidad de archivos es menor al mínimo permitido');
49
- }
50
- documents.map(async document => {
51
- const isPDF = document.type.includes('pdf');
52
- const isImage = document.type.includes('image');
53
- if (onlyPDFAllowed(allowedTypes) && !isPDF) {
54
- throw new Error(fileTypeError || 'El tipo de archivo debe ser PDF.');
55
- }
56
- if (allowedTypes && !isImage && !isImageByUri(document.uri) && !isPDF) {
57
- throw new Error(fileTypeError || 'Tipo de archivo inválido.');
58
- }
59
- if (maxFileByteSize && document.size > maxFileByteSize) {
60
- onMaxSizeError(document.size, maxFileByteSize);
61
- return;
62
- }
63
-
64
- const file = !avoidRetrieveFile && (await retrieveFile(document.uri, document.type));
65
-
66
- if (file && isPDF && !isEmpty(allowedPDFUploadSizes)) {
67
- const isWrongFormat = await pdfAspectRatioValidation(file, allowedPDFUploadSizes);
68
- if (isWrongFormat) {
69
- throw new Error(
70
- pdfFormatError ||
71
- `El formato de archivo es inválido. (Válidos: ${allowedPDFUploadSizes
72
- ?.map(aspectRatio => aspectRatio.name)
73
- .join(' - ')})`
74
- );
64
+ const filesSelectedQuantity = uploadedFiles.length + documents.length;
65
+ validateFileQuantity(filesSelectedQuantity, { maxFiles, minFiles }, fileTypeError);
66
+
67
+ await Promise.all(
68
+ documents.map(async document => {
69
+ const hasFileBeenUploaded = uploadedFiles.some(fileAdded => fileAdded.name === document.name);
70
+
71
+ if (!hasFileBeenUploaded) {
72
+ validateOnlyPDFAllowed(document, allowedTypes, fileTypeError);
73
+ validateFileType(document, allowedTypes, fileTypeError);
74
+
75
+ const isValid = isInvalidFileSize(document, maxFileByteSize, onMaxSizeError);
76
+ if (isValid) return;
77
+
78
+ const file =
79
+ !avoidRetrieveFile && (await retrieveFile(document.uri, document.type, document.name));
80
+
81
+ await validateFileFormat(file, document, allowedPDFUploadSizes, pdfFormatError);
82
+
83
+ const fileToUpload = avoidRetrieveFile ? { document } : { file: blobToFile(file, document.type) };
84
+
85
+ this.setState(prevState => ({
86
+ uploadedFiles: [...prevState.uploadedFiles, { name: document.name, size: document.size }],
87
+ rawFiles: [...prevState.rawFiles, fileToUpload]
88
+ }));
75
89
  }
76
- }
77
-
78
- if (onChange) {
79
- onChange(avoidRetrieveFile ? { document } : { file: blobToFile(file, document.type) });
80
- }
81
- this.setState(prevState => ({
82
- uploadedFiles: [...prevState.uploadedFiles, { name: document.name, size: document.size }]
83
- }));
84
- });
90
+ })
91
+ );
85
92
  } catch (err) {
86
93
  if (!DocumentPicker.isCancel(err)) {
87
94
  onError(err.message);
@@ -95,7 +102,8 @@ class MultipleFilePicker extends Component {
95
102
  onChange(null);
96
103
  }
97
104
  this.setState(prevState => ({
98
- uploadedFiles: prevState.uploadedFiles.filter((a, i) => i !== index)
105
+ uploadedFiles: prevState.uploadedFiles.filter((a, i) => i !== index),
106
+ rawFiles: prevState.rawFiles.filter((a, i) => i !== index)
99
107
  }));
100
108
  };
101
109
 
@@ -1,4 +1,7 @@
1
1
  import { PDFDocument } from 'pdf-lib';
2
+ import { isEmpty } from 'lodash';
3
+
4
+ import { isImageByUri } from '../../utils/fileUtils.js';
2
5
 
3
6
  export const onlyPDFAllowed = allowedTypes => allowedTypes.length === 1 && allowedTypes[0].includes('pdf');
4
7
 
@@ -39,3 +42,67 @@ export const pdfAspectRatioValidation = async (file, allowedPDFUploadSizes) => {
39
42
  return !pageMatches({ width, height }, allowedPDFUploadSizes);
40
43
  });
41
44
  };
45
+
46
+ export const validateFileQuantity = (fieldQuantity, { maxFiles, minFiles }, fileTypeError) => {
47
+ if (fieldQuantity > maxFiles) {
48
+ throw new Error(fileTypeError || 'La cantidad de archivos supera al máximo permitido');
49
+ }
50
+ if (fieldQuantity < minFiles) {
51
+ throw new Error(fileTypeError || 'La cantidad de archivos es menor al mínimo permitido');
52
+ }
53
+ };
54
+
55
+ const isPDF = document => document.type.includes('pdf');
56
+ const isImage = document => document.type.includes('image');
57
+
58
+ export const validateOnlyPDFAllowed = (document, allowedTypes, fileTypeError) => {
59
+ const condition = onlyPDFAllowed(allowedTypes) && !isPDF(document);
60
+ if (condition) {
61
+ throw new Error(fileTypeError || 'El tipo de archivo debe ser PDF.');
62
+ }
63
+ };
64
+
65
+ export const validateFileType = (document, allowedTypes, fileTypeError) => {
66
+ const isInvalidImage = !isImage(document) && !isImageByUri(document.uri);
67
+ const condition = allowedTypes && isInvalidImage && !isPDF(document);
68
+ if (condition) {
69
+ throw new Error(fileTypeError || 'Tipo de archivo inválido.');
70
+ }
71
+ };
72
+
73
+ export const isInvalidFileSize = (document, maxFileByteSize, onMaxSizeError) => {
74
+ const isInvalid = maxFileByteSize && document.size > maxFileByteSize;
75
+ if (isInvalid) {
76
+ if (onMaxSizeError) {
77
+ onMaxSizeError(document.size, maxFileByteSize);
78
+ } else {
79
+ throw new Error(`El archivo debe ser menor a ${maxFileByteSize}`);
80
+ }
81
+ }
82
+ return isInvalid;
83
+ };
84
+
85
+ export const validateFileFormat = async (file, document, allowedPDFUploadSizes, pdfFormatError) => {
86
+ const isInvalid = file && isPDF(document) && !isEmpty(allowedPDFUploadSizes);
87
+ if (isInvalid) {
88
+ const isWrongFormat = await pdfAspectRatioValidation(file, allowedPDFUploadSizes);
89
+ if (isWrongFormat) {
90
+ throw new Error(
91
+ pdfFormatError ||
92
+ `El formato de archivo es inválido. (Válidos: ${allowedPDFUploadSizes
93
+ ?.map(aspectRatio => aspectRatio.name)
94
+ .join(' - ')})`
95
+ );
96
+ }
97
+ }
98
+ };
99
+
100
+ export const getInitialValuesFrom = files =>
101
+ files
102
+ ?.map(fileBlob => {
103
+ // eslint-disable-next-line no-underscore-dangle
104
+ const fileData = fileBlob?.file?._data || {};
105
+
106
+ return fileData ? { name: fileData?.name, size: fileData?.size } : null;
107
+ })
108
+ .filter(file => file !== null) || [];
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@widergy/mobile-ui",
3
3
  "description": "Widergy Mobile Components",
4
4
  "author": "widergy",
5
- "version": "1.26.0",
5
+ "version": "1.26.1",
6
6
  "repository": "https://github.com/widergy/mobile-ui.git",
7
7
  "main": "lib/index.js",
8
8
  "files": [