Skip to content

Commit

Permalink
Merge pull request #2775 from SUI-Components/feature/add-view-type-li…
Browse files Browse the repository at this point in the history
…st-photouploader

feat(components/molecule/photoUploader): add new view type list to ph…
  • Loading branch information
davidmartin84 authored Oct 30, 2024
2 parents 1390dfa + 8b7b167 commit 90ebe01
Show file tree
Hide file tree
Showing 7 changed files with 140 additions and 14 deletions.
13 changes: 10 additions & 3 deletions components/molecule/photoUploader/src/PhotosPreview/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ import {
DEFAULT_NOTIFICATION_ERROR,
ROTATION_DIRECTION,
THUMB_CLASS_NAME,
THUMB_SORTABLE_CLASS_NAME
THUMB_SORTABLE_CLASS_NAME,
VIEW_TYPE
} from '../config.js'
import {callbackUploadPhotoHandler} from '../fileTools.js'
import {base64ToBlob, cropAndRotateImage, formatToBase64} from '../photoTools.js'
Expand All @@ -33,6 +34,7 @@ const PhotosPreview = ({
content,
defaultFormatToBase64Options,
deleteIcon,
dragIcon,
dragDelay,
errorInitialPhotoDownloadErrorText,
files,
Expand All @@ -46,7 +48,8 @@ const PhotosPreview = ({
setFiles,
setIsLoading,
setNotificationError,
thumbIconSize
thumbIconSize,
viewType
}) => {
const _onSortEnd = event => {
_callbackPhotosUploaded(files, {action: ACTIONS.SORT, data: event})
Expand Down Expand Up @@ -169,9 +172,11 @@ const PhotosPreview = ({
content={content}
rotateIcon={rotateIcon()}
deleteIcon={deleteIcon()}
dragIcon={dragIcon()}
retryIcon={retryIcon()}
rejectPhotosIcon={rejectPhotosIcon()}
outputImageAspectRatioDisabled={outputImageAspectRatioDisabled}
viewType={viewType}
/>
)}
</li>
Expand Down Expand Up @@ -218,6 +223,7 @@ PhotosPreview.propTypes = {
content: PropTypes.func,
defaultFormatToBase64Options: PropTypes.object.isRequired,
deleteIcon: PropTypes.node.isRequired,
dragIcon: PropTypes.node,
dragDelay: PropTypes.number.isRequired,
errorInitialPhotoDownloadErrorText: PropTypes.string.isRequired,
files: PropTypes.array.isRequired,
Expand All @@ -231,7 +237,8 @@ PhotosPreview.propTypes = {
setFiles: PropTypes.func.isRequired,
setIsLoading: PropTypes.func.isRequired,
setNotificationError: PropTypes.func.isRequired,
thumbIconSize: PropTypes.oneOf(Object.keys(ATOM_ICON_SIZES))
thumbIconSize: PropTypes.oneOf(Object.keys(ATOM_ICON_SIZES)),
viewType: PropTypes.oneOf(Object.keys(VIEW_TYPE))
}

export default PhotosPreview
22 changes: 17 additions & 5 deletions components/molecule/photoUploader/src/ThumbCard/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,25 +12,32 @@ import {
THUMB_CARD_CLASS_NAME
} from './config.js'

import {DEFAULT_VIEW_TYPE, VIEW_TYPE} from './../config.js'

const ThumbCard = ({
iconSize = ATOM_ICON_SIZES.small,
callbackDeleteItem,
callbackRetryUpload,
callbackRotateItem,
content: Content = () => null,
deleteIcon,
dragIcon,
index,
image,
mainPhotoLabel,
outputImageAspectRatioDisabled,
rejectPhotosIcon,
retryIcon,
rotateIcon
rotateIcon,
viewType
}) => {
const hasErrors = image.hasErrors

const isDefaultView = viewType === DEFAULT_VIEW_TYPE
const isListtView = viewType === VIEW_TYPE.LIST

const counterClass = cx(`${THUMB_CARD_CLASS_NAME}-counter`, {
[`${THUMB_CARD_CLASS_NAME}-mainCounter`]: index === 0
[`${THUMB_CARD_CLASS_NAME}-mainCounter`]: index === 0 && isDefaultView
})

const imageThumbClass = cx(IMAGE_THUMB_CARD_CLASS_NAME, {
Expand All @@ -39,14 +46,17 @@ const ThumbCard = ({

return (
<div className={THUMB_CARD_CLASS_NAME}>
<div className={counterClass}>{index === 0 ? mainPhotoLabel : index + 1}</div>
<div className={counterClass}>{index === 0 && isDefaultView ? mainPhotoLabel : index + 1}</div>
<div className={CONTAINER_THUMB_CARD_CLASS_NAME}>
{hasErrors ? (
<div className={`${ICON_THUMB_CARD_CLASS_NAME}`}>
<AtomIcon size={ATOM_ICON_SIZES.extraLarge}>{rejectPhotosIcon}</AtomIcon>
</div>
) : (
<img src={image.preview} className={imageThumbClass} />
<>
{isListtView && <AtomIcon size={iconSize}>{dragIcon}</AtomIcon>}
<img src={image.preview} className={imageThumbClass} />
</>
)}
</div>
<Content file={image} index={index} />
Expand Down Expand Up @@ -77,13 +87,15 @@ ThumbCard.propTypes = {
callbackRotateItem: PropTypes.func,
content: PropTypes.func,
deleteIcon: PropTypes.node.isRequired,
dragIcon: PropTypes.node.isRequired,
index: PropTypes.number,
image: PropTypes.object.isRequired,
mainPhotoLabel: PropTypes.string,
outputImageAspectRatioDisabled: PropTypes.bool,
rejectPhotosIcon: PropTypes.node.isRequired,
retryIcon: PropTypes.node.isRequired,
rotateIcon: PropTypes.node.isRequired
rotateIcon: PropTypes.node.isRequired,
viewType: PropTypes.oneOf(Object.keys(VIEW_TYPE))
}

export default ThumbCard
7 changes: 7 additions & 0 deletions components/molecule/photoUploader/src/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,3 +47,10 @@ export const ACTIONS = {
RETRY_UPLOAD: 'RETRY_UPLOAD',
INITIAL_LOAD: 'INITIAL_LOAD'
}

export const VIEW_TYPE = {
GRID: 'grid',
LIST: 'list'
}

export const DEFAULT_VIEW_TYPE = VIEW_TYPE.GRID
30 changes: 25 additions & 5 deletions components/molecule/photoUploader/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,9 @@ import {
DRAG_STATE_STATUS_REJECTED,
DROPZONE_CLASS_NAME,
REJECT_FILES_REASONS,
ROTATION_DIRECTION
ROTATION_DIRECTION,
VIEW_TYPE,
DEFAULT_VIEW_TYPE
} from './config.js'
import {filterValidFiles, loadInitialPhotos, prepareFiles} from './fileTools.js'

Expand All @@ -51,6 +53,7 @@ const MoleculePhotoUploader = forwardRef(
callbackUploadPhoto,
content,
deleteIcon,
dragIcon,
disableScrollToBottom = false,
dragDelay = DEFAULT_DRAG_DELAY_TIME,
dragPhotoDividerTextInitialContent,
Expand Down Expand Up @@ -85,7 +88,8 @@ const MoleculePhotoUploader = forwardRef(
rotationDirection = ROTATION_DIRECTION.counterclockwise,
thumbIconSize,
uploadingPhotosText,
isClickable = true
isClickable = true,
viewType = DEFAULT_VIEW_TYPE
},
forwardedRef
) => {
Expand Down Expand Up @@ -235,6 +239,10 @@ const MoleculePhotoUploader = forwardRef(

const inputRef = useMergeRefs(dropzoneInputRef, forwardedRef)

const mainClassName = cx(BASE_CLASS_NAME, {
[`${BASE_CLASS_NAME}--${viewType}`]: viewType !== DEFAULT_VIEW_TYPE
})

const dropzoneClassName = cx(DROPZONE_CLASS_NAME, {
[`${DROPZONE_CLASS_NAME}--disabled`]: isPhotoUploaderFully(),
[`${DROPZONE_CLASS_NAME}--empty`]: isPhotoUploaderEmpty
Expand All @@ -260,7 +268,7 @@ const MoleculePhotoUploader = forwardRef(

return (
<>
<div className={BASE_CLASS_NAME}>
<div className={mainClassName}>
<div {...getRootProps({className: dropzoneClassName})}>
<input {...getInputProps()} ref={inputRef} />
{isPhotoUploaderEmpty && !isDragActive && (
Expand Down Expand Up @@ -288,6 +296,7 @@ const MoleculePhotoUploader = forwardRef(
content={content}
defaultFormatToBase64Options={DEFAULT_FORMAT_TO_BASE_64_OPTIONS}
deleteIcon={deleteIcon}
dragIcon={dragIcon}
dragDelay={dragDelay}
errorInitialPhotoDownloadErrorText={errorInitialPhotoDownloadErrorText}
files={files}
Expand All @@ -302,6 +311,7 @@ const MoleculePhotoUploader = forwardRef(
setIsLoading={setIsLoading}
setNotificationError={setNotificationError}
thumbIconSize={thumbIconSize}
viewType={viewType}
/>
)}
{isDragAccept && !isPhotoUploaderFully() && !isLoading && (
Expand Down Expand Up @@ -394,6 +404,9 @@ MoleculePhotoUploader.propTypes = {
/** Icon placed in the button that deletes image */
deleteIcon: PropTypes.func.isRequired,

/** Icon placed for draggable help in viewtype list */
dragIcon: PropTypes.func,

/** A boolean to disable that the component scroll to bottom everytime the user add a photo or there's an error */
disableScrollToBottom: PropTypes.bool,

Expand Down Expand Up @@ -526,9 +539,16 @@ MoleculePhotoUploader.propTypes = {
onSortPhotoStart: PropTypes.func,

/** A boolean to enable click in dropzone area */
isClickable: PropTypes.bool
isClickable: PropTypes.bool,

/** View types of the component */
viewType: PropTypes.oneOf(Object.values(VIEW_TYPE))
}

export default MoleculePhotoUploader

export {ROTATION_DIRECTION as MoleculePhotoUploaderRotationDirection, ACTIONS as MoleculePhotoUploaderActions}
export {
ROTATION_DIRECTION as MoleculePhotoUploaderRotationDirection,
ACTIONS as MoleculePhotoUploaderActions,
VIEW_TYPE as MoleculePhotoUploaderViewType
}
72 changes: 72 additions & 0 deletions components/molecule/photoUploader/src/styles/index.scss
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,78 @@ $skeleton-class: '#{$base-class}-skeleton';
&-notification {
margin-top: $m-m;
}

/** VIEW_TYPES */
&--list {
#{$base-class}-dropzone {
background: none;
border: none;
padding: 0;
}

#{$base-class}-preview {
grid-auto-rows: auto;
grid-gap: $g-l;
grid-template-columns: repeat(auto-fit, 100%);
}

#{$base-class}-skeleton {
flex-direction: row;
padding: $p-m 0;
width: 100%;

&-text {
margin-left: $m-l;
margin-top: 0;
}
}

#{$base-class}-thumb {
background: $bg-photo-uploader;
}

#{$base-class}-thumbCard {
flex-direction: row;
justify-content: space-between;

&-actions {
display: flex;
flex-direction: row-reverse;
gap: $g-m;
width: auto;
}

&-button {
background: none;
margin-right: $m-m;
&:hover {
@include media-breakpoint-up(m) {
background: none;
}
}
}

&-counter {
left: -$m-m;
top: -$m-m;
}

&-imageContainer {
align-items: center;
display: flex;
font-size: $fz-l;
padding-left: $p-m;
width: 100%;
}

&-image {
border-radius: $bdrs-l;
height: $h-photo-uploader-thumb-image-list;
margin: $m-m;
width: $w-photo-uploader-thumb-image-list;
}
}
}
}

#{$thumb-class} {
Expand Down
2 changes: 2 additions & 0 deletions components/molecule/photoUploader/src/styles/settings.scss
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ $p-photo-uploader-desktop: $p-xl !default;
$p-photo-uploader: $p-m !default;
$s-photo-uploader-thumb-icons: 16px !default;
$w-photo-uploader-thumb-image-desktop: 160px !default;
$w-photo-uploader-thumb-image-list: 60px !default;
$w-photo-uploader-thumb-image: 100% !default;
$p-photo-uploader-initial-state: 0 !default;

Expand All @@ -54,6 +55,7 @@ $bgc-photo-uploader-counter: $c-primary !default;
$bdrs-photo-uploader-counter: $bdrs-rounded !default;
$h-photo-uploader-thumb-image: ($w-photo-uploader-thumb-image * 3) * 0.25;
$h-photo-uploader-thumb-image-desktop: ($w-photo-uploader-thumb-image-desktop * 3) * 0.25;
$h-photo-uploader-thumb-image-list: ($w-photo-uploader-thumb-image-list * 3) * 0.25;
$w-photo-uploader-skeleton: $w-photo-uploader-thumb-image;
$w-photo-uploader-skeleton-desktop: $w-photo-uploader-thumb-image-desktop;
$maw-photo-uploader-thumb-drag-text: 200px;
8 changes: 7 additions & 1 deletion components/molecule/photoUploader/test/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,18 @@ describe(json.name, () => {
it('library should include defined exported elements', () => {
// Given
const library = pkg
const libraryExportedMembers = ['MoleculePhotoUploaderRotationDirection', 'MoleculePhotoUploaderActions', 'default']
const libraryExportedMembers = [
'MoleculePhotoUploaderRotationDirection',
'MoleculePhotoUploaderActions',
'MoleculePhotoUploaderViewType',
'default'
]

// When
const {
MoleculePhotoUploaderRotationDirection,
MoleculePhotoUploaderActions,
MoleculePhotoUploaderViewType,
default: MoleculePhotoUploader,
...others
} = library
Expand Down

0 comments on commit 90ebe01

Please sign in to comment.