Skip to content
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion apps/meteor/client/sidebar/RoomMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@ import React, { memo, ReactElement, useMemo } from 'react';
import { RoomManager } from '../../app/ui-utils/client';
import { UiTextContext } from '../../definition/IRoomTypeConfig';
import { GenericModalDoNotAskAgain } from '../components/GenericModal';
import WarningModal from '../components/WarningModal';
import { useDontAskAgain } from '../hooks/useDontAskAgain';
import { roomCoordinator } from '../lib/rooms/roomCoordinator';
import WarningModal from '../views/admin/apps/WarningModal';

const fields: Fields = {
f: true,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,23 +1,24 @@
import { ISetting } from '@rocket.chat/apps-engine/definition/settings';
import { App } from '@rocket.chat/core-typings';
import { Button, ButtonGroup, Box, Throbber, Tabs } from '@rocket.chat/fuselage';
import { useMutableCallback } from '@rocket.chat/fuselage-hooks';
import { useTranslation, useCurrentRoute, useRoute, useRouteParameter } from '@rocket.chat/ui-contexts';
import React, { useState, useCallback, useRef, FC } from 'react';

import { ISettings } from '../../../../app/apps/client/@types/IOrchestrator';
import { Apps } from '../../../../app/apps/client/orchestrator';
import Page from '../../../components/Page';
import AppDetails from './AppDetails';
import AppDetailsHeader from './AppDetailsHeader';
import AppLogs from './AppLogs';
import AppReleases from './AppReleases';
import AppSecurity from './AppSecurity';
import LoadingDetails from './LoadingDetails';
import SettingsDisplay from './SettingsDisplay';
import { handleAPIError } from './helpers';
import { useAppInfo } from './hooks/useAppInfo';

const AppDetailsPage: FC<{ id: string }> = function AppDetailsPage({ id }) {
import React, { useState, useCallback, useRef, ReactElement } from 'react';

import { ISettings } from '../../../../../app/apps/client/@types/IOrchestrator';
import { Apps } from '../../../../../app/apps/client/orchestrator';
import Page from '../../../../components/Page';
import { handleAPIError } from '../helpers';
import { useAppInfo } from '../hooks/useAppInfo';
import AppDetailsPageHeader from './AppDetailsPageHeader';
import AppDetailsPageLoading from './AppDetailsPageLoading';
import AppDetails from './tabs/AppDetails';
import AppLogs from './tabs/AppLogs';
import AppReleases from './tabs/AppReleases';
import AppSecurity from './tabs/AppSecurity';
import AppSettings from './tabs/AppSettings';

const AppDetailsPage = ({ id }: { id: App['id'] }): ReactElement => {
const t = useTranslation();

const [hasUnsavedChanges, setHasUnsavedChanges] = useState(false);
Expand Down Expand Up @@ -81,11 +82,10 @@ const AppDetailsPage: FC<{ id: string }> = function AppDetailsPage({ id }) {
</Page.Header>
<Page.ScrollableContentWithShadow padding='x24'>
<Box w='full' alignSelf='center'>
{!appData && <LoadingDetails />}
{!appData && <AppDetailsPageLoading />}
{appData && (
<>
<AppDetailsHeader app={appData} />

<AppDetailsPageHeader app={appData} />
<Tabs>
<Tabs.Item onClick={(): void => handleTabClick('details')} selected={!tab || tab === 'details'}>
{t('Details')}
Expand All @@ -111,9 +111,7 @@ const AppDetailsPage: FC<{ id: string }> = function AppDetailsPage({ id }) {
</Tabs.Item>
)}
</Tabs>

{Boolean(!tab || tab === 'details') && <AppDetails app={appData} />}

{tab === 'security' && isSecurityVisible && (
<AppSecurity
privacyPolicySummary={privacyPolicySummary}
Expand All @@ -122,17 +120,14 @@ const AppDetailsPage: FC<{ id: string }> = function AppDetailsPage({ id }) {
privacyLink={privacyLink}
/>
)}

{tab === 'releases' && <AppReleases id={id} />}

{Boolean(tab === 'settings' && settings && Object.values(settings).length) && (
<SettingsDisplay
<AppSettings
settings={settings || ({} as ISettings)}
setHasUnsavedChanges={setHasUnsavedChanges}
settingsRef={settingsRef}
/>
)}

{tab === 'logs' && <AppLogs id={id} />}
</>
)}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import type { App } from '@rocket.chat/core-typings';
import { Box } from '@rocket.chat/fuselage';
import { useTranslation } from '@rocket.chat/ui-contexts';
import moment from 'moment';
import React, { ReactElement } from 'react';

import AppAvatar from '../../../components/avatar/AppAvatar';
import AppMenu from './AppMenu';
import AppStatus from './AppStatus';
import BundleChips from './BundleChips';
import { App } from './types';
import AppAvatar from '../../../../components/avatar/AppAvatar';
import AppMenu from '../AppMenu';
import BundleChips from '../BundleChips';
import AppStatus from './tabs/AppStatus';

const AppDetailsHeader = ({ app }: { app: App }): ReactElement => {
const AppDetailsPageHeader = ({ app }: { app: App }): ReactElement => {
const t = useTranslation();
const { iconFileData, name, author, version, iconFileContent, installed, isSubscribed, modifiedAt, bundledIn } = app;
const lastUpdated = modifiedAt && moment(modifiedAt).fromNow();
Expand All @@ -26,9 +26,7 @@ const AppDetailsHeader = ({ app }: { app: App }): ReactElement => {
</Box>
{app?.shortDescription && <Box mbe='x16'>{app.shortDescription}</Box>}
<Box display='flex' flexDirection='row' alignItems='center' mbe='x16'>
<Box display='flex' flexDirection='row' alignItems='center'>
<AppStatus app={app} installed={installed} isAppDetailsPage={true} isSubscribed={isSubscribed} />
</Box>
<AppStatus app={app} installed={installed} isAppDetailsPage={true} isSubscribed={isSubscribed} />
{(installed || isSubscribed) && <AppMenu app={app} mis='x8' />}
</Box>
<Box display='flex' flexDirection='row' color='hint' alignItems='center'>
Expand All @@ -53,4 +51,4 @@ const AppDetailsHeader = ({ app }: { app: App }): ReactElement => {
);
};

export default AppDetailsHeader;
export default AppDetailsPageHeader;
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Box, Skeleton } from '@rocket.chat/fuselage';
import React, { FC } from 'react';

const LoadingDetails: FC = () => (
const AppDetailsPageLoading: FC = () => (
<Box display='flex' flexDirection='row' mbe='x20' w='full'>
<Skeleton variant='rect' w='x120' h='x120' mie='x20' />
<Box display='flex' flexDirection='column' justifyContent='space-between' flexGrow={1}>
Expand All @@ -12,4 +12,4 @@ const LoadingDetails: FC = () => (
</Box>
);

export default LoadingDetails;
export default AppDetailsPageLoading;
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from './AppDetailsPage';
Original file line number Diff line number Diff line change
@@ -1,17 +1,14 @@
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';
import React, { ReactElement } from 'react';

import APIsDisplay from './APIsDisplay';
import ScreenshotCarouselAnchor from './components/ScreenshotCarouselAnchor';
import { AppInfo } from './definitions/AppInfo';
import ScreenshotCarouselAnchor from '../../../components/ScreenshotCarouselAnchor';
import { AppInfo } from '../../../definitions/AppInfo';
import AppDetailsAPIs from './AppDetailsAPIs';

type AppDetailsProps = {
app: AppInfo;
};

const AppDetails: FC<AppDetailsProps> = ({ app }) => {
const AppDetails = ({ app }: { app: AppInfo }): ReactElement => {
const t = useTranslation();
const {
author: { homepage, support },
detailedDescription,
Expand All @@ -21,8 +18,6 @@ const AppDetails: FC<AppDetailsProps> = ({ app }) => {
apis,
} = app;

const t = useTranslation();

const isMarkdown = detailedDescription && Object.keys(detailedDescription).length !== 0 && detailedDescription.rendered;
const isCarouselVisible = screenshots && Boolean(screenshots.length);

Expand Down Expand Up @@ -90,7 +85,7 @@ const AppDetails: FC<AppDetailsProps> = ({ app }) => {

{apis?.length ? (
<Box is='section'>
<APIsDisplay apis={apis || []} />
<AppDetailsAPIs apis={apis || []} />
</Box>
) : null}
</Margins>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@ import { Box } from '@rocket.chat/fuselage';
import { useAbsoluteUrl, useTranslation } from '@rocket.chat/ui-contexts';
import React, { FC, Fragment } from 'react';

import { apiCurlGetter } from './helpers';
import { apiCurlGetter } from '../../../helpers';

type APIsDisplayProps = {
type AppDetailsAPIsProps = {
apis: IApiEndpointMetadata[];
};

const APIsDisplay: FC<APIsDisplayProps> = ({ apis }) => {
const AppDetailsAPIs: FC<AppDetailsAPIsProps> = ({ apis }) => {
const t = useTranslation();
const absoluteUrl = useAbsoluteUrl();
const getApiCurl = apiCurlGetter(absoluteUrl);
Expand Down Expand Up @@ -48,4 +48,4 @@ const APIsDisplay: FC<APIsDisplayProps> = ({ apis }) => {
);
};

export default APIsDisplay;
export default AppDetailsAPIs;
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from './AppDetails';
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ import { Accordion, Box } from '@rocket.chat/fuselage';
import { useTranslation } from '@rocket.chat/ui-contexts';
import React, { ReactElement } from 'react';

import { useFormatDateAndTime } from '../../../hooks/useFormatDateAndTime';
import AccordionLoading from './AccordionLoading';
import LogItem from './LogItem';
import { useLogs } from './hooks/useLogs';
import { useFormatDateAndTime } from '../../../../../../hooks/useFormatDateAndTime';
import AccordionLoading from '../../../AccordionLoading';
import { useLogs } from '../../../hooks/useLogs';
import AppLogsItem from './AppLogsItem';

const AppLogs = ({ id }: { id: string }): ReactElement => {
const t = useTranslation();
Expand All @@ -23,7 +23,7 @@ const AppLogs = ({ id }: { id: string }): ReactElement => {
{isSuccess && (
<Accordion width='100%' alignSelf='center'>
{data?.logs?.map((log) => (
<LogItem
<AppLogsItem
key={log._createdAt}
title={`${formatDateAndTime(log._createdAt)}: "${log.method}" (${log.totalTime}ms)`}
instanceId={log.instanceId}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,15 @@ import { Box, Accordion } from '@rocket.chat/fuselage';
import { useTranslation } from '@rocket.chat/ui-contexts';
import React, { FC } from 'react';

import LogEntry from './LogEntry';
import AppLogsItemEntry from './AppLogsItemEntry';

type LogItemProps = {
type AppLogsItemProps = {
entries: ILogEntry[];
instanceId: string;
title: string;
};

const LogItem: FC<LogItemProps> = ({ entries, instanceId, title, ...props }) => {
const AppLogsItem: FC<AppLogsItemProps> = ({ entries, instanceId, title, ...props }) => {
const t = useTranslation();

return (
Expand All @@ -22,10 +22,10 @@ const LogItem: FC<LogItemProps> = ({ entries, instanceId, title, ...props }) =>
</Box>
)}
{entries.map(({ severity, timestamp, caller, args }, i) => (
<LogEntry key={i} severity={severity} timestamp={timestamp} caller={caller} args={args} />
<AppLogsItemEntry key={i} severity={severity} timestamp={timestamp} caller={caller} args={args} />
))}
</Accordion.Item>
);
};

export default LogItem;
export default AppLogsItem;
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,16 @@ import { Box } from '@rocket.chat/fuselage';
import { useTranslation } from '@rocket.chat/ui-contexts';
import React, { FC } from 'react';

import { useHighlightedCode } from '../../../hooks/useHighlightedCode';
import { useHighlightedCode } from '../../../../../../hooks/useHighlightedCode';

type LogEntryProps = {
type AppLogsItemEntryProps = {
severity: string;
timestamp: string;
caller: string;
args: unknown;
};

const LogEntry: FC<LogEntryProps> = ({ severity, timestamp, caller, args }) => {
const AppLogsItemEntry: FC<AppLogsItemEntryProps> = ({ severity, timestamp, caller, args }) => {
const t = useTranslation();

return (
Expand All @@ -32,4 +32,4 @@ const LogEntry: FC<LogEntryProps> = ({ severity, timestamp, caller, args }) => {
);
};

export default LogEntry;
export default AppLogsItemEntry;
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from './AppLogs';
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { App } from '@rocket.chat/core-typings';
import { Accordion } from '@rocket.chat/fuselage';
import React, { ReactElement } from 'react';

import { useEndpointData } from '../../../../../../hooks/useEndpointData';
import { AsyncStatePhase } from '../../../../../../lib/asyncState/AsyncStatePhase';
import AccordionLoading from '../../../AccordionLoading';
import AppReleasesItem from './AppReleasesItem';

// TODO: replace useEndpointData
const AppReleases = ({ id }: { id: App['id'] }): ReactElement => {
const result = useEndpointData(`/apps/${id}/versions`);

return (
<>
<Accordion width='100%' alignSelf='center'>
{result.phase === AsyncStatePhase.LOADING && <AccordionLoading />}
{result.phase === AsyncStatePhase.RESOLVED && (
<>
{result.value.apps.map((release) => (
<AppReleasesItem release={release} key={release.version} />
))}
</>
)}
</Accordion>
</>
);
};

export default AppReleases;
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { Accordion, Box } from '@rocket.chat/fuselage';
import React from 'react';
import { useTranslation } from '@rocket.chat/ui-contexts';
import React, { ReactElement } from 'react';

import { useTimeAgo } from '../../../hooks/useTimeAgo';
import { useTimeAgo } from '../../../../../../hooks/useTimeAgo';

type release = {
type IRelease = {
version: string;
createdDate: string;
detailedChangelog: {
Expand All @@ -13,10 +14,11 @@ type release = {
};

type ReleaseItemProps = {
release: release;
release: IRelease;
};

const ReleaseItem = ({ release, ...props }: ReleaseItemProps): JSX.Element => {
const AppReleasesItem = ({ release, ...props }: ReleaseItemProps): ReactElement => {
const t = useTranslation();
const formatDate = useTimeAgo();

const title = (
Expand All @@ -35,10 +37,10 @@ const ReleaseItem = ({ release, ...props }: ReleaseItemProps): JSX.Element => {
{release.detailedChangelog?.rendered ? (
<Box dangerouslySetInnerHTML={{ __html: release.detailedChangelog?.rendered }} />
) : (
'No release information provided'
t('No_release_information_provided')
)}
</Accordion.Item>
);
};

export default ReleaseItem;
export default AppReleasesItem;
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from './AppReleases';
Loading