From 7d493d61dbaeb9916262c9164f237a56659a4977 Mon Sep 17 00:00:00 2001 From: Ronald Langeveld Date: Fri, 13 Oct 2023 14:15:14 +0700 Subject: [PATCH] Cleaned up Unsplash component in Admin (#18603) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit no issue - Fixed a bug where the Unsplash button in site design didn't hide if the integration was disabled. - Cleaned up Unsplash in preparation for moving it to it's own package in future. --- ### 🤖 Generated by Copilot at 4da5d12 Refactored and improved the Unsplash integration feature in the admin settings app. Moved all files related to Unsplash to a separate `unsplash` folder and renamed some classes and interfaces to avoid confusion. Added a feature flag for Unsplash in the brand settings component and a prop to customize the portal container for the Unsplash search modal. Created a new class `PhotoUseCases` to handle the logic for fetching, searching, and downloading photos from Unsplash. --- apps/admin-x-settings/src/App.tsx | 2 +- .../components/providers/ServiceProvider.tsx | 2 +- .../site/designAndBranding/BrandSettings.tsx | 4 +- apps/admin-x-settings/src/main.tsx | 2 +- .../unsplash/UnsplashSearchModal.tsx | 12 +++--- .../{utils => }/unsplash/UnsplashService.ts | 0 .../src/{utils => }/unsplash/UnsplashTypes.ts | 0 .../api/InMemoryUnsplashProvider.ts} | 3 +- .../api/UnsplashProvider.ts} | 10 +---- .../unsplash/api/unsplashFixtures.ts | 0 .../unsplash/assets/kg-card-type-unsplash.svg | 0 .../unsplash/assets/kg-close.svg | 0 .../unsplash/assets/kg-download.svg | 0 .../unsplash/assets/kg-search.svg | 0 .../unsplash/assets/kg-unsplash-heart.svg | 0 .../unsplash/masonry/MasonryService.ts | 0 .../src/unsplash/photo/PhotoUseCase.ts | 37 +++++++++++++++++++ .../src/{utils => unsplash}/portal.tsx | 5 ++- .../unsplash/ui/UnsplashButton.tsx | 0 .../unsplash/ui/UnsplashGallery.tsx | 2 +- .../unsplash/ui/UnsplashImage.tsx | 2 +- .../unsplash/ui/UnsplashSelector.tsx | 0 .../unsplash/ui/UnsplashZoomed.tsx | 3 +- .../src/utils/unsplash/photo/PhotoUseCase.ts | 36 ------------------ .../test/unit/unsplash/Masonry.test.ts | 6 +-- .../unit/unsplash/UnsplashService.test.ts | 17 ++++----- 26 files changed, 67 insertions(+), 76 deletions(-) rename apps/admin-x-settings/src/{utils => }/unsplash/UnsplashSearchModal.tsx (94%) rename apps/admin-x-settings/src/{utils => }/unsplash/UnsplashService.ts (100%) rename apps/admin-x-settings/src/{utils => }/unsplash/UnsplashTypes.ts (100%) rename apps/admin-x-settings/src/{utils/unsplash/api/InMemoryUnsplashRepository.ts => unsplash/api/InMemoryUnsplashProvider.ts} (91%) rename apps/admin-x-settings/src/{utils/unsplash/api/UnsplashRepository.ts => unsplash/api/UnsplashProvider.ts} (94%) rename apps/admin-x-settings/src/{utils => }/unsplash/api/unsplashFixtures.ts (100%) rename apps/admin-x-settings/src/{admin-x-ds => }/unsplash/assets/kg-card-type-unsplash.svg (100%) rename apps/admin-x-settings/src/{admin-x-ds => }/unsplash/assets/kg-close.svg (100%) rename apps/admin-x-settings/src/{admin-x-ds => }/unsplash/assets/kg-download.svg (100%) rename apps/admin-x-settings/src/{admin-x-ds => }/unsplash/assets/kg-search.svg (100%) rename apps/admin-x-settings/src/{admin-x-ds => }/unsplash/assets/kg-unsplash-heart.svg (100%) rename apps/admin-x-settings/src/{utils => }/unsplash/masonry/MasonryService.ts (100%) create mode 100644 apps/admin-x-settings/src/unsplash/photo/PhotoUseCase.ts rename apps/admin-x-settings/src/{utils => unsplash}/portal.tsx (77%) rename apps/admin-x-settings/src/{admin-x-ds => }/unsplash/ui/UnsplashButton.tsx (100%) rename apps/admin-x-settings/src/{admin-x-ds => }/unsplash/ui/UnsplashGallery.tsx (98%) rename apps/admin-x-settings/src/{admin-x-ds => }/unsplash/ui/UnsplashImage.tsx (97%) rename apps/admin-x-settings/src/{admin-x-ds => }/unsplash/ui/UnsplashSelector.tsx (100%) rename apps/admin-x-settings/src/{admin-x-ds => }/unsplash/ui/UnsplashZoomed.tsx (94%) delete mode 100644 apps/admin-x-settings/src/utils/unsplash/photo/PhotoUseCase.ts diff --git a/apps/admin-x-settings/src/App.tsx b/apps/admin-x-settings/src/App.tsx index 264a6cd092..218c616501 100644 --- a/apps/admin-x-settings/src/App.tsx +++ b/apps/admin-x-settings/src/App.tsx @@ -4,7 +4,7 @@ import MainContent from './MainContent'; import NiceModal from '@ebay/nice-modal-react'; import RoutingProvider, {ExternalLink} from './components/providers/RoutingProvider'; import clsx from 'clsx'; -import {DefaultHeaderTypes} from './utils/unsplash/UnsplashTypes'; +import {DefaultHeaderTypes} from './unsplash/UnsplashTypes'; import {FetchKoenigLexical, OfficialTheme, ServicesProvider} from './components/providers/ServiceProvider'; import {GlobalDirtyStateProvider} from './hooks/useGlobalDirtyState'; import {QueryClient, QueryClientProvider} from '@tanstack/react-query'; diff --git a/apps/admin-x-settings/src/components/providers/ServiceProvider.tsx b/apps/admin-x-settings/src/components/providers/ServiceProvider.tsx index ad65ef90d0..8b1b541771 100644 --- a/apps/admin-x-settings/src/components/providers/ServiceProvider.tsx +++ b/apps/admin-x-settings/src/components/providers/ServiceProvider.tsx @@ -1,6 +1,6 @@ import React, {createContext, useContext} from 'react'; import useSearchService, {SearchService} from '../../utils/search'; -import {DefaultHeaderTypes} from '../../utils/unsplash/UnsplashTypes'; +import {DefaultHeaderTypes} from '../../unsplash/UnsplashTypes'; import {UpgradeStatusType} from '../../utils/globalTypes'; import {ZapierTemplate} from '../settings/advanced/integrations/ZapierModal'; diff --git a/apps/admin-x-settings/src/components/settings/site/designAndBranding/BrandSettings.tsx b/apps/admin-x-settings/src/components/settings/site/designAndBranding/BrandSettings.tsx index 77dd91d934..5516f88ff0 100644 --- a/apps/admin-x-settings/src/components/settings/site/designAndBranding/BrandSettings.tsx +++ b/apps/admin-x-settings/src/components/settings/site/designAndBranding/BrandSettings.tsx @@ -5,7 +5,7 @@ import ImageUpload from '../../../../admin-x-ds/global/form/ImageUpload'; import React, {useRef, useState} from 'react'; import SettingGroupContent from '../../../../admin-x-ds/settings/SettingGroupContent'; import TextField from '../../../../admin-x-ds/global/form/TextField'; -import UnsplashSearchModal from '../../../../utils/unsplash/UnsplashSearchModal'; +import UnsplashSearchModal from '../../../../unsplash/UnsplashSearchModal'; import useHandleError from '../../../../utils/api/handleError'; import usePinturaEditor from '../../../../hooks/usePinturaEditor'; import {SettingValue, getSettingValues} from '../../../../api/settings'; @@ -144,7 +144,7 @@ const BrandSettings: React.FC<{ values: BrandSettingValues, updateSetting: (key: } } unsplashButtonClassName='!top-1 !right-1' - unsplashEnabled={true} + unsplashEnabled={unsplashEnabled} onDelete={() => updateSetting('cover_image', null)} onUpload={async (file) => { try { diff --git a/apps/admin-x-settings/src/main.tsx b/apps/admin-x-settings/src/main.tsx index 4eced56ed7..abc3657d80 100644 --- a/apps/admin-x-settings/src/main.tsx +++ b/apps/admin-x-settings/src/main.tsx @@ -2,7 +2,7 @@ import './styles/demo.css'; import App from './App.tsx'; import React from 'react'; import ReactDOM from 'react-dom/client'; -import {DefaultHeaderTypes} from './utils/unsplash/UnsplashTypes.ts'; +import {DefaultHeaderTypes} from './unsplash/UnsplashTypes.ts'; ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render( diff --git a/apps/admin-x-settings/src/utils/unsplash/UnsplashSearchModal.tsx b/apps/admin-x-settings/src/unsplash/UnsplashSearchModal.tsx similarity index 94% rename from apps/admin-x-settings/src/utils/unsplash/UnsplashSearchModal.tsx rename to apps/admin-x-settings/src/unsplash/UnsplashSearchModal.tsx index c847c3fd6a..86c00216c1 100644 --- a/apps/admin-x-settings/src/utils/unsplash/UnsplashSearchModal.tsx +++ b/apps/admin-x-settings/src/unsplash/UnsplashSearchModal.tsx @@ -1,11 +1,11 @@ import MasonryService from './masonry/MasonryService'; -import Portal from '../portal'; +import Portal from './portal'; import React, {useMemo, useRef, useState} from 'react'; -import UnsplashGallery from '../../admin-x-ds/unsplash/ui/UnsplashGallery'; -import UnsplashSelector from '../../admin-x-ds/unsplash/ui/UnsplashSelector'; +import UnsplashGallery from './ui/UnsplashGallery'; +import UnsplashSelector from './ui/UnsplashSelector'; import {DefaultHeaderTypes, Photo} from './UnsplashTypes'; import {PhotoUseCases} from './photo/PhotoUseCase'; -import {UnsplashRepository} from './api/UnsplashRepository'; +import {UnsplashProvider} from './api/UnsplashProvider'; import {UnsplashService} from './UnsplashService'; interface UnsplashModalProps { @@ -17,7 +17,7 @@ interface UnsplashModalProps { } const UnsplashSearchModal : React.FC = ({onClose, onImageInsert, unsplashConf}) => { - const unsplashRepo = useMemo(() => new UnsplashRepository(unsplashConf.defaultHeaders), [unsplashConf.defaultHeaders]); + const unsplashRepo = useMemo(() => new UnsplashProvider(unsplashConf.defaultHeaders), [unsplashConf.defaultHeaders]); const photoUseCase = useMemo(() => new PhotoUseCases(unsplashRepo), [unsplashRepo]); const masonryService = useMemo(() => new MasonryService(3), []); const UnsplashLib = useMemo(() => new UnsplashService(photoUseCase, masonryService), [photoUseCase, masonryService]); @@ -170,7 +170,7 @@ const UnsplashSearchModal : React.FC = ({onClose, onImageIns } } return ( - + ; - fetchNextPage(): Promise; - searchPhotos(term: string): Promise; - triggerDownload(photo: Photo): void; - searchIsRunning(): boolean; - } - -export class UnsplashRepository implements IUnsplashRepository { +export class UnsplashProvider { API_URL: string = 'https://api.unsplash.com'; HEADERS: DefaultHeaderTypes; ERROR: string | null = null; diff --git a/apps/admin-x-settings/src/utils/unsplash/api/unsplashFixtures.ts b/apps/admin-x-settings/src/unsplash/api/unsplashFixtures.ts similarity index 100% rename from apps/admin-x-settings/src/utils/unsplash/api/unsplashFixtures.ts rename to apps/admin-x-settings/src/unsplash/api/unsplashFixtures.ts diff --git a/apps/admin-x-settings/src/admin-x-ds/unsplash/assets/kg-card-type-unsplash.svg b/apps/admin-x-settings/src/unsplash/assets/kg-card-type-unsplash.svg similarity index 100% rename from apps/admin-x-settings/src/admin-x-ds/unsplash/assets/kg-card-type-unsplash.svg rename to apps/admin-x-settings/src/unsplash/assets/kg-card-type-unsplash.svg diff --git a/apps/admin-x-settings/src/admin-x-ds/unsplash/assets/kg-close.svg b/apps/admin-x-settings/src/unsplash/assets/kg-close.svg similarity index 100% rename from apps/admin-x-settings/src/admin-x-ds/unsplash/assets/kg-close.svg rename to apps/admin-x-settings/src/unsplash/assets/kg-close.svg diff --git a/apps/admin-x-settings/src/admin-x-ds/unsplash/assets/kg-download.svg b/apps/admin-x-settings/src/unsplash/assets/kg-download.svg similarity index 100% rename from apps/admin-x-settings/src/admin-x-ds/unsplash/assets/kg-download.svg rename to apps/admin-x-settings/src/unsplash/assets/kg-download.svg diff --git a/apps/admin-x-settings/src/admin-x-ds/unsplash/assets/kg-search.svg b/apps/admin-x-settings/src/unsplash/assets/kg-search.svg similarity index 100% rename from apps/admin-x-settings/src/admin-x-ds/unsplash/assets/kg-search.svg rename to apps/admin-x-settings/src/unsplash/assets/kg-search.svg diff --git a/apps/admin-x-settings/src/admin-x-ds/unsplash/assets/kg-unsplash-heart.svg b/apps/admin-x-settings/src/unsplash/assets/kg-unsplash-heart.svg similarity index 100% rename from apps/admin-x-settings/src/admin-x-ds/unsplash/assets/kg-unsplash-heart.svg rename to apps/admin-x-settings/src/unsplash/assets/kg-unsplash-heart.svg diff --git a/apps/admin-x-settings/src/utils/unsplash/masonry/MasonryService.ts b/apps/admin-x-settings/src/unsplash/masonry/MasonryService.ts similarity index 100% rename from apps/admin-x-settings/src/utils/unsplash/masonry/MasonryService.ts rename to apps/admin-x-settings/src/unsplash/masonry/MasonryService.ts diff --git a/apps/admin-x-settings/src/unsplash/photo/PhotoUseCase.ts b/apps/admin-x-settings/src/unsplash/photo/PhotoUseCase.ts new file mode 100644 index 0000000000..d46cd8e131 --- /dev/null +++ b/apps/admin-x-settings/src/unsplash/photo/PhotoUseCase.ts @@ -0,0 +1,37 @@ +import {InMemoryUnsplashProvider} from '../api/InMemoryUnsplashProvider'; +import {Photo} from '../UnsplashTypes'; +import {UnsplashProvider} from '../api/UnsplashProvider'; + +export class PhotoUseCases { + private _provider: UnsplashProvider | InMemoryUnsplashProvider; // InMemoryUnsplashProvider is for testing purposes + + constructor(provider: UnsplashProvider | InMemoryUnsplashProvider) { + this._provider = provider; + } + + async fetchPhotos(): Promise { + return await this._provider.fetchPhotos(); + } + + async searchPhotos(term: string): Promise { + return await this._provider.searchPhotos(term); + } + + async triggerDownload(photo: Photo): Promise { + this._provider.triggerDownload(photo); + } + + async fetchNextPage(): Promise { + let request = await this._provider.fetchNextPage(); + + if (request) { + return request; + } + + return null; + } + + searchIsRunning(): boolean { + return this._provider.searchIsRunning(); + } +} diff --git a/apps/admin-x-settings/src/utils/portal.tsx b/apps/admin-x-settings/src/unsplash/portal.tsx similarity index 77% rename from apps/admin-x-settings/src/utils/portal.tsx rename to apps/admin-x-settings/src/unsplash/portal.tsx index 5afe1b540c..8f0620221a 100644 --- a/apps/admin-x-settings/src/utils/portal.tsx +++ b/apps/admin-x-settings/src/unsplash/portal.tsx @@ -4,9 +4,10 @@ import {createPortal} from 'react-dom'; interface PortalProps { children: ReactNode; to?: Element; + classNames?: string; } -const Portal: React.FC = ({children, to}) => { +const Portal: React.FC = ({children, to, classNames}) => { const container: Element = to || document.body; if (!container) { @@ -18,7 +19,7 @@ const Portal: React.FC = ({children, to}) => { }; return createPortal( -
+
{children}
diff --git a/apps/admin-x-settings/src/admin-x-ds/unsplash/ui/UnsplashButton.tsx b/apps/admin-x-settings/src/unsplash/ui/UnsplashButton.tsx similarity index 100% rename from apps/admin-x-settings/src/admin-x-ds/unsplash/ui/UnsplashButton.tsx rename to apps/admin-x-settings/src/unsplash/ui/UnsplashButton.tsx diff --git a/apps/admin-x-settings/src/admin-x-ds/unsplash/ui/UnsplashGallery.tsx b/apps/admin-x-settings/src/unsplash/ui/UnsplashGallery.tsx similarity index 98% rename from apps/admin-x-settings/src/admin-x-ds/unsplash/ui/UnsplashGallery.tsx rename to apps/admin-x-settings/src/unsplash/ui/UnsplashGallery.tsx index bd3a165d7c..e162358094 100644 --- a/apps/admin-x-settings/src/admin-x-ds/unsplash/ui/UnsplashGallery.tsx +++ b/apps/admin-x-settings/src/unsplash/ui/UnsplashGallery.tsx @@ -1,7 +1,7 @@ import React, {ReactNode, RefObject} from 'react'; import UnsplashImage from './UnsplashImage'; import UnsplashZoomed from './UnsplashZoomed'; -import {Photo} from '../../../utils/unsplash/UnsplashTypes'; +import {Photo} from '../UnsplashTypes'; interface MasonryColumnProps { children: ReactNode; diff --git a/apps/admin-x-settings/src/admin-x-ds/unsplash/ui/UnsplashImage.tsx b/apps/admin-x-settings/src/unsplash/ui/UnsplashImage.tsx similarity index 97% rename from apps/admin-x-settings/src/admin-x-ds/unsplash/ui/UnsplashImage.tsx rename to apps/admin-x-settings/src/unsplash/ui/UnsplashImage.tsx index 949173c8e9..f4c36bae1d 100644 --- a/apps/admin-x-settings/src/admin-x-ds/unsplash/ui/UnsplashImage.tsx +++ b/apps/admin-x-settings/src/unsplash/ui/UnsplashImage.tsx @@ -1,6 +1,6 @@ import UnsplashButton from './UnsplashButton'; import {FC, MouseEvent} from 'react'; -import {Links, Photo, User} from '../../../utils/unsplash/UnsplashTypes'; +import {Links, Photo, User} from '../UnsplashTypes'; export interface UnsplashImageProps { payload: Photo; diff --git a/apps/admin-x-settings/src/admin-x-ds/unsplash/ui/UnsplashSelector.tsx b/apps/admin-x-settings/src/unsplash/ui/UnsplashSelector.tsx similarity index 100% rename from apps/admin-x-settings/src/admin-x-ds/unsplash/ui/UnsplashSelector.tsx rename to apps/admin-x-settings/src/unsplash/ui/UnsplashSelector.tsx diff --git a/apps/admin-x-settings/src/admin-x-ds/unsplash/ui/UnsplashZoomed.tsx b/apps/admin-x-settings/src/unsplash/ui/UnsplashZoomed.tsx similarity index 94% rename from apps/admin-x-settings/src/admin-x-ds/unsplash/ui/UnsplashZoomed.tsx rename to apps/admin-x-settings/src/unsplash/ui/UnsplashZoomed.tsx index 3589f152a0..88860d3b18 100644 --- a/apps/admin-x-settings/src/admin-x-ds/unsplash/ui/UnsplashZoomed.tsx +++ b/apps/admin-x-settings/src/unsplash/ui/UnsplashZoomed.tsx @@ -1,7 +1,6 @@ import UnsplashImage, {UnsplashImageProps} from './UnsplashImage'; import {FC} from 'react'; - -import {Photo} from '../../../utils/unsplash/UnsplashTypes'; +import {Photo} from '../UnsplashTypes'; interface UnsplashZoomedProps extends Omit { zoomed: Photo | null; diff --git a/apps/admin-x-settings/src/utils/unsplash/photo/PhotoUseCase.ts b/apps/admin-x-settings/src/utils/unsplash/photo/PhotoUseCase.ts deleted file mode 100644 index a77d3b95b6..0000000000 --- a/apps/admin-x-settings/src/utils/unsplash/photo/PhotoUseCase.ts +++ /dev/null @@ -1,36 +0,0 @@ -import {IUnsplashRepository} from '../api/UnsplashRepository'; -import {Photo} from '../UnsplashTypes'; - -export class PhotoUseCases { - private repository: IUnsplashRepository; - - constructor(repository: IUnsplashRepository) { - this.repository = repository; - } - - async fetchPhotos(): Promise { - return await this.repository.fetchPhotos(); - } - - async searchPhotos(term: string): Promise { - return await this.repository.searchPhotos(term); - } - - async triggerDownload(photo: Photo): Promise { - this.repository.triggerDownload(photo); - } - - async fetchNextPage(): Promise { - let request = await this.repository.fetchNextPage(); - - if (request) { - return request; - } - - return null; - } - - searchIsRunning(): boolean { - return this.repository.searchIsRunning(); - } -} diff --git a/apps/admin-x-settings/test/unit/unsplash/Masonry.test.ts b/apps/admin-x-settings/test/unit/unsplash/Masonry.test.ts index dcfd9452b9..e42ecafe94 100644 --- a/apps/admin-x-settings/test/unit/unsplash/Masonry.test.ts +++ b/apps/admin-x-settings/test/unit/unsplash/Masonry.test.ts @@ -1,6 +1,6 @@ -import MasonryService from '../../../src/utils/unsplash/masonry/MasonryService'; -import {Photo} from '../../../src/utils/unsplash/UnsplashTypes'; -import {fixturePhotos} from '../../../src/utils/unsplash/api/unsplashFixtures'; +import MasonryService from '../../../src/unsplash/masonry/MasonryService'; +import {Photo} from '../../../src/unsplash/UnsplashTypes'; +import {fixturePhotos} from '../../../src/unsplash/api/unsplashFixtures'; describe('MasonryService', () => { let service: MasonryService; diff --git a/apps/admin-x-settings/test/unit/unsplash/UnsplashService.test.ts b/apps/admin-x-settings/test/unit/unsplash/UnsplashService.test.ts index 1900d86b9d..35ae259827 100644 --- a/apps/admin-x-settings/test/unit/unsplash/UnsplashService.test.ts +++ b/apps/admin-x-settings/test/unit/unsplash/UnsplashService.test.ts @@ -1,20 +1,19 @@ -import MasonryService from '../../../src/utils/unsplash/masonry/MasonryService'; -import {IUnsplashRepository} from '../../../src/utils/unsplash/api/UnsplashRepository'; -import {IUnsplashService, UnsplashService} from '../../../src/utils/unsplash/UnsplashService'; -import {InMemoryUnsplashRepository} from '../../../src/utils/unsplash/api/InMemoryUnsplashRepository'; -import {PhotoUseCases} from '../../../src/utils/unsplash/photo/PhotoUseCase'; -import {fixturePhotos} from '../../../src/utils/unsplash/api/unsplashFixtures'; +import MasonryService from '../../../src/unsplash/masonry/MasonryService'; +import {IUnsplashService, UnsplashService} from '../../../src/unsplash/UnsplashService'; +import {InMemoryUnsplashProvider} from '../../../src/unsplash/api/InMemoryUnsplashProvider'; +import {PhotoUseCases} from '../../../src/unsplash/photo/PhotoUseCase'; +import {fixturePhotos} from '../../../src/unsplash/api/unsplashFixtures'; describe('UnsplashService', () => { let unsplashService: IUnsplashService; - let unsplashRepository: IUnsplashRepository; + let UnsplashProvider: InMemoryUnsplashProvider; let masonryService: MasonryService; let photoUseCases: PhotoUseCases; beforeEach(() => { - unsplashRepository = new InMemoryUnsplashRepository(); + UnsplashProvider = new InMemoryUnsplashProvider(); masonryService = new MasonryService(3); - photoUseCases = new PhotoUseCases(unsplashRepository); + photoUseCases = new PhotoUseCases(UnsplashProvider); unsplashService = new UnsplashService(photoUseCases, masonryService); });