From b6bdc4ae80ff6ab70045541282420e8ecb0a01ed Mon Sep 17 00:00:00 2001 From: MartinSchoeler Date: Mon, 9 Sep 2024 14:35:24 -0300 Subject: [PATCH] feat: New outdated marketplace empty state --- apps/meteor/client/contexts/AppsContext.tsx | 9 +++-- .../providers/AppsProvider/AppsProvider.tsx | 10 +++--- .../marketplace/AppsPage/AppsPageContent.tsx | 9 ++++- .../UnsupportedEmptyState.stories.tsx | 16 +++++++++ .../AppsPage/UnsupportedEmptyState.tsx | 34 +++++++++++++++++++ .../components/MarketplaceHeader.tsx | 16 +++++++-- .../components/UpdateRocketChatBtn.tsx | 21 ++++++++++++ 7 files changed, 102 insertions(+), 13 deletions(-) create mode 100644 apps/meteor/client/views/marketplace/AppsPage/UnsupportedEmptyState.stories.tsx create mode 100644 apps/meteor/client/views/marketplace/AppsPage/UnsupportedEmptyState.tsx create mode 100644 apps/meteor/client/views/marketplace/components/UpdateRocketChatBtn.tsx diff --git a/apps/meteor/client/contexts/AppsContext.tsx b/apps/meteor/client/contexts/AppsContext.tsx index 2be8e74c2d67..a67759c99223 100644 --- a/apps/meteor/client/contexts/AppsContext.tsx +++ b/apps/meteor/client/contexts/AppsContext.tsx @@ -27,9 +27,9 @@ export interface IAppsOrchestrator { } export type AppsContextValue = { - installedApps: Omit, 'error'>; - marketplaceApps: Omit, 'error'>; - privateApps: Omit, 'error'>; + installedApps: AsyncState<{ apps: App[] }>; + marketplaceApps: AsyncState<{ apps: App[] }>; + privateApps: AsyncState<{ apps: App[] }>; reload: () => Promise; orchestrator?: IAppsOrchestrator; }; @@ -38,14 +38,17 @@ export const AppsContext = createContext({ installedApps: { phase: AsyncStatePhase.LOADING, value: undefined, + error: undefined, }, marketplaceApps: { phase: AsyncStatePhase.LOADING, value: undefined, + error: undefined, }, privateApps: { phase: AsyncStatePhase.LOADING, value: undefined, + error: undefined, }, reload: () => Promise.resolve(), orchestrator: undefined, diff --git a/apps/meteor/client/providers/AppsProvider/AppsProvider.tsx b/apps/meteor/client/providers/AppsProvider/AppsProvider.tsx index cf1d4d671d94..d0c1bb08f78d 100644 --- a/apps/meteor/client/providers/AppsProvider/AppsProvider.tsx +++ b/apps/meteor/client/providers/AppsProvider/AppsProvider.tsx @@ -17,14 +17,12 @@ import { storeQueryFunction } from './storeQueryFunction'; const getAppState = ( loading: boolean, apps: App[] | undefined, -): Omit< - AsyncState<{ - apps: App[]; - }>, - 'error' -> => ({ +): AsyncState<{ + apps: App[]; +}> => ({ phase: loading ? AsyncStatePhase.LOADING : AsyncStatePhase.RESOLVED, value: { apps: apps || [] }, + error: undefined, }); type AppsProviderProps = { diff --git a/apps/meteor/client/views/marketplace/AppsPage/AppsPageContent.tsx b/apps/meteor/client/views/marketplace/AppsPage/AppsPageContent.tsx index e72a30e6a5c9..2780e4802c13 100644 --- a/apps/meteor/client/views/marketplace/AppsPage/AppsPageContent.tsx +++ b/apps/meteor/client/views/marketplace/AppsPage/AppsPageContent.tsx @@ -20,6 +20,7 @@ import NoInstalledAppMatchesEmptyState from './NoInstalledAppMatchesEmptyState'; import NoInstalledAppsEmptyState from './NoInstalledAppsEmptyState'; import NoMarketplaceOrInstalledAppMatchesEmptyState from './NoMarketplaceOrInstalledAppMatchesEmptyState'; import PrivateEmptyState from './PrivateEmptyState'; +import UnsupportedEmptyState from './UnsupportedEmptyState'; const AppsPageContent = (): ReactElement => { const t = useTranslation(); @@ -134,6 +135,9 @@ const AppsPageContent = (): ReactElement => { const noInstalledApps = appsResult.phase === AsyncStatePhase.RESOLVED && !isMarketplace && appsResult.value?.totalAppsLength === 0; + // TODO, add api error return when https://rocketchat.atlassian.net/browse/CONN-334 is done + const unsupportedVersion = appsResult.phase === AsyncStatePhase.REJECTED && appsResult.error === 'unsupported version'; + const noMarketplaceOrInstalledAppMatches = appsResult.phase === AsyncStatePhase.RESOLVED && (isMarketplace || isPremium) && appsResult.value?.count === 0; @@ -210,6 +214,9 @@ const AppsPageContent = (): ReactElement => { if (noInstalledApps) { return context === 'private' ? : ; } + if (unsupportedVersion) { + return ; + } }; return ( @@ -229,7 +236,7 @@ const AppsPageContent = (): ReactElement => { context={context || 'explore'} /> {appsResult.phase === AsyncStatePhase.LOADING && } - {appsResult.phase === AsyncStatePhase.RESOLVED && noErrorsOcurred && ( + {appsResult.phase === AsyncStatePhase.RESOLVED && noErrorsOcurred && !unsupportedVersion && ( ; + +export const Default: ComponentStory = () => ; +Default.storyName = 'UnsupportedEmptyState'; diff --git a/apps/meteor/client/views/marketplace/AppsPage/UnsupportedEmptyState.tsx b/apps/meteor/client/views/marketplace/AppsPage/UnsupportedEmptyState.tsx new file mode 100644 index 000000000000..05a6aba8fe05 --- /dev/null +++ b/apps/meteor/client/views/marketplace/AppsPage/UnsupportedEmptyState.tsx @@ -0,0 +1,34 @@ +import { Box, States, StatesIcon, StatesTitle, StatesSubtitle, StatesActions, Button } from '@rocket.chat/fuselage'; +import { usePermission } from '@rocket.chat/ui-contexts'; +import type { ReactElement } from 'react'; +import React from 'react'; +import { useTranslation } from 'react-i18next'; + +import UpdateRocketChatBtn from '../components/UpdateRocketChatBtn'; + +const UnsupportedEmptyState = (): ReactElement => { + const isAdmin = usePermission('manage-apps'); + const { t } = useTranslation(); + + const title = isAdmin ? t('Update_to_access_marketplace') : t('Marketplace_unavailable'); + const description = isAdmin ? t('Update_to_access_marketplace_description') : t('Marketplace_unavailable_description'); + + // Check why is always primary + return ( + + + + {title} + {description} + + + + + + + ); +}; + +export default UnsupportedEmptyState; diff --git a/apps/meteor/client/views/marketplace/components/MarketplaceHeader.tsx b/apps/meteor/client/views/marketplace/components/MarketplaceHeader.tsx index dfc3033e9812..4b95b41c4b38 100644 --- a/apps/meteor/client/views/marketplace/components/MarketplaceHeader.tsx +++ b/apps/meteor/client/views/marketplace/components/MarketplaceHeader.tsx @@ -8,6 +8,7 @@ import { PageHeader } from '../../../components/Page'; import UnlimitedAppsUpsellModal from '../UnlimitedAppsUpsellModal'; import { useAppsCountQuery } from '../hooks/useAppsCountQuery'; import EnabledAppsCount from './EnabledAppsCount'; +import UpdateRocketChatBtn from './UpdateRocketChatBtn'; const MarketplaceHeader = ({ title }: { title: string }): ReactElement | null => { const t = useTranslation(); @@ -17,6 +18,9 @@ const MarketplaceHeader = ({ title }: { title: string }): ReactElement | null => const setModal = useSetModal(); const result = useAppsCountQuery(context); + // TODO, add api error return when https://rocketchat.atlassian.net/browse/CONN-334 is done + const unsupportedVersion = result.error === 'unsupported version'; + const handleUploadButtonClick = useCallback((): void => { route.push({ context, page: 'install' }); }, [context, route]); @@ -29,8 +33,10 @@ const MarketplaceHeader = ({ title }: { title: string }): ReactElement | null => {result.isLoading && } - {result.isSuccess && !result.data.hasUnlimitedApps && } - {isAdmin && result.isSuccess && !result.data.hasUnlimitedApps && ( + {!unsupportedVersion && result.isSuccess && !result.data.hasUnlimitedApps && ( + + )} + {!unsupportedVersion && isAdmin && result.isSuccess && !result.data.hasUnlimitedApps && ( )} - {isAdmin && context === 'private' && } + {!unsupportedVersion && isAdmin && context === 'private' && ( + + )} + + {unsupportedVersion && } ); diff --git a/apps/meteor/client/views/marketplace/components/UpdateRocketChatBtn.tsx b/apps/meteor/client/views/marketplace/components/UpdateRocketChatBtn.tsx new file mode 100644 index 000000000000..6afc488fbf4b --- /dev/null +++ b/apps/meteor/client/views/marketplace/components/UpdateRocketChatBtn.tsx @@ -0,0 +1,21 @@ +import { Button } from '@rocket.chat/fuselage'; +import { usePermission } from '@rocket.chat/ui-contexts'; +import React from 'react'; +import { useTranslation } from 'react-i18next'; + +const UpdateRocketChatBtn = () => { + const isAdmin = usePermission('manage-apps'); + const { t } = useTranslation(); + + return ( + <> + {isAdmin && ( + + )} + + ); +}; + +export default UpdateRocketChatBtn;