-
Notifications
You must be signed in to change notification settings - Fork 10.9k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
7fc4af0
commit c0b9fcb
Showing
6 changed files
with
428 additions
and
72 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
import React, { useState, useEffect } from 'react'; | ||
import { Button, ButtonGroup, Icon, Avatar, Box, Divider, Chip, Margins } from '@rocket.chat/fuselage'; | ||
|
||
import Page from '../../components/basic/Page'; | ||
import { useMethod } from '../../contexts/ServerContext'; | ||
import PriceDisplay from './PriceDisplay'; | ||
import { AppStatus } from './AppStatus'; | ||
import { useTranslation } from '../../contexts/TranslationContext'; | ||
import { Apps } from '../../../app/apps/client/orchestrator'; | ||
|
||
const objectFit = { objectFit: 'contain' }; | ||
|
||
const useSpecificApp = (id) => { | ||
const [data, setData] = useState({}); | ||
useEffect(() => { | ||
(async () => { | ||
const app = await Apps.getAppFromMarketplace(id); | ||
|
||
setData(app); | ||
})(); | ||
}, [id]); | ||
|
||
return data; | ||
}; | ||
|
||
export default function AppDetailsPage({ id }) { | ||
const t = useTranslation(); | ||
const data = useSpecificApp(id); | ||
const [modal, setModal] = useState(null); | ||
|
||
const { | ||
iconFileData = '', | ||
name, | ||
author: { name: authorName, homepage, support } = {}, | ||
description, | ||
categories = [], | ||
version, | ||
price, | ||
purchaseType, | ||
pricingPlans, | ||
} = data; | ||
|
||
const getLoggedInCloud = useMethod('cloud:checkUserLoggedIn'); | ||
const isLoggedIn = getLoggedInCloud(); | ||
|
||
return <><Page flexDirection='column'> | ||
<Page.Header title={t('App_Details')}> | ||
<ButtonGroup> | ||
<Button primary disabled> | ||
{t('Save_changes')} | ||
</Button> | ||
<Button> | ||
<Icon name='back'/> | ||
{t('Back')} | ||
</Button> | ||
</ButtonGroup> | ||
</Page.Header> | ||
<Page.Content maxWidth='x600' w='full' alignSelf='center'> | ||
<Box display='flex' flexDirection='row' mbe='x20'> | ||
<Avatar style={objectFit} size='x120' mie='x20' url={`data:image/png;base64,${ iconFileData }`}/> | ||
<Box display='flex' flexDirection='column' justifyContent='space-between'> | ||
<Box fontScale='h1' fontWeight='500'>{name}</Box> | ||
<Box display='flex' flexDirection='row' color='hint' alignItems='center'> | ||
<Box fontScale='p2' mie='x4'>{`${ t('By') } ${ authorName }`}</Box> | ||
| | ||
<Box mis= 'x4'>{`${ t('Version') } ${ version }`}</Box> | ||
</Box> | ||
<Box display='flex' flexDirection='row' alignItems='center'> | ||
<AppStatus app={data} setModal={setModal} isLoggedIn={isLoggedIn}/> | ||
<PriceDisplay mis='x12' purchaseType={purchaseType} pricingPlans={pricingPlans} price={price} showType={false}/> | ||
</Box> | ||
</Box> | ||
</Box> | ||
<Divider /> | ||
<Box display='flex' flexDirection='column'> | ||
|
||
<Margins block='x12'> | ||
<Box fontScale='h1' textTransform='uppercase'>{t('Categories')}</Box> | ||
<Box display='flex' flexDirection='row'> | ||
{categories && categories.map((current) => <Chip key={current} textTransform='uppercase' mie='x8'><Box color='hint'>{current}</Box></Chip>)} | ||
</Box> | ||
|
||
<Box fontScale='h1' textTransform='uppercase'>{t('Contact')}</Box> | ||
<Box display='flex' flexDirection='row'> | ||
<Box display='flex' flexDirection='column' mie='x12'> | ||
<Box fontScale='s1' color='hint' textTransform='uppercase'>{t('Author_Site')}</Box> | ||
<Box withRichContent><a href={homepage}>{homepage}</a></Box> | ||
</Box> | ||
<Box display='flex' flexDirection='column'> | ||
<Box fontScale='s1' color='hint' textTransform='uppercase'>{t('Support')}</Box> | ||
<Box withRichContent><a href={support}>{support}</a></Box> | ||
</Box> | ||
</Box> | ||
|
||
<Box fontScale='h1' textTransform='uppercase'>{t('Details')}</Box> | ||
<Box display='flex' flexDirection='row'>{description}</Box> | ||
</Margins> | ||
|
||
</Box> | ||
</Page.Content> | ||
</Page>{modal}</>; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
import React, { useCallback, useEffect, useState } from 'react'; | ||
import { Box, Button, Icon, Throbber } from '@rocket.chat/fuselage'; | ||
|
||
import { Modal } from '../../components/basic/Modal'; | ||
import { useTranslation } from '../../contexts/TranslationContext'; | ||
import { appButtonProps, appStatusSpanProps, handleAPIError, warnStatusChange } from '../../../app/apps/client/admin/helpers'; | ||
import { Apps } from '../../../app/apps/client/orchestrator'; | ||
|
||
const iframeMsgListener = (confirm, cancel) => (e) => { | ||
let data; | ||
try { | ||
data = JSON.parse(e.data); | ||
} catch (e) { | ||
return; | ||
} | ||
|
||
if (data.result) { | ||
confirm(data); | ||
} else { | ||
cancel(); | ||
} | ||
}; | ||
|
||
const IframeModal = ({ url, confirm, cancel, ...props }) => { | ||
useEffect(() => { | ||
const listener = iframeMsgListener(confirm, cancel); | ||
window.addEventListener('message', listener); | ||
|
||
return () => window.removeEventListener('message', listener); | ||
}, []); | ||
return <Modal padding='x12' minHeight='x400' {...props}> | ||
<iframe style={{ border: 'none', height: '100%', width: '100%' }} src={url}/> | ||
</Modal>; | ||
}; | ||
|
||
const installApp = async ({ id, name, version }, callback) => { | ||
try { | ||
const { status } = await Apps.installApp(id, version); | ||
warnStatusChange(name, status); | ||
} catch (error) { | ||
handleAPIError(error); | ||
} finally { | ||
callback(); | ||
} | ||
}; | ||
|
||
const actions = { | ||
purchase: installApp, | ||
install: installApp, | ||
update: async ({ id, name, version }, callback) => { | ||
try { | ||
const { status } = await Apps.updateApp(id, version); | ||
warnStatusChange(name, status); | ||
} catch (error) { | ||
handleAPIError(error); | ||
} finally { | ||
callback(); | ||
} | ||
}, | ||
}; | ||
|
||
export const AppStatus = React.memo(({ app, show = true, setModal, isLoggedIn, ...props }) => { | ||
const t = useTranslation(); | ||
const [loading, setLoading] = useState(); | ||
|
||
const button = appButtonProps(app); | ||
const status = !button && appStatusSpanProps(app); | ||
|
||
const { id } = app; | ||
|
||
const confirmAction = () => { | ||
actions[button.action](app, () => { | ||
setLoading(false); | ||
setModal(null); | ||
}); | ||
}; | ||
|
||
const openModal = async () => { | ||
setLoading(true); | ||
try { | ||
const data = await Apps.buildExternalUrl(app.id, app.purchaseType, false); | ||
|
||
setModal(() => <IframeModal url={data.url} cancel={() => setModal(null)} confirm={confirmAction}/>); | ||
} catch (error) { | ||
handleAPIError(error); | ||
} | ||
}; | ||
|
||
const openLoginPrompt = () => setModal(); | ||
|
||
const handleClick = useCallback((e) => { | ||
e.preventDefault(); | ||
e.stopPropagation(); | ||
isLoggedIn ? openModal() : openLoginPrompt(); | ||
}, [id, isLoggedIn]); | ||
|
||
return <Box display={show || status || loading ? 'box' : 'none'}> | ||
{button && <Button primary disabled={loading} onClick={handleClick}> | ||
{loading && <Throbber />} | ||
{!loading && button.icon && <Icon name={button.icon} />} | ||
{!loading && t(button.label)} | ||
</Button>} | ||
{status && <Box color={status.label === 'Disabled' ? 'warning' : 'hint'}> | ||
<Icon size='x20' name={status.icon} mie='x4'/> | ||
{t(status.label)} | ||
</Box>} | ||
</Box>; | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.