From 6bd600480a15ba5edc0879948b73031432c0ffeb Mon Sep 17 00:00:00 2001 From: Didd Date: Tue, 29 Oct 2024 12:56:30 +0300 Subject: [PATCH] chore(): update gallery section on edit extension form --- .../pages/extension-edit-page/step2-page.tsx | 112 ++++------------ .../pages/customise-notification-page.tsx | 7 +- .../src/components/EditProfile/index.tsx | 2 +- .../ExtensionEditStep2Form/Gallery/index.tsx | 121 +++++++++--------- .../UsefulLinks/index.tsx | 4 +- .../ExtensionEditStep2Form/index.tsx | 15 +-- .../src/components/ImageOverlay/index.tsx | 4 +- 7 files changed, 102 insertions(+), 163 deletions(-) diff --git a/extensions/apps/extensions/src/components/pages/extension-edit-page/step2-page.tsx b/extensions/apps/extensions/src/components/pages/extension-edit-page/step2-page.tsx index 9a4273df4a..38da7ed7fb 100644 --- a/extensions/apps/extensions/src/components/pages/extension-edit-page/step2-page.tsx +++ b/extensions/apps/extensions/src/components/pages/extension-edit-page/step2-page.tsx @@ -1,22 +1,11 @@ -import React, { useContext, useEffect, useMemo, useState } from 'react'; +import React, { useContext, useMemo } from 'react'; import { useTranslation } from 'react-i18next'; import { useNavigate } from '@tanstack/react-router'; import Stack from '@akashaorg/design-system-core/lib/components/Stack'; import Text from '@akashaorg/design-system-core/lib/components/Text'; import ExtensionEditStep2Form from '@akashaorg/design-system-components/lib/components/ExtensionEditStep2Form'; -import { - getMediaUrl, - saveMediaFile, - transformSource, - useAkashaStore, - useRootComponentProps, -} from '@akashaorg/ui-awf-hooks'; -import { - GalleryImage, - NotificationEvents, - NotificationTypes, - Extension, -} from '@akashaorg/typings/lib/ui'; +import { useAkashaStore, transformSource, useRootComponentProps } from '@akashaorg/ui-awf-hooks'; +import { NotificationEvents, NotificationTypes, Extension } from '@akashaorg/typings/lib/ui'; import { DRAFT_EXTENSIONS } from '../../../constants'; import { useAtom } from 'jotai'; import { AtomContext, FormData } from './main-page'; @@ -76,76 +65,23 @@ export const ExtensionEditStep2Page: React.FC = ({ const [, setForm] = useAtom(useContext(AtomContext)); - const [uploading, setUploading] = useState(false); - const [galleryImages, setGalleryImages] = useState( - formDefault?.gallery?.map(img => { - const imgWithGateway = transformSource(img); - return { - ...img, - src: img?.src, - displaySrc: imgWithGateway?.src, - size: { - height: img?.height, - width: img?.width, - }, - }; - }), + const galleryImages = useMemo( + () => + formDefault?.gallery?.map(img => { + const imgWithGateway = transformSource(img); + return { + ...img, + src: img?.src, + displaySrc: imgWithGateway?.src, + size: { + height: img?.height, + width: img?.width, + }, + }; + }), + [formDefault?.gallery], ); - const onUpload = async (image: File | string, isUrl?: boolean) => { - if (!image) return null; - setUploading(true); - - const imageName = typeof image === 'string' ? image : image.name || 'extension-gallery-image'; - - try { - const mediaFile = await saveMediaFile({ - name: imageName, - isUrl: isUrl || false, - content: image, - }); - setUploading(false); - if (!mediaFile) return null; - - const mediaUri = `ipfs://${mediaFile.CID}`; - - const mediaUrl = getMediaUrl(mediaUri); - - const imageObj = { - size: { height: mediaFile.size.height, width: mediaFile.size.width }, - displaySrc: mediaUrl.originLink || mediaUrl.fallbackLink, - src: mediaUri, - name: imageName, - originalSrc: typeof image === 'string' ? image : URL.createObjectURL(image), - }; - - return imageObj; - } catch (error) { - setUploading(false); - showErrorNotification(t("The image wasn't uploaded correctly. Please try again!")); - return null; - } - }; - - const uploadNewImage = async (image: File | string, isUrl?: boolean) => { - const uploadedImage = await onUpload(image, isUrl); - setGalleryImages(prev => [ - ...prev, - { - name: uploadedImage?.name, - src: uploadedImage?.src, - displaySrc: uploadedImage?.displaySrc, - originalSrc: uploadedImage?.originalSrc, - size: uploadedImage?.size, - }, - ]); - }; - - const handleDeleteImage = (element: GalleryImage) => { - const newImages = galleryImages.filter(image => image.src !== element.src); - setGalleryImages(newImages); - }; - return ( @@ -158,9 +94,9 @@ export const ExtensionEditStep2Page: React.FC = ({ nsfwDescriptionLabel={t('Once you mark it as NSFW, you can’t change it back')} descriptionFieldLabel={t('Description')} descriptionPlaceholderLabel={t('What does this extension do?')} - galleryFieldLabel={t('Gallery')} + galleryFieldLabel={t('Extension Gallery')} galleryDescriptionLabel={t( - 'Having a gallery to show off the extension will increase installs', + 'The first three images, based on your order, will be featured on the main extension card.', )} usefulLinksFieldLabel={t('Useful Links')} usefulLinksDescriptionLabel={t( @@ -169,11 +105,13 @@ export const ExtensionEditStep2Page: React.FC = ({ linkTitleLabel={t('Link')} linkPlaceholderLabel={t('Link title')} addLabel={t('Add')} - uploading={uploading} - handleImageUpload={uploadNewImage} - handleImageDelete={handleDeleteImage} + uploadAndEditLabel={t('Upload & Edit')} + imagesUploadedLabel={t('images uploaded')} images={galleryImages} defaultValues={formDefault} + handleMediaClick={() => { + //todo + }} cancelButton={{ label: t('Back'), disabled: false, diff --git a/extensions/apps/notifications/src/components/pages/customise-notification-page.tsx b/extensions/apps/notifications/src/components/pages/customise-notification-page.tsx index 5b3f885ee4..975cacf117 100644 --- a/extensions/apps/notifications/src/components/pages/customise-notification-page.tsx +++ b/extensions/apps/notifications/src/components/pages/customise-notification-page.tsx @@ -8,12 +8,7 @@ import React, { } from 'react'; import { useTranslation } from 'react-i18next'; -import { - IMenuItem, - MenuItemAreaType, - NotificationEvents, - NotificationTypes, -} from '@akashaorg/typings/lib/ui'; +import { MenuItemAreaType, NotificationEvents, NotificationTypes } from '@akashaorg/typings/lib/ui'; import { useRootComponentProps, useSaveSettings, diff --git a/libs/design-system-components/src/components/EditProfile/index.tsx b/libs/design-system-components/src/components/EditProfile/index.tsx index a01a9d31ad..a28f0e9564 100644 --- a/libs/design-system-components/src/components/EditProfile/index.tsx +++ b/libs/design-system-components/src/components/EditProfile/index.tsx @@ -91,7 +91,7 @@ const EditProfile: React.FC = ({ if (isValid && isFormDirty) { saveButton.handleClick({ ...formValues, - links: formValues.links?.map(link => link.href)?.filter(link => link) || [], + links: formValues.links?.map(link => link.href?.trim())?.filter(link => link) || [], }); } }; diff --git a/libs/design-system-components/src/components/ExtensionEditStep2Form/Gallery/index.tsx b/libs/design-system-components/src/components/ExtensionEditStep2Form/Gallery/index.tsx index e089cbb2d5..4ccc6dd29d 100644 --- a/libs/design-system-components/src/components/ExtensionEditStep2Form/Gallery/index.tsx +++ b/libs/design-system-components/src/components/ExtensionEditStep2Form/Gallery/index.tsx @@ -1,22 +1,23 @@ -import React, { RefObject, useRef } from 'react'; - +import React, { Fragment, useState } from 'react'; import Button from '@akashaorg/design-system-core/lib/components/Button'; import Stack from '@akashaorg/design-system-core/lib/components/Stack'; import Text from '@akashaorg/design-system-core/lib/components/Text'; import Image from '@akashaorg/design-system-core/lib/components/Image'; -import Icon from '@akashaorg/design-system-core/lib/components/Icon'; -import Spinner from '@akashaorg/design-system-core/lib/components/Spinner'; -import { PlusIcon, TrashIcon } from '@heroicons/react/24/outline'; +import ImageOverlay from '../../ImageOverlay'; +import { PlusIcon } from '@heroicons/react/24/outline'; import { type GalleryImage } from '@akashaorg/typings/lib/ui'; +const MAX_IMAGES_DISPLAY = 3; +const MAX_IMAGES = 16; + export type GalleryProps = { - galleryFieldLabel?: string; - galleryDescriptionLabel?: string; - addLabel?: string; + galleryFieldLabel: string; + galleryDescriptionLabel: string; + addLabel: string; + uploadAndEditLabel: string; + imagesUploadedLabel: string; images: GalleryImage[]; - handleImageUpload?: (image: File) => void; - handleImageDelete?: (image: GalleryImage) => void; - uploading?: boolean; + handleMediaClick: () => void; }; export const Gallery: React.FC = props => { @@ -24,33 +25,37 @@ export const Gallery: React.FC = props => { galleryFieldLabel, galleryDescriptionLabel, addLabel, + uploadAndEditLabel, + imagesUploadedLabel, images, - uploading, - handleImageUpload, - handleImageDelete, + handleMediaClick, } = props; - const uploadInputRef: RefObject = useRef(null); - const imageUploadDisabled = React.useMemo(() => { - return images?.length > 15 || uploading; - }, [images, uploading]); + const galleryHasImages = images?.length > 0; + const slicedImagesArr = galleryHasImages ? images.slice(0, MAX_IMAGES_DISPLAY) : []; + const [showOverlay, setShowOverlay] = useState(false); + const [selectedImage, setSelectedImage] = useState(null); + + const handleCloseOverlay = () => { + setShowOverlay(false); + }; - const handleMediaClick = () => { - if (uploadInputRef.current && !imageUploadDisabled) { - uploadInputRef.current.click(); - } + const handleImageClick = (image: GalleryImage) => { + setShowOverlay(true); + setSelectedImage(image); }; return ( - - + + - {galleryFieldLabel} + + {galleryFieldLabel} + + {galleryHasImages && ( + + {slicedImagesArr.map((image, index) => ( + + {image.name} handleImageClick(image)} + customStyle="object-contain w-[10.625rem] h-[10.625rem] object-cover rounded-lg cursor-pointer" + /> + {showOverlay && ( + ({ + name: image.name, + size: image.size, + src: image.originalSrc || image.displaySrc || image.src, + }))} + clickedImg={{ + name: selectedImage.name, + size: selectedImage.size, + src: selectedImage.originalSrc || selectedImage.displaySrc || selectedImage.src, + }} + closeModal={handleCloseOverlay} + /> + )} + + ))} - ))} - {uploading && } - { - handleImageUpload(e.target.files[0]); - uploadInputRef.current.value = ''; - }} - hidden - /> + )} + + {images?.length ?? 0}/{MAX_IMAGES} {imagesUploadedLabel} + ); }; diff --git a/libs/design-system-components/src/components/ExtensionEditStep2Form/UsefulLinks/index.tsx b/libs/design-system-components/src/components/ExtensionEditStep2Form/UsefulLinks/index.tsx index b765892935..72bf6aa07e 100644 --- a/libs/design-system-components/src/components/ExtensionEditStep2Form/UsefulLinks/index.tsx +++ b/libs/design-system-components/src/components/ExtensionEditStep2Form/UsefulLinks/index.tsx @@ -40,7 +40,9 @@ export const UsefulLinks: React.FC = ({ - {usefulLinksTitleLabel} + + {usefulLinksTitleLabel} +