From 81469cab6878ba7db42af858eaab2387cbf88bac Mon Sep 17 00:00:00 2001 From: jvega190 Date: Fri, 10 May 2024 16:16:01 -0600 Subject: [PATCH 01/30] [6633] Remove logicalResource from ConflictedPathDiffDialog --- .../ConflictedPathDiffDialog.tsx | 27 +++++++------------ .../ConflictedPathDiffDialogUI.tsx | 6 ++--- 2 files changed, 12 insertions(+), 21 deletions(-) diff --git a/ui/app/src/components/ConflictedPathDiffDialog/ConflictedPathDiffDialog.tsx b/ui/app/src/components/ConflictedPathDiffDialog/ConflictedPathDiffDialog.tsx index 2b6c735cf1..25b7b9ea27 100644 --- a/ui/app/src/components/ConflictedPathDiffDialog/ConflictedPathDiffDialog.tsx +++ b/ui/app/src/components/ConflictedPathDiffDialog/ConflictedPathDiffDialog.tsx @@ -14,7 +14,7 @@ * along with this program. If not, see . */ -import React, { useEffect, useMemo, useState } from 'react'; +import React, { useEffect, useState } from 'react'; import Dialog from '@mui/material/Dialog'; import DialogHeader from '../DialogHeader'; import DialogBody from '../DialogBody/DialogBody'; @@ -23,7 +23,6 @@ import { FormattedMessage, useIntl } from 'react-intl'; import { diffConflictedFile } from '../../services/repositories'; import ApiResponse from '../../models/ApiResponse'; import { FileDiff } from '../../models/Repository'; -import { SuspenseWithEmptyState } from '../Suspencified'; import ConflictedPathDiffDialogUI from './ConflictedPathDiffDialogUI'; import SecondaryButton from '../SecondaryButton'; import ConfirmDropdown from '../ConfirmDropdown'; @@ -33,7 +32,8 @@ import { makeStyles } from 'tss-react/mui'; import Tab from '@mui/material/Tab'; import Tabs from '@mui/material/Tabs'; import { useActiveSiteId } from '../../hooks/useActiveSiteId'; -import { useLogicResource } from '../../hooks/useLogicResource'; +import { ApiResponseErrorState } from '../ApiResponseErrorState'; +import { LoadingState } from '../LoadingState'; export interface RemoteRepositoriesDiffDialogProps { open: boolean; @@ -101,17 +101,6 @@ export function ConflictedPathDiffDialog(props: RemoteRepositoriesDiffDialogProp setTab(newValue); }; - const resource = useLogicResource( - useMemo(() => ({ fileDiff, error, fetching }), [fileDiff, error, fetching]), - { - shouldResolve: (source) => Boolean(source.fileDiff) && !fetching, - shouldReject: ({ error }) => Boolean(error), - shouldRenew: (source, resource) => fetching && resource.complete, - resultSelector: (source) => source.fileDiff, - errorSelector: () => error - } - ); - return ( - - - + {error ? ( + + ) : fetching ? ( + + ) : fileDiff ? ( + + ) : null} diff --git a/ui/app/src/components/ConflictedPathDiffDialog/ConflictedPathDiffDialogUI.tsx b/ui/app/src/components/ConflictedPathDiffDialog/ConflictedPathDiffDialogUI.tsx index 8d2c313a57..5a91c76f76 100644 --- a/ui/app/src/components/ConflictedPathDiffDialog/ConflictedPathDiffDialogUI.tsx +++ b/ui/app/src/components/ConflictedPathDiffDialog/ConflictedPathDiffDialogUI.tsx @@ -14,7 +14,6 @@ * along with this program. If not, see . */ -import { Resource } from '../../models/Resource'; import { FileDiff } from '../../models/Repository'; import React from 'react'; import { makeStyles } from 'tss-react/mui'; @@ -54,13 +53,12 @@ const useStyles = makeStyles()((theme) => ({ })); export interface RemoteRepositoriesDiffDialogUIProps { - resource: Resource; + fileDiff: FileDiff; tab: number; } export function ConflictedPathDiffDialogUI(props: RemoteRepositoriesDiffDialogUIProps) { - const { resource, tab } = props; - const fileDiff = resource.read(); + const { fileDiff, tab } = props; const { classes } = useStyles(); return ( From 4eec13543118ca4d4cd62c42b4d3c6c95a5f76e8 Mon Sep 17 00:00:00 2001 From: jvega190 Date: Fri, 10 May 2024 16:16:15 -0600 Subject: [PATCH 02/30] [6633] Remove logicalResource from PreviewPageExplorerPanel.tsx --- .../PreviewPageExplorerPanel.tsx | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/ui/app/src/components/PreviewPageExplorerPanel/PreviewPageExplorerPanel.tsx b/ui/app/src/components/PreviewPageExplorerPanel/PreviewPageExplorerPanel.tsx index df79539adf..8a02916f95 100644 --- a/ui/app/src/components/PreviewPageExplorerPanel/PreviewPageExplorerPanel.tsx +++ b/ui/app/src/components/PreviewPageExplorerPanel/PreviewPageExplorerPanel.tsx @@ -43,8 +43,6 @@ import { sortItemOperationComplete } from '../../state/actions/preview'; import { getHostToGuestBus, getHostToHostBus } from '../../utils/subjects'; -import Suspencified from '../Suspencified/Suspencified'; -import { Resource } from '../../models/Resource'; import palette from '../../styles/palette'; import { useDispatch } from 'react-redux'; import Typography from '@mui/material/Typography'; @@ -60,6 +58,7 @@ import { usePreviewGuest } from '../../hooks/usePreviewGuest'; import { useLogicResource } from '../../hooks/useLogicResource'; import { useUnmount } from '../../hooks/useUnmount'; import { useSpreadState } from '../../hooks/useSpreadState'; +import { LoadingState } from '../LoadingState'; const rootPrefix = '{root}_'; @@ -733,7 +732,7 @@ export function PreviewPageExplorerPanel() { - + {models && ContentTypesById ? ( - + ) : ( + + )} ); } interface PageExplorerUIProps { - resource: Resource; optionsMenu: { modelId: string; anchorEl: Element; @@ -777,7 +776,6 @@ interface PageExplorerUIProps { function PageExplorerUI(props: PageExplorerUIProps) { const { - resource, handleScroll, handleClick, handleOptions, @@ -794,8 +792,6 @@ function PageExplorerUI(props: PageExplorerUIProps) { const { classes } = useStyles(); const { formatMessage } = useIntl(); - resource.read(); - let node: any = null; if (selected === 'root') { From b8e510bee010cdf2df69880bebde808c11334870 Mon Sep 17 00:00:00 2001 From: jvega190 Date: Fri, 10 May 2024 16:36:50 -0600 Subject: [PATCH 03/30] [6633] Remove logicalResource from SiteManagement --- .../SiteManagement/SiteManagement.tsx | 104 ++++++++---------- ui/app/src/components/SitesGrid/SitesGrid.tsx | 6 +- 2 files changed, 48 insertions(+), 62 deletions(-) diff --git a/ui/app/src/components/SiteManagement/SiteManagement.tsx b/ui/app/src/components/SiteManagement/SiteManagement.tsx index 1102a1034a..bf54c58ee4 100644 --- a/ui/app/src/components/SiteManagement/SiteManagement.tsx +++ b/ui/app/src/components/SiteManagement/SiteManagement.tsx @@ -14,7 +14,7 @@ * along with this program. If not, see . */ -import React, { useEffect, useMemo, useState } from 'react'; +import React, { useEffect, useState } from 'react'; import { defineMessages, FormattedMessage, useIntl } from 'react-intl'; import AddIcon from '@mui/icons-material/Add'; import SkeletonSitesGrid from '../SitesGrid/SitesGridSkeleton'; @@ -35,7 +35,6 @@ import { fetchSites, popSite } from '../../state/actions/sites'; import { showErrorDialog } from '../../state/reducers/dialogs/error'; import { showEditSiteDialog } from '../../state/actions/dialogs'; import { ErrorBoundary } from '../ErrorBoundary/ErrorBoundary'; -import { SuspenseWithEmptyState } from '../Suspencified/Suspencified'; import SitesGrid from '../SitesGrid/SitesGrid'; import PublishingStatusDialog from '../PublishingStatusDialog'; import GlobalAppToolbar from '../GlobalAppToolbar'; @@ -45,7 +44,6 @@ import { hasGlobalPermissions } from '../../services/users'; import { foo } from '../../utils/object'; import { useEnv } from '../../hooks/useEnv'; import { useActiveUser } from '../../hooks/useActiveUser'; -import { useLogicResource } from '../../hooks/useLogicResource'; import { useSpreadState } from '../../hooks/useSpreadState'; import { useSitesBranch } from '../../hooks/useSitesBranch'; import Paper from '@mui/material/Paper'; @@ -60,6 +58,7 @@ import Alert from '@mui/material/Alert'; import FormControlLabel from '@mui/material/FormControlLabel'; import Checkbox from '@mui/material/Checkbox'; import { ConfirmDialog } from '../ConfirmDialog'; +import EmptyState from '../EmptyState'; const translations = defineMessages({ siteDeleted: { @@ -84,6 +83,7 @@ export function SiteManagement() { getStoredGlobalMenuSiteViewPreference(user.username) ?? 'grid' ); const { byId: sitesById, isFetching, active } = useSitesBranch(); + const sitesList = sitesById ? Object.values(sitesById) : null; const [selectedSiteStatus, setSelectedSiteStatus] = useState(null); const [permissionsLookup, setPermissionsLookup] = useState>(foo); const duplicateSiteDialogState = useEnhancedDialogState(); @@ -99,17 +99,6 @@ export function SiteManagement() { return () => subscription.unsubscribe(); }, []); - const resource = useLogicResource; isFetching: boolean }>( - useMemo(() => ({ sitesById, isFetching, permissionsLookup }), [sitesById, isFetching, permissionsLookup]), - { - shouldResolve: (source) => Boolean(source.sitesById) && permissionsLookup !== foo && !isFetching, - shouldReject: () => false, - shouldRenew: (source, resource) => resource.complete, - resultSelector: () => Object.values(sitesById), - errorSelector: () => null - } - ); - const onSiteClick = (site: Site) => { setSiteCookie(site.id, useBaseDomain); window.location.href = getSystemLink({ @@ -221,16 +210,25 @@ export function SiteManagement() { } /> - - }} - withEmptyStateProps={{ - emptyStateProps: { - title: , - styles: { root: { margin: undefined } }, - sxs: { + {isFetching ? ( + + ) : sitesList ? ( + sitesList.length > 0 ? ( + + ) : ( + } + styles={{ root: { margin: undefined } }} + sxs={{ root: { p: 5, bgcolor: 'background.default', @@ -240,40 +238,30 @@ export function SiteManagement() { marginLeft: 'auto', marginRight: 'auto' } - }, - children: ( - - {hasCreateSitePermission ? ( - {cardHeaderBlock} - ) : ( - cardHeaderBlock - )} - - ) - } - }} - > - - + }} + > + + {hasCreateSitePermission ? ( + {cardHeaderBlock} + ) : ( + cardHeaderBlock + )} + + + ) + ) : ( + <> + )} ; + sites: Site[]; onSiteClick(site: Site): void; onDeleteSiteClick(site: Site): void; onEditSiteClick(site: Site): void; @@ -40,7 +39,7 @@ interface SitesGridProps { export function SitesGrid(props: SitesGridProps) { const { - resource, + sites, onSiteClick, onDeleteSiteClick, onEditSiteClick, @@ -49,7 +48,6 @@ export function SitesGrid(props: SitesGridProps) { onPublishButtonClick, disabledSitesLookup } = props; - const sites = resource.read(); const { classes } = useSitesGridStyles(); return (
From 57932d9bb7696370c10a27d9480870f776770289 Mon Sep 17 00:00:00 2001 From: jvega190 Date: Mon, 20 May 2024 15:29:09 -0600 Subject: [PATCH 04/30] [6633] Remove logicalResource from NewContentDialog --- .../ChangeContentTypeDialogContainer.tsx | 79 ++++++++----------- .../NewContentDialog/NewContentDialog.tsx | 5 +- .../NewContentDialogContainer.tsx | 69 ++++++++-------- .../src/components/NewContentDialog/utils.ts | 3 +- 4 files changed, 70 insertions(+), 86 deletions(-) diff --git a/ui/app/src/components/ChangeContentTypeDialog/ChangeContentTypeDialogContainer.tsx b/ui/app/src/components/ChangeContentTypeDialog/ChangeContentTypeDialogContainer.tsx index ddd6ee09b2..f830c05dd9 100644 --- a/ui/app/src/components/ChangeContentTypeDialog/ChangeContentTypeDialogContainer.tsx +++ b/ui/app/src/components/ChangeContentTypeDialog/ChangeContentTypeDialogContainer.tsx @@ -17,11 +17,10 @@ import { ChangeContentTypeDialogContainerProps } from './utils'; import { useActiveSiteId } from '../../hooks/useActiveSiteId'; import { useDispatch } from 'react-redux'; -import React, { useEffect, useMemo, useState } from 'react'; +import React, { useEffect, useState } from 'react'; import { LegacyContentType } from '../../models/ContentType'; import { fetchLegacyContentTypes } from '../../services/contentTypes'; import { showErrorDialog } from '../../state/reducers/dialogs/error'; -import { useLogicResource } from '../../hooks/useLogicResource'; import { useSubject } from '../../hooks/useSubject'; import { debounceTime } from 'rxjs/operators'; import DialogBody from '../DialogBody/DialogBody'; @@ -29,10 +28,10 @@ import { Box, Checkbox, FormControlLabel } from '@mui/material'; import SingleItemSelector from '../SingleItemSelector'; import { FormattedMessage } from 'react-intl'; import SearchBar from '../SearchBar/SearchBar'; -import { SuspenseWithEmptyState } from '../Suspencified/Suspencified'; import { ContentTypesGrid, ContentTypesLoader } from '../NewContentDialog'; import DialogFooter from '../DialogFooter/DialogFooter'; import { makeStyles } from 'tss-react/mui'; +import EmptyState from '../EmptyState'; const useStyles = makeStyles()(() => ({ compact: { @@ -61,8 +60,12 @@ export function ChangeContentTypeDialogContainer(props: ChangeContentTypeDialogC const [openSelector, setOpenSelector] = useState(false); const [selectedItem, setSelectedItem] = useState(item); const [contentTypes, setContentTypes] = useState(); + const [isFetching, setIsFetching] = useState(false); const [keyword, setKeyword] = useState(''); const [debounceKeyword, setDebounceKeyword] = useState(''); + const filteredContentTypes = contentTypes?.filter((contentType) => + contentType.label.toLowerCase().includes(debounceKeyword.toLowerCase()) + ); const onSelectedContentType = (contentType: LegacyContentType) => { onContentTypeSelected?.({ @@ -72,8 +75,10 @@ export function ChangeContentTypeDialogContainer(props: ChangeContentTypeDialogC useEffect(() => { if (selectedItem.path) { - fetchLegacyContentTypes(site, selectedItem.path).subscribe( - (response) => { + setIsFetching(true); + fetchLegacyContentTypes(site, selectedItem.path).subscribe({ + next: (response) => { + setIsFetching(false); setContentTypes( response.filter( (contentType) => @@ -81,28 +86,14 @@ export function ChangeContentTypeDialogContainer(props: ChangeContentTypeDialogC ) ); }, - (response) => { + error: (response) => { + setIsFetching(false); dispatch(showErrorDialog({ error: response })); } - ); + }); } }, [dispatch, selectedItem, site]); - const resource = useLogicResource( - useMemo(() => ({ contentTypes, debounceKeyword }), [contentTypes, debounceKeyword]), - { - shouldResolve: ({ contentTypes }) => Boolean(contentTypes), - shouldReject: () => null, - shouldRenew: (source, resource) => resource.complete, - resultSelector: ({ contentTypes, debounceKeyword }) => { - return contentTypes.filter((contentType) => - contentType.label.toLowerCase().includes(debounceKeyword.toLowerCase()) - ); - }, - errorSelector: () => null - } - ); - const onSearch$ = useSubject(); useEffect(() => { @@ -138,32 +129,32 @@ export function ChangeContentTypeDialogContainer(props: ChangeContentTypeDialogC - - }} - withEmptyStateProps={{ - emptyStateProps: { - classes: { - image: classes.emptyStateImg - }, - title: ( + {isFetching ? ( + + ) : filteredContentTypes ? ( + filteredContentTypes.length > 0 ? ( + + ) : ( + - ) - } - }} - > - - + } + classes={{ + image: classes.emptyStateImg + }} + /> + ) + ) : ( + <> + )} - {filterContentTypes.map((content) => ( + {contentTypes.map((content) => ( (); + const [isFetching, setIsFetching] = useState(false); const [keyword, setKeyword] = useState(''); const [debounceKeyword, setDebounceKeyword] = useState(''); const [selectedFilter, setSelectedFilter] = useState('all'); + const filteredContentTypes = contentTypes?.filter( + (contentType) => + contentType.label.toLowerCase().includes(debounceKeyword.toLowerCase()) && + (selectedFilter === 'all' || contentType.type === selectedFilter) + ); const filters = [ { @@ -93,8 +98,10 @@ export function NewContentDialogContainer(props: NewContentDialogContainerProps) ? `${selectedItem.path}/` : selectedItem.path; + setIsFetching(true); fetchLegacyContentTypes(site, path).subscribe({ next(response) { + setIsFetching(false); if (response.length === 1) { dispatch(closeNewContentDialog()); onSelectedContentType(response[0]); @@ -103,29 +110,13 @@ export function NewContentDialogContainer(props: NewContentDialogContainerProps) } }, error(response) { + setIsFetching(false); dispatch(showErrorDialog({ error: response })); } }); } }, [dispatch, selectedItem, site, onSelectedContentType]); - const resource = useLogicResource( - useMemo(() => ({ contentTypes, selectedFilter, debounceKeyword }), [contentTypes, selectedFilter, debounceKeyword]), - { - shouldResolve: ({ contentTypes }) => Boolean(contentTypes), - shouldReject: () => null, - shouldRenew: (source, resource) => resource.complete, - resultSelector: ({ contentTypes, debounceKeyword, selectedFilter }) => { - return contentTypes.filter( - (contentType) => - contentType.label.toLowerCase().includes(debounceKeyword.toLowerCase()) && - (selectedFilter === 'all' || contentType.type === selectedFilter) - ); - }, - errorSelector: () => null - } - ); - const onSearch$ = useSubject(); useEffect(() => { @@ -162,24 +153,28 @@ export function NewContentDialogContainer(props: NewContentDialogContainerProps) - - }} - withEmptyStateProps={{ - emptyStateProps: { - classes: { - image: classes.emptyStateImg - }, - title: ( + {isFetching ? ( + + ) : filteredContentTypes ? ( + filteredContentTypes.length > 0 ? ( + + ) : ( + - ) - } - }} - > - - + } + classes={{ + image: classes.emptyStateImg + }} + /> + ) + ) : ( + <> + )} . */ -import { Resource } from '../../models/Resource'; import { LegacyContentType } from '../../models/ContentType'; import { DetailedItem } from '../../models/Item'; import StandardAction from '../../models/StandardAction'; @@ -22,7 +21,7 @@ import { EnhancedDialogProps } from '../EnhancedDialog'; import { EnhancedDialogState } from '../../hooks/useEnhancedDialogState'; export interface ContentTypesGridProps { - resource: Resource; + contentTypes: LegacyContentType[]; isCompact: boolean; selectedContentType?: string; onTypeOpen(data: LegacyContentType): void; From 576214d65a2deb98d0a9fea7f463bcf0bcf3e62b Mon Sep 17 00:00:00 2001 From: jvega190 Date: Mon, 20 May 2024 15:47:23 -0600 Subject: [PATCH 05/30] [6633] Remove logicalResource from PreviewDropTargetsPanel --- .../PreviewDropTargetsPanel.tsx | 62 +++++++++---------- 1 file changed, 28 insertions(+), 34 deletions(-) diff --git a/ui/app/src/components/PreviewDropTargetsPanel/PreviewDropTargetsPanel.tsx b/ui/app/src/components/PreviewDropTargetsPanel/PreviewDropTargetsPanel.tsx index ce6a6c3a50..382b5862b8 100644 --- a/ui/app/src/components/PreviewDropTargetsPanel/PreviewDropTargetsPanel.tsx +++ b/ui/app/src/components/PreviewDropTargetsPanel/PreviewDropTargetsPanel.tsx @@ -36,12 +36,10 @@ import { scrollToDropTarget, setPreviewEditMode } from '../../state/actions/preview'; -import { Resource } from '../../models/Resource'; -import { SuspenseWithEmptyState } from '../Suspencified/Suspencified'; -import { LookupTable } from '../../models/LookupTable'; import { useSelection } from '../../hooks/useSelection'; -import { useLogicResource } from '../../hooks/useLogicResource'; import { useMount } from '../../hooks/useMount'; +import LoadingState from '../LoadingState'; +import { EmptyState } from '../EmptyState'; const translations = defineMessages({ dropTargetsPanel: { @@ -83,6 +81,13 @@ export function PreviewDropTargetsPanel() { : null; const { formatMessage } = useIntl(); const dispatch = useDispatch(); + const filteredDropTargets = dropTargetsBranch + ? dropTargetsBranch.byId + ? Object.values(dropTargetsBranch.byId).filter( + (dropTarget) => dropTarget.contentTypeId === dropTargetsBranch.selectedContentType + ) + : [] + : null; useMount(() => { return () => { @@ -110,22 +115,6 @@ export function PreviewDropTargetsPanel() { }); } - const dropTargetsResource = useLogicResource< - ContentTypeDropTarget[], - { selectedContentType: string; byId: LookupTable } - >(dropTargetsBranch, { - shouldResolve: (source) => source.selectedContentType === null || Boolean(source.byId), - shouldReject: (source) => false, - shouldRenew: (source, resource) => resource.complete, - resultSelector: (source) => - source.byId - ? Object.values(source.byId).filter( - (dropTarget) => dropTarget.contentTypeId === dropTargetsBranch.selectedContentType - ) - : [], - errorSelector: (source) => null - }); - return ( <>
@@ -147,30 +136,35 @@ export function PreviewDropTargetsPanel() {
- - - + {dropTargetsBranch?.selectedContentType !== null && !Boolean(dropTargetsBranch?.byId) ? ( + + ) : filteredDropTargets ? ( + filteredDropTargets.length > 0 ? ( + + ) : ( + + ) + ) : ( + <> + )} ); } interface DropTargetsListProps { - resource: Resource; + dropTargets: ContentTypeDropTarget[]; onSelectedDropZone(dropTarget: ContentTypeDropTarget): void; } function DropTargetsList(props: DropTargetsListProps) { - const dropTargets = props.resource.read(); + const { dropTargets } = props; return ( <> {dropTargets?.map((dropTarget: ContentTypeDropTarget) => ( From dd5da3cfae947949a02509c7eec431616ca455a0 Mon Sep 17 00:00:00 2001 From: jvega190 Date: Mon, 20 May 2024 15:53:43 -0600 Subject: [PATCH 06/30] [6633] Remove logicalResource from PreviewPageExplorerPanel --- .../PreviewPageExplorerPanel.tsx | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/ui/app/src/components/PreviewPageExplorerPanel/PreviewPageExplorerPanel.tsx b/ui/app/src/components/PreviewPageExplorerPanel/PreviewPageExplorerPanel.tsx index 843750dbb6..1db1e317c3 100644 --- a/ui/app/src/components/PreviewPageExplorerPanel/PreviewPageExplorerPanel.tsx +++ b/ui/app/src/components/PreviewPageExplorerPanel/PreviewPageExplorerPanel.tsx @@ -54,7 +54,6 @@ import { showItemMegaMenu } from '../../state/actions/dialogs'; import { useSelection } from '../../hooks/useSelection'; import { useActiveSiteId } from '../../hooks/useActiveSiteId'; import { usePreviewGuest } from '../../hooks/usePreviewGuest'; -import { useLogicResource } from '../../hooks/useLogicResource'; import { useUnmount } from '../../hooks/useUnmount'; import { useSpreadState } from '../../hooks/useSpreadState'; import { SimpleTreeView } from '@mui/x-tree-view'; @@ -715,17 +714,6 @@ export function PreviewPageExplorerPanel() { setKeyword(keyword); }; - const resource = useLogicResource( - { models, byId: ContentTypesById }, - { - shouldResolve: (source) => Boolean(source.models && source.byId), - shouldReject: () => false, - shouldRenew: () => !Object.keys(processedModels.current).length && resource.complete, - resultSelector: () => true, - errorSelector: null - } - ); - useUnmount(onBack); return ( From a199d9e1bc485b75ab3292290ef43133c310680b Mon Sep 17 00:00:00 2001 From: jvega190 Date: Mon, 20 May 2024 16:16:54 -0600 Subject: [PATCH 07/30] [6633] Remove logicalResource from DeleteContentTypeDialog --- .../DeleteContentTypeDialogBody.tsx | 3 +- .../DeleteContentTypeDialogContainer.tsx | 59 ++++++++++++++----- .../DeleteContentTypeDialog/utils.ts | 2 +- 3 files changed, 45 insertions(+), 19 deletions(-) diff --git a/ui/app/src/components/DeleteContentTypeDialog/DeleteContentTypeDialogBody.tsx b/ui/app/src/components/DeleteContentTypeDialog/DeleteContentTypeDialogBody.tsx index 0a9682fce5..0b65fc8d28 100644 --- a/ui/app/src/components/DeleteContentTypeDialog/DeleteContentTypeDialogBody.tsx +++ b/ui/app/src/components/DeleteContentTypeDialog/DeleteContentTypeDialogBody.tsx @@ -81,8 +81,7 @@ const useStyles = makeStyles()((theme) => ({ export function DeleteContentTypeDialogBody(props: DeleteContentTypeDialogBodyProps) { const { classes } = useStyles(); - const { onCloseButtonClick, resource, contentType, onSubmit: onSubmitProp, password = 'delete', submitting } = props; - const data = resource.read(); + const { onCloseButtonClick, data, contentType, onSubmit: onSubmitProp, password = 'delete', submitting } = props; const { formatMessage } = useIntl(); const dataEntries = Object.entries(data) as Array<[keyof FetchContentTypeUsageResponse, SandboxItem[]]>; const entriesWithItems = dataEntries.filter(([, items]) => items.length > 0); diff --git a/ui/app/src/components/DeleteContentTypeDialog/DeleteContentTypeDialogContainer.tsx b/ui/app/src/components/DeleteContentTypeDialog/DeleteContentTypeDialogContainer.tsx index 27a42ffe67..5a938314e6 100644 --- a/ui/app/src/components/DeleteContentTypeDialog/DeleteContentTypeDialogContainer.tsx +++ b/ui/app/src/components/DeleteContentTypeDialog/DeleteContentTypeDialogContainer.tsx @@ -19,13 +19,14 @@ import { useActiveSiteId } from '../../hooks/useActiveSiteId'; import { defineMessages, useIntl } from 'react-intl'; import { useDispatch } from 'react-redux'; import * as React from 'react'; -import { useMemo } from 'react'; -import { createResource } from '../../utils/resource'; +import { useEffect } from 'react'; import { deleteContentType, fetchContentTypeUsage } from '../../services/contentTypes'; import { showSystemNotification } from '../../state/actions/system'; -import Suspencified from '../Suspencified/Suspencified'; import DeleteContentTypeDialogBody from './DeleteContentTypeDialogBody'; import useUpdateRefs from '../../hooks/useUpdateRefs'; +import useSpreadState from '../../hooks/useSpreadState'; +import ApiResponseErrorState from '../ApiResponseErrorState'; +import LoadingState from '../LoadingState'; const messages = defineMessages({ deleteComplete: { @@ -46,11 +47,31 @@ export function DeleteContentTypeDialogContainer(props: DeleteContentTypeDialogC const functionRefs = useUpdateRefs({ onSubmittingAndOrPendingChange }); + const [{ data, isFetching, error }, setState] = useSpreadState({ + data: null, + isFetching: false, + error: null + }); + + useEffect(() => { + setState({ isFetching: true }); + fetchContentTypeUsage(site, contentType.id).subscribe({ + next(response) { + setState({ + data: response, + isFetching: false, + error: null + }); + }, + error(e) { + setState({ + error: e, + isFetching: false + }); + } + }); + }, [site, contentType.id, setState]); - const resource = useMemo( - () => createResource(() => fetchContentTypeUsage(site, contentType.id).toPromise()), - [site, contentType.id] - ); const onSubmit = () => { functionRefs.current.onSubmittingAndOrPendingChange({ isSubmitting: true @@ -81,14 +102,20 @@ export function DeleteContentTypeDialogContainer(props: DeleteContentTypeDialogC const onCloseButtonClick = (e: React.MouseEvent) => onClose(e, null); return ( - - - + <> + {error ? ( + + ) : isFetching ? ( + + ) : data ? ( + + ) : null} + ); } diff --git a/ui/app/src/components/DeleteContentTypeDialog/utils.ts b/ui/app/src/components/DeleteContentTypeDialog/utils.ts index cca2cc41a1..5c1a2627ca 100644 --- a/ui/app/src/components/DeleteContentTypeDialog/utils.ts +++ b/ui/app/src/components/DeleteContentTypeDialog/utils.ts @@ -36,7 +36,7 @@ export interface DeleteContentTypeDialogContainerProps export interface DeleteContentTypeDialogBodyProps { submitting: boolean; contentType: ContentType; - resource: Resource; + data: FetchContentTypeUsageResponse; password?: string; onCloseButtonClick?(e: React.MouseEvent): void; onSubmit(): void; From c70e7867f4bb23f0b1beb92758dfb85d36257704 Mon Sep 17 00:00:00 2001 From: jvega190 Date: Mon, 20 May 2024 16:25:38 -0600 Subject: [PATCH 08/30] [6633] Remove logicalResource from UninstallPluginDialog --- .../DeleteContentTypeDialogContainer.tsx | 30 +++++------ .../UninstallPluginDialogBody.tsx | 10 +--- .../UninstallPluginDialogContainer.tsx | 52 ++++++++++++++----- .../components/DeletePluginDialog/utils.ts | 2 +- 4 files changed, 55 insertions(+), 39 deletions(-) diff --git a/ui/app/src/components/DeleteContentTypeDialog/DeleteContentTypeDialogContainer.tsx b/ui/app/src/components/DeleteContentTypeDialog/DeleteContentTypeDialogContainer.tsx index 5a938314e6..7790b6efd2 100644 --- a/ui/app/src/components/DeleteContentTypeDialog/DeleteContentTypeDialogContainer.tsx +++ b/ui/app/src/components/DeleteContentTypeDialog/DeleteContentTypeDialogContainer.tsx @@ -101,21 +101,17 @@ export function DeleteContentTypeDialogContainer(props: DeleteContentTypeDialogC const onCloseButtonClick = (e: React.MouseEvent) => onClose(e, null); - return ( - <> - {error ? ( - - ) : isFetching ? ( - - ) : data ? ( - - ) : null} - - ); + return error ? ( + + ) : isFetching ? ( + + ) : data ? ( + + ) : null; } diff --git a/ui/app/src/components/DeletePluginDialog/UninstallPluginDialogBody.tsx b/ui/app/src/components/DeletePluginDialog/UninstallPluginDialogBody.tsx index 778070ff3f..f7f2dc1dc6 100644 --- a/ui/app/src/components/DeletePluginDialog/UninstallPluginDialogBody.tsx +++ b/ui/app/src/components/DeletePluginDialog/UninstallPluginDialogBody.tsx @@ -60,15 +60,7 @@ function getStyles(sx: UninstallPluginDialogBodyPartialSx): UninstallPluginDialo } export function UninstallPluginDialogBody(props: UninstallPluginDialogBodyProps) { - const { - onCloseButtonClick, - resource, - pluginId, - onSubmit: onSubmitProp, - password = 'uninstall', - isSubmitting - } = props; - const data = resource.read(); + const { onCloseButtonClick, data, pluginId, onSubmit: onSubmitProp, password = 'uninstall', isSubmitting } = props; const hasUsages = data.length > 0; const [confirmPasswordPassed, setConfirmPasswordPassed] = useState(false); const [passwordFieldValue, setPasswordFieldValue] = useState(''); diff --git a/ui/app/src/components/DeletePluginDialog/UninstallPluginDialogContainer.tsx b/ui/app/src/components/DeletePluginDialog/UninstallPluginDialogContainer.tsx index 561ee5d476..6be95bccd1 100644 --- a/ui/app/src/components/DeletePluginDialog/UninstallPluginDialogContainer.tsx +++ b/ui/app/src/components/DeletePluginDialog/UninstallPluginDialogContainer.tsx @@ -17,7 +17,7 @@ import * as React from 'react'; import { UninstallPluginDialogContainerProps } from './utils'; import { useActiveSiteId } from '../../hooks/useActiveSiteId'; -import { useMemo } from 'react'; +import { useEffect, useMemo } from 'react'; import { createResource } from '../../utils/resource'; import { uninstallMarketplacePlugin, fetchMarketplacePluginUsage } from '../../services/marketplace'; import Suspencified from '../Suspencified/Suspencified'; @@ -25,12 +25,38 @@ import { UninstallPluginDialogBody } from './UninstallPluginDialogBody'; import { useDispatch } from 'react-redux'; import { showErrorDialog } from '../../state/reducers/dialogs/error'; import useUpdateRefs from '../../hooks/useUpdateRefs'; +import useSpreadState from '../../hooks/useSpreadState'; +import { ApiResponseErrorState } from '../ApiResponseErrorState'; +import { LoadingState } from '../LoadingState'; export function UninstallPluginDialogContainer(props: UninstallPluginDialogContainerProps) { const { onClose, pluginId, onComplete, isSubmitting, onSubmittingAndOrPendingChange } = props; const site = useActiveSiteId(); const dispatch = useDispatch(); const callbacksRef = useUpdateRefs({ onSubmittingAndOrPendingChange }); + const [{ data, isFetching, error }, setState] = useSpreadState({ + data: null, + isFetching: false, + error: null + }); + + useEffect(() => { + setState({ isFetching: true }); + fetchMarketplacePluginUsage(site, pluginId).subscribe({ + next(response) { + setState({ + data: response, + isFetching: false + }); + }, + error: ({ response: { response } }) => { + setState({ + error: response, + isFetching: false + }); + } + }); + }, [site, pluginId, setState]); const resource = useMemo(() => { return createResource(() => fetchMarketplacePluginUsage(site, pluginId).toPromise()); @@ -59,15 +85,17 @@ export function UninstallPluginDialogContainer(props: UninstallPluginDialogConta const onCloseButtonClick = (e: React.MouseEvent) => onClose(e, null); - return ( - - onSubmit(pluginId)} - /> - - ); + return error ? ( + + ) : isFetching ? ( + + ) : data ? ( + onSubmit(pluginId)} + /> + ) : null; } diff --git a/ui/app/src/components/DeletePluginDialog/utils.ts b/ui/app/src/components/DeletePluginDialog/utils.ts index 2f66a6a4ac..c0e2b32446 100644 --- a/ui/app/src/components/DeletePluginDialog/utils.ts +++ b/ui/app/src/components/DeletePluginDialog/utils.ts @@ -36,7 +36,7 @@ export interface UninstallPluginDialogContainerProps export interface UninstallPluginDialogBodyProps { isSubmitting: boolean; pluginId: string; - resource: Resource; + data: SandboxItem[]; password?: string; sx?: UninstallPluginDialogBodyPartialSx; onCloseButtonClick?(e: React.MouseEvent): void; From 0476aef0dc6c48f71776a815a703c71b794a81e7 Mon Sep 17 00:00:00 2001 From: jvega190 Date: Mon, 20 May 2024 16:27:37 -0600 Subject: [PATCH 09/30] [6633] Remove unused imports --- ui/app/src/components/DeleteContentTypeDialog/utils.ts | 1 - .../UninstallPluginDialogContainer.tsx | 10 ++-------- ui/app/src/components/DeletePluginDialog/utils.ts | 1 - 3 files changed, 2 insertions(+), 10 deletions(-) diff --git a/ui/app/src/components/DeleteContentTypeDialog/utils.ts b/ui/app/src/components/DeleteContentTypeDialog/utils.ts index 5c1a2627ca..c7b027cb3e 100644 --- a/ui/app/src/components/DeleteContentTypeDialog/utils.ts +++ b/ui/app/src/components/DeleteContentTypeDialog/utils.ts @@ -14,7 +14,6 @@ * along with this program. If not, see . */ import ContentType from '../../models/ContentType'; -import { Resource } from '../../models/Resource'; import { FetchContentTypeUsageResponse } from '../../services/contentTypes'; import { EnhancedDialogProps } from '../EnhancedDialog'; import React from 'react'; diff --git a/ui/app/src/components/DeletePluginDialog/UninstallPluginDialogContainer.tsx b/ui/app/src/components/DeletePluginDialog/UninstallPluginDialogContainer.tsx index 6be95bccd1..3a7073c2ca 100644 --- a/ui/app/src/components/DeletePluginDialog/UninstallPluginDialogContainer.tsx +++ b/ui/app/src/components/DeletePluginDialog/UninstallPluginDialogContainer.tsx @@ -15,12 +15,10 @@ */ import * as React from 'react'; +import { useEffect } from 'react'; import { UninstallPluginDialogContainerProps } from './utils'; import { useActiveSiteId } from '../../hooks/useActiveSiteId'; -import { useEffect, useMemo } from 'react'; -import { createResource } from '../../utils/resource'; -import { uninstallMarketplacePlugin, fetchMarketplacePluginUsage } from '../../services/marketplace'; -import Suspencified from '../Suspencified/Suspencified'; +import { fetchMarketplacePluginUsage, uninstallMarketplacePlugin } from '../../services/marketplace'; import { UninstallPluginDialogBody } from './UninstallPluginDialogBody'; import { useDispatch } from 'react-redux'; import { showErrorDialog } from '../../state/reducers/dialogs/error'; @@ -58,10 +56,6 @@ export function UninstallPluginDialogContainer(props: UninstallPluginDialogConta }); }, [site, pluginId, setState]); - const resource = useMemo(() => { - return createResource(() => fetchMarketplacePluginUsage(site, pluginId).toPromise()); - }, [site, pluginId]); - const onSubmit = (id: string) => { onSubmittingAndOrPendingChange({ isSubmitting: true diff --git a/ui/app/src/components/DeletePluginDialog/utils.ts b/ui/app/src/components/DeletePluginDialog/utils.ts index c0e2b32446..00be193c5c 100644 --- a/ui/app/src/components/DeletePluginDialog/utils.ts +++ b/ui/app/src/components/DeletePluginDialog/utils.ts @@ -16,7 +16,6 @@ import { EnhancedDialogProps } from '../EnhancedDialog'; import { onSubmittingAndOrPendingChangeProps } from '../../hooks/useEnhancedDialogState'; -import { Resource } from '../../models/Resource'; import { SandboxItem } from '../../models/Item'; import { FullSxRecord, PartialSxRecord } from '../../models/CustomRecord'; From ad3838fc8291b866e01463201c4e177d5243701c Mon Sep 17 00:00:00 2001 From: jvega190 Date: Tue, 21 May 2024 10:03:54 -0600 Subject: [PATCH 10/30] [6633] Remove logicalResource from QuickCreate, delete pages/QuickCreateMenu.tsx --- .../components/QuickCreate/QuickCreate.tsx | 57 ++++++++------- ui/app/src/env/codebase-bridge.tsx | 1 - ui/app/src/pages/QuickCreateMenu.tsx | 73 ------------------- 3 files changed, 30 insertions(+), 101 deletions(-) delete mode 100644 ui/app/src/pages/QuickCreateMenu.tsx diff --git a/ui/app/src/components/QuickCreate/QuickCreate.tsx b/ui/app/src/components/QuickCreate/QuickCreate.tsx index b274cf5f58..1e715a62c4 100644 --- a/ui/app/src/components/QuickCreate/QuickCreate.tsx +++ b/ui/app/src/components/QuickCreate/QuickCreate.tsx @@ -14,7 +14,7 @@ * along with this program. If not, see . */ -import React, { forwardRef, useState } from 'react'; +import React, { forwardRef, useEffect, useState } from 'react'; import { defineMessages, FormattedMessage, useIntl } from 'react-intl'; import IconButton from '@mui/material/IconButton'; import AddCircleIcon from '@mui/icons-material/AddRounded'; @@ -30,19 +30,20 @@ import CardContent from '@mui/material/CardContent'; import Button from '@mui/material/Button'; import ErrorOutlineOutlinedIcon from '@mui/icons-material/ErrorOutlineOutlined'; import QuickCreateItem from '../../models/content/QuickCreateItem'; -import { Resource } from '../../models/Resource'; -import Suspencified from '../Suspencified/Suspencified'; -import { getSimplifiedVersion } from '../../utils/string'; import palette from '../../styles/palette'; import Tooltip from '@mui/material/Tooltip'; import { DetailedItem } from '../../models/Item'; import { useSelection } from '../../hooks/useSelection'; import { usePreviewState } from '../../hooks/usePreviewState'; -import { useQuickCreateListResource } from '../../hooks/useQuickCreateListResource'; -import { useSystemVersionResource } from '../../hooks/useSystemVersionResource'; import { useItemsByPath } from '../../hooks/useItemsByPath'; import { lookupItemByPath } from '../../utils/content'; import { processPathMacros } from '../../utils/path'; +import { fetchQuickCreateList } from '../../state/actions/content'; +import useQuickCreateState from '../../hooks/useQuickCreateState'; +import useActiveSiteId from '../../hooks/useActiveSiteId'; +import useSystemVersion from '../../hooks/useSystemVersion'; +import { ApiResponseErrorState } from '../ApiResponseErrorState'; +import { LoadingState } from '../LoadingState'; const translations = defineMessages({ quickCreateBtnLabel: { @@ -104,10 +105,6 @@ interface QuickCreateMenuProps { open: boolean; item?: DetailedItem; anchorEl: HTMLElement; - resource: { - version: Resource; - quickCreate: Resource; - }; onNewContentSelected?(): void; onQuickCreateItemSelected?(props: { authoringBase: string; @@ -126,17 +123,17 @@ interface QuickCreateMenuButtonProps { interface QuickCreateSectionProps { classes: { [className: string]: string }; onItemSelected: (item: QuickCreateItem) => any; - resource: { - version: Resource; - quickCreate: Resource; - }; + version: string; + quickCreateItems: QuickCreateItem[]; } export function QuickCreateMenu(props: QuickCreateMenuProps) { - const { open, onClose, anchorEl, resource, onNewContentSelected, onQuickCreateItemSelected, item } = props; + const { open, onClose, anchorEl, onNewContentSelected, onQuickCreateItemSelected, item } = props; const { classes } = useStyles(); const authoringBase = useSelection((state) => state.env.authoringBase); const itemNewContentButton = item?.availableActionsMap.createContent; + const { error, isFetching, items: quickCreateItems } = useQuickCreateState(); + const systemVersion = useSystemVersion(); const onFormDisplay = (item: QuickCreateItem) => { const { contentTypeId, path } = item; @@ -171,19 +168,25 @@ export function QuickCreateMenu(props: QuickCreateMenuProps) { - - - + {error ? ( + + ) : isFetching ? ( + + ) : quickCreateItems && systemVersion ? ( + + ) : null} ); } function QuickCreateSection(props: QuickCreateSectionProps) { - const { resource, classes, onItemSelected } = props; - const quickCreateItems = resource.quickCreate.read(); - - let version = getSimplifiedVersion(resource.version.read()); + const { version, quickCreateItems, classes, onItemSelected } = props; return ( <> @@ -249,6 +252,11 @@ const QuickCreate = forwardRef((prop const { guest } = usePreviewState(); const dispatch = useDispatch(); const items = useItemsByPath(); + const site = useActiveSiteId(); + + useEffect(() => { + site && dispatch(fetchQuickCreateList()); + }, [site, dispatch]); const onMenuBtnClick = (e) => { setAnchorEl(e.currentTarget); @@ -285,10 +293,6 @@ const QuickCreate = forwardRef((prop ); }; - const quickCreateResource = useQuickCreateListResource(); - - const versionResource = useSystemVersionResource(); - return ( <> @@ -297,7 +301,6 @@ const QuickCreate = forwardRef((prop open={Boolean(anchorEl)} anchorEl={anchorEl} onClose={onMenuClose} - resource={{ quickCreate: quickCreateResource, version: versionResource }} onNewContentSelected={onNewContentSelected} onQuickCreateItemSelected={onQuickCreateItemSelected} /> diff --git a/ui/app/src/env/codebase-bridge.tsx b/ui/app/src/env/codebase-bridge.tsx index bfcccbd954..71f0bc52cc 100644 --- a/ui/app/src/env/codebase-bridge.tsx +++ b/ui/app/src/env/codebase-bridge.tsx @@ -121,7 +121,6 @@ export function createCodebaseBridge() { SiteTools: lazy(() => import('../pages/SiteTools')), Login: lazy(() => import('../pages/Login')), PagesWidget: lazy(() => import('../components/PathNavigator/PathNavigator')), - QuickCreateMenu: lazy(() => import('../pages/QuickCreateMenu')), DeleteContentTypeButton: lazy(() => import('../pages/DeleteContentTypeButton')), PreviewCompatDialog: lazy(() => import('../components/PreviewCompatibilityDialog/PreviewCompatibilityDialog')) }, diff --git a/ui/app/src/pages/QuickCreateMenu.tsx b/ui/app/src/pages/QuickCreateMenu.tsx deleted file mode 100644 index 7aa3c4610c..0000000000 --- a/ui/app/src/pages/QuickCreateMenu.tsx +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright (C) 2007-2022 Crafter Software Corporation. All Rights Reserved. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 3 as published by - * the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -import React, { useState } from 'react'; -import { QuickCreateMenu } from '../components/QuickCreate/QuickCreate'; -import { useQuickCreateListResource } from '../hooks/useQuickCreateListResource'; -import { useSystemVersionResource } from '../hooks/useSystemVersionResource'; - -interface QuickCreateMenuProps { - anchorEl: HTMLElement; - onNewContentSelected?(): void; - onQuickCreateItemSelected?(props: { - authoringBase: string; - path: string; - contentTypeId: string; - isNewContent: boolean; - }): void; - onClose?(): void; -} - -export default function QuickCreateMenuApp(props: QuickCreateMenuProps) { - const { anchorEl, onClose, onQuickCreateItemSelected, onNewContentSelected } = props; - const [open, setOpen] = useState(true); - - // Wait a few millis for the animation to finish before - // notifying legacy that the menu is closed to avoid - // the animation getting cut of by the unmounting - const onCloseDiffered = () => { - setTimeout(onClose, 500); - }; - - const closeMenu = () => { - setOpen(false); - onCloseDiffered(); - }; - - const quickCreateResource = useQuickCreateListResource(); - - const versionResource = useSystemVersionResource(); - - return ( - { - closeMenu(); - onNewContentSelected(); - }} - onQuickCreateItemSelected={(props) => { - closeMenu(); - onQuickCreateItemSelected(props); - }} - /> - ); -} From 7596ecaf3c9d6db4c1dcf4c93e3d6fec22304b8e Mon Sep 17 00:00:00 2001 From: jvega190 Date: Tue, 21 May 2024 10:30:55 -0600 Subject: [PATCH 11/30] [6633] Remove PreviewInPageInstancesPanel.tsx, update Changelog --- ui/app/src/CHANGELOG.md | 2 + .../PreviewInPageInstancesPanel.tsx | 264 ------------------ .../PreviewInPageInstancesPanel/index.ts | 19 -- ui/app/src/components/index.ts | 1 - ui/app/src/env/studioUI.ts | 1 - 5 files changed, 2 insertions(+), 285 deletions(-) delete mode 100644 ui/app/src/components/PreviewInPageInstancesPanel/PreviewInPageInstancesPanel.tsx delete mode 100644 ui/app/src/components/PreviewInPageInstancesPanel/index.ts diff --git a/ui/app/src/CHANGELOG.md b/ui/app/src/CHANGELOG.md index 010bdcd798..9ce832e561 100644 --- a/ui/app/src/CHANGELOG.md +++ b/ui/app/src/CHANGELOG.md @@ -36,6 +36,8 @@ * [hooks] * `usePreviewUrlControl`: Removed `history` prop. Retrieval of search and navigate (previously called 'push') is now done internally. * Removed deprecated `aws-file-upload` and `aws-video` upload controls. +* Removed `PreviewPageExplorerPanel` component. +* Removed `pages/QuickCreateMenu` component. ## 4.1.5 * [common-api.js] diff --git a/ui/app/src/components/PreviewInPageInstancesPanel/PreviewInPageInstancesPanel.tsx b/ui/app/src/components/PreviewInPageInstancesPanel/PreviewInPageInstancesPanel.tsx deleted file mode 100644 index ec90b303ab..0000000000 --- a/ui/app/src/components/PreviewInPageInstancesPanel/PreviewInPageInstancesPanel.tsx +++ /dev/null @@ -1,264 +0,0 @@ -/* - * Copyright (C) 2007-2022 Crafter Software Corporation. All Rights Reserved. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 3 as published by - * the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -import React, { useEffect, useMemo, useState } from 'react'; -import { defineMessages, useIntl } from 'react-intl'; -import MenuItem from '@mui/material/MenuItem'; -import { makeStyles } from 'tss-react/mui'; -import { contentTreeFieldSelected, setContentTypeFilter, setPreviewEditMode } from '../../state/actions/preview'; -import { useDispatch } from 'react-redux'; -import Suspencified from '../Suspencified/Suspencified'; -import ContentInstance from '../../models/ContentInstance'; -import LookupTable from '../../models/LookupTable'; -import SearchBar from '../SearchBar/SearchBar'; -import Select from '@mui/material/Select'; -import ListItem from '@mui/material/ListItem'; -import Avatar from '@mui/material/Avatar'; -import { getInitials } from '../../utils/string'; -import ListItemAvatar from '@mui/material/ListItemAvatar'; -import ListItemText from '@mui/material/ListItemText'; -import CircularProgress from '@mui/material/CircularProgress'; -import { getHostToGuestBus } from '../../utils/subjects'; -import EmptyState from '../EmptyState/EmptyState'; -import { Resource } from '../../models/Resource'; -import { useSelection } from '../../hooks/useSelection'; -import { usePreviewGuest } from '../../hooks/usePreviewGuest'; -import { useContentTypes } from '../../hooks/useContentTypes'; -import { useLogicResource } from '../../hooks/useLogicResource'; - -const translations = defineMessages({ - previewInPageInstancesPanel: { - id: 'previewInPageInstancesPanel.title', - defaultMessage: 'In this Page' - }, - noResults: { - id: 'previewInPageInstancesPanel.noResults', - defaultMessage: 'No results found.' - }, - selectContentType: { - id: 'previewInPageInstancesPanel.selectContentType', - defaultMessage: 'Select content type' - }, - chooseContentType: { - id: 'previewInPageInstancesPanel.chooseContentType', - defaultMessage: 'Please choose a content type.' - } -}); - -const useStyles = makeStyles()(() => ({ - search: { - padding: '15px 15px 0 15px' - }, - Select: { - width: '100%', - marginTop: '15px' - }, - noWrapping: { - overflow: 'hidden', - whiteSpace: 'nowrap', - textOverflow: 'ellipsis', - display: 'block' - }, - selectProgress: { - position: 'absolute', - right: '28px' - }, - emptyStateTitle: { - fontSize: '1em' - }, - item: {} -})); - -export function PreviewInPageInstancesPanel() { - const { classes } = useStyles(); - const { formatMessage } = useIntl(); - const dispatch = useDispatch(); - const contentTypeLookup = useContentTypes(); - const contentTypeFilter = useSelection((state) => state.preview.components.contentTypeFilter); - const guest = usePreviewGuest(); - const [keyword, setKeyword] = useState(''); - const hostToGuest$ = getHostToGuestBus(); - const editMode = useSelection((state) => state.preview.editMode); - const models = useMemo(() => { - return guest?.models; - }, [guest]); - - const selectedModels = useMemo(() => { - return Object.values(models ?? []).filter((model) => { - return ( - model.craftercms.contentTypeId === contentTypeFilter && - (model.craftercms.label.toLowerCase().includes(keyword.toLowerCase()) || - model.craftercms.contentTypeId.toLowerCase().includes(keyword.toLowerCase())) - ); - }); - // filter using .includes(keyword) on model.craftercms.label - }, [contentTypeFilter, models, keyword]); - - const [contentTypes, setContentTypes] = useState([]); - - // setting contentTypes - useEffect(() => { - if (models) { - const contentTypes = []; - Object.values(models ?? []).forEach((model) => { - // TODO: Groovy Controller Issue; - if (model.craftercms.contentTypeId && contentTypes.indexOf(model.craftercms.contentTypeId) <= 0) { - contentTypes.push(model.craftercms.contentTypeId); - } - }); - setContentTypes(contentTypes); - } - return () => { - setContentTypes([]); - setKeyword(''); - }; - }, [models]); - - const resource = useLogicResource< - ContentInstance[], - { models: LookupTable; contentTypeFilter: string } - >( - { - models, - contentTypeFilter - }, - { - shouldRenew: (source, resource) => Boolean(contentTypeFilter) && !keyword && resource.complete, - shouldResolve: (source) => Boolean(source.models), - shouldReject: (source) => false, - errorSelector: (source) => null, - resultSelector: (source) => { - return Object.values(source.models)?.filter((model) => model.craftercms.contentTypeId === contentTypeFilter); - } - } - ); - - const handleSearchKeyword = (keyword) => { - setKeyword(keyword); - }; - - const handleSelectChange = (value: string) => { - setKeyword(''); - dispatch(setContentTypeFilter(value)); - }; - - const onItemClick = (instance: ContentInstance) => { - if (!editMode) { - dispatch(setPreviewEditMode({ editMode: true })); - } - hostToGuest$.next( - contentTreeFieldSelected({ - name: instance.craftercms.label, - scrollElement: null, - iceProps: { - modelId: instance.craftercms.id, - fieldId: null, - index: null - } - }) - ); - return; - }; - - return ( - <> -
- - -
- - - - - ); -} - -interface InPageInstancesUIProps { - resource: Resource; - selectedModels: ContentInstance[]; - contentTypeFilter: string; - onItemClick(instance: ContentInstance): void; -} - -function InPageInstancesUI(props: InPageInstancesUIProps) { - const { resource, selectedModels, onItemClick, contentTypeFilter } = props; - resource.read(); - const { classes } = useStyles(); - const { formatMessage } = useIntl(); - - return ( - <> - {selectedModels.length ? ( - selectedModels.map((instance: ContentInstance) => ( - onItemClick(instance)} - > - - {getInitials(instance.craftercms.label)} - - - - )) - ) : ( - - )} - - ); -} - -export default PreviewInPageInstancesPanel; diff --git a/ui/app/src/components/PreviewInPageInstancesPanel/index.ts b/ui/app/src/components/PreviewInPageInstancesPanel/index.ts deleted file mode 100644 index 0ef0bcab96..0000000000 --- a/ui/app/src/components/PreviewInPageInstancesPanel/index.ts +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright (C) 2007-2022 Crafter Software Corporation. All Rights Reserved. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 3 as published by - * the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -export { default } from './PreviewInPageInstancesPanel'; - -export * from './PreviewInPageInstancesPanel'; diff --git a/ui/app/src/components/index.ts b/ui/app/src/components/index.ts index 6a533ea2d2..fdd99dc945 100644 --- a/ui/app/src/components/index.ts +++ b/ui/app/src/components/index.ts @@ -190,7 +190,6 @@ export * from './PreviewConcierge'; export * from './PreviewDialog'; export * from './PreviewDropTargetsPanel'; export * from './PreviewForwardButton'; -export * from './PreviewInPageInstancesPanel'; export * from './PreviewPageExplorerPanel'; export * from './PreviewSearchPanel'; export * from './PreviewSettingsPanel'; diff --git a/ui/app/src/env/studioUI.ts b/ui/app/src/env/studioUI.ts index 919741db69..b51bc81042 100644 --- a/ui/app/src/env/studioUI.ts +++ b/ui/app/src/env/studioUI.ts @@ -235,7 +235,6 @@ export const components = { PreviewDialog: lazy(() => import('../components/PreviewDialog')), PreviewDropTargetsPanel: lazy(() => import('../components/PreviewDropTargetsPanel')), PreviewForwardButton: lazy(() => import('../components/PreviewForwardButton')), - PreviewInPageInstancesPanel: lazy(() => import('../components/PreviewInPageInstancesPanel')), PreviewPageExplorerPanel: lazy(() => import('../components/PreviewPageExplorerPanel')), PreviewSearchPanel: lazy(() => import('../components/PreviewSearchPanel')), PreviewSettingsPanel: lazy(() => import('../components/PreviewSettingsPanel')), From abb624f29b952e0d1fae94b1c4e4631e99429358 Mon Sep 17 00:00:00 2001 From: jvega190 Date: Tue, 21 May 2024 10:53:02 -0600 Subject: [PATCH 12/30] [6633] Remove logical resource from ViewVersionDialogContainer --- .../ViewVersionDialog/LegacyVersionDialog.tsx | 2 +- .../ViewVersionDialogContainer.tsx | 28 ++++++++----------- .../src/components/ViewVersionDialog/utils.ts | 14 ++++------ 3 files changed, 18 insertions(+), 26 deletions(-) diff --git a/ui/app/src/components/ViewVersionDialog/LegacyVersionDialog.tsx b/ui/app/src/components/ViewVersionDialog/LegacyVersionDialog.tsx index be2f827c3b..387b9be493 100644 --- a/ui/app/src/components/ViewVersionDialog/LegacyVersionDialog.tsx +++ b/ui/app/src/components/ViewVersionDialog/LegacyVersionDialog.tsx @@ -20,7 +20,7 @@ import React from 'react'; import { getLegacyDialogStyles } from './ViewVersionDialog'; export function LegacyVersionDialog(props: VersionViewProps) { - const { version } = props.resource.read(); + const { version } = props; const { classes } = getLegacyDialogStyles(); const authoringUrl = useSelection((state) => state.env.authoringBase); return ( diff --git a/ui/app/src/components/ViewVersionDialog/ViewVersionDialogContainer.tsx b/ui/app/src/components/ViewVersionDialog/ViewVersionDialogContainer.tsx index ec5b4304bd..5aca568b85 100644 --- a/ui/app/src/components/ViewVersionDialog/ViewVersionDialogContainer.tsx +++ b/ui/app/src/components/ViewVersionDialog/ViewVersionDialogContainer.tsx @@ -14,31 +14,25 @@ * along with this program. If not, see . */ -import { VersionResource, ViewVersionDialogContainerProps } from './utils'; -import { useLogicResource } from '../../hooks/useLogicResource'; +import { ViewVersionDialogContainerProps } from './utils'; import DialogBody from '../DialogBody/DialogBody'; -import { SuspenseWithEmptyState } from '../Suspencified/Suspencified'; import React from 'react'; import LegacyVersionDialog from './LegacyVersionDialog'; +import ApiResponseErrorState from '../ApiResponseErrorState'; +import { LoadingState } from '../LoadingState'; export function ViewVersionDialogContainer(props: ViewVersionDialogContainerProps) { - const resource = useLogicResource(props, { - shouldResolve: (source) => - source.version && source.contentTypesBranch.byId && !source.isFetching && !source.contentTypesBranch.isFetching, - shouldReject: (source) => Boolean(source.error) || Boolean(source.contentTypesBranch.error), - shouldRenew: (source, resource) => (source.isFetching || source.contentTypesBranch.isFetching) && resource.complete, - resultSelector: (source) => ({ - version: source.version, - contentTypes: source.contentTypesBranch.byId - }), - errorSelector: (source) => source.error || source.contentTypesBranch.error - }); + const { error, isFetching, version } = props; return ( - - - + {error ? ( + + ) : isFetching ? ( + + ) : version ? ( + + ) : null} ); } diff --git a/ui/app/src/components/ViewVersionDialog/utils.ts b/ui/app/src/components/ViewVersionDialog/utils.ts index b53709feee..09883d56c0 100644 --- a/ui/app/src/components/ViewVersionDialog/utils.ts +++ b/ui/app/src/components/ViewVersionDialog/utils.ts @@ -20,18 +20,16 @@ import { DialogHeaderStateAction } from '../DialogHeader'; import { DialogHeaderActionProps } from '../DialogHeaderAction'; import { ApiResponse } from '../../models/ApiResponse'; import StandardAction from '../../models/StandardAction'; -import { LookupTable } from '../../models/LookupTable'; -import { Resource } from '../../models/Resource'; import { EnhancedDialogProps } from '../EnhancedDialog'; import { EnhancedDialogState } from '../../hooks/useEnhancedDialogState'; export interface VersionViewProps { - resource: Resource; -} - -export interface VersionResource { - version: any; - contentTypes: LookupTable; + version: { + content: string; + path: string; + site: string; + versionNumber: string; + }; } export interface ViewVersionDialogBaseProps { From 688ff84427bb199846ec731b6fdd0c44ecec51cb Mon Sep 17 00:00:00 2001 From: jvega190 Date: Tue, 21 May 2024 11:48:25 -0600 Subject: [PATCH 13/30] [6633] Remove logical resource from CompareVersionsDialog --- .../CompareVersionsDialog/CompareVersions.tsx | 13 +---- .../CompareVersionsDialogContainer.tsx | 56 ++++++------------- 2 files changed, 18 insertions(+), 51 deletions(-) diff --git a/ui/app/src/components/CompareVersionsDialog/CompareVersions.tsx b/ui/app/src/components/CompareVersionsDialog/CompareVersions.tsx index 7517811201..48c078d155 100644 --- a/ui/app/src/components/CompareVersionsDialog/CompareVersions.tsx +++ b/ui/app/src/components/CompareVersionsDialog/CompareVersions.tsx @@ -18,10 +18,7 @@ import { makeStyles } from 'tss-react/mui'; import ContentInstance from '../../models/ContentInstance'; -import { LookupTable } from '../../models/LookupTable'; -import ContentType from '../../models/ContentType'; import React from 'react'; -import { Resource } from '../../models/Resource'; import { useSelection } from '../../hooks/useSelection'; // declare const monaco: any; @@ -151,14 +148,8 @@ import { useSelection } from '../../hooks/useSelection'; } }); */ -export interface CompareVersionsResource { - a: ContentInstance; - b: any; - contentTypes: LookupTable; -} - interface CompareVersionsProps { - resource: Resource; + versions: ContentInstance[]; } const getLegacyDialogStyles = makeStyles()(() => ({ @@ -169,7 +160,7 @@ const getLegacyDialogStyles = makeStyles()(() => ({ })); export function CompareVersions(props: CompareVersionsProps) { - const { a, b } = props.resource.read(); + const [a, b] = props.versions; const { classes } = getLegacyDialogStyles(); const authoringUrl = useSelection((state) => state.env.authoringBase); return ( diff --git a/ui/app/src/components/CompareVersionsDialog/CompareVersionsDialogContainer.tsx b/ui/app/src/components/CompareVersionsDialog/CompareVersionsDialogContainer.tsx index b41fa2d90c..0e3eb276e2 100644 --- a/ui/app/src/components/CompareVersionsDialog/CompareVersionsDialogContainer.tsx +++ b/ui/app/src/components/CompareVersionsDialog/CompareVersionsDialogContainer.tsx @@ -16,13 +16,10 @@ import { CompareVersionsDialogContainerProps } from './utils'; import { FormattedMessage } from 'react-intl'; -import React, { useMemo, useState } from 'react'; +import React, { useState } from 'react'; import { useDispatch } from 'react-redux'; -import { useLogicResource } from '../../hooks/useLogicResource'; -import { CompareVersionsBranch, ItemHistoryEntry } from '../../models/Version'; -import { CompareVersions, CompareVersionsResource } from './CompareVersions'; -import { EntityState } from '../../models/EntityState'; -import ContentType from '../../models/ContentType'; +import { ItemHistoryEntry } from '../../models/Version'; +import { CompareVersions } from './CompareVersions'; import { compareBothVersions, compareVersion, @@ -32,7 +29,6 @@ import { import VersionList from '../VersionList'; import DialogBody from '../DialogBody/DialogBody'; import SingleItemSelector from '../SingleItemSelector'; -import { SuspenseWithEmptyState } from '../Suspencified/Suspencified'; import EmptyState from '../EmptyState/EmptyState'; import Typography from '@mui/material/Typography'; import DialogFooter from '../DialogFooter/DialogFooter'; @@ -40,6 +36,7 @@ import { HistoryDialogPagination } from '../HistoryDialog'; import { makeStyles } from 'tss-react/mui'; import { ErrorBoundary } from '../ErrorBoundary'; import { LoadingState } from '../LoadingState'; +import ApiResponseErrorState from '../ApiResponseErrorState'; const useStyles = makeStyles()(() => ({ dialogBody: { @@ -58,42 +55,13 @@ const useStyles = makeStyles()(() => ({ })); export function CompareVersionsDialogContainer(props: CompareVersionsDialogContainerProps) { - const { selectedA, selectedB, versionsBranch, disableItemSwitching = false, contentTypesBranch } = props; + const { selectedA, selectedB, versionsBranch, disableItemSwitching = false } = props; const { count, page, limit, selected, compareVersionsBranch, current, item, rootPath } = versionsBranch; const { classes, cx } = useStyles(); const [openSelector, setOpenSelector] = useState(false); const dispatch = useDispatch(); const compareMode = selectedA && selectedB; - const compareVersionsData = useMemo( - () => ({ - compareVersionsBranch, - contentTypesBranch - }), - [compareVersionsBranch, contentTypesBranch] - ); - - const compareVersionsResource = useLogicResource< - CompareVersionsResource, - { compareVersionsBranch: CompareVersionsBranch; contentTypesBranch: EntityState } - >(compareVersionsData, { - shouldResolve: ({ compareVersionsBranch, contentTypesBranch }) => - compareVersionsBranch.compareVersions && - contentTypesBranch.byId && - !compareVersionsBranch.isFetching && - !contentTypesBranch.isFetching, - shouldReject: ({ compareVersionsBranch, contentTypesBranch }) => - Boolean(compareVersionsBranch.error || contentTypesBranch.error), - shouldRenew: ({ compareVersionsBranch, contentTypesBranch }, resource) => resource.complete, - resultSelector: ({ compareVersionsBranch, contentTypesBranch }) => ({ - a: compareVersionsBranch.compareVersions?.[0], - b: compareVersionsBranch.compareVersions?.[1], - contentTypes: contentTypesBranch.byId - }), - errorSelector: ({ compareVersionsBranch, contentTypesBranch }) => - compareVersionsBranch.error || contentTypesBranch.error - }); - const handleItemClick = (version: ItemHistoryEntry) => { if (!selected[0]) { dispatch(compareVersion({ id: version.versionNumber })); @@ -128,9 +96,17 @@ export function CompareVersionsDialogContainer(props: CompareVersionsDialogConta /> )} {compareMode ? ( - - - + compareVersionsBranch ? ( + compareVersionsBranch.error ? ( + + ) : compareVersionsBranch.isFetching ? ( + + ) : compareVersionsBranch.compareVersions?.length > 0 ? ( + + ) : ( + } /> + ) + ) : null ) : item ? ( {versionsBranch.isFetching ? ( From 66fe83f0142223616078354dd35c21b4ebbd72fa Mon Sep 17 00:00:00 2001 From: jvega190 Date: Wed, 22 May 2024 10:52:34 -0600 Subject: [PATCH 14/30] [6633] Remove logical resource from ToolsPanel --- .../src/components/ToolsPanel/ToolsPanel.tsx | 70 ++++++++----------- 1 file changed, 30 insertions(+), 40 deletions(-) diff --git a/ui/app/src/components/ToolsPanel/ToolsPanel.tsx b/ui/app/src/components/ToolsPanel/ToolsPanel.tsx index b6bc9e5c11..de231a7218 100644 --- a/ui/app/src/components/ToolsPanel/ToolsPanel.tsx +++ b/ui/app/src/components/ToolsPanel/ToolsPanel.tsx @@ -14,26 +14,25 @@ * along with this program. If not, see . */ -import React, { useEffect } from 'react'; +import React, { Suspense, useEffect } from 'react'; import { defineMessages, FormattedMessage } from 'react-intl'; import { initToolsPanelConfig, updateToolsPanelWidth } from '../../state/actions/preview'; import { useDispatch } from 'react-redux'; import ResizeableDrawer from '../ResizeableDrawer/ResizeableDrawer'; import { renderWidgets } from '../Widget'; import { WidgetDescriptor } from '../../models'; -import { Resource } from '../../models/Resource'; -import { SuspenseWithEmptyState } from '../Suspencified/Suspencified'; import { makeStyles } from 'tss-react/mui'; import { useSelection } from '../../hooks/useSelection'; import { useActiveSiteId } from '../../hooks/useActiveSiteId'; import { usePreviewState } from '../../hooks/usePreviewState'; import { useActiveUser } from '../../hooks/useActiveUser'; -import { useLogicResource } from '../../hooks/useLogicResource'; import { useSiteUIConfig } from '../../hooks/useSiteUIConfig'; -import LookupTable from '../../models/LookupTable'; import { nnou } from '../../utils/object'; import { getStoredPreviewToolsPanelPage, getStoredPreviewToolsPanelWidth } from '../../utils/state'; import { useActiveSite } from '../../hooks/useActiveSite'; +import { ApiResponseErrorState } from '../ApiResponseErrorState'; +import { LoadingState } from '../LoadingState'; +import { EmptyState } from '../EmptyState'; defineMessages({ previewSiteExplorerPanelTitle: { @@ -63,8 +62,7 @@ export function ToolsPanel() { const dispatch = useDispatch(); const { id: siteId, uuid } = useActiveSite(); const { classes } = useStyles(); - const { showToolsPanel, toolsPanel, toolsPanelWidth, windowSize } = usePreviewState(); - const pages = useSelection((state) => state.preview.toolsPanelPageStack); + const { showToolsPanel, toolsPanel, toolsPanelWidth, windowSize, toolsPanelPageStack } = usePreviewState(); const uiConfig = useSiteUIConfig(); const baseUrl = useSelection((state) => state.env.authoringBase); const { username } = useActiveUser(); @@ -77,14 +75,6 @@ export function ToolsPanel() { } }, [uiConfig.xml, toolsPanel, dispatch, uuid, username, siteId]); - const resource = useLogicResource>(toolsPanel, { - errorSelector: (source) => uiConfig.error, - resultSelector: (source) => source.widgets, - shouldReject: (source) => false, - shouldResolve: (source) => Boolean(source), - shouldRenew: (source, resource) => uiConfig.isFetching || resource.complete - }); - const onWidthChange = (width) => { dispatch( updateToolsPanelWidth({ @@ -106,46 +96,46 @@ export function ToolsPanel() { drawerPaperBelowToolbar: { top: '64px' } }} > - !siteId || widgets?.length === 0, - emptyStateProps: { - title: siteId ? ( - - ) : ( - - ), - ...(!siteId && { image: `${baseUrl}/static-assets/images/choose_option.svg` }), - classes: { root: classes.emptyState, image: classes.emptyStateImage } - } - }} - > - - + {uiConfig ? ( + uiConfig.error ? ( + + ) : uiConfig.isFetching || !toolsPanel ? ( + + ) : !siteId || !toolsPanel.widgets || toolsPanel.widgets.length === 0 || !toolsPanelPageStack ? ( + + ) : ( + + ) + } + image={!siteId ? `${baseUrl}/static-assets/images/choose_option.svg` : undefined} + classes={{ root: classes.emptyState, image: classes.emptyStateImage }} + /> + ) : ( + + ) + ) : null} ); } interface ToolsPaneBodyProps { - resource: Resource; + root: WidgetDescriptor[]; pageStack: WidgetDescriptor[]; } function ToolsPaneBody(props: ToolsPaneBodyProps) { - const root = props.resource.read(); + const { root, pageStack } = props; const site = useActiveSiteId(); - const { pageStack } = props; const { rolesBySite } = useActiveUser(); return ( - <> + {renderWidgets(pageStack.length ? pageStack.slice(props.pageStack.length - 1) : root, { userRoles: rolesBySite[site] })} - + ); } From f5b358d01f5b96e9291bd291020f4311d2d2a459 Mon Sep 17 00:00:00 2001 From: jvega190 Date: Wed, 22 May 2024 11:53:38 -0600 Subject: [PATCH 15/30] [6633] Add suspense to components --- .../ChangeContentTypeDialogContainer.tsx | 16 ++++++---- .../CompareVersionsDialogContainer.tsx | 6 ++-- .../ConflictedPathDiffDialog.tsx | 6 ++-- .../DeleteContentTypeDialogContainer.tsx | 18 ++++++----- .../UninstallPluginDialogContainer.tsx | 18 ++++++----- .../NewContentDialogContainer.tsx | 14 ++++---- .../PreviewDropTargetsPanel.tsx | 6 ++-- .../PreviewPageExplorerPanel.tsx | 32 ++++++++++--------- .../components/QuickCreate/QuickCreate.tsx | 16 ++++++---- .../SiteManagement/SiteManagement.tsx | 24 +++++++------- .../ViewVersionDialogContainer.tsx | 6 ++-- 11 files changed, 92 insertions(+), 70 deletions(-) diff --git a/ui/app/src/components/ChangeContentTypeDialog/ChangeContentTypeDialogContainer.tsx b/ui/app/src/components/ChangeContentTypeDialog/ChangeContentTypeDialogContainer.tsx index f830c05dd9..9c9ab47715 100644 --- a/ui/app/src/components/ChangeContentTypeDialog/ChangeContentTypeDialogContainer.tsx +++ b/ui/app/src/components/ChangeContentTypeDialog/ChangeContentTypeDialogContainer.tsx @@ -17,7 +17,7 @@ import { ChangeContentTypeDialogContainerProps } from './utils'; import { useActiveSiteId } from '../../hooks/useActiveSiteId'; import { useDispatch } from 'react-redux'; -import React, { useEffect, useState } from 'react'; +import React, { Suspense, useEffect, useState } from 'react'; import { LegacyContentType } from '../../models/ContentType'; import { fetchLegacyContentTypes } from '../../services/contentTypes'; import { showErrorDialog } from '../../state/reducers/dialogs/error'; @@ -133,12 +133,14 @@ export function ChangeContentTypeDialogContainer(props: ChangeContentTypeDialogC ) : filteredContentTypes ? ( filteredContentTypes.length > 0 ? ( - + + + ) : ( ) : compareVersionsBranch.compareVersions?.length > 0 ? ( - + + + ) : ( } /> ) diff --git a/ui/app/src/components/ConflictedPathDiffDialog/ConflictedPathDiffDialog.tsx b/ui/app/src/components/ConflictedPathDiffDialog/ConflictedPathDiffDialog.tsx index 25b7b9ea27..4b2b0e5f68 100644 --- a/ui/app/src/components/ConflictedPathDiffDialog/ConflictedPathDiffDialog.tsx +++ b/ui/app/src/components/ConflictedPathDiffDialog/ConflictedPathDiffDialog.tsx @@ -14,7 +14,7 @@ * along with this program. If not, see . */ -import React, { useEffect, useState } from 'react'; +import React, { Suspense, useEffect, useState } from 'react'; import Dialog from '@mui/material/Dialog'; import DialogHeader from '../DialogHeader'; import DialogBody from '../DialogBody/DialogBody'; @@ -137,7 +137,9 @@ export function ConflictedPathDiffDialog(props: RemoteRepositoriesDiffDialogProp ) : fetching ? ( ) : fileDiff ? ( - + + + ) : null} diff --git a/ui/app/src/components/DeleteContentTypeDialog/DeleteContentTypeDialogContainer.tsx b/ui/app/src/components/DeleteContentTypeDialog/DeleteContentTypeDialogContainer.tsx index 7790b6efd2..feb5c3f05c 100644 --- a/ui/app/src/components/DeleteContentTypeDialog/DeleteContentTypeDialogContainer.tsx +++ b/ui/app/src/components/DeleteContentTypeDialog/DeleteContentTypeDialogContainer.tsx @@ -19,7 +19,7 @@ import { useActiveSiteId } from '../../hooks/useActiveSiteId'; import { defineMessages, useIntl } from 'react-intl'; import { useDispatch } from 'react-redux'; import * as React from 'react'; -import { useEffect } from 'react'; +import { Suspense, useEffect } from 'react'; import { deleteContentType, fetchContentTypeUsage } from '../../services/contentTypes'; import { showSystemNotification } from '../../state/actions/system'; import DeleteContentTypeDialogBody from './DeleteContentTypeDialogBody'; @@ -106,12 +106,14 @@ export function DeleteContentTypeDialogContainer(props: DeleteContentTypeDialogC ) : isFetching ? ( ) : data ? ( - + + + ) : null; } diff --git a/ui/app/src/components/DeletePluginDialog/UninstallPluginDialogContainer.tsx b/ui/app/src/components/DeletePluginDialog/UninstallPluginDialogContainer.tsx index 3a7073c2ca..f9dcebefeb 100644 --- a/ui/app/src/components/DeletePluginDialog/UninstallPluginDialogContainer.tsx +++ b/ui/app/src/components/DeletePluginDialog/UninstallPluginDialogContainer.tsx @@ -15,7 +15,7 @@ */ import * as React from 'react'; -import { useEffect } from 'react'; +import { Suspense, useEffect } from 'react'; import { UninstallPluginDialogContainerProps } from './utils'; import { useActiveSiteId } from '../../hooks/useActiveSiteId'; import { fetchMarketplacePluginUsage, uninstallMarketplacePlugin } from '../../services/marketplace'; @@ -84,12 +84,14 @@ export function UninstallPluginDialogContainer(props: UninstallPluginDialogConta ) : isFetching ? ( ) : data ? ( - onSubmit(pluginId)} - /> + + onSubmit(pluginId)} + /> + ) : null; } diff --git a/ui/app/src/components/NewContentDialog/NewContentDialogContainer.tsx b/ui/app/src/components/NewContentDialog/NewContentDialogContainer.tsx index e152d3b081..b57f17f13f 100644 --- a/ui/app/src/components/NewContentDialog/NewContentDialogContainer.tsx +++ b/ui/app/src/components/NewContentDialog/NewContentDialogContainer.tsx @@ -20,7 +20,7 @@ import { FormattedMessage, useIntl } from 'react-intl'; import { useDispatch } from 'react-redux'; import useStyles from './styles'; import { useSelection } from '../../hooks/useSelection'; -import React, { useCallback, useEffect, useState } from 'react'; +import React, { Suspense, useCallback, useEffect, useState } from 'react'; import { LegacyContentType } from '../../models/ContentType'; import translations from './translations'; import { withoutIndex } from '../../utils/path'; @@ -157,11 +157,13 @@ export function NewContentDialogContainer(props: NewContentDialogContainerProps) ) : filteredContentTypes ? ( filteredContentTypes.length > 0 ? ( - + + + ) : ( . */ -import React from 'react'; +import React, { Suspense } from 'react'; import { defineMessages, useIntl } from 'react-intl'; import { getHostToGuestBus } from '../../utils/subjects'; import { makeStyles } from 'tss-react/mui'; @@ -140,7 +140,9 @@ export function PreviewDropTargetsPanel() { ) : filteredDropTargets ? ( filteredDropTargets.length > 0 ? ( - + + + ) : ( . */ -import React, { useCallback, useEffect, useRef, useState } from 'react'; +import React, { Suspense, useCallback, useEffect, useRef, useState } from 'react'; import { defineMessages, FormattedMessage, useIntl } from 'react-intl'; import { makeStyles } from 'tss-react/mui'; import IconButton from '@mui/material/IconButton'; @@ -741,20 +741,22 @@ export function PreviewPageExplorerPanel() { {models && ContentTypesById ? ( - + + + ) : ( )} diff --git a/ui/app/src/components/QuickCreate/QuickCreate.tsx b/ui/app/src/components/QuickCreate/QuickCreate.tsx index 1e715a62c4..b657a2283c 100644 --- a/ui/app/src/components/QuickCreate/QuickCreate.tsx +++ b/ui/app/src/components/QuickCreate/QuickCreate.tsx @@ -14,7 +14,7 @@ * along with this program. If not, see . */ -import React, { forwardRef, useEffect, useState } from 'react'; +import React, { forwardRef, Suspense, useEffect, useState } from 'react'; import { defineMessages, FormattedMessage, useIntl } from 'react-intl'; import IconButton from '@mui/material/IconButton'; import AddCircleIcon from '@mui/icons-material/AddRounded'; @@ -173,12 +173,14 @@ export function QuickCreateMenu(props: QuickCreateMenuProps) { ) : isFetching ? ( ) : quickCreateItems && systemVersion ? ( - + + + ) : null} diff --git a/ui/app/src/components/SiteManagement/SiteManagement.tsx b/ui/app/src/components/SiteManagement/SiteManagement.tsx index bf54c58ee4..135df26153 100644 --- a/ui/app/src/components/SiteManagement/SiteManagement.tsx +++ b/ui/app/src/components/SiteManagement/SiteManagement.tsx @@ -14,7 +14,7 @@ * along with this program. If not, see . */ -import React, { useEffect, useState } from 'react'; +import React, { Suspense, useEffect, useState } from 'react'; import { defineMessages, FormattedMessage, useIntl } from 'react-intl'; import AddIcon from '@mui/icons-material/Add'; import SkeletonSitesGrid from '../SitesGrid/SitesGridSkeleton'; @@ -214,16 +214,18 @@ export function SiteManagement() { ) : sitesList ? ( sitesList.length > 0 ? ( - + + + ) : ( } diff --git a/ui/app/src/components/ViewVersionDialog/ViewVersionDialogContainer.tsx b/ui/app/src/components/ViewVersionDialog/ViewVersionDialogContainer.tsx index 5aca568b85..a667af2c81 100644 --- a/ui/app/src/components/ViewVersionDialog/ViewVersionDialogContainer.tsx +++ b/ui/app/src/components/ViewVersionDialog/ViewVersionDialogContainer.tsx @@ -16,7 +16,7 @@ import { ViewVersionDialogContainerProps } from './utils'; import DialogBody from '../DialogBody/DialogBody'; -import React from 'react'; +import React, { Suspense } from 'react'; import LegacyVersionDialog from './LegacyVersionDialog'; import ApiResponseErrorState from '../ApiResponseErrorState'; import { LoadingState } from '../LoadingState'; @@ -31,7 +31,9 @@ export function ViewVersionDialogContainer(props: ViewVersionDialogContainerProp ) : isFetching ? ( ) : version ? ( - + + + ) : null} ); From 840d2f0c6fb45ad29a8ff426591c7ad6794c7239 Mon Sep 17 00:00:00 2001 From: jvega190 Date: Wed, 29 May 2024 15:56:25 -0600 Subject: [PATCH 16/30] [6633] Restore PreviewInPageInstancesPanel --- .../PreviewInPageInstancesPanel.tsx | 246 ++++++++++++++++++ .../PreviewInPageInstancesPanel/index.ts | 19 ++ ui/app/src/components/index.ts | 1 + ui/app/src/env/studioUI.ts | 1 + 4 files changed, 267 insertions(+) create mode 100644 ui/app/src/components/PreviewInPageInstancesPanel/PreviewInPageInstancesPanel.tsx create mode 100644 ui/app/src/components/PreviewInPageInstancesPanel/index.ts diff --git a/ui/app/src/components/PreviewInPageInstancesPanel/PreviewInPageInstancesPanel.tsx b/ui/app/src/components/PreviewInPageInstancesPanel/PreviewInPageInstancesPanel.tsx new file mode 100644 index 0000000000..332c57a76c --- /dev/null +++ b/ui/app/src/components/PreviewInPageInstancesPanel/PreviewInPageInstancesPanel.tsx @@ -0,0 +1,246 @@ +/* + * Copyright (C) 2007-2024 Crafter Software Corporation. All Rights Reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 3 as published by + * the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +import React, { useEffect, useMemo, useState } from 'react'; +import { defineMessages, useIntl } from 'react-intl'; +import MenuItem from '@mui/material/MenuItem'; +import { makeStyles } from 'tss-react/mui'; +import { contentTreeFieldSelected, setContentTypeFilter, setPreviewEditMode } from '../../state/actions/preview'; +import { useDispatch } from 'react-redux'; +import Suspencified from '../Suspencified/Suspencified'; +import ContentInstance from '../../models/ContentInstance'; +import SearchBar from '../SearchBar/SearchBar'; +import Select from '@mui/material/Select'; +import ListItem from '@mui/material/ListItem'; +import Avatar from '@mui/material/Avatar'; +import { getInitials } from '../../utils/string'; +import ListItemAvatar from '@mui/material/ListItemAvatar'; +import ListItemText from '@mui/material/ListItemText'; +import CircularProgress from '@mui/material/CircularProgress'; +import { getHostToGuestBus } from '../../utils/subjects'; +import EmptyState from '../EmptyState/EmptyState'; +import { useSelection } from '../../hooks/useSelection'; +import { usePreviewGuest } from '../../hooks/usePreviewGuest'; +import { useContentTypes } from '../../hooks/useContentTypes'; +import { LoadingState } from '../LoadingState'; + +const translations = defineMessages({ + previewInPageInstancesPanel: { + id: 'previewInPageInstancesPanel.title', + defaultMessage: 'In this Page' + }, + noResults: { + id: 'previewInPageInstancesPanel.noResults', + defaultMessage: 'No results found.' + }, + selectContentType: { + id: 'previewInPageInstancesPanel.selectContentType', + defaultMessage: 'Select content type' + }, + chooseContentType: { + id: 'previewInPageInstancesPanel.chooseContentType', + defaultMessage: 'Please choose a content type.' + } +}); + +const useStyles = makeStyles()(() => ({ + search: { + padding: '15px 15px 0 15px' + }, + Select: { + width: '100%', + marginTop: '15px' + }, + noWrapping: { + overflow: 'hidden', + whiteSpace: 'nowrap', + textOverflow: 'ellipsis', + display: 'block' + }, + selectProgress: { + position: 'absolute', + right: '28px' + }, + emptyStateTitle: { + fontSize: '1em' + }, + item: {} +})); + +export function PreviewInPageInstancesPanel() { + const { classes } = useStyles(); + const { formatMessage } = useIntl(); + const dispatch = useDispatch(); + const contentTypeLookup = useContentTypes(); + const contentTypeFilter = useSelection((state) => state.preview.components.contentTypeFilter); + const guest = usePreviewGuest(); + const [keyword, setKeyword] = useState(''); + const hostToGuest$ = getHostToGuestBus(); + const editMode = useSelection((state) => state.preview.editMode); + const models = useMemo(() => { + return guest?.models; + }, [guest]); + const filteredContentTypes = + models && Object.values(models)?.filter((model) => model.craftercms.contentTypeId === contentTypeFilter); + + const selectedModels = useMemo(() => { + return Object.values(models ?? []).filter((model) => { + return ( + model.craftercms.contentTypeId === contentTypeFilter && + (model.craftercms.label.toLowerCase().includes(keyword.toLowerCase()) || + model.craftercms.contentTypeId.toLowerCase().includes(keyword.toLowerCase())) + ); + }); + // filter using .includes(keyword) on model.craftercms.label + }, [contentTypeFilter, models, keyword]); + + const [contentTypes, setContentTypes] = useState([]); + + // setting contentTypes + useEffect(() => { + if (models) { + const contentTypes = []; + Object.values(models ?? []).forEach((model) => { + // TODO: Groovy Controller Issue; + if (model.craftercms.contentTypeId && contentTypes.indexOf(model.craftercms.contentTypeId) <= 0) { + contentTypes.push(model.craftercms.contentTypeId); + } + }); + setContentTypes(contentTypes); + } + return () => { + setContentTypes([]); + setKeyword(''); + }; + }, [models]); + + const handleSearchKeyword = (keyword) => { + setKeyword(keyword); + }; + + const handleSelectChange = (value: string) => { + setKeyword(''); + dispatch(setContentTypeFilter(value)); + }; + + const onItemClick = (instance: ContentInstance) => { + if (!editMode) { + dispatch(setPreviewEditMode({ editMode: true })); + } + hostToGuest$.next( + contentTreeFieldSelected({ + name: instance.craftercms.label, + scrollElement: null, + iceProps: { + modelId: instance.craftercms.id, + fieldId: null, + index: null + } + }) + ); + return; + }; + + return ( + <> +
+ + +
+ + {filteredContentTypes ? ( + + ) : ( + + )} + + + ); +} + +interface InPageInstancesUIProps { + selectedModels: ContentInstance[]; + contentTypeFilter: string; + onItemClick(instance: ContentInstance): void; +} + +function InPageInstancesUI(props: InPageInstancesUIProps) { + const { selectedModels, onItemClick, contentTypeFilter } = props; + const { classes } = useStyles(); + const { formatMessage } = useIntl(); + + return ( + <> + {selectedModels.length ? ( + selectedModels.map((instance: ContentInstance) => ( + onItemClick(instance)} + > + + {getInitials(instance.craftercms.label)} + + + + )) + ) : ( + + )} + + ); +} + +export default PreviewInPageInstancesPanel; diff --git a/ui/app/src/components/PreviewInPageInstancesPanel/index.ts b/ui/app/src/components/PreviewInPageInstancesPanel/index.ts new file mode 100644 index 0000000000..1d2c080044 --- /dev/null +++ b/ui/app/src/components/PreviewInPageInstancesPanel/index.ts @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2007-2024 Crafter Software Corporation. All Rights Reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 3 as published by + * the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +export { default } from './PreviewInPageInstancesPanel'; + +export * from './PreviewInPageInstancesPanel'; diff --git a/ui/app/src/components/index.ts b/ui/app/src/components/index.ts index 21b4d1cdb1..0798a168ac 100644 --- a/ui/app/src/components/index.ts +++ b/ui/app/src/components/index.ts @@ -191,6 +191,7 @@ export * from './PreviewConcierge'; export * from './PreviewDialog'; export * from './PreviewDropTargetsPanel'; export * from './PreviewForwardButton'; +export * from './PreviewInPageInstancesPanel'; export * from './PreviewPageExplorerPanel'; export * from './PreviewSearchPanel'; export * from './PreviewSettingsPanel'; diff --git a/ui/app/src/env/studioUI.ts b/ui/app/src/env/studioUI.ts index cafda7e504..0da39ac01e 100644 --- a/ui/app/src/env/studioUI.ts +++ b/ui/app/src/env/studioUI.ts @@ -236,6 +236,7 @@ export const components = { PreviewDialog: lazy(() => import('../components/PreviewDialog')), PreviewDropTargetsPanel: lazy(() => import('../components/PreviewDropTargetsPanel')), PreviewForwardButton: lazy(() => import('../components/PreviewForwardButton')), + PreviewInPageInstancesPanel: lazy(() => import('../components/PreviewInPageInstancesPanel')), PreviewPageExplorerPanel: lazy(() => import('../components/PreviewPageExplorerPanel')), PreviewSearchPanel: lazy(() => import('../components/PreviewSearchPanel')), PreviewSettingsPanel: lazy(() => import('../components/PreviewSettingsPanel')), From 874ff32c68e5db123c2772a9065f9bea350ab4aa Mon Sep 17 00:00:00 2001 From: jvega190 Date: Wed, 29 May 2024 15:57:34 -0600 Subject: [PATCH 17/30] [6633] Remove useLogicResource, useSelectorResource and useQuickCreateListResource --- ui/app/src/CHANGELOG.md | 3 ++ ui/app/src/hooks/useLogicResource.ts | 45 ------------------- .../src/hooks/useQuickCreateListResource.ts | 40 ----------------- ui/app/src/hooks/useSelectorResource.ts | 38 ---------------- 4 files changed, 3 insertions(+), 123 deletions(-) delete mode 100644 ui/app/src/hooks/useLogicResource.ts delete mode 100644 ui/app/src/hooks/useQuickCreateListResource.ts delete mode 100644 ui/app/src/hooks/useSelectorResource.ts diff --git a/ui/app/src/CHANGELOG.md b/ui/app/src/CHANGELOG.md index 1fe8f3289a..03764ce9bb 100644 --- a/ui/app/src/CHANGELOG.md +++ b/ui/app/src/CHANGELOG.md @@ -36,6 +36,9 @@ * `actions/dialogs`: Renamed `updateEditConfig` action to `updateEditDialogConfig` * [hooks] * `usePreviewUrlControl`: Removed `history` prop. Retrieval of search and navigate (previously called 'push') is now done internally. + * Removed `useLogicResource` hook. + * Removed `useSelectorResource` hook. + * Removed `useQuickCreateListResource` hook. * Removed deprecated `aws-file-upload` and `aws-video` upload controls. * Migrated the Studio UI build to Vite/SWC * Rollup's XB build to use SWC diff --git a/ui/app/src/hooks/useLogicResource.ts b/ui/app/src/hooks/useLogicResource.ts deleted file mode 100644 index d19c0cc022..0000000000 --- a/ui/app/src/hooks/useLogicResource.ts +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (C) 2007-2022 Crafter Software Corporation. All Rights Reserved. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 3 as published by - * the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -import { CustomResourceSelectors } from './useSelectorResource'; -import { Resource } from '../models/Resource'; -import { useEffect, useRef, useState } from 'react'; -import { createResourceBundle } from '../utils/resource'; - -export function useLogicResource( - source: SourceType, - checkers: CustomResourceSelectors -): Resource { - const checkersRef = useRef>(); - const [[resource, resolve, reject], setBundle] = useState(() => createResourceBundle()); - - checkersRef.current = checkers; - - useEffect(() => { - const { shouldRenew, shouldReject, shouldResolve, errorSelector, resultSelector } = checkersRef.current; - if (shouldRenew(source, resource)) { - setBundle(createResourceBundle); - } else if (shouldReject(source, resource)) { - reject(errorSelector(source, resource)); - } else if (shouldResolve(source, resource)) { - resolve(resultSelector(source, resource)); - } - }, [source, resource, reject, resolve]); - - return resource; -} - -export default useLogicResource; diff --git a/ui/app/src/hooks/useQuickCreateListResource.ts b/ui/app/src/hooks/useQuickCreateListResource.ts deleted file mode 100644 index 0dc301cf38..0000000000 --- a/ui/app/src/hooks/useQuickCreateListResource.ts +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (C) 2007-2022 Crafter Software Corporation. All Rights Reserved. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 3 as published by - * the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -import { useDispatch } from 'react-redux'; -import { useActiveSiteId } from './useActiveSiteId'; -import { useQuickCreateState } from './useQuickCreateState'; -import { useEffect } from 'react'; -import { fetchQuickCreateList } from '../state/actions/content'; -import { useLogicResource } from './useLogicResource'; - -export function useQuickCreateListResource() { - const dispatch = useDispatch(); - const site = useActiveSiteId(); - const quickCreate = useQuickCreateState(); - useEffect(() => { - site && dispatch(fetchQuickCreateList()); - }, [site, dispatch]); - return useLogicResource(quickCreate, { - errorSelector: (source) => source.error, - resultSelector: (source) => source.items, - shouldReject: (source) => Boolean(source.error), - shouldResolve: (source) => Boolean(source.items) && !source.isFetching, - shouldRenew: (source) => Boolean(source.items) && source.isFetching - }); -} - -export default useQuickCreateListResource; diff --git a/ui/app/src/hooks/useSelectorResource.ts b/ui/app/src/hooks/useSelectorResource.ts deleted file mode 100644 index a59fef9b60..0000000000 --- a/ui/app/src/hooks/useSelectorResource.ts +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (C) 2007-2022 Crafter Software Corporation. All Rights Reserved. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 3 as published by - * the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -import { Resource } from '../models/Resource'; -import GlobalState from '../models/GlobalState'; -import { useSelection } from './useSelection'; -import { useLogicResource } from './useLogicResource'; - -export interface CustomResourceSelectors { - shouldResolve: (source: SourceType, resource: Resource) => boolean; - shouldReject: (source: SourceType, resource: Resource) => boolean; - shouldRenew: (source: SourceType, resource: Resource) => boolean; - resultSelector: (source: SourceType, resource: Resource) => ReturnType; - errorSelector: (source: SourceType, resource: Resource) => ErrorType; -} - -export function useSelectorResource( - sourceSelector: (state: GlobalState) => SourceType, - checkers: CustomResourceSelectors -): Resource { - const state = useSelection(sourceSelector); - return useLogicResource(state, checkers); -} - -export default useSelectorResource; From 2509f33f55062d1e7445e52504a51e30620e205e Mon Sep 17 00:00:00 2001 From: jvega190 Date: Tue, 4 Jun 2024 16:54:18 -0600 Subject: [PATCH 18/30] [6633] Rollback CHANGELOG entry --- ui/app/src/CHANGELOG.md | 1 - 1 file changed, 1 deletion(-) diff --git a/ui/app/src/CHANGELOG.md b/ui/app/src/CHANGELOG.md index 03764ce9bb..a804ebe7ba 100644 --- a/ui/app/src/CHANGELOG.md +++ b/ui/app/src/CHANGELOG.md @@ -43,7 +43,6 @@ * Migrated the Studio UI build to Vite/SWC * Rollup's XB build to use SWC * Upgraded target compilation to ES2022, dropping many code transforms for features that are supported by most modern browsers such as nullish coalescing, optional chaining, object spreading and destructuring. -* Removed `PreviewPageExplorerPanel` component. * Removed `pages/QuickCreateMenu` component. ## 4.1.5 From 2fff863be3b36c144a6b53fc6dabeb1b2dc6f318 Mon Sep 17 00:00:00 2001 From: jvega190 Date: Fri, 21 Jun 2024 10:50:03 -0600 Subject: [PATCH 19/30] [6633] Memoize filteredContentTypes --- .../ChangeContentTypeDialogContainer.tsx | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/ui/app/src/components/ChangeContentTypeDialog/ChangeContentTypeDialogContainer.tsx b/ui/app/src/components/ChangeContentTypeDialog/ChangeContentTypeDialogContainer.tsx index 9c9ab47715..dc350263da 100644 --- a/ui/app/src/components/ChangeContentTypeDialog/ChangeContentTypeDialogContainer.tsx +++ b/ui/app/src/components/ChangeContentTypeDialog/ChangeContentTypeDialogContainer.tsx @@ -17,7 +17,7 @@ import { ChangeContentTypeDialogContainerProps } from './utils'; import { useActiveSiteId } from '../../hooks/useActiveSiteId'; import { useDispatch } from 'react-redux'; -import React, { Suspense, useEffect, useState } from 'react'; +import React, { Suspense, useEffect, useMemo, useState } from 'react'; import { LegacyContentType } from '../../models/ContentType'; import { fetchLegacyContentTypes } from '../../services/contentTypes'; import { showErrorDialog } from '../../state/reducers/dialogs/error'; @@ -63,9 +63,10 @@ export function ChangeContentTypeDialogContainer(props: ChangeContentTypeDialogC const [isFetching, setIsFetching] = useState(false); const [keyword, setKeyword] = useState(''); const [debounceKeyword, setDebounceKeyword] = useState(''); - const filteredContentTypes = contentTypes?.filter((contentType) => - contentType.label.toLowerCase().includes(debounceKeyword.toLowerCase()) - ); + const filteredContentTypes = useMemo(() => { + const lowercaseKeyword = debounceKeyword.toLowerCase(); + return contentTypes?.filter((contentType) => contentType.label.toLowerCase().includes(lowercaseKeyword)); + }, [contentTypes, debounceKeyword]); const onSelectedContentType = (contentType: LegacyContentType) => { onContentTypeSelected?.({ From 40bd902e42ae6455117ee2fa7f7f50b5ec110b4f Mon Sep 17 00:00:00 2001 From: jvega190 Date: Fri, 21 Jun 2024 12:15:13 -0600 Subject: [PATCH 20/30] [6633] Add cancellation --- .../ChangeContentTypeDialogContainer.tsx | 5 ++++- .../DeleteContentTypeDialogContainer.tsx | 5 ++++- .../DeletePluginDialog/UninstallPluginDialogContainer.tsx | 5 ++++- .../NewContentDialog/NewContentDialogContainer.tsx | 5 ++++- 4 files changed, 16 insertions(+), 4 deletions(-) diff --git a/ui/app/src/components/ChangeContentTypeDialog/ChangeContentTypeDialogContainer.tsx b/ui/app/src/components/ChangeContentTypeDialog/ChangeContentTypeDialogContainer.tsx index dc350263da..26adc9d2e9 100644 --- a/ui/app/src/components/ChangeContentTypeDialog/ChangeContentTypeDialogContainer.tsx +++ b/ui/app/src/components/ChangeContentTypeDialog/ChangeContentTypeDialogContainer.tsx @@ -77,7 +77,7 @@ export function ChangeContentTypeDialogContainer(props: ChangeContentTypeDialogC useEffect(() => { if (selectedItem.path) { setIsFetching(true); - fetchLegacyContentTypes(site, selectedItem.path).subscribe({ + const sub = fetchLegacyContentTypes(site, selectedItem.path).subscribe({ next: (response) => { setIsFetching(false); setContentTypes( @@ -92,6 +92,9 @@ export function ChangeContentTypeDialogContainer(props: ChangeContentTypeDialogC dispatch(showErrorDialog({ error: response })); } }); + return () => { + sub.unsubscribe(); + }; } }, [dispatch, selectedItem, site]); diff --git a/ui/app/src/components/DeleteContentTypeDialog/DeleteContentTypeDialogContainer.tsx b/ui/app/src/components/DeleteContentTypeDialog/DeleteContentTypeDialogContainer.tsx index feb5c3f05c..8e46e42c9a 100644 --- a/ui/app/src/components/DeleteContentTypeDialog/DeleteContentTypeDialogContainer.tsx +++ b/ui/app/src/components/DeleteContentTypeDialog/DeleteContentTypeDialogContainer.tsx @@ -55,7 +55,7 @@ export function DeleteContentTypeDialogContainer(props: DeleteContentTypeDialogC useEffect(() => { setState({ isFetching: true }); - fetchContentTypeUsage(site, contentType.id).subscribe({ + const sub = fetchContentTypeUsage(site, contentType.id).subscribe({ next(response) { setState({ data: response, @@ -70,6 +70,9 @@ export function DeleteContentTypeDialogContainer(props: DeleteContentTypeDialogC }); } }); + return () => { + sub.unsubscribe(); + }; }, [site, contentType.id, setState]); const onSubmit = () => { diff --git a/ui/app/src/components/DeletePluginDialog/UninstallPluginDialogContainer.tsx b/ui/app/src/components/DeletePluginDialog/UninstallPluginDialogContainer.tsx index f9dcebefeb..285c6a9a31 100644 --- a/ui/app/src/components/DeletePluginDialog/UninstallPluginDialogContainer.tsx +++ b/ui/app/src/components/DeletePluginDialog/UninstallPluginDialogContainer.tsx @@ -40,7 +40,7 @@ export function UninstallPluginDialogContainer(props: UninstallPluginDialogConta useEffect(() => { setState({ isFetching: true }); - fetchMarketplacePluginUsage(site, pluginId).subscribe({ + const sub = fetchMarketplacePluginUsage(site, pluginId).subscribe({ next(response) { setState({ data: response, @@ -54,6 +54,9 @@ export function UninstallPluginDialogContainer(props: UninstallPluginDialogConta }); } }); + return () => { + sub.unsubscribe(); + }; }, [site, pluginId, setState]); const onSubmit = (id: string) => { diff --git a/ui/app/src/components/NewContentDialog/NewContentDialogContainer.tsx b/ui/app/src/components/NewContentDialog/NewContentDialogContainer.tsx index b57f17f13f..2e9a1f8a34 100644 --- a/ui/app/src/components/NewContentDialog/NewContentDialogContainer.tsx +++ b/ui/app/src/components/NewContentDialog/NewContentDialogContainer.tsx @@ -99,7 +99,7 @@ export function NewContentDialogContainer(props: NewContentDialogContainerProps) : selectedItem.path; setIsFetching(true); - fetchLegacyContentTypes(site, path).subscribe({ + const sub = fetchLegacyContentTypes(site, path).subscribe({ next(response) { setIsFetching(false); if (response.length === 1) { @@ -114,6 +114,9 @@ export function NewContentDialogContainer(props: NewContentDialogContainerProps) dispatch(showErrorDialog({ error: response })); } }); + return () => { + sub.unsubscribe(); + }; } }, [dispatch, selectedItem, site, onSelectedContentType]); From 23ba80f1a6e48edcf1a4441598c3ea71071ffb16 Mon Sep 17 00:00:00 2001 From: jvega190 Date: Fri, 21 Jun 2024 12:22:15 -0600 Subject: [PATCH 21/30] [6633] Memoize filteredContentTypes --- .../NewContentDialogContainer.tsx | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/ui/app/src/components/NewContentDialog/NewContentDialogContainer.tsx b/ui/app/src/components/NewContentDialog/NewContentDialogContainer.tsx index 2e9a1f8a34..c7f0046500 100644 --- a/ui/app/src/components/NewContentDialog/NewContentDialogContainer.tsx +++ b/ui/app/src/components/NewContentDialog/NewContentDialogContainer.tsx @@ -20,7 +20,7 @@ import { FormattedMessage, useIntl } from 'react-intl'; import { useDispatch } from 'react-redux'; import useStyles from './styles'; import { useSelection } from '../../hooks/useSelection'; -import React, { Suspense, useCallback, useEffect, useState } from 'react'; +import React, { Suspense, useCallback, useEffect, useMemo, useState } from 'react'; import { LegacyContentType } from '../../models/ContentType'; import translations from './translations'; import { withoutIndex } from '../../utils/path'; @@ -55,11 +55,14 @@ export function NewContentDialogContainer(props: NewContentDialogContainerProps) const [keyword, setKeyword] = useState(''); const [debounceKeyword, setDebounceKeyword] = useState(''); const [selectedFilter, setSelectedFilter] = useState('all'); - const filteredContentTypes = contentTypes?.filter( - (contentType) => - contentType.label.toLowerCase().includes(debounceKeyword.toLowerCase()) && - (selectedFilter === 'all' || contentType.type === selectedFilter) - ); + const filteredContentTypes = useMemo(() => { + const lowercaseKeyword = debounceKeyword.toLowerCase(); + return contentTypes?.filter( + (contentType) => + contentType.label.toLowerCase().includes(lowercaseKeyword) && + (selectedFilter === 'all' || contentType.type === selectedFilter) + ); + }, [contentTypes, debounceKeyword, selectedFilter]); const filters = [ { From d9d8971fb309f9bff19861b184d9f597a10baa08 Mon Sep 17 00:00:00 2001 From: jvega190 Date: Fri, 21 Jun 2024 12:27:43 -0600 Subject: [PATCH 22/30] [6633] Rollback PreviewInPageInstancesPanel/index.ts --- ui/app/src/components/PreviewInPageInstancesPanel/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/app/src/components/PreviewInPageInstancesPanel/index.ts b/ui/app/src/components/PreviewInPageInstancesPanel/index.ts index 1d2c080044..0ef0bcab96 100644 --- a/ui/app/src/components/PreviewInPageInstancesPanel/index.ts +++ b/ui/app/src/components/PreviewInPageInstancesPanel/index.ts @@ -1,5 +1,5 @@ /* - * Copyright (C) 2007-2024 Crafter Software Corporation. All Rights Reserved. + * Copyright (C) 2007-2022 Crafter Software Corporation. All Rights Reserved. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3 as published by From 79fdb97e0844026fb86c1c7bea27608ffcd5d0a6 Mon Sep 17 00:00:00 2001 From: jvega190 Date: Fri, 21 Jun 2024 12:31:02 -0600 Subject: [PATCH 23/30] [6633] update filteredContentTypes models validation --- .../PreviewInPageInstancesPanel.tsx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/ui/app/src/components/PreviewInPageInstancesPanel/PreviewInPageInstancesPanel.tsx b/ui/app/src/components/PreviewInPageInstancesPanel/PreviewInPageInstancesPanel.tsx index 332c57a76c..7bf8148fa2 100644 --- a/ui/app/src/components/PreviewInPageInstancesPanel/PreviewInPageInstancesPanel.tsx +++ b/ui/app/src/components/PreviewInPageInstancesPanel/PreviewInPageInstancesPanel.tsx @@ -93,8 +93,9 @@ export function PreviewInPageInstancesPanel() { const models = useMemo(() => { return guest?.models; }, [guest]); - const filteredContentTypes = - models && Object.values(models)?.filter((model) => model.craftercms.contentTypeId === contentTypeFilter); + const filteredContentTypes = Object.values(models ?? {}).filter( + (model) => model.craftercms.contentTypeId === contentTypeFilter + ); const selectedModels = useMemo(() => { return Object.values(models ?? []).filter((model) => { From 73986eecde31b3ea2446089305d21623d9dd220e Mon Sep 17 00:00:00 2001 From: jvega190 Date: Fri, 21 Jun 2024 12:57:37 -0600 Subject: [PATCH 24/30] [6633] Cleanup code, update CHANGELOG --- ui/app/src/CHANGELOG.md | 6 ++- .../PreviewBrowseComponentsPanelUI.tsx | 8 ---- ui/app/src/components/RejectDialog/utils.ts | 1 - .../components/Suspencified/Suspencified.tsx | 44 +------------------ ui/app/src/hooks/useSystemVersionResource.ts | 24 ---------- 5 files changed, 5 insertions(+), 78 deletions(-) delete mode 100644 ui/app/src/hooks/useSystemVersionResource.ts diff --git a/ui/app/src/CHANGELOG.md b/ui/app/src/CHANGELOG.md index 3b18a9cc15..fb344bd215 100644 --- a/ui/app/src/CHANGELOG.md +++ b/ui/app/src/CHANGELOG.md @@ -24,6 +24,8 @@ * `listItemProps` are routed to the list `ListItem` component instead of the `ListItemButton` * Added `listItemButtonProps` property * `DraggablePanelListItem` prop `onMenu` send the pointer event as its first and only argument instead of the anchor element attached to the event. Can get element through `event.currentTarget`. + * Removed `pages/QuickCreateMenu` component. + * Removed `SuspenseWithEmptyState` and `WithEmptyState` components. * [services] Removed services associated with v1 APIs: * `fetchLegacyGetGoLiveItems` * `fetchLegacyUserActivities` @@ -40,14 +42,14 @@ * Removed `useLogicResource` hook. * Removed `useSelectorResource` hook. * Removed `useQuickCreateListResource` hook. + * Removed `useSystemVersionResource` hook. * Removed deprecated `aws-file-upload` and `aws-video` upload controls. * Migrated the Studio UI build to Vite/SWC * Rollup's XB build to use SWC * Upgraded target compilation to ES2022, dropping many code transforms for features that are supported by most modern browsers such as nullish coalescing, optional chaining, object spreading and destructuring. * The `allowedContentTypes` ContentTypeField validation changed from being an array to a Record * Remove legacy `browseCMIS` dialog and `openCMISBrowse` function from common-api. -* Remove `CMIS-repo`, `CMIS-upload`, `img-cmis-repo`, `img-CMIS-upload`, `video-cmis-repo` and `video-CMIS-upload` datasources. -* Removed `pages/QuickCreateMenu` component. +* Remove `CMIS-repo`, `CMIS-upload`, `img-cmis-repo`, `img-CMIS-upload`, `video-cmis-repo` and `video-CMIS-upload` datasources. ## 4.1.5 * [common-api.js] diff --git a/ui/app/src/components/PreviewBrowseComponentsPanel/PreviewBrowseComponentsPanelUI.tsx b/ui/app/src/components/PreviewBrowseComponentsPanel/PreviewBrowseComponentsPanelUI.tsx index 6adf90032a..0904920d5f 100644 --- a/ui/app/src/components/PreviewBrowseComponentsPanel/PreviewBrowseComponentsPanelUI.tsx +++ b/ui/app/src/components/PreviewBrowseComponentsPanel/PreviewBrowseComponentsPanelUI.tsx @@ -25,14 +25,6 @@ import { useComponentsPanelUI } from './styles'; import FormHelperText from '@mui/material/FormHelperText'; import Pagination from '../Pagination'; -export interface ComponentResource { - count: number; - limit: number; - pageNumber: number; - contentTypeFilter: string; - items: Array; -} - export interface PreviewBrowseComponentsPanelUIProps { items: Array; count: number; diff --git a/ui/app/src/components/RejectDialog/utils.ts b/ui/app/src/components/RejectDialog/utils.ts index a65e4b2e91..c3a4b774c1 100644 --- a/ui/app/src/components/RejectDialog/utils.ts +++ b/ui/app/src/components/RejectDialog/utils.ts @@ -14,7 +14,6 @@ * along with this program. If not, see . */ -import { Resource } from '../../models/Resource'; import StandardAction from '../../models/StandardAction'; import { SandboxItem } from '../../models/Item'; import { ApiResponse } from '../../models/ApiResponse'; diff --git a/ui/app/src/components/Suspencified/Suspencified.tsx b/ui/app/src/components/Suspencified/Suspencified.tsx index 1502ec66aa..14cd21afba 100644 --- a/ui/app/src/components/Suspencified/Suspencified.tsx +++ b/ui/app/src/components/Suspencified/Suspencified.tsx @@ -14,25 +14,9 @@ * along with this program. If not, see . */ -import React, { Fragment, PropsWithChildren, Suspense, SuspenseProps } from 'react'; +import React, { PropsWithChildren, Suspense, SuspenseProps } from 'react'; import { ErrorBoundary, ErrorBoundaryProps } from '../ErrorBoundary/ErrorBoundary'; import LoadingState, { LoadingStateProps } from '../LoadingState/LoadingState'; -import { Resource } from '../../models/Resource'; -import EmptyState, { EmptyStateProps } from '../EmptyState/EmptyState'; -import { FormattedMessage } from 'react-intl'; - -export type PropsWithResource = PropsWithChildren< - { - resource: Resource; - } & Props ->; - -type SuspenseWithEmptyStateProps = PropsWithChildren< - PropsWithResource & { - isEmpty?(value: ResourceType): boolean; - emptyStateProps?: Partial; - } ->; type SuspencifiedProps = PropsWithChildren<{ suspenseProps?: SuspenseProps; @@ -40,16 +24,6 @@ type SuspencifiedProps = PropsWithChildren<{ errorBoundaryProps?: ErrorBoundaryProps; }>; -export function WithEmptyState(props: SuspenseWithEmptyStateProps) { - const { children, isEmpty = (value: ResourceType) => (value as any).length === 0, resource, emptyStateProps } = props; - const value = resource.read(); - const finalEmptyStateProps: EmptyStateProps = { - title: , - ...emptyStateProps - }; - return {isEmpty(value) ? : children}; -} - export function Suspencified(props: SuspencifiedProps) { const { children, loadingStateProps, errorBoundaryProps, suspenseProps } = props; return ( @@ -59,20 +33,4 @@ export function Suspencified(props: SuspencifiedProps) { ); } -export function SuspenseWithEmptyState( - props: SuspencifiedProps & { - resource: Resource; - withEmptyStateProps?: Partial>; - } -) { - const { children, withEmptyStateProps, resource } = props; - return ( - - - {children} - - - ); -} - export default Suspencified; diff --git a/ui/app/src/hooks/useSystemVersionResource.ts b/ui/app/src/hooks/useSystemVersionResource.ts deleted file mode 100644 index d60c526568..0000000000 --- a/ui/app/src/hooks/useSystemVersionResource.ts +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright (C) 2007-2022 Crafter Software Corporation. All Rights Reserved. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 3 as published by - * the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -import { useSystemVersion } from './useSystemVersion'; -import { useResolveWhenNotNullResource } from './useResolveWhenNotNullResource'; - -export function useSystemVersionResource() { - return useResolveWhenNotNullResource(useSystemVersion()); -} - -export default useSystemVersionResource; From f6d61b8f78985896f6b6c1a41025698739fd7b42 Mon Sep 17 00:00:00 2001 From: jvega190 Date: Fri, 21 Jun 2024 15:00:42 -0600 Subject: [PATCH 25/30] [6633] Remove unnecessary Suspense usages --- .../ChangeContentTypeDialogContainer.tsx | 14 ++++----- .../CompareVersionsDialogContainer.tsx | 4 +-- .../ConflictedPathDiffDialog.tsx | 4 +-- .../DeleteContentTypeDialogContainer.tsx | 16 +++++----- .../NewContentDialogContainer.tsx | 12 ++++---- .../PreviewDropTargetsPanel.tsx | 4 +-- .../PreviewPageExplorerPanel.tsx | 30 +++++++++---------- .../components/QuickCreate/QuickCreate.tsx | 14 ++++----- .../SiteManagement/SiteManagement.tsx | 22 +++++++------- .../ViewVersionDialogContainer.tsx | 4 +-- 10 files changed, 52 insertions(+), 72 deletions(-) diff --git a/ui/app/src/components/ChangeContentTypeDialog/ChangeContentTypeDialogContainer.tsx b/ui/app/src/components/ChangeContentTypeDialog/ChangeContentTypeDialogContainer.tsx index 26adc9d2e9..d70ac5fced 100644 --- a/ui/app/src/components/ChangeContentTypeDialog/ChangeContentTypeDialogContainer.tsx +++ b/ui/app/src/components/ChangeContentTypeDialog/ChangeContentTypeDialogContainer.tsx @@ -137,14 +137,12 @@ export function ChangeContentTypeDialogContainer(props: ChangeContentTypeDialogC ) : filteredContentTypes ? ( filteredContentTypes.length > 0 ? ( - - - + ) : ( ) : compareVersionsBranch.compareVersions?.length > 0 ? ( - - - + ) : ( } /> ) diff --git a/ui/app/src/components/ConflictedPathDiffDialog/ConflictedPathDiffDialog.tsx b/ui/app/src/components/ConflictedPathDiffDialog/ConflictedPathDiffDialog.tsx index 4b2b0e5f68..d331184744 100644 --- a/ui/app/src/components/ConflictedPathDiffDialog/ConflictedPathDiffDialog.tsx +++ b/ui/app/src/components/ConflictedPathDiffDialog/ConflictedPathDiffDialog.tsx @@ -137,9 +137,7 @@ export function ConflictedPathDiffDialog(props: RemoteRepositoriesDiffDialogProp ) : fetching ? ( ) : fileDiff ? ( - - - + ) : null} diff --git a/ui/app/src/components/DeleteContentTypeDialog/DeleteContentTypeDialogContainer.tsx b/ui/app/src/components/DeleteContentTypeDialog/DeleteContentTypeDialogContainer.tsx index 8e46e42c9a..e0e99822cd 100644 --- a/ui/app/src/components/DeleteContentTypeDialog/DeleteContentTypeDialogContainer.tsx +++ b/ui/app/src/components/DeleteContentTypeDialog/DeleteContentTypeDialogContainer.tsx @@ -109,14 +109,12 @@ export function DeleteContentTypeDialogContainer(props: DeleteContentTypeDialogC ) : isFetching ? ( ) : data ? ( - - - + ) : null; } diff --git a/ui/app/src/components/NewContentDialog/NewContentDialogContainer.tsx b/ui/app/src/components/NewContentDialog/NewContentDialogContainer.tsx index c7f0046500..4e18818e35 100644 --- a/ui/app/src/components/NewContentDialog/NewContentDialogContainer.tsx +++ b/ui/app/src/components/NewContentDialog/NewContentDialogContainer.tsx @@ -163,13 +163,11 @@ export function NewContentDialogContainer(props: NewContentDialogContainerProps) ) : filteredContentTypes ? ( filteredContentTypes.length > 0 ? ( - - - + ) : ( ) : filteredDropTargets ? ( filteredDropTargets.length > 0 ? ( - - - + ) : ( {models && ContentTypesById ? ( - - - + ) : ( )} diff --git a/ui/app/src/components/QuickCreate/QuickCreate.tsx b/ui/app/src/components/QuickCreate/QuickCreate.tsx index b657a2283c..2b1d6fad23 100644 --- a/ui/app/src/components/QuickCreate/QuickCreate.tsx +++ b/ui/app/src/components/QuickCreate/QuickCreate.tsx @@ -173,14 +173,12 @@ export function QuickCreateMenu(props: QuickCreateMenuProps) { ) : isFetching ? ( ) : quickCreateItems && systemVersion ? ( - - - + ) : null} diff --git a/ui/app/src/components/SiteManagement/SiteManagement.tsx b/ui/app/src/components/SiteManagement/SiteManagement.tsx index 135df26153..8c5b7122ab 100644 --- a/ui/app/src/components/SiteManagement/SiteManagement.tsx +++ b/ui/app/src/components/SiteManagement/SiteManagement.tsx @@ -214,18 +214,16 @@ export function SiteManagement() { ) : sitesList ? ( sitesList.length > 0 ? ( - - - + ) : ( } diff --git a/ui/app/src/components/ViewVersionDialog/ViewVersionDialogContainer.tsx b/ui/app/src/components/ViewVersionDialog/ViewVersionDialogContainer.tsx index a667af2c81..a6ffd89240 100644 --- a/ui/app/src/components/ViewVersionDialog/ViewVersionDialogContainer.tsx +++ b/ui/app/src/components/ViewVersionDialog/ViewVersionDialogContainer.tsx @@ -31,9 +31,7 @@ export function ViewVersionDialogContainer(props: ViewVersionDialogContainerProp ) : isFetching ? ( ) : version ? ( - - - + ) : null} ); From 46afeb57e1993f9e3a3f21cb73582a7cb5e398b0 Mon Sep 17 00:00:00 2001 From: jvega190 Date: Fri, 21 Jun 2024 15:04:18 -0600 Subject: [PATCH 26/30] [6633] Remove unused imports --- .../ChangeContentTypeDialogContainer.tsx | 2 +- .../CompareVersionsDialog/CompareVersionsDialogContainer.tsx | 2 +- .../ConflictedPathDiffDialog/ConflictedPathDiffDialog.tsx | 2 +- .../DeleteContentTypeDialogContainer.tsx | 2 +- .../components/NewContentDialog/NewContentDialogContainer.tsx | 2 +- .../PreviewDropTargetsPanel/PreviewDropTargetsPanel.tsx | 2 +- .../PreviewPageExplorerPanel/PreviewPageExplorerPanel.tsx | 2 +- ui/app/src/components/QuickCreate/QuickCreate.tsx | 2 +- ui/app/src/components/SiteManagement/SiteManagement.tsx | 2 +- .../components/ViewVersionDialog/ViewVersionDialogContainer.tsx | 2 +- 10 files changed, 10 insertions(+), 10 deletions(-) diff --git a/ui/app/src/components/ChangeContentTypeDialog/ChangeContentTypeDialogContainer.tsx b/ui/app/src/components/ChangeContentTypeDialog/ChangeContentTypeDialogContainer.tsx index d70ac5fced..6381ba8522 100644 --- a/ui/app/src/components/ChangeContentTypeDialog/ChangeContentTypeDialogContainer.tsx +++ b/ui/app/src/components/ChangeContentTypeDialog/ChangeContentTypeDialogContainer.tsx @@ -17,7 +17,7 @@ import { ChangeContentTypeDialogContainerProps } from './utils'; import { useActiveSiteId } from '../../hooks/useActiveSiteId'; import { useDispatch } from 'react-redux'; -import React, { Suspense, useEffect, useMemo, useState } from 'react'; +import React, { useEffect, useMemo, useState } from 'react'; import { LegacyContentType } from '../../models/ContentType'; import { fetchLegacyContentTypes } from '../../services/contentTypes'; import { showErrorDialog } from '../../state/reducers/dialogs/error'; diff --git a/ui/app/src/components/CompareVersionsDialog/CompareVersionsDialogContainer.tsx b/ui/app/src/components/CompareVersionsDialog/CompareVersionsDialogContainer.tsx index 2e593f5b00..138b525ba8 100644 --- a/ui/app/src/components/CompareVersionsDialog/CompareVersionsDialogContainer.tsx +++ b/ui/app/src/components/CompareVersionsDialog/CompareVersionsDialogContainer.tsx @@ -16,7 +16,7 @@ import { CompareVersionsDialogContainerProps } from './utils'; import { FormattedMessage } from 'react-intl'; -import React, { Suspense, useState } from 'react'; +import React, { useState } from 'react'; import { useDispatch } from 'react-redux'; import { ItemHistoryEntry } from '../../models/Version'; import { CompareVersions } from './CompareVersions'; diff --git a/ui/app/src/components/ConflictedPathDiffDialog/ConflictedPathDiffDialog.tsx b/ui/app/src/components/ConflictedPathDiffDialog/ConflictedPathDiffDialog.tsx index d331184744..25b7b9ea27 100644 --- a/ui/app/src/components/ConflictedPathDiffDialog/ConflictedPathDiffDialog.tsx +++ b/ui/app/src/components/ConflictedPathDiffDialog/ConflictedPathDiffDialog.tsx @@ -14,7 +14,7 @@ * along with this program. If not, see . */ -import React, { Suspense, useEffect, useState } from 'react'; +import React, { useEffect, useState } from 'react'; import Dialog from '@mui/material/Dialog'; import DialogHeader from '../DialogHeader'; import DialogBody from '../DialogBody/DialogBody'; diff --git a/ui/app/src/components/DeleteContentTypeDialog/DeleteContentTypeDialogContainer.tsx b/ui/app/src/components/DeleteContentTypeDialog/DeleteContentTypeDialogContainer.tsx index e0e99822cd..59bca89c4e 100644 --- a/ui/app/src/components/DeleteContentTypeDialog/DeleteContentTypeDialogContainer.tsx +++ b/ui/app/src/components/DeleteContentTypeDialog/DeleteContentTypeDialogContainer.tsx @@ -19,7 +19,7 @@ import { useActiveSiteId } from '../../hooks/useActiveSiteId'; import { defineMessages, useIntl } from 'react-intl'; import { useDispatch } from 'react-redux'; import * as React from 'react'; -import { Suspense, useEffect } from 'react'; +import { useEffect } from 'react'; import { deleteContentType, fetchContentTypeUsage } from '../../services/contentTypes'; import { showSystemNotification } from '../../state/actions/system'; import DeleteContentTypeDialogBody from './DeleteContentTypeDialogBody'; diff --git a/ui/app/src/components/NewContentDialog/NewContentDialogContainer.tsx b/ui/app/src/components/NewContentDialog/NewContentDialogContainer.tsx index 4e18818e35..a4c1302a29 100644 --- a/ui/app/src/components/NewContentDialog/NewContentDialogContainer.tsx +++ b/ui/app/src/components/NewContentDialog/NewContentDialogContainer.tsx @@ -20,7 +20,7 @@ import { FormattedMessage, useIntl } from 'react-intl'; import { useDispatch } from 'react-redux'; import useStyles from './styles'; import { useSelection } from '../../hooks/useSelection'; -import React, { Suspense, useCallback, useEffect, useMemo, useState } from 'react'; +import React, { useCallback, useEffect, useMemo, useState } from 'react'; import { LegacyContentType } from '../../models/ContentType'; import translations from './translations'; import { withoutIndex } from '../../utils/path'; diff --git a/ui/app/src/components/PreviewDropTargetsPanel/PreviewDropTargetsPanel.tsx b/ui/app/src/components/PreviewDropTargetsPanel/PreviewDropTargetsPanel.tsx index 7128b76e9d..731a3cd27a 100644 --- a/ui/app/src/components/PreviewDropTargetsPanel/PreviewDropTargetsPanel.tsx +++ b/ui/app/src/components/PreviewDropTargetsPanel/PreviewDropTargetsPanel.tsx @@ -14,7 +14,7 @@ * along with this program. If not, see . */ -import React, { Suspense } from 'react'; +import React from 'react'; import { defineMessages, useIntl } from 'react-intl'; import { getHostToGuestBus } from '../../utils/subjects'; import { makeStyles } from 'tss-react/mui'; diff --git a/ui/app/src/components/PreviewPageExplorerPanel/PreviewPageExplorerPanel.tsx b/ui/app/src/components/PreviewPageExplorerPanel/PreviewPageExplorerPanel.tsx index 6698246659..1db1e317c3 100644 --- a/ui/app/src/components/PreviewPageExplorerPanel/PreviewPageExplorerPanel.tsx +++ b/ui/app/src/components/PreviewPageExplorerPanel/PreviewPageExplorerPanel.tsx @@ -14,7 +14,7 @@ * along with this program. If not, see . */ -import React, { Suspense, useCallback, useEffect, useRef, useState } from 'react'; +import React, { useCallback, useEffect, useRef, useState } from 'react'; import { defineMessages, FormattedMessage, useIntl } from 'react-intl'; import { makeStyles } from 'tss-react/mui'; import IconButton from '@mui/material/IconButton'; diff --git a/ui/app/src/components/QuickCreate/QuickCreate.tsx b/ui/app/src/components/QuickCreate/QuickCreate.tsx index 2b1d6fad23..1e715a62c4 100644 --- a/ui/app/src/components/QuickCreate/QuickCreate.tsx +++ b/ui/app/src/components/QuickCreate/QuickCreate.tsx @@ -14,7 +14,7 @@ * along with this program. If not, see . */ -import React, { forwardRef, Suspense, useEffect, useState } from 'react'; +import React, { forwardRef, useEffect, useState } from 'react'; import { defineMessages, FormattedMessage, useIntl } from 'react-intl'; import IconButton from '@mui/material/IconButton'; import AddCircleIcon from '@mui/icons-material/AddRounded'; diff --git a/ui/app/src/components/SiteManagement/SiteManagement.tsx b/ui/app/src/components/SiteManagement/SiteManagement.tsx index 8c5b7122ab..bf54c58ee4 100644 --- a/ui/app/src/components/SiteManagement/SiteManagement.tsx +++ b/ui/app/src/components/SiteManagement/SiteManagement.tsx @@ -14,7 +14,7 @@ * along with this program. If not, see . */ -import React, { Suspense, useEffect, useState } from 'react'; +import React, { useEffect, useState } from 'react'; import { defineMessages, FormattedMessage, useIntl } from 'react-intl'; import AddIcon from '@mui/icons-material/Add'; import SkeletonSitesGrid from '../SitesGrid/SitesGridSkeleton'; diff --git a/ui/app/src/components/ViewVersionDialog/ViewVersionDialogContainer.tsx b/ui/app/src/components/ViewVersionDialog/ViewVersionDialogContainer.tsx index a6ffd89240..5aca568b85 100644 --- a/ui/app/src/components/ViewVersionDialog/ViewVersionDialogContainer.tsx +++ b/ui/app/src/components/ViewVersionDialog/ViewVersionDialogContainer.tsx @@ -16,7 +16,7 @@ import { ViewVersionDialogContainerProps } from './utils'; import DialogBody from '../DialogBody/DialogBody'; -import React, { Suspense } from 'react'; +import React from 'react'; import LegacyVersionDialog from './LegacyVersionDialog'; import ApiResponseErrorState from '../ApiResponseErrorState'; import { LoadingState } from '../LoadingState'; From f7f25c9557ee11683272d62e2a03e4088f2de554 Mon Sep 17 00:00:00 2001 From: jvega190 Date: Fri, 28 Jun 2024 14:34:00 -0600 Subject: [PATCH 27/30] [6633] Remove remaining resource-related things, update CHANGELOG --- ui/app/src/CHANGELOG.md | 3 + .../StoreProvider/StoreProvider.tsx | 13 +--- .../hooks/useResolveWhenNotNullResource.ts | 34 --------- ui/app/src/models/Resource.ts | 22 ------ ui/app/src/models/index.ts | 1 - ui/app/src/utils/resource.ts | 70 ------------------- 6 files changed, 6 insertions(+), 137 deletions(-) delete mode 100644 ui/app/src/hooks/useResolveWhenNotNullResource.ts delete mode 100644 ui/app/src/models/Resource.ts delete mode 100644 ui/app/src/utils/resource.ts diff --git a/ui/app/src/CHANGELOG.md b/ui/app/src/CHANGELOG.md index fe5a8aef24..2e283267dd 100644 --- a/ui/app/src/CHANGELOG.md +++ b/ui/app/src/CHANGELOG.md @@ -3,6 +3,7 @@ * [utils/xml] Upgrade prettier to v3x which changed from sync apis to async * `serialize` no longer formats code * `beautify` is now async +* [utils/resource] Removed `createFakeResource`, `createResource` and `createResourceBundle` utils. * [components] * HostUI removed, merged with Host (its container component) * EditModeSwitcherUI removed, merged with EditModeSwitcher (its container component) @@ -26,6 +27,7 @@ * `DraggablePanelListItem` prop `onMenu` send the pointer event as its first and only argument instead of the anchor element attached to the event. Can get element through `event.currentTarget`. * Removed `pages/QuickCreateMenu` component. * Removed `SuspenseWithEmptyState` and `WithEmptyState` components. + * Removed `resource` prop from StoreProvider * [services] Removed services associated with v1 APIs: * `fetchLegacyGetGoLiveItems` * `fetchLegacyUserActivities` @@ -43,6 +45,7 @@ * Removed `useSelectorResource` hook. * Removed `useQuickCreateListResource` hook. * Removed `useSystemVersionResource` hook. + * Removed `useResolveWhenNoNullResource` hook. * Removed deprecated `aws-file-upload` and `aws-video` upload controls. * Migrated the Studio UI build to Vite/SWC * Rollup's XB build to use SWC diff --git a/ui/app/src/components/StoreProvider/StoreProvider.tsx b/ui/app/src/components/StoreProvider/StoreProvider.tsx index b7a09f58f8..2b50937308 100644 --- a/ui/app/src/components/StoreProvider/StoreProvider.tsx +++ b/ui/app/src/components/StoreProvider/StoreProvider.tsx @@ -15,20 +15,13 @@ */ import React, { PropsWithChildren } from 'react'; -import { Resource } from '../../models/Resource'; import { CrafterCMSStore } from '../../state/store'; import { Provider } from 'react-redux'; -type StoreProviderPropsA = PropsWithChildren<{ resource: Resource }>; -type StoreProviderPropsB = PropsWithChildren<{ store: CrafterCMSStore }>; -export type StoreProviderProps = StoreProviderPropsA | StoreProviderPropsB; +export type StoreProviderProps = PropsWithChildren<{ store: CrafterCMSStore }>; -export function StoreProvider(props: StoreProviderPropsA): JSX.Element; -export function StoreProvider(props: StoreProviderPropsB): JSX.Element; -export function StoreProvider( - props: PropsWithChildren<{ store?: CrafterCMSStore; resource?: Resource }> -) { - const store = props.store ?? props.resource.read(); +export function StoreProvider(props: StoreProviderProps): JSX.Element { + const { store } = props; return ; } diff --git a/ui/app/src/hooks/useResolveWhenNotNullResource.ts b/ui/app/src/hooks/useResolveWhenNotNullResource.ts deleted file mode 100644 index b282e47484..0000000000 --- a/ui/app/src/hooks/useResolveWhenNotNullResource.ts +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (C) 2007-2022 Crafter Software Corporation. All Rights Reserved. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 3 as published by - * the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -import { Resource } from '../models/Resource'; -import { useEffect, useState } from 'react'; -import { nnou } from '../utils/object'; -import { createResourceBundle } from '../utils/resource'; - -export function useResolveWhenNotNullResource(source: ResultType): Resource { - const [[resource, resolve], setBundle] = useState(() => createResourceBundle()); - useEffect(() => { - if (resource.complete) { - setBundle(createResourceBundle); - } else if (nnou(source)) { - resolve(source); - } - }, [source, resource, resolve]); - return resource; -} - -export default useResolveWhenNotNullResource; diff --git a/ui/app/src/models/Resource.ts b/ui/app/src/models/Resource.ts deleted file mode 100644 index 49e494201b..0000000000 --- a/ui/app/src/models/Resource.ts +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright (C) 2007-2022 Crafter Software Corporation. All Rights Reserved. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 3 as published by - * the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -export interface Resource { - readonly complete: boolean; - readonly error: boolean; - - read(): T; -} diff --git a/ui/app/src/models/index.ts b/ui/app/src/models/index.ts index 6f7cf28623..4daa736cc9 100644 --- a/ui/app/src/models/index.ts +++ b/ui/app/src/models/index.ts @@ -55,7 +55,6 @@ export * from './PluginFileBuilder'; export * from './ProjectLifecycleEvent'; export * from './Publishing'; export * from './Repository'; -export * from './Resource'; export * from './Search'; export * from './Site'; export * from './SiteConfigurationFile'; diff --git a/ui/app/src/utils/resource.ts b/ui/app/src/utils/resource.ts deleted file mode 100644 index 38eaace020..0000000000 --- a/ui/app/src/utils/resource.ts +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (C) 2007-2022 Crafter Software Corporation. All Rights Reserved. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 3 as published by - * the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -import { Resource } from '../models/Resource'; - -export function createFakeResource(result: T): Resource { - return { - complete: true, - error: false, - read() { - return result; - } - }; -} - -export function createResource(factoryFn: () => Promise): Resource { - let result, - promise, - resource, - status = 'pending'; - promise = factoryFn().then( - (response) => { - status = 'success'; - result = response; - }, - (error) => { - status = 'error'; - result = error; - } - ); - resource = { - complete: false, - error: false, - read() { - if (status === 'pending') { - throw promise; - } else if (status === 'error') { - resource.complete = true; - resource.error = true; - throw result; - } else if (status === 'success') { - resource.complete = true; - return result; - } - } - }; - return resource; -} - -export function createResourceBundle(): [Resource, (value?: unknown) => void, (reason?: any) => void] { - let resolve, reject; - let promise = new Promise((resolvePromise, rejectPromise) => { - resolve = resolvePromise; - reject = rejectPromise; - }); - return [createResource(() => promise), resolve, reject]; -} From 879f191295bf2122a9eb1282ead62e86f13fe32a Mon Sep 17 00:00:00 2001 From: jvega190 Date: Fri, 6 Sep 2024 16:04:45 -0600 Subject: [PATCH 28/30] [6633] Fix conflicts --- .../CompareVersionsDialogContainer.tsx | 63 ++++------- .../PreviewDropTargetsPanel.tsx | 61 +++++----- .../SiteManagement/SiteManagement.tsx | 104 ++++++++---------- 3 files changed, 92 insertions(+), 136 deletions(-) diff --git a/ui/app/src/components/CompareVersionsDialog/CompareVersionsDialogContainer.tsx b/ui/app/src/components/CompareVersionsDialog/CompareVersionsDialogContainer.tsx index ffdb9dd5bc..8fd9ee740c 100644 --- a/ui/app/src/components/CompareVersionsDialog/CompareVersionsDialogContainer.tsx +++ b/ui/app/src/components/CompareVersionsDialog/CompareVersionsDialogContainer.tsx @@ -15,15 +15,14 @@ */ import { CompareVersionsDialogContainerProps } from './utils'; -import React, { useMemo } from 'react'; -import { useLogicResource } from '../../hooks/useLogicResource'; -import { CompareVersionsBranch } from '../../models/Version'; -import { CompareVersions, CompareVersionsResource } from './CompareVersions'; -import { EntityState } from '../../models/EntityState'; -import ContentType from '../../models/ContentType'; +import React from 'react'; +import { CompareVersions } from './CompareVersions'; import DialogBody from '../DialogBody/DialogBody'; -import { SuspenseWithEmptyState } from '../Suspencified/Suspencified'; import { makeStyles } from 'tss-react/mui'; +import { ApiResponseErrorState } from '../ApiResponseErrorState'; +import { LoadingState } from '../LoadingState'; +import { EmptyState } from '../EmptyState'; +import { FormattedMessage } from 'react-intl'; const useStyles = makeStyles()(() => ({ dialogBody: { @@ -42,47 +41,23 @@ const useStyles = makeStyles()(() => ({ })); export function CompareVersionsDialogContainer(props: CompareVersionsDialogContainerProps) { - const { versionsBranch, contentTypesBranch } = props; + const { versionsBranch } = props; const { compareVersionsBranch } = versionsBranch; const { classes, cx } = useStyles(); - const compareVersionsData = useMemo( - () => ({ - compareVersionsBranch, - contentTypesBranch - }), - [compareVersionsBranch, contentTypesBranch] - ); - - const compareVersionsResource = useLogicResource< - CompareVersionsResource, - { compareVersionsBranch: CompareVersionsBranch; contentTypesBranch: EntityState } - >(compareVersionsData, { - shouldResolve: ({ compareVersionsBranch, contentTypesBranch }) => - compareVersionsBranch.compareVersions && - contentTypesBranch.byId && - !compareVersionsBranch.isFetching && - !contentTypesBranch.isFetching, - shouldReject: ({ compareVersionsBranch, contentTypesBranch }) => - Boolean(compareVersionsBranch.error || contentTypesBranch.error), - shouldRenew: ({ compareVersionsBranch, contentTypesBranch }, resource) => resource.complete, - resultSelector: ({ compareVersionsBranch, contentTypesBranch }) => ({ - a: compareVersionsBranch.compareVersions?.[0], - b: compareVersionsBranch.compareVersions?.[1], - contentTypes: contentTypesBranch.byId - }), - errorSelector: ({ compareVersionsBranch, contentTypesBranch }) => - compareVersionsBranch.error || contentTypesBranch.error - }); - return ( - <> - - - - - - + + {compareVersionsBranch && + (compareVersionsBranch.error ? ( + + ) : compareVersionsBranch.isFetching ? ( + + ) : compareVersionsBranch.compareVersions?.length > 0 ? ( + + ) : ( + } /> + ))} + ); } diff --git a/ui/app/src/components/PreviewDropTargetsPanel/PreviewDropTargetsPanel.tsx b/ui/app/src/components/PreviewDropTargetsPanel/PreviewDropTargetsPanel.tsx index 210cd22d87..0c4e3e4ca6 100644 --- a/ui/app/src/components/PreviewDropTargetsPanel/PreviewDropTargetsPanel.tsx +++ b/ui/app/src/components/PreviewDropTargetsPanel/PreviewDropTargetsPanel.tsx @@ -32,11 +32,7 @@ import { scrollToDropTarget, setPreviewEditMode } from '../../state/actions/preview'; -import { Resource } from '../../models/Resource'; -import { SuspenseWithEmptyState } from '../Suspencified/Suspencified'; -import { LookupTable } from '../../models/LookupTable'; import { useSelection } from '../../hooks/useSelection'; -import { useLogicResource } from '../../hooks/useLogicResource'; import { useMount } from '../../hooks/useMount'; import { getAvatarWithIconColors } from '../../utils/contentType'; import { darken, useTheme } from '@mui/material/styles'; @@ -55,6 +51,7 @@ import HourglassEmptyRounded from '@mui/icons-material/HourglassEmptyRounded'; import Alert from '@mui/material/Alert'; import { EmptyState } from '../EmptyState'; import FormHelperText from '@mui/material/FormHelperText'; +import { LoadingState } from '../LoadingState'; const translations = defineMessages({ dropTargetsPanel: { @@ -108,6 +105,13 @@ export function PreviewDropTargetsPanel() { }); return allowedTypes; }, [allowedTypesData, contentTypes]); + const filteredDropTargets = dropTargetsBranch + ? dropTargetsBranch.byId + ? Object.values(dropTargetsBranch.byId).filter( + (dropTarget) => dropTarget.contentTypeId === dropTargetsBranch.selectedContentType + ) + : [] + : null; useMount(() => { return () => { @@ -138,22 +142,6 @@ export function PreviewDropTargetsPanel() { hostToGuest$.next(clearHighlightedDropTargets()); }; - const dropTargetsResource = useLogicResource< - ContentTypeDropTarget[], - { selectedContentType: string; byId: LookupTable } - >(dropTargetsBranch, { - shouldResolve: (source) => source.selectedContentType === null || Boolean(source.byId), - shouldReject: (source) => false, - shouldRenew: (source, resource) => resource.complete, - resultSelector: (source) => - source.byId - ? Object.values(source.byId).filter( - (dropTarget) => dropTarget.contentTypeId === dropTargetsBranch.selectedContentType - ) - : [], - errorSelector: (source) => null - }); - return awaitingGuestCheckIn ? ( } sx={{ border: 0 }}> @@ -225,18 +213,23 @@ export function PreviewDropTargetsPanel() { )} - - - + {dropTargetsBranch?.selectedContentType !== null && !Boolean(dropTargetsBranch?.byId) ? ( + + ) : filteredDropTargets ? ( + filteredDropTargets.length > 0 ? ( + + ) : ( + + ) + ) : ( + <> + )} ) @@ -281,12 +274,12 @@ function ContentTypeItem(props: ContentTypeItemContentProps) { } interface DropTargetsListProps { - resource: Resource; + dropTargets: ContentTypeDropTarget[]; onSelectedDropZone(dropTarget: ContentTypeDropTarget): void; } function DropTargetsList(props: DropTargetsListProps) { - const dropTargets = props.resource.read(); + const { dropTargets } = props; return dropTargets?.map((dropTarget: ContentTypeDropTarget) => ( props.onSelectedDropZone(dropTarget)}> diff --git a/ui/app/src/components/SiteManagement/SiteManagement.tsx b/ui/app/src/components/SiteManagement/SiteManagement.tsx index 6f27d9ac71..3a9d26477f 100644 --- a/ui/app/src/components/SiteManagement/SiteManagement.tsx +++ b/ui/app/src/components/SiteManagement/SiteManagement.tsx @@ -14,7 +14,7 @@ * along with this program. If not, see . */ -import React, { useEffect, useMemo, useState } from 'react'; +import React, { useEffect, useState } from 'react'; import { defineMessages, FormattedMessage, useIntl } from 'react-intl'; import AddIcon from '@mui/icons-material/Add'; import SkeletonSitesGrid from '../SitesGrid/SitesGridSkeleton'; @@ -35,7 +35,6 @@ import { fetchSites, popSite } from '../../state/actions/sites'; import { showErrorDialog } from '../../state/reducers/dialogs/error'; import { showEditSiteDialog } from '../../state/actions/dialogs'; import { ErrorBoundary } from '../ErrorBoundary/ErrorBoundary'; -import { SuspenseWithEmptyState } from '../Suspencified/Suspencified'; import SitesGrid from '../SitesGrid/SitesGrid'; import PublishingStatusDialog from '../PublishingStatusDialog'; import GlobalAppToolbar from '../GlobalAppToolbar'; @@ -45,7 +44,6 @@ import { hasGlobalPermissions } from '../../services/users'; import { foo } from '../../utils/object'; import { useEnv } from '../../hooks/useEnv'; import { useActiveUser } from '../../hooks/useActiveUser'; -import { useLogicResource } from '../../hooks/useLogicResource'; import { useSpreadState } from '../../hooks/useSpreadState'; import { useSitesBranch } from '../../hooks/useSitesBranch'; import Paper from '@mui/material/Paper'; @@ -61,6 +59,7 @@ import FormControlLabel from '@mui/material/FormControlLabel'; import Checkbox from '@mui/material/Checkbox'; import { ConfirmDialog } from '../ConfirmDialog'; import { previewSwitch } from '../../services/security'; +import { EmptyState } from '../EmptyState'; const translations = defineMessages({ siteDeleted: { @@ -85,6 +84,7 @@ export function SiteManagement() { getStoredGlobalMenuSiteViewPreference(user.username) ?? 'grid' ); const { byId: sitesById, isFetching, active } = useSitesBranch(); + const sitesList = sitesById ? Object.values(sitesById) : null; const [selectedSiteStatus, setSelectedSiteStatus] = useState(null); const [permissionsLookup, setPermissionsLookup] = useState>(foo); const duplicateSiteDialogState = useEnhancedDialogState(); @@ -100,17 +100,6 @@ export function SiteManagement() { return () => subscription.unsubscribe(); }, []); - const resource = useLogicResource; isFetching: boolean }>( - useMemo(() => ({ sitesById, isFetching, permissionsLookup }), [sitesById, isFetching, permissionsLookup]), - { - shouldResolve: (source) => Boolean(source.sitesById) && permissionsLookup !== foo && !isFetching, - shouldReject: () => false, - shouldRenew: (source, resource) => resource.complete, - resultSelector: () => Object.values(sitesById), - errorSelector: () => null - } - ); - const onSiteClick = (site: Site) => { setSiteCookie(site.id, useBaseDomain); previewSwitch().subscribe(() => { @@ -224,16 +213,25 @@ export function SiteManagement() { } /> - - }} - withEmptyStateProps={{ - emptyStateProps: { - title: , - styles: { root: { margin: undefined } }, - sxs: { + {isFetching ? ( + + ) : sitesList ? ( + sitesList.length > 0 ? ( + + ) : ( + } + styles={{ root: { margin: undefined } }} + sxs={{ root: { p: 5, bgcolor: 'background.default', @@ -243,40 +241,30 @@ export function SiteManagement() { marginLeft: 'auto', marginRight: 'auto' } - }, - children: ( - - {hasCreateSitePermission ? ( - {cardHeaderBlock} - ) : ( - cardHeaderBlock - )} - - ) - } - }} - > - - + }} + > + + {hasCreateSitePermission ? ( + {cardHeaderBlock} + ) : ( + cardHeaderBlock + )} + + + ) + ) : ( + <> + )}
Date: Thu, 14 Nov 2024 11:38:36 -0600 Subject: [PATCH 29/30] [6694] Revert utils/resource.ts and Resource.ts model removal --- ui/app/src/models/Resource.ts | 22 +++++++++++ ui/app/src/models/index.ts | 1 + ui/app/src/utils/resource.ts | 70 +++++++++++++++++++++++++++++++++++ 3 files changed, 93 insertions(+) create mode 100644 ui/app/src/models/Resource.ts create mode 100644 ui/app/src/utils/resource.ts diff --git a/ui/app/src/models/Resource.ts b/ui/app/src/models/Resource.ts new file mode 100644 index 0000000000..9d8c8cd796 --- /dev/null +++ b/ui/app/src/models/Resource.ts @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2007-2024 Crafter Software Corporation. All Rights Reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 3 as published by + * the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +export interface Resource { + readonly complete: boolean; + readonly error: boolean; + + read(): T; +} diff --git a/ui/app/src/models/index.ts b/ui/app/src/models/index.ts index 1733091c67..cfd60e5809 100644 --- a/ui/app/src/models/index.ts +++ b/ui/app/src/models/index.ts @@ -55,6 +55,7 @@ export * from './PluginFileBuilder'; export * from './ProjectLifecycleEvent'; export * from './Publishing'; export * from './Repository'; +export * from './Resource'; export * from './Search'; export * from './SimpleAjaxError'; export * from './Site'; diff --git a/ui/app/src/utils/resource.ts b/ui/app/src/utils/resource.ts new file mode 100644 index 0000000000..fd0657ede0 --- /dev/null +++ b/ui/app/src/utils/resource.ts @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2007-2024 Crafter Software Corporation. All Rights Reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 3 as published by + * the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +import { Resource } from '../models/Resource'; + +export function createFakeResource(result: T): Resource { + return { + complete: true, + error: false, + read() { + return result; + } + }; +} + +export function createResource(factoryFn: () => Promise): Resource { + let result, + promise, + resource, + status = 'pending'; + promise = factoryFn().then( + (response) => { + status = 'success'; + result = response; + }, + (error) => { + status = 'error'; + result = error; + } + ); + resource = { + complete: false, + error: false, + read() { + if (status === 'pending') { + throw promise; + } else if (status === 'error') { + resource.complete = true; + resource.error = true; + throw result; + } else if (status === 'success') { + resource.complete = true; + return result; + } + } + }; + return resource; +} + +export function createResourceBundle(): [Resource, (value?: unknown) => void, (reason?: any) => void] { + let resolve, reject; + let promise = new Promise((resolvePromise, rejectPromise) => { + resolve = resolvePromise; + reject = rejectPromise; + }); + return [createResource(() => promise), resolve, reject]; +} From ba1f72f8eb892aa06472050fa9fc3373bb59ad4c Mon Sep 17 00:00:00 2001 From: jvega190 Date: Thu, 14 Nov 2024 11:38:55 -0600 Subject: [PATCH 30/30] [6694] Add memo to filteredDropTargets --- .../PreviewDropTargetsPanel.tsx | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/ui/app/src/components/PreviewDropTargetsPanel/PreviewDropTargetsPanel.tsx b/ui/app/src/components/PreviewDropTargetsPanel/PreviewDropTargetsPanel.tsx index 0c4e3e4ca6..9ab123934a 100644 --- a/ui/app/src/components/PreviewDropTargetsPanel/PreviewDropTargetsPanel.tsx +++ b/ui/app/src/components/PreviewDropTargetsPanel/PreviewDropTargetsPanel.tsx @@ -105,13 +105,15 @@ export function PreviewDropTargetsPanel() { }); return allowedTypes; }, [allowedTypesData, contentTypes]); - const filteredDropTargets = dropTargetsBranch - ? dropTargetsBranch.byId - ? Object.values(dropTargetsBranch.byId).filter( - (dropTarget) => dropTarget.contentTypeId === dropTargetsBranch.selectedContentType - ) - : [] - : null; + const filteredDropTargets = useMemo(() => { + return dropTargetsBranch + ? dropTargetsBranch.byId + ? Object.values(dropTargetsBranch.byId).filter( + (dropTarget) => dropTarget.contentTypeId === dropTargetsBranch.selectedContentType + ) + : [] + : null; + }, [dropTargetsBranch]); useMount(() => { return () => {