From 01279a8e333cf6d5381448608bbcfa3a4395d985 Mon Sep 17 00:00:00 2001 From: frozenhelium Date: Sun, 7 Jun 2026 14:43:45 +0545 Subject: [PATCH] fix(assess-image): remove direct image option --- .../ValidateImageDetails/index.tsx | 11 +- app/contexts/EnumsContext.ts | 7 - .../DirectImageAsset/index.tsx | 207 ------------------ .../DirectImageAsset/styles.module.css | 22 -- .../DirectImagesInput/index.tsx | 172 --------------- .../ValidateImageProjectSpecifics/index.tsx | 47 +--- .../styles.module.css | 10 - .../EditProject/UpdateProjectForm/index.tsx | 41 +++- app/views/RootLayout/index.tsx | 9 - .../0001-remove-direct-image-upload-option.md | 64 ++++++ 10 files changed, 109 insertions(+), 481 deletions(-) delete mode 100644 app/views/EditProject/UpdateProjectForm/ValidateImageProjectSpecifics/DirectImageAsset/index.tsx delete mode 100644 app/views/EditProject/UpdateProjectForm/ValidateImageProjectSpecifics/DirectImageAsset/styles.module.css delete mode 100644 app/views/EditProject/UpdateProjectForm/ValidateImageProjectSpecifics/DirectImagesInput/index.tsx create mode 100644 docs/adr/0001-remove-direct-image-upload-option.md diff --git a/app/components/domain/ProjectSpecificDetails/ValidateImageDetails/index.tsx b/app/components/domain/ProjectSpecificDetails/ValidateImageDetails/index.tsx index 83e3f874..9ecc38d1 100644 --- a/app/components/domain/ProjectSpecificDetails/ValidateImageDetails/index.tsx +++ b/app/components/domain/ProjectSpecificDetails/ValidateImageDetails/index.tsx @@ -1,12 +1,9 @@ -import { useContext } from 'react'; import { isNotDefined } from '@togglecorp/fujs'; import { removeNull } from '@togglecorp/toggle-form'; import Container from '#components/Container'; import CustomOptionPreview from '#components/domain/CustomOptionsPreview'; import ListLayout from '#components/ListLayout'; -import TextOutput from '#components/TextOutput'; -import EnumsContext from '#contexts/EnumsContext'; import { ValidateImageProjectPropertyType } from '#generated/types/graphql'; interface Props { @@ -16,18 +13,12 @@ interface Props { function ValidateImageDetails(props: Props) { const { data } = props; - const { validateImageSourceTypeMapping } = useContext(EnumsContext); - - if (isNotDefined(data) || isNotDefined(data.sourceType)) { + if (isNotDefined(data)) { return null; } return ( - | undefined; - validateImageSourceTypeMapping: Record< - AllEnumsQuery['enums']['ValidateImageSourceTypeEnum'][number]['key'], - AllEnumsQuery['enums']['ValidateImageSourceTypeEnum'][number] - > | undefined; projectStatusMapping: Record< AllEnumsQuery['enums']['ProjectStatusEnum'][number]['key'], AllEnumsQuery['enums']['ProjectStatusEnum'][number] @@ -54,7 +49,6 @@ export interface EnumsContextProps { export const defaultAllEnumsValue: EnumsContextProps = { validateObjectSourceTypeOptions: [], - validateImageSourceTypeOptions: [], projectStatusOptions: [], projectTypeOptions: [], tutorialInformationPageBlockTypeOptions: [], @@ -65,7 +59,6 @@ export const defaultAllEnumsValue: EnumsContextProps = { subGridSizeOptions: [], validateObjectSourceTypeMapping: undefined, - validateImageSourceTypeMapping: undefined, projectStatusMapping: undefined, projectTypeMapping: undefined, tutorialInformationPageBlockTypeMapping: undefined, diff --git a/app/views/EditProject/UpdateProjectForm/ValidateImageProjectSpecifics/DirectImageAsset/index.tsx b/app/views/EditProject/UpdateProjectForm/ValidateImageProjectSpecifics/DirectImageAsset/index.tsx deleted file mode 100644 index 374589fb..00000000 --- a/app/views/EditProject/UpdateProjectForm/ValidateImageProjectSpecifics/DirectImageAsset/index.tsx +++ /dev/null @@ -1,207 +0,0 @@ -import { - useCallback, - useContext, - useEffect, - useState, -} from 'react'; -import { - PiCheck, - PiSpinner, - PiTimer, - PiTrash, - PiWarningCircle, -} from 'react-icons/pi'; - -import Button from '#components/Button'; -import ColorPreview from '#components/ColorSelectInput/ColorPreview'; -import Container from '#components/Container'; -import InlineLayout from '#components/InlineLayout'; -import ListLayout from '#components/ListLayout'; -import PopupButton from '#components/PopupButton'; -import Tag from '#components/Tag'; -import BulkUploadContext from '#contexts/BulkUpload'; -import { - ProjectAssetInputTypeEnum, - useCreateProjectAssetMutation, -} from '#generated/types/graphql'; -import { - getErrorMessageAndDescriptionForCombinedError, - getErrorMessageFromResult, -} from '#utils/error'; - -import styles from './styles.module.css'; - -export interface DirectImage { - clientId: string; - file: File; -} - -interface Props { - projectId: string; - value: DirectImage; - onRemove: (clientId: string) => void; -} - -function DirectImageAsset(props: Props) { - const { - projectId, - value, - onRemove, - } = props; - - const { - statusMap, - uploadTokens, - register, - unregister, - updateStatus, - } = useContext(BulkUploadContext); - - const [errorMessage, setErrorMessage] = useState(); - - useEffect(() => { - register(value.clientId); - - return () => { unregister(value.clientId); }; - }, [register, unregister, value.clientId]); - - const [ - { fetching: createProjectAssetPending }, - createProjectAsset, - ] = useCreateProjectAssetMutation(); - - const uploadDatasetItem = useCallback(async () => { - try { - const result = await createProjectAsset({ - data: { - clientId: value.clientId, - project: projectId, - inputType: ProjectAssetInputTypeEnum.ObjectImage, - file: value.file, - }, - }); - - if ( - // eslint-disable-next-line no-underscore-dangle - result.data?.createProjectAsset.__typename === 'ProjectAssetTypeMutationResponseType' - && result.data.createProjectAsset.ok - && result.data.createProjectAsset.result - ) { - updateStatus(value.clientId, 'success'); - setErrorMessage(undefined); - return; - } - - const resultErrorMessage = getErrorMessageFromResult(result); - updateStatus(value.clientId, 'failed'); - - setErrorMessage( - resultErrorMessage ?? 'Unknown error occured!', - ); - } catch (combinedError) { - const { message } = getErrorMessageAndDescriptionForCombinedError(combinedError); - updateStatus(value.clientId, 'failed'); - setErrorMessage(message); - } - }, [createProjectAsset, projectId, updateStatus, value]); - - const canStartUpload = uploadTokens[value.clientId]; - - useEffect(() => { - if (canStartUpload) { - uploadDatasetItem(); - } - }, [canStartUpload, uploadDatasetItem]); - - const currentStatus = statusMap[value.clientId]; - - return ( - - {value.file.name} - - )} - spacing="sm" - headingLevel={6} - headerActions={( - - )} - headerDescription={( - - - {currentStatus === 'ready' && ( - } - withCenterAlign - spacing="xs" - > - Ready - - )} - {createProjectAssetPending && ( - } - withCenterAlign - spacing="xs" - > - Uploading - - - )} - {currentStatus === 'success' && ( - } - withCenterAlign - spacing="xs" - > - Done - - )} - {currentStatus === 'failed' && ( - } - withCenterAlign - spacing="xs" - end={( - - )} - > - {errorMessage} - - )} - > - Failed - - )} - - - )} - > - {null} - - ); -} - -export default DirectImageAsset; diff --git a/app/views/EditProject/UpdateProjectForm/ValidateImageProjectSpecifics/DirectImageAsset/styles.module.css b/app/views/EditProject/UpdateProjectForm/ValidateImageProjectSpecifics/DirectImageAsset/styles.module.css deleted file mode 100644 index 8606b2b5..00000000 --- a/app/views/EditProject/UpdateProjectForm/ValidateImageProjectSpecifics/DirectImageAsset/styles.module.css +++ /dev/null @@ -1,22 +0,0 @@ -.direct-image-asset { - .file-name { - overflow-wrap: anywhere; - } - - .spinner { - animation: spin 1s linear infinite; - } - - .meta { - font-size: var(--font-size-sm); - } -} - -@keyframes spin { - 50% { - transform: rotate(180deg); - } - 100% { - transform: rotate(360deg); - } -} diff --git a/app/views/EditProject/UpdateProjectForm/ValidateImageProjectSpecifics/DirectImagesInput/index.tsx b/app/views/EditProject/UpdateProjectForm/ValidateImageProjectSpecifics/DirectImagesInput/index.tsx deleted file mode 100644 index f3c43a31..00000000 --- a/app/views/EditProject/UpdateProjectForm/ValidateImageProjectSpecifics/DirectImagesInput/index.tsx +++ /dev/null @@ -1,172 +0,0 @@ -import { - useCallback, - useId, - useState, -} from 'react'; -import { PiCloudArrowUp } from 'react-icons/pi'; -import { - isDefined, - isNotDefined, -} from '@togglecorp/fujs'; -import { ulid } from 'ulid'; - -import Button from '#components/Button'; -import Container from '#components/Container'; -import FileInput from '#components/FileInput'; -import ListLayout from '#components/ListLayout'; -import Modal from '#components/Modal'; -import ProgressBar from '#components/ProgressBar'; -import TextOutput from '#components/TextOutput'; -import BulkUploadContext, { useBulkUploadProvider } from '#contexts/BulkUpload'; -import { AssetMimetypeEnum } from '#generated/types/graphql'; - -import DirectImageAsset, { DirectImage } from '../DirectImageAsset'; - -const imageMimeTypeEnumMap: Record = { - 'image/jpeg': AssetMimetypeEnum.ImageJpeg, - 'image/png': AssetMimetypeEnum.ImagePng, - 'image/gif': AssetMimetypeEnum.ImageGif, -}; - -interface Props { - projectId: string; - onUploadModalClose: () => void; -} - -function DirectImagesInput(props: Props) { - const { - projectId, - onUploadModalClose, - } = props; - - const inputId = useId(); - - const [ - selectedImageFiles, - setSelectedImageFiles, - ] = useState(); - - const handleUploadImagesCancel = useCallback(() => { - setSelectedImageFiles(undefined); - onUploadModalClose(); - }, [onUploadModalClose]); - - const handleUploadImageFileRemove = useCallback((clientId: string) => { - setSelectedImageFiles((prevSelectedFiles) => { - const fileIndex = prevSelectedFiles?.findIndex((file) => file.clientId === clientId); - - if (isNotDefined(fileIndex) || fileIndex === -1) { - return prevSelectedFiles; - } - - return prevSelectedFiles?.toSpliced(fileIndex, 1); - }); - }, []); - - const handleImagesDirectorySelect = useCallback((files: File[] | undefined) => { - const pendingFiles = files?.filter( - (file) => !!imageMimeTypeEnumMap[file.type], - ).map((file) => ({ - clientId: ulid(), - file, - })); - - setSelectedImageFiles(pendingFiles); - }, []); - - const { - value, - startUpload, - pauseUpload, - uploadPending, - } = useBulkUploadProvider(); - - const numAssetsUploaded = Object.values(value.statusMap).filter((status) => status === 'success').length; - - return ( - - - {isDefined(selectedImageFiles) && ( - - - - - - )} - onClose={handleUploadImagesCancel} - footerActions={( - <> - - - - )} - size="lg" - withHeaderBorder - withFooterBorder - withWelledContent - > - - - {selectedImageFiles.map((selectedFile) => ( - - ))} - - - - )} - - ); -} - -export default DirectImagesInput; diff --git a/app/views/EditProject/UpdateProjectForm/ValidateImageProjectSpecifics/index.tsx b/app/views/EditProject/UpdateProjectForm/ValidateImageProjectSpecifics/index.tsx index a7b3b1f7..1ac3564f 100644 --- a/app/views/EditProject/UpdateProjectForm/ValidateImageProjectSpecifics/index.tsx +++ b/app/views/EditProject/UpdateProjectForm/ValidateImageProjectSpecifics/index.tsx @@ -1,6 +1,5 @@ import { useCallback, - useContext, useState, } from 'react'; import { IoAdd } from 'react-icons/io5'; @@ -32,20 +31,15 @@ import ListLayout from '#components/ListLayout/index.tsx'; import Modal from '#components/Modal/index.tsx'; import NonFieldError from '#components/NonFieldError/index.tsx'; import Pager from '#components/Pager/index.tsx'; -import RadioInput from '#components/RadioInput/index.tsx'; -import EnumsContext from '#contexts/EnumsContext.ts'; import { useProjectObjectImageAssetsQuery, useRemoveAllObjectImageAssetsMutation, - ValidateImageSourceTypeEnum, } from '#generated/types/graphql.ts'; import useAlert from '#hooks/useAlert.ts'; import useConfirmation from '#hooks/useConfirmation.ts'; import { DEFAULT_PAGE, defaultPagePerItemOptions, - keySelector, - labelSelector, } from '#utils/common.ts'; import { checkAndAlertGraphQLResultError, @@ -54,19 +48,16 @@ import { import { OPERATION_INFO_FRAGMENT } from '#utils/query.ts'; import DatasetFileInput from './DatasetFileInput/index.tsx'; -import DirectImagesInput from './DirectImagesInput/index.tsx'; import { type PartialValidateImageSpecificFields } from './schema.ts'; import styles from './styles.module.css'; -const DIRECT_IMAGES_ENABLED = false; - // eslint-disable-next-line @typescript-eslint/no-unused-vars const PROJECT_OBJECT_IMAGE_ASSETS_QUERY = gql` -query ProjectObjectImageAssets($projectId: ID!, $withoutMimeType: Boolean, $pagination: OffsetPaginationInput!) { +query ProjectObjectImageAssets($projectId: ID!, $pagination: OffsetPaginationInput!) { projectAssets( pagination: $pagination - filters: {projectId: {exact: $projectId}, inputType: {exact: OBJECT_IMAGE}, mimetype: {isNull: $withoutMimeType}} + filters: {projectId: {exact: $projectId}, inputType: {exact: OBJECT_IMAGE}, mimetype: {isNull: true}} ) { totalCount results { @@ -135,7 +126,6 @@ function ValidateProjectSpecifics(props: Props) { } = props; const alert = useAlert(); - const { validateImageSourceTypeOptions: sourceTypeOptions } = useContext(EnumsContext); const [activeAssetsPage, setActiveAssetsPage] = useState(DEFAULT_PAGE); const [assetsPerPage, setAssetsPerPage] = useState(20); @@ -155,7 +145,6 @@ function ValidateProjectSpecifics(props: Props) { offset: (activeAssetsPage - 1) * assetsPerPage, limit: assetsPerPage, }, - withoutMimeType: value?.sourceType !== ValidateImageSourceTypeEnum.DirectImages, }, }); @@ -283,32 +272,11 @@ function ValidateProjectSpecifics(props: Props) { headingLevel={4} heading="Images" > - 0} /> - {value?.sourceType === ValidateImageSourceTypeEnum.DirectImages - && DIRECT_IMAGES_ENABLED - && ( - - )} - {value?.sourceType === ValidateImageSourceTypeEnum.DatasetFile && ( - 0} - /> - )} {isDefined(objectImageAssetsResponse) && ( 0 && ( + headerActions={numUploadedImages > 0 && (