From 3540d471584a9b1946d69fe3cc44a9ce23df9f6c Mon Sep 17 00:00:00 2001 From: Matt Raible Date: Tue, 30 Aug 2022 22:19:04 -0600 Subject: [PATCH 1/7] Add image support --- .../components/form/inputs/jhi-image-input.js | 47 +++++++++++++++++++ .../components/form/jhi-form-field.js.ejs | 16 +++++++ lib/entity-helpers.js | 15 ++++-- 3 files changed, 75 insertions(+), 3 deletions(-) create mode 100644 generators/app/templates/app/shared/components/form/inputs/jhi-image-input.js diff --git a/generators/app/templates/app/shared/components/form/inputs/jhi-image-input.js b/generators/app/templates/app/shared/components/form/inputs/jhi-image-input.js new file mode 100644 index 000000000..9a96faa3e --- /dev/null +++ b/generators/app/templates/app/shared/components/form/inputs/jhi-image-input.js @@ -0,0 +1,47 @@ +import React from 'react'; +import { View, StyleSheet, Text, Image } from 'react-native'; +/* eslint-disable react-native/no-inline-styles */ + +export default React.forwardRef((props, ref) => { + const { label, labelStyle, error, inputType, contentType, value, testID, ...otherProps } = props; + return ( + + {/* if there's a label, render it */} + {label && {label}} + {/* render the base64 image or plain image input */} + {inputType === 'image-base64' ? + + : + + } + {/* if there's an error, render it */} + {!!error && !!error.message && {error && error.message}} + + ); +}); + +const styles = StyleSheet.create({ + imageBlob : { + width: 100, + height: 100, + }, + imageSize : { + width: 100, + height: 100, + }, + container: { + marginVertical: 8, + }, + label: { + paddingVertical: 5, + fontSize: 16, + fontWeight: 'bold', + }, + textError: { + color: '#fc6d47', + fontSize: 14, + }, +}); diff --git a/generators/app/templates/app/shared/components/form/jhi-form-field.js.ejs b/generators/app/templates/app/shared/components/form/jhi-form-field.js.ejs index 01802303f..a4d308344 100644 --- a/generators/app/templates/app/shared/components/form/jhi-form-field.js.ejs +++ b/generators/app/templates/app/shared/components/form/jhi-form-field.js.ejs @@ -6,6 +6,7 @@ import AppSwitchInput from './inputs/jhi-switch-input'; import AppListInput from './inputs/jhi-list-input'; import AppMultiListInput from './inputs/jhi-multi-list-input'; import AppDateInput from './inputs/jhi-date-input'; +import AppImageInput from './inputs/jhi-image-input'; import { StyleSheet, Text } from 'react-native'; import ApplicationStyles from '../../themes/application.styles'; @@ -36,6 +37,10 @@ export default React.forwardRef((props, ref) => { // number values have to be strings values[name] = String(values[name]); } + if (inputType === 'image-base64' || inputType === 'image') { + // number values have to be strings + // values[name] = String(values[name]); + } const hasError = errors[name] && touched[name]; return ( @@ -108,6 +113,17 @@ export default React.forwardRef((props, ref) => { {...otherProps} /> )} + {(inputType === 'image-base64' || inputType === 'image') && ( + setFieldValue(name, value)} + onBlur={() => setFieldTouched(name)} + error={hasError} + {...otherProps} + /> + )} {hasError && {errors[name]}} ); diff --git a/lib/entity-helpers.js b/lib/entity-helpers.js index f772c1e46..e40e260e0 100644 --- a/lib/entity-helpers.js +++ b/lib/entity-helpers.js @@ -13,7 +13,8 @@ const getEntityFormFieldType = field => { fieldType === 'Float' || fieldType === 'Decimal' || fieldType === 'Double' || - fieldType === 'BigDecimal' + fieldType === 'BigDecimal' || + fieldType === 'ImageBlob' ) { return 'number'; } @@ -26,6 +27,9 @@ const getEntityFormFieldType = field => { if (fieldType === 'Boolean') { return 'boolean'; } + if (fieldType === 'ImageBlob') { + return 'image-base64'; + } if (fieldIsEnum) { return 'select-one'; } @@ -60,7 +64,8 @@ const getEntityFormFieldAttributes = ( fieldType === 'Float' || fieldType === 'Decimal' || fieldType === 'Double' || - fieldType === 'BigDecimal' + fieldType === 'BigDecimal' || + fieldType === 'ImageBlob' ) { attributes += ` inputType='number' @@ -69,6 +74,10 @@ const getEntityFormFieldAttributes = ( attributes += ` inputType='date' `; + } else if (fieldType === 'ImageBlob') { + attributes += ` + inputType='image-base64' + `; } else if (fieldType === 'Instant' || fieldType === 'ZonedDateTime') { attributes += ` inputType='datetime' @@ -106,7 +115,6 @@ const getEntityFormField = (field, nextField, numRelationships) => { const nextFieldIsEnum = nextField ? nextField.fieldIsEnum : null; if (field.fieldType === 'byte[]' && field.fieldTypeBlobContent !== 'text') { - // need to add a contentType input for blobs const attributes = getEntityFormFieldAttributes( fieldType, fieldName, @@ -163,6 +171,7 @@ const getFieldValidateType = fieldType => { switch (fieldType) { case 'LocalDate': case 'ZonedDateTime': + case 'ImageBlob': case 'Instant': fieldValidateType = 'date'; break; From e05f88831d85b1b5386efc66b4647373c43cbc68 Mon Sep 17 00:00:00 2001 From: Matt Raible Date: Tue, 30 Aug 2022 22:39:41 -0600 Subject: [PATCH 2/7] Thanks eslint! --- lib/entity-helpers.js | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/lib/entity-helpers.js b/lib/entity-helpers.js index e40e260e0..af2fb92ec 100644 --- a/lib/entity-helpers.js +++ b/lib/entity-helpers.js @@ -13,8 +13,7 @@ const getEntityFormFieldType = field => { fieldType === 'Float' || fieldType === 'Decimal' || fieldType === 'Double' || - fieldType === 'BigDecimal' || - fieldType === 'ImageBlob' + fieldType === 'BigDecimal' ) { return 'number'; } @@ -64,8 +63,7 @@ const getEntityFormFieldAttributes = ( fieldType === 'Float' || fieldType === 'Decimal' || fieldType === 'Double' || - fieldType === 'BigDecimal' || - fieldType === 'ImageBlob' + fieldType === 'BigDecimal' ) { attributes += ` inputType='number' From ce85dc5263190b8939f743c2511602e77dedf73a Mon Sep 17 00:00:00 2001 From: Matt Raible Date: Wed, 31 Aug 2022 00:31:27 -0600 Subject: [PATCH 3/7] Polishing --- generators/app/files.js | 1 + .../inputs/{jhi-image-input.js => jhi-image-input.js.ejs} | 6 +----- 2 files changed, 2 insertions(+), 5 deletions(-) rename generators/app/templates/app/shared/components/form/inputs/{jhi-image-input.js => jhi-image-input.js.ejs} (94%) diff --git a/generators/app/files.js b/generators/app/files.js index a93ffa86b..2760cb6f3 100644 --- a/generators/app/files.js +++ b/generators/app/files.js @@ -46,6 +46,7 @@ const files = { 'app/shared/components/alert-message/alert-message.styles.js', 'app/shared/components/form/inputs/jhi-date-input.js', 'app/shared/components/form/inputs/jhi-date-input.web.js', + 'app/shared/components/form/inputs/jhi-image-input.js', 'app/shared/components/form/inputs/jhi-list-input.js', 'app/shared/components/form/inputs/jhi-multi-list-input.js', 'app/shared/components/form/inputs/jhi-switch-input.js', diff --git a/generators/app/templates/app/shared/components/form/inputs/jhi-image-input.js b/generators/app/templates/app/shared/components/form/inputs/jhi-image-input.js.ejs similarity index 94% rename from generators/app/templates/app/shared/components/form/inputs/jhi-image-input.js rename to generators/app/templates/app/shared/components/form/inputs/jhi-image-input.js.ejs index 9a96faa3e..530c9b0b5 100644 --- a/generators/app/templates/app/shared/components/form/inputs/jhi-image-input.js +++ b/generators/app/templates/app/shared/components/form/inputs/jhi-image-input.js.ejs @@ -24,11 +24,7 @@ export default React.forwardRef((props, ref) => { }); const styles = StyleSheet.create({ - imageBlob : { - width: 100, - height: 100, - }, - imageSize : { + imageSize: { width: 100, height: 100, }, From fc86411408ce5b4ce1b478f08e95aa4ada93c2ff Mon Sep 17 00:00:00 2001 From: Matt Raible Date: Thu, 1 Sep 2022 01:19:28 -0600 Subject: [PATCH 4/7] Add ability to replace and delete image --- .../form/inputs/jhi-image-input.js.ejs | 72 +++++++++++++++---- .../components/form/jhi-form-field.js.ejs | 6 +- .../shared/themes/application.styles.js.ejs | 7 +- generators/app/templates/package.json | 1 + generators/app/templates/package.json.ejs | 1 + lib/entity-helpers.js | 10 ++- 6 files changed, 73 insertions(+), 24 deletions(-) diff --git a/generators/app/templates/app/shared/components/form/inputs/jhi-image-input.js.ejs b/generators/app/templates/app/shared/components/form/inputs/jhi-image-input.js.ejs index 530c9b0b5..9e527300d 100644 --- a/generators/app/templates/app/shared/components/form/inputs/jhi-image-input.js.ejs +++ b/generators/app/templates/app/shared/components/form/inputs/jhi-image-input.js.ejs @@ -1,22 +1,62 @@ -import React from 'react'; -import { View, StyleSheet, Text, Image } from 'react-native'; +import React, { useEffect } from 'react'; +import { View, StyleSheet, Text, Image, Button, Platform } from 'react-native'; +import * as ImagePicker from 'expo-image-picker'; +import { MaterialIcons } from '@expo/vector-icons'; /* eslint-disable react-native/no-inline-styles */ export default React.forwardRef((props, ref) => { - const { label, labelStyle, error, inputType, contentType, value, testID, ...otherProps } = props; + const { label, labelStyle, error, onChange, inputType, contentType, value, testID, ...otherProps } = props; + + const [photo, setPhoto] = React.useState(null); + + useEffect(() => { + (async () => { + if (Platform.OS !== 'web') { + const { status } = await ImagePicker.requestMediaLibraryPermissionsAsync(); + if (status !== 'granted') { + // eslint-disable-next-line no-alert + alert('Sorry, Camera roll permissions are required to make this work!'); + } + } + })(); + }, []); + + const choosePhoto = async () => { + let result = await ImagePicker.launchImageLibraryAsync({ + mediaTypes: ImagePicker.MediaTypeOptions.All, + aspect: [4, 3], + quality: 1, + allowsEditing: true, + base64: true, + }); + if (!result.cancelled) { + onChange(result.base64); + } + }; + + const removePhoto = () => { + onChange(''); + }; + return ( {/* if there's a label, render it */} {label && {label}} +