Skip to content

Commit

Permalink
review
Browse files Browse the repository at this point in the history
  • Loading branch information
ggazzo committed Sep 7, 2022
1 parent 4c074b0 commit 1b1fd62
Show file tree
Hide file tree
Showing 12 changed files with 90 additions and 113 deletions.
15 changes: 13 additions & 2 deletions apps/meteor/client/components/Page/Page.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,24 @@
import { Box } from '@rocket.chat/fuselage';
import Colors from '@rocket.chat/fuselage-tokens/colors';
import React, { useState, ReactElement, ComponentProps } from 'react';

import PageContext from './PageContext';

const Page = (props: ComponentProps<typeof Box>): ReactElement => {
type PageProps = Omit<ComponentProps<typeof Box>, 'backgroundColor'> & {
surface?: 'light' | 'tint' | 'neutral';
};

const surfaceMap = {
light: Colors.white,
tint: Colors.n100,
neutral: Colors.n400,
}; // TODO: Remove this export after the migration is complete

const Page = ({ surface = 'light', ...props }: PageProps): ReactElement => {
const [border, setBorder] = useState(false);
return (
<PageContext.Provider value={[border, setBorder]}>
<Box
backgroundColor='surface'
is='section'
display='flex'
flexDirection='column'
Expand All @@ -17,6 +27,7 @@ const Page = (props: ComponentProps<typeof Box>): ReactElement => {
height='full'
overflow='hidden'
{...props}
backgroundColor={`var(--rcx-color-surface-${surface}, ${surfaceMap[surface]})`}
/>
</PageContext.Provider>
);
Expand Down
24 changes: 0 additions & 24 deletions apps/meteor/client/views/admin/apps/AllAppsSection.tsx

This file was deleted.

10 changes: 5 additions & 5 deletions apps/meteor/client/views/admin/apps/AppDetails.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Box, Callout, Chip, Margins } from '@rocket.chat/fuselage';
import { Box, ButtonGroup, Callout, Chip, Margins } from '@rocket.chat/fuselage';
import { ExternalLink } from '@rocket.chat/ui-client';
import { TranslationKey, useTranslation } from '@rocket.chat/ui-contexts';
import React, { FC } from 'react';
Expand Down Expand Up @@ -59,13 +59,13 @@ const AppDetails: FC<AppDetailsProps> = ({ app }) => {
<Box fontScale='h4' mbe='x8'>
{t('Categories')}
</Box>
<Box display='flex' flexDirection='row'>
<ButtonGroup medium flexWrap='wrap'>
{categories?.map((current) => (
<Chip key={current} textTransform='uppercase' mie='x8'>
<Box color='hint'>{current}</Box>
<Chip key={current} textTransform='uppercase'>
{current}
</Chip>
))}
</Box>
</ButtonGroup>
</Box>

<Box is='section'>
Expand Down
2 changes: 1 addition & 1 deletion apps/meteor/client/views/admin/apps/AppDetailsPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ const AppDetailsPage: FC<{ id: string }> = function AppDetailsPage({ id }) {
<>
<AppDetailsHeader app={appData} />

<Tabs mis='-x24' mb='x36'>
<Tabs>
<Tabs.Item onClick={(): void => handleTabClick('details')} selected={!tab || tab === 'details'}>
{t('Details')}
</Tabs.Item>
Expand Down
26 changes: 6 additions & 20 deletions apps/meteor/client/views/admin/apps/AppsPage.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { Button, ButtonGroup, Icon, Skeleton, Tabs } from '@rocket.chat/fuselage';
import colors from '@rocket.chat/fuselage-tokens/colors';
import { useRoute, useSetting, useMethod, useTranslation } from '@rocket.chat/ui-contexts';
import React, { useEffect, useState, ReactElement } from 'react';

Expand Down Expand Up @@ -37,8 +36,8 @@ const AppsPage = ({ isMarketplace }: AppsPageProps): ReactElement => {
};

return (
<Page backgroundColor={colors.n100}>
<Page.Header title={t('Apps')} bg={colors.n100}>
<Page surface='tint'>
<Page.Header title={t('Apps')}>
<ButtonGroup>
{isMarketplace && !isLoggedInCloud && (
<Button disabled={isLoggedInCloud === undefined} onClick={handleLoginButtonClick}>
Expand All @@ -58,28 +57,15 @@ const AppsPage = ({ isMarketplace }: AppsPageProps): ReactElement => {
)}
</ButtonGroup>
</Page.Header>
<Tabs bg={colors.n100} borderBlockEnd='4px solid #CBCED1' marginInline='x24'>
<Tabs.Item
onClick={(): void => marketplaceRoute.push({ context: '' })}
selected={isMarketplace}
mbe='neg-x4'
mis='neg-x12'
borderWidth='0'
borderBlockWidth='x4'
>
<Tabs>
<Tabs.Item onClick={(): void => marketplaceRoute.push({ context: '' })} selected={isMarketplace}>
{t('Marketplace')}
</Tabs.Item>
<Tabs.Item
onClick={(): void => marketplaceRoute.push({ context: 'installed' })}
selected={!isMarketplace}
mbe='neg-x4'
borderWidth='0'
borderBlockWidth='x4'
>
<Tabs.Item onClick={(): void => marketplaceRoute.push({ context: 'installed' })} selected={!isMarketplace}>
{t('Installed')}
</Tabs.Item>
</Tabs>
<Page.Content bg={colors.n100} overflowY='auto'>
<Page.Content overflowY='auto'>
<AppsPageContent isMarketplace={isMarketplace} />
</Page.Content>
</Page>
Expand Down
64 changes: 23 additions & 41 deletions apps/meteor/client/views/admin/apps/AppsPageContent.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import { Pagination, Divider, Skeleton, Box } from '@rocket.chat/fuselage';
import { Pagination, Divider } from '@rocket.chat/fuselage';
import { useDebouncedState } from '@rocket.chat/fuselage-hooks';
import { useRoute, useTranslation } from '@rocket.chat/ui-contexts';
import React, { ReactElement, useMemo, useState } from 'react';

import { usePagination } from '../../../components/GenericTable/hooks/usePagination';
import { AsyncStatePhase } from '../../../lib/asyncState';
import AllAppsSection from './AllAppsSection';
import { useAppsReload, useAppsResult } from './AppsContext';
import AppsFilters from './AppsFilters';
import AppsList from './AppsList';
import AppsPageContentSkeleton from './AppsPageContentSkeleton';
import ConnectionErrorEmptyState from './ConnectionErrorEmptyState';
import FeaturedAppsSections from './FeaturedAppsSections';
import NoInstalledAppMatchesEmptyState from './NoInstalledAppMatchesEmptyState';
Expand Down Expand Up @@ -84,8 +85,6 @@ const AppsPageContent = ({ isMarketplace }: { isMarketplace: boolean }): ReactEl
sortFilterStructure.items.find((item) => item.checked)?.id !== 'mru' ||
selectedCategories.length > 0;

const loadingRows = Array.from({ length: 3 }, (_, i) => <Skeleton key={i} height='x56' mbe='x8' width='100%' variant='rect' />);

return (
<>
<AppsFilters
Expand All @@ -101,54 +100,37 @@ const AppsPageContent = ({ isMarketplace }: { isMarketplace: boolean }): ReactEl
statusFilterStructure={statusFilterStructure}
statusFilterOnSelected={statusFilterOnSelected}
/>

{appsResult.phase === AsyncStatePhase.LOADING && (
<>
<Box mbe='x36'>
<Skeleton height='x28' width='x150' mbe='x20' variant='rect' />
{loadingRows}
</Box>
<Box mbe='x36'>
<Skeleton height='x28' width='x150' mbe='x20' variant='rect' />
{loadingRows}
</Box>
<Skeleton height='x28' width='x150' mbe='x20' variant='rect' />
{loadingRows}
</>
)}

<FeaturedAppsSections appsResult={appsResult} isMarketplace={isMarketplace} isFiltered={isFiltered} />

<AllAppsSection appsResult={appsResult} isMarketplace={isMarketplace} />

{appsResult.phase === AsyncStatePhase.RESOLVED && Boolean(appsResult.value.count) && (
<>
<Divider />
<Pagination
current={current}
itemsPerPage={itemsPerPage}
count={appsResult.value.total}
onSetItemsPerPage={onSetItemsPerPage}
onSetCurrent={onSetCurrent}
{...paginationProps}
/>
</>
)}

{appsResult.phase === AsyncStatePhase.LOADING && <AppsPageContentSkeleton />}

{appsResult.phase === AsyncStatePhase.RESOLVED &&
!noMarketplaceOrInstalledAppMatches &&
!noInstalledAppMatches &&
!noMarketplaceOrInstalledAppMatches && (
<>
{isMarketplace && !isFiltered && <FeaturedAppsSections appsResult={appsResult.value.items} />}
<AppsList apps={appsResult.value.items} title={t('All_Apps')} isMarketplace={isMarketplace} />
<Divider />
<Pagination
current={current}
itemsPerPage={itemsPerPage}
count={appsResult.value.total}
onSetItemsPerPage={onSetItemsPerPage}
onSetCurrent={onSetCurrent}
{...paginationProps}
/>
</>
)}
{noMarketplaceOrInstalledAppMatches && (
<NoMarketplaceOrInstalledAppMatchesEmptyState shouldShowSearchText={appsResult.value.shouldShowSearchText} text={text} />
)}

{noInstalledAppMatches && (
<NoInstalledAppMatchesEmptyState
shouldShowSearchText={appsResult.value.shouldShowSearchText}
text={text}
onButtonClick={(): void => marketplaceRoute.push({ context: '' })}
/>
)}

{noInstalledAppsFound && <NoInstalledAppsFoundEmptyState onButtonClick={(): void => marketplaceRoute.push({ context: '' })} />}

{appsResult.phase === AsyncStatePhase.REJECTED && <ConnectionErrorEmptyState onButtonClick={reload} />}
</>
);
Expand Down
22 changes: 22 additions & 0 deletions apps/meteor/client/views/admin/apps/AppsPageContentSkeleton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { Skeleton, Box } from '@rocket.chat/fuselage';
import React, { ReactElement } from 'react';

const AppsPageContentSkeleton = (): ReactElement => {
const loadingRows = Array.from({ length: 3 }, (_, i) => <Skeleton key={i} height='x56' mbe='x8' width='100%' variant='rect' />);
return (
<>
<Box mbe='x36'>
<Skeleton height='x28' width='x150' mbe='x20' variant='rect' />
{loadingRows}
</Box>
<Box mbe='x36'>
<Skeleton height='x28' width='x150' mbe='x20' variant='rect' />
{loadingRows}
</Box>
<Skeleton height='x28' width='x150' mbe='x20' variant='rect' />
{loadingRows}
</>
);
};

export default AppsPageContentSkeleton;
2 changes: 1 addition & 1 deletion apps/meteor/client/views/admin/apps/BundleChips.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ const BundleChips = ({ bundledIn, isIconOnly }: BundleChipsProps): ReactElement
>
<Icon name='bag' size='x20' />
{!isIconOnly && (
<Box fontWeight='c2' fontSize='c2' color='info' style={{ whiteSpace: 'nowrap' }}>
<Box fontScale='c2' color='info' style={{ whiteSpace: 'nowrap' }}>
{t('bundle_chip_title', {
bundleName: bundle.bundleName,
})}
Expand Down
26 changes: 8 additions & 18 deletions apps/meteor/client/views/admin/apps/FeaturedAppsSections.tsx
Original file line number Diff line number Diff line change
@@ -1,39 +1,29 @@
import { App } from '@rocket.chat/core-typings';
import { PaginatedResult } from '@rocket.chat/rest-typings';
import { useTranslation } from '@rocket.chat/ui-contexts';
import React, { ReactElement } from 'react';

import { useEndpointData } from '../../../hooks/useEndpointData';
import { AsyncState, AsyncStatePhase } from '../../../lib/asyncState';
import AppsList from './AppsList';
import normalizeFeaturedApps from './helpers/normalizeFeaturedApps';
import { useFeaturedApps } from './hooks/useFeaturedApps';

type FeaturedSectionsProps = {
appsResult: AsyncState<{ items: App[] } & { shouldShowSearchText: boolean } & PaginatedResult>;
isMarketplace: boolean;
isFiltered: boolean;
appsResult: App[];
};

const FeaturedAppsSections = ({ appsResult, isMarketplace, isFiltered }: FeaturedSectionsProps): ReactElement | null => {
const FeaturedAppsSections = ({ appsResult }: FeaturedSectionsProps): ReactElement | null => {
const t = useTranslation();
const featuredApps = useEndpointData('/apps/featured-apps');

const shouldShowFeaturedSections =
featuredApps.phase === AsyncStatePhase.RESOLVED &&
appsResult.phase === AsyncStatePhase.RESOLVED &&
Boolean(appsResult.value.count) &&
Boolean(featuredApps.value.sections) &&
!isFiltered;
const featuredApps = useFeaturedApps();

if (shouldShowFeaturedSections && isMarketplace) {
if (featuredApps.isSuccess) {
return (
<>
{featuredApps.value.sections.map((section) => (
{featuredApps.data.sections.map((section) => (
<AppsList
key={section.slug}
apps={normalizeFeaturedApps(section.apps, appsResult.value.items)}
apps={normalizeFeaturedApps(section.apps, appsResult)}
title={t.has(section.i18nLabel) ? t(section.i18nLabel) : section.i18nLabel}
isMarketplace={isMarketplace}
isMarketplace={true}
/>
))}
</>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { App } from '@rocket.chat/core-typings';
import { AppOverview } from '@rocket.chat/core-typings/dist/AppOverview';
import type { AppOverview } from '@rocket.chat/core-typings';

const normalizeFeaturedApps = (appOverviewList: AppOverview[], appsResultItems: App[]): App[] => {
const featuredAppsIdList = appOverviewList.map<string>((featuredApp) => featuredApp.latest.id);
Expand Down
9 changes: 9 additions & 0 deletions apps/meteor/client/views/admin/apps/hooks/useFeaturedApps.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { OperationResult } from '@rocket.chat/rest-typings';
import { useEndpoint } from '@rocket.chat/ui-contexts';
import { useQuery, UseQueryResult } from '@tanstack/react-query';

export const useFeaturedApps = (): UseQueryResult<OperationResult<'GET', '/apps/featured-apps'>> => {
const featuredApps = useEndpoint('GET', '/apps/featured-apps');

return useQuery(['featured-apps'], () => featuredApps());
};
1 change: 1 addition & 0 deletions packages/core-typings/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export * from './Apps';
export * from './AppOverview';
export * from './FeaturedApps';
export * from './IRoom';
export * from './UIKit';
Expand Down

0 comments on commit 1b1fd62

Please sign in to comment.