Skip to content
Snippets Groups Projects
Unverified Commit df64d55f authored by Tiago Evangelista Pinto's avatar Tiago Evangelista Pinto Committed by GitHub
Browse files

fix(marketplace): `AppsInfo` small UX problems (#30012)

parent 6e428433
No related branches found
No related tags found
No related merge requests found
...@@ -8,6 +8,7 @@ import React from 'react'; ...@@ -8,6 +8,7 @@ import React from 'react';
import ScreenshotCarouselAnchor from '../../../components/ScreenshotCarouselAnchor'; import ScreenshotCarouselAnchor from '../../../components/ScreenshotCarouselAnchor';
import type { AppInfo } from '../../../definitions/AppInfo'; import type { AppInfo } from '../../../definitions/AppInfo';
import AppDetailsAPIs from './AppDetailsAPIs'; import AppDetailsAPIs from './AppDetailsAPIs';
import { normalizeUrl } from './normalizeUrl';
const AppDetails = ({ app }: { app: AppInfo }): ReactElement => { const AppDetails = ({ app }: { app: AppInfo }): ReactElement => {
const t = useTranslation(); const t = useTranslation();
...@@ -18,12 +19,15 @@ const AppDetails = ({ app }: { app: AppInfo }): ReactElement => { ...@@ -18,12 +19,15 @@ const AppDetails = ({ app }: { app: AppInfo }): ReactElement => {
categories = [], categories = [],
screenshots, screenshots,
apis, apis,
documentationUrl, documentationUrl: documentation,
} = app; } = app;
const isMarkdown = detailedDescription && Object.keys(detailedDescription).length !== 0 && detailedDescription.rendered; const isMarkdown = detailedDescription && Object.keys(detailedDescription).length !== 0 && detailedDescription.rendered;
const isCarouselVisible = screenshots && Boolean(screenshots.length); const isCarouselVisible = screenshots && Boolean(screenshots.length);
const normalizeDocumentationUrl = documentationUrl?.startsWith('http') ? documentationUrl : `https://${documentationUrl}`;
const normalizedHomepageUrl = normalizeUrl(homepage);
const normalizedSupportUrl = normalizeUrl(support);
const normalizedDocumentationUrl = normalizeUrl(documentation);
return ( return (
<Box maxWidth='x640' w='full' marginInline='auto' color='default'> <Box maxWidth='x640' w='full' marginInline='auto' color='default'>
...@@ -76,24 +80,21 @@ const AppDetails = ({ app }: { app: AppInfo }): ReactElement => { ...@@ -76,24 +80,21 @@ const AppDetails = ({ app }: { app: AppInfo }): ReactElement => {
<Box fontScale='h4' color='hint'> <Box fontScale='h4' color='hint'>
{t('Author_Site')} {t('Author_Site')}
</Box> </Box>
<ExternalLink to={homepage} /> {normalizedHomepageUrl ? <ExternalLink to={normalizedHomepageUrl}>{homepage}</ExternalLink> : homepage}
</Box> </Box>
<Box display='flex' flexDirection='column' flexGrow={1}> <Box display='flex' flexDirection='column' flexGrow={1}>
<Box fontScale='h4' color='hint'> <Box fontScale='h4' color='hint'>
{t('Support')} {t('Support')}
</Box> </Box>
<ExternalLink to={support} /> {normalizedSupportUrl ? <ExternalLink to={normalizedSupportUrl}>{support}</ExternalLink> : support}
</Box> </Box>
</Box> </Box>
<>
{documentationUrl && ( <Box fontScale='h4' color='hint'>
<> {t('Documentation')}
<Box fontScale='h4' color='hint'> </Box>
{t('Documentation')} {normalizedDocumentationUrl ? <ExternalLink to={normalizedDocumentationUrl}>{documentation}</ExternalLink> : documentation}
</Box> </>
<ExternalLink to={normalizeDocumentationUrl} />
</>
)}
</Box> </Box>
{apis?.length ? ( {apis?.length ? (
......
import { it } from '@jest/globals';
import { normalizeUrl } from './normalizeUrl';
it.each([
['https://rocket.chat', 'https://rocket.chat'],
['//rocket.chat', 'https://rocket.chat'],
['rocket.chat', 'https://rocket.chat'],
['rocketchat@rocket.chat', 'mailto:rocketchat@rocket.chat'],
['plain_text', undefined],
])('should normalize %o as %o', (input, output) => {
expect(normalizeUrl(input)).toBe(output);
});
import { parse } from '@rocket.chat/message-parser';
export const normalizeUrl = (url: string): string | undefined => {
if (url.startsWith('http')) {
return url;
}
if (url.startsWith('//')) {
return `https:${url}`;
}
const parsedUrl = parse(url);
if (parsedUrl[0].type === 'PARAGRAPH') {
if (parsedUrl[0].value[0].type === 'LINK') {
if (parsedUrl[0].value[0].value.src.value.startsWith('//')) {
return `https:${parsedUrl[0].value[0].value.src.value}`;
}
return parsedUrl[0].value[0].value.src.value;
}
}
return undefined;
};
import type { AppPricingPlan, PurchaseType } from '@rocket.chat/core-typings'; import type { AppPricingPlan, PurchaseType } from '@rocket.chat/core-typings';
import { Box, Tag } from '@rocket.chat/fuselage'; import { Box, Margins, Tag } from '@rocket.chat/fuselage';
import type { TranslationKey } from '@rocket.chat/ui-contexts';
import { useTranslation } from '@rocket.chat/ui-contexts'; import { useTranslation } from '@rocket.chat/ui-contexts';
import type { FC } from 'react'; import type { FC } from 'react';
import React, { useMemo } from 'react'; import React, { useMemo } from 'react';
...@@ -24,10 +23,12 @@ const AppStatusPriceDisplay: FC<AppStatusPriceDisplayProps> = ({ purchaseType, p ...@@ -24,10 +23,12 @@ const AppStatusPriceDisplay: FC<AppStatusPriceDisplayProps> = ({ purchaseType, p
); );
return ( return (
<Tag> <Margins inline={4}>
{showType && <Box color='default'>{t(type as TranslationKey)}</Box>} <Tag>
<Box>{!showType && type === 'Free' ? t(type) : formattedPrice}</Box> {showType && <Box color='default'>{t.has(type) ? t(type) : type}</Box>}
</Tag> <Box>{!showType && type === 'Free' ? t(type) : formattedPrice}</Box>
</Tag>
</Margins>
); );
}; };
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment