Skip to content

Commit

Permalink
feat: New outdated marketplace empty state
Browse files Browse the repository at this point in the history
  • Loading branch information
MartinSchoeler committed Sep 9, 2024
1 parent e0050c3 commit b6bdc4a
Show file tree
Hide file tree
Showing 7 changed files with 102 additions and 13 deletions.
9 changes: 6 additions & 3 deletions apps/meteor/client/contexts/AppsContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,9 @@ export interface IAppsOrchestrator {
}

export type AppsContextValue = {
installedApps: Omit<AsyncState<{ apps: App[] }>, 'error'>;
marketplaceApps: Omit<AsyncState<{ apps: App[] }>, 'error'>;
privateApps: Omit<AsyncState<{ apps: App[] }>, 'error'>;
installedApps: AsyncState<{ apps: App[] }>;
marketplaceApps: AsyncState<{ apps: App[] }>;
privateApps: AsyncState<{ apps: App[] }>;
reload: () => Promise<void>;
orchestrator?: IAppsOrchestrator;
};
Expand All @@ -38,14 +38,17 @@ export const AppsContext = createContext<AppsContextValue>({
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,
Expand Down
10 changes: 4 additions & 6 deletions apps/meteor/client/providers/AppsProvider/AppsProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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 = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -210,6 +214,9 @@ const AppsPageContent = (): ReactElement => {
if (noInstalledApps) {
return context === 'private' ? <PrivateEmptyState /> : <NoInstalledAppsEmptyState onButtonClick={handleReturn} />;
}
if (unsupportedVersion) {
return <UnsupportedEmptyState />;
}
};

return (
Expand All @@ -229,7 +236,7 @@ const AppsPageContent = (): ReactElement => {
context={context || 'explore'}
/>
{appsResult.phase === AsyncStatePhase.LOADING && <AppsPageContentSkeleton />}
{appsResult.phase === AsyncStatePhase.RESOLVED && noErrorsOcurred && (
{appsResult.phase === AsyncStatePhase.RESOLVED && noErrorsOcurred && !unsupportedVersion && (
<AppsPageContentBody
isMarketplace={isMarketplace}
isFiltered={isFiltered}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import type { ComponentMeta, ComponentStory } from '@storybook/react';
import React from 'react';

import UnsupportedEmptyState from './UnsupportedEmptyState';

export default {
title: 'Marketplace/Components/UnsupportedEmptyState',
component: UnsupportedEmptyState,
parameters: {
layout: 'fullscreen',
controls: { hideNoControlsWarning: true },
},
} as ComponentMeta<typeof UnsupportedEmptyState>;

export const Default: ComponentStory<typeof UnsupportedEmptyState> = () => <UnsupportedEmptyState />;
Default.storyName = 'UnsupportedEmptyState';
Original file line number Diff line number Diff line change
@@ -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 <StatesAction> is always primary
return (
<Box mbs={64}>
<States>
<StatesIcon name='warning' />
<StatesTitle>{title}</StatesTitle>
<StatesSubtitle>{description}</StatesSubtitle>
<StatesActions>
<Button secondary is='a' href='https://docs.rocket.chat/docs/support-prerequisites' external>
{t('Learn_more')}
</Button>
<UpdateRocketChatBtn />
</StatesActions>
</States>
</Box>
);
};

export default UnsupportedEmptyState;
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand All @@ -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]);
Expand All @@ -29,8 +33,10 @@ const MarketplaceHeader = ({ title }: { title: string }): ReactElement | null =>
<PageHeader title={title}>
<ButtonGroup wrap align='end'>
{result.isLoading && <GenericResourceUsageSkeleton />}
{result.isSuccess && !result.data.hasUnlimitedApps && <EnabledAppsCount {...result.data} context={context} />}
{isAdmin && result.isSuccess && !result.data.hasUnlimitedApps && (
{!unsupportedVersion && result.isSuccess && !result.data.hasUnlimitedApps && (
<EnabledAppsCount {...result.data} context={context} />
)}
{!unsupportedVersion && isAdmin && result.isSuccess && !result.data.hasUnlimitedApps && (
<Button
onClick={() => {
setModal(<UnlimitedAppsUpsellModal onClose={() => setModal(null)} />);
Expand All @@ -39,7 +45,11 @@ const MarketplaceHeader = ({ title }: { title: string }): ReactElement | null =>
{t('Enable_unlimited_apps')}
</Button>
)}
{isAdmin && context === 'private' && <Button onClick={handleUploadButtonClick}>{t('Upload_private_app')}</Button>}
{!unsupportedVersion && isAdmin && context === 'private' && (
<Button onClick={handleUploadButtonClick}>{t('Upload_private_app')}</Button>
)}

{unsupportedVersion && <UpdateRocketChatBtn />}
</ButtonGroup>
</PageHeader>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -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 && (
<Button primary is='a' href='https://docs.rocket.chat/v1/docs/en/updating-rocketchat' external>
{t('Update_RocketChat')}
</Button>
)}
</>
);
};

export default UpdateRocketChatBtn;

0 comments on commit b6bdc4a

Please sign in to comment.