import React, { useEffect, useMemo, useState } from 'react'; import _ from 'lodash'; import styled from 'styled-components'; import { Typography, Box, SingleSelectOption, SingleSelect, Combobox, ComboboxOption, TextInput, Checkbox, TextButton, Button, Loader, } from '@strapi/design-system'; import { Collection, Entity } from 'types/data'; import PageContainer from '../../components/PageContainer'; import useApi from '../../utils/useApi'; import { fetchIntegrations, fetchCollections, fetchEntities, uploadEntities } from '../../api'; import Alert from '../../components/Alert'; import ErrorsList from './ErrorsList'; import Results from './Results'; const Entities = styled.div` display: grid; grid-template-columns: repeat(4, 1fr); gap: 20px; word-break: break-word; `; const EntitiesControlWrapper = styled.div` display: flex; align-items: baseline; gap: 20px; margin: 30px 0; `; const PageTitle = styled(Typography)` display: block; margin-bottom: 20px; `; const SelectsContainer = styled.div` width: 100%; display: flex; flex-direction: column; gap: 20px; `; const EntitiesContainer = styled.div` margin: 20px 0; `; const TextWithMargin = styled.p` margin: 10px 0; `; const ActionContainer = styled(Box)` box-shadow: ${({ theme }) => theme.shadows.filterShadow}; border-radius: 4px; padding: 15px 20px; `; const LoaderWrapper = styled.div` display: flex; justify-content: center; margin: 10px 0; `; const HomePage = () => { const [action, setAction] = useState<'upload' | 'download'>('upload'); const [selectedCollection, setSelectedCollection] = useState(); const { makeRequest: loadIntegrations, data: integrations, isLoading: integrationsLoading, isInitial: integrationsIsInitial, } = useApi(fetchIntegrations); const { makeRequest: loadEntities, data: collectionEntities, reset: resetEntities, isLoading: entitiesLoading, isInitial: entitiesIsInitial, } = useApi(fetchEntities); const { makeRequest: loadCollections, data: collections, isLoading: collectionsLoading, isInitial: collectionsIsInitial, } = useApi(fetchCollections); const [uploadAlert, setUploadAlert] = useState(''); const { makeRequest: uploadEntitiesRequest, errors: uploadErrors, data: uploadResults, reset: resetUploadRequest, isLoading: uploadLoading, } = useApi(uploadEntities, { onSuccess: () => { setUploadAlert('success'); }, onError: () => { setUploadAlert('error'); }, }); const [selectedIntegration, setSelectedIntegration] = useState(null); const [entitySearchText, setEntitySearchText] = useState(''); const [selectedEntities, setSelectedEntities] = useState([]); const [createRelations, setCreateRelations] = useState(false); const [uploadMedia, setUploadMedia] = useState(false); const [transferLocales, setTransferLocales] = useState(false); const entities = useMemo(() => { if (!entitySearchText || !selectedCollection) { return collectionEntities; } const { mainField } = selectedCollection; return _.filter(collectionEntities, entity => _.includes(_.toLower(entity[mainField]), _.toLower(entitySearchText))); }, [entitySearchText, collectionEntities, selectedCollection]); useEffect(() => { loadCollections(); loadIntegrations(); }, []); useEffect(() => { if (selectedCollection) { loadEntities(selectedCollection.id); } }, [selectedCollection]); const handleCollectionChange = (value: string) => { const collection = _.find(collections, (collection) => collection.id === value); setSelectedCollection(collection ?? null); handleClearCollection(); }; const handleClearCollection = () => { resetEntities(); resetUploadRequest(); setSelectedEntities([]); setEntitySearchText(''); }; const handleEntitySearchChange = (event: React.ChangeEvent) => { setEntitySearchText(event.target.value); }; const handleCheckEntity = (entity: Entity) => (event: React.ChangeEvent) => { const checked = event.target.checked; setSelectedEntities(checked ? [...selectedEntities, entity] : _.filter(selectedEntities, selected => selected.id !== entity.id)); }; const handleSelectAllEntities = () => { setSelectedEntities(entities ?? []); }; const handleClearEntitySelection = () => { setSelectedEntities([]); }; const renderOptions = () => _.map(collections, (collection) => { return ( {collection.name} ); }); const renderEntities = () => { if (!selectedCollection) { return null; } if (entitiesLoading || entitiesIsInitial) { return ( ); } if (_.isEmpty(collectionEntities)) { return ( There are no entities in the selected collection ); } const entityOptions = _.map(entities, (entity, index) => { const mainField = (entity as any)[selectedCollection.mainField] ?? null; const checked = Boolean(_.find(selectedEntities, e => e.id === entity.id)); const key = `${mainField}-${index}` ?? `${selectedCollection.apiNameSingular}-${index}`; return ( {mainField ?? `${selectedCollection.name}-${entity.id}`} ); }); return ( Main field for collection {selectedCollection.name}: {selectedCollection.mainField} Select all found Clear all {entityOptions} ); }; const handleAction = () => { if (!selectedCollection || !selectedIntegration) { return; } if (action === 'upload') { resetUploadRequest(); uploadEntitiesRequest({ collection: selectedCollection, entities: selectedEntities, createRelations, uploadMedia, transferLocales, integrationId: selectedIntegration, }); } }; const getSelectedIntegrationLabel = (val: string) => { const option = _.find(integrations, integration => String(integration.id) === val); return option ? option.name : 'Unknown option selected'; }; const renderErrors = () => { if (_.isEmpty(uploadErrors) || !selectedCollection) { return null; } return ( ); }; const renderResults = () => { if (_.isEmpty(uploadResults) || !selectedCollection || uploadLoading) { return null; } const integration = _.find(integrations, integration => String(integration.id) === selectedIntegration); const integrationUrl = integration?.url ?? ''; return ( ); }; const renderActionBlock = () => { if (!selectedCollection || _.isEmpty(selectedEntities)) { return null; } if (uploadLoading) { return ( ); } const actionDisabled = uploadLoading || !selectedIntegration; const actionName = action === 'download' ? 'Download' : 'Upload'; return ( {actionName} {selectedEntities.length} entities from collection {selectedCollection.name} setUploadMedia(!uploadMedia)} disabled={uploadLoading} > Upload media setCreateRelations(!createRelations)} disabled={uploadLoading} > Create relations setTransferLocales(!transferLocales)} disabled={uploadLoading} > Transfer locales {_.map(integrations, integration => ( {integration.name}
{integration.url}
))}

{renderErrors()} {renderResults()}
); }; const renderContent = () => { if (collectionsLoading || integrationsLoading || collectionsIsInitial || integrationsIsInitial) { return ( ); } return ( <> Upload Download {renderOptions()} {renderEntities()} {renderActionBlock()} ); }; return ( Content transfer setUploadAlert('')} title="Entities uploaded!" variant="success" /> setUploadAlert('')} title="Errors uploading entities" variant="danger" /> {renderContent()} ); }; export default HomePage;