Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat/mmaa 27790 create image field #497

Draft
wants to merge 2 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions components/form/builder/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
"@s-ui/react-molecule-dropdown-option": "1",
"@s-ui/react-molecule-field": "1",
"@s-ui/react-molecule-input-field": "4",
"@s-ui/react-molecule-photo-uploader": "^2.17.0",
"@s-ui/react-molecule-radio-button-field": "1",
"@s-ui/react-molecule-radio-button-group": "1",
"@s-ui/react-molecule-select-field": "1",
Expand Down
5 changes: 2 additions & 3 deletions components/form/builder/src/Checkbox/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -82,9 +82,8 @@ const Checkbox = ({
// render SUI component
return (
<div
className={`sui-FormBuilder-field sui-FormBuilder-Switch sui-FormBuilder-${
checkboxProps.id || tabIndex
}`}
className={`sui-FormBuilder-field sui-FormBuilder-Switch sui-FormBuilder-${checkboxProps.id ||
tabIndex}`}
>
<MoleculeCheckboxField {...checkboxProps} {...rendererResponse} />
</div>
Expand Down
14 changes: 14 additions & 0 deletions components/form/builder/src/Icons/IconDelete.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import {memo} from 'react'
import PropTypes from 'prop-types'

const SVG = ({className}) => (
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<path d="M8 22c-1.7 0-3-1.5-3-3.3V6c0-.6.4-1 1-1h12c.6 0 1 .4 1 1v12.7c0 1.8-1.3 3.3-3 3.3H8zM7 7v11.7c0 .7.5 1.3 1 1.3h8c.5 0 1-.6 1-1.3V7H7zm1-2V4c0-1.1.9-2 2-2h4c1.1 0 2 .9 2 2v1h3.9c.6 0 1.1.4 1.1 1s-.5 1-1.1 1H4.1C3.5 7 3 6.6 3 6s.5-1 1.1-1H8zm2 0h4V4h-4v1zm5.4 11.7c-.4.4-1 .4-1.4 0l-1.9-1.9-1.9 1.9c-.4.4-1 .4-1.4 0-.4-.4-.4-1 0-1.4l1.9-1.9-1.9-1.9c-.4-.4-.4-1 0-1.4.4-.4 1-.4 1.4 0l1.9 1.9 1.9-1.9c.4-.4 1-.4 1.4 0 .4.4.4 1 0 1.4l-1.9 1.9 1.9 1.9c.4.4.4 1 0 1.4z" />
</svg>
)

SVG.propTypes = {
className: PropTypes.string
}

export default memo(SVG)
19 changes: 19 additions & 0 deletions components/form/builder/src/Icons/IconDragAndDrop.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import {memo} from 'react'
import PropTypes from 'prop-types'

const SVG = ({className}) => (
<svg width="24" height="24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path
fillRule="evenodd"
clipRule="evenodd"
d="M6 2C3.7909 2 2 3.7909 2 6v8c0 2.2091 1.7909 4 4 4h2c.5523 0 1-.4477 1-1s-.4477-1-1-1H6c-1.1046 0-2-.8954-2-2V6c0-1.1046.8954-2 2-2h8c.8079 0 1.504.479 1.8196 1.1687.197.4304.5642.8313 1.0375.8313.6312 0 1.1594-.5221.9817-1.1278C17.3519 3.2122 15.8175 2 14 2H6Zm8.4388 4.4757c-.633-.5187-1.5033-.6222-2.2374-.2662C11.4673 6.5656 11 7.318 11 8.1437v8.6359c0 .8184.4591 1.5653 1.1832 1.9252.7242.36 1.5871.27 2.224-.2318l.2845-.2241 1.1974 2.534c.4969 1.0515 1.7309 1.507 2.7773 1.025l1.4783-.6809c.518-.2386.9192-.6792 1.113-1.222a2.1733 2.1733 0 0 0-.0837-1.6619l-1.1388-2.3946.2429-.0464c.8096-.1545 1.4568-.7726 1.6579-1.5833.2011-.8108-.0805-1.6663-.7215-2.1914l-6.7757-5.5517Zm3.56 7.5801 1.889-.3604-6.7757-5.5517v8.6359l1.4948-1.1776.2053-.1282a.8205.8205 0 0 1 .412-.0756l.0089.0007a.8294.8294 0 0 1 .6714.4594l1.889 3.9975 1.4783-.6809-1.8972-3.9895a.9886.9886 0 0 1-.0161-.0348l-.0062-.0149-.0038-.0093c-.0937-.2376-.0614-.4962.0677-.7012a.8066.8066 0 0 1 .3527-.3053l.2299-.0641Z"
fill="#191C1E"
/>
</svg>
)

SVG.propTypes = {
className: PropTypes.string
}

export default memo(SVG)
14 changes: 14 additions & 0 deletions components/form/builder/src/Icons/IconInfo.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import {memo} from 'react'
import PropTypes from 'prop-types'

const SVG = ({className}) => (
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">
<path d="M8 13.3c2.9 0 5.3-2.4 5.3-5.3 0-1.4-.6-2.8-1.6-3.8S9.4 2.7 8 2.7C5.1 2.7 2.7 5.1 2.7 8s2.4 5.3 5.3 5.3zm0 1.4A6.7 6.7 0 018 1.3c1.8 0 3.5.7 4.7 2s2 2.9 2 4.7c0 3.7-3 6.7-6.7 6.7zm-.7-7.4c0-.3.3-.6.7-.6s.7.3.7.6v3.3c0 .4-.3.7-.7.7s-.7-.3-.7-.6V7.3zM8 6c.4 0 .7-.3.7-.7s-.3-.6-.7-.6-.7.3-.7.6.3.7.7.7z" />
</svg>
)

SVG.propTypes = {
className: PropTypes.string
}

export default memo(SVG)
17 changes: 17 additions & 0 deletions components/form/builder/src/Icons/IconPlusPrimary.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import {memo} from 'react'
import PropTypes from 'prop-types'

const SVG = ({className}) => (
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<path
fillRule="evenodd"
d="M11 13H6.51a1 1 0 110-2H11V6.52a1 1 0 012 0V11h4.49a1 1 0 010 2H13v4.49a1 1 0 01-2 0z"
/>
</svg>
)

SVG.propTypes = {
className: PropTypes.string
}

export default memo(SVG)
14 changes: 14 additions & 0 deletions components/form/builder/src/Icons/IconReject.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import {memo} from 'react'
import PropTypes from 'prop-types'

const SVG = ({className}) => (
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<path d="M3 18a1 1 0 001 1h16a1.07 1.07 0 00.52-.14 1 1 0 00.33-1.38l-8-13.1a1 1 0 00-.33-.38 1 1 0 00-1.37.34l-8 13.1A1 1 0 003 18zm-1.53-1.6l8-13.11a3 3 0 015.12 0l8 13.11a3 3 0 01-1 4.12A3.05 3.05 0 0120 21H4a3 3 0 01-3-3 2.93 2.93 0 01.47-1.6zM12 17.62a1 1 0 10-1-1 1 1 0 001 1zM12 7.5a1 1 0 011 1v5a1 1 0 01-2 0v-5a1 1 0 011-1z" />
</svg>
)

SVG.propTypes = {
className: PropTypes.string
}

export default memo(SVG)
14 changes: 14 additions & 0 deletions components/form/builder/src/Icons/IconRetry.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import {memo} from 'react'
import PropTypes from 'prop-types'

const SVG = ({className}) => (
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<path d="M12.08 2.8a9.41 9.41 0 017.27 3.41V3.96a1 1 0 112 0l.08 4.61a1 1 0 01-1 1l-4.61.08a1 1 0 010-2h2.13a7.39 7.39 0 00-5.87-2.85 7.5 7.5 0 106.68 10.89 1 1 0 011.79.9A9.49 9.49 0 1112.08 2.8z" />
</svg>
)

SVG.propTypes = {
className: PropTypes.string
}

export default memo(SVG)
17 changes: 17 additions & 0 deletions components/form/builder/src/Icons/IconRotate.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import {memo} from 'react'
import PropTypes from 'prop-types'

const SVG = ({className}) => (
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<path
fillRule="evenodd"
d="M12 10H4a2 2 0 00-2 2v8a2 2 0 002 2h8a2 2 0 002-2v-8a2 2 0 00-2-2zm0 2v8H4v-8zm.26-9.61a1 1 0 01-.08 1.32l-.1.09-.25.2A11 11 0 0122 15a1 1 0 01-2 0 9 9 0 00-8.3-9l.3.27a1 1 0 01.15 1.31l-.08.1a1 1 0 01-1.31.16l-.1-.08-2.33-2.09a1 1 0 010-1.46l.09-.08 2.47-1.92a1 1 0 011.37.18z"
/>
</svg>
)

SVG.propTypes = {
className: PropTypes.string
}

export default memo(SVG)
59 changes: 59 additions & 0 deletions components/form/builder/src/Images/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import MoleculePhotoUploader from '@s-ui/react-molecule-photo-uploader'

import IconDelete from '../Icons/IconDelete.js'
import IconDragAndDrop from '../Icons/IconDragAndDrop.js'
import IconInfo from '../Icons/IconInfo.js'
import IconPlusPrimary from '../Icons/IconPlusPrimary.js'
import IconReject from '../Icons/IconReject.js'
import IconRetry from '../Icons/IconRetry.js'
import IconRotate from '../Icons/IconRotate.js'

const _infoIcon = () => <IconInfo />
const _rotateIcon = () => <IconRotate />
const _deleteIcon = () => <IconDelete />
const _dragPhotosIcon = () => <IconDragAndDrop />
const _rejectPhotosIcon = () => <IconReject />
const _addMorePhotosIcon = () => <IconPlusPrimary />
const _retryErrorPhotosIcon = () => <IconRetry />

const Images = ({field}) => {
return (
<div
className={`sui-FormBuilder-field sui-FormBuilder-Input sui-FormBuilder-${field.id}`}
>
<MoleculePhotoUploader
// Icons (required props)
addMorePhotosIcon={_addMorePhotosIcon}
deleteIcon={_deleteIcon}
dragPhotosIcon={_dragPhotosIcon}
infoIcon={_infoIcon}
rejectPhotosIcon={_rejectPhotosIcon}
retryIcon={_retryErrorPhotosIcon}
rotateIcon={_rotateIcon}
// Texts (required props)
addPhotoTextButton="Seleccionalas de tu dispositivo"
addPhotoTextSkeleton="Añadir más"
dragPhotoTextInitialContent="Arrastra las fotos aquí"
dropPhotosHereText="Suelta las fotos aquí"
errorFileExcededMaxSizeText="Las fotografías deben tener un peso máximo de 50 MB"
errorFormatPhotoUploadedText="Las fotografías deben tener formato JPEG, PNG, GIF, BMP o WEBP"
errorInitialPhotoDownloadErrorText="Error al descargar imágenes"
notificationErrorFormatPhotoUploaded="Sólo se aceptan los formatos: formato JPEG, PNG, GIF, BMP o WEBP"
uploadingPhotosText="Subiendo imágenes..."
errorCorruptedPhotoUploadedText="Archivo %{filepath} ha fallado"
// Not required props
callbackPhotosRejected={rejectedPhotos => console.log(rejectedPhotos)}
callbackPhotosUploaded={acceptedPhotos => console.log(acceptedPhotos)}
callbackUploadPhoto={(file, oldUrl) => console.log(file, oldUrl)}
limitPhotosUploadedText="Máximo de fotos subidas"
limitPhotosUploadedNotification="Maxímo de 10 fotos subidas"
mainPhotoLabel="PRINCIPAL"
maxPhotos={10}
rotationDirection="clockwise"
initialPhotos={field?.values}
/>
</div>
)
}

export default Images
1 change: 1 addition & 0 deletions components/form/builder/src/Images/index.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
@import '~@s-ui/react-molecule-photo-uploader/lib/index';
14 changes: 14 additions & 0 deletions components/form/builder/src/ProxyField/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import FieldSetField from '../Standard/Fields/FieldSet/index.js'
import PickerField from '../Standard/Fields/Picker/index.js'
import MultiPickerField from '../Standard/Fields/Multicheckbox/index.js'
import RangeField from '../Standard/Fields/Range/index.js'
import Images from '../Images/index.js'

const ProxyField = ({
field,
Expand Down Expand Up @@ -102,6 +103,19 @@ const ProxyField = ({
})
break

case FIELDS.IMAGES:
Field = Images({
field,
tabIndex,
onChange,
onFocus,
onBlur,
errors,
alerts,
renderer
})
break

default: {
const rendererResponse = renderer({
id: field.id,
Expand Down
55 changes: 27 additions & 28 deletions components/form/builder/src/Standard/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ const FIELDS = {
FIELDSET: 'fieldset',
PICKER: 'picker',
MULTIPICKER: 'multipicker',
RANGE: 'range'
RANGE: 'range',
IMAGES: 'images'
}

const DISPLAYS = {
Expand Down Expand Up @@ -172,34 +173,32 @@ const checkConstraintsFromField = (field, locale) => {
return errorMessages
}

const checkConstraintsFactory =
(json, locale) =>
({for: fieldID, all}) => {
let fieldsToValidate = []
if (all && fieldID) {
window.console.warn(
'[form/builder]: checkConstraintsFactory: both modes validate all fields and validate a concrete field are not compatible, please use one of them'
)
} else if (all) {
fieldsToValidate = fieldsNamesInOrderOfDefinition(json?.form?.fields)
} else if (fieldID) {
fieldsToValidate = [fieldID]
const checkConstraintsFactory = (json, locale) => ({for: fieldID, all}) => {
let fieldsToValidate = []
if (all && fieldID) {
window.console.warn(
'[form/builder]: checkConstraintsFactory: both modes validate all fields and validate a concrete field are not compatible, please use one of them'
)
} else if (all) {
fieldsToValidate = fieldsNamesInOrderOfDefinition(json?.form?.fields)
} else if (fieldID) {
fieldsToValidate = [fieldID]
} else {
window.console.warn(
'[form/builder]: checkConstraintsFactory: Specify if you want to validate a specific field or all the fields'
)
}

const fieldsWithErrors = {}
fieldsToValidate.forEach(fieldId => {
const field = pickFieldById(json.form.fields, fieldId)
if (!field.hidden) {
fieldsWithErrors[field.id] = checkConstraintsFromField(field, locale)
} else {
window.console.warn(
'[form/builder]: checkConstraintsFactory: Specify if you want to validate a specific field or all the fields'
)
fieldsWithErrors[field.id] = []
}

const fieldsWithErrors = {}
fieldsToValidate.forEach(fieldId => {
const field = pickFieldById(json.form.fields, fieldId)
if (!field.hidden) {
fieldsWithErrors[field.id] = checkConstraintsFromField(field, locale)
} else {
fieldsWithErrors[field.id] = []
}
})
return fieldsWithErrors
}
})
return fieldsWithErrors
}

export {FIELDS, DISPLAYS, CONSTRAINTS, checkConstraintsFactory}
1 change: 1 addition & 0 deletions components/form/builder/src/index.scss
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
@import './Stepper/index';
@import './MultiButton/index';
@import './Range/Default/index';
@import './Images/index';

$self: 'sui-FormBuilder';

Expand Down