Skip to content
Merged
Show file tree
Hide file tree
Changes from 7 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
3 changes: 2 additions & 1 deletion client/admin/sidebar/AdminSidebar.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { useAbsoluteUrl } from '../../contexts/ServerContext';
import { useAtLeastOnePermission } from '../../contexts/AuthorizationContext';
import SettingsProvider from '../../providers/SettingsProvider';
import { sidebarItems } from '../sidebarItems';
import PlanTag from '../../components/basic/PlanTag';

const SidebarItem = React.memo(({ permissionGranted, pathGroup, href, icon, label, currentPath }) => {
const params = useMemo(() => ({ group: pathGroup }), [pathGroup]);
Expand Down Expand Up @@ -195,7 +196,7 @@ export default React.memo(function AdminSidebar() {
return <SettingsProvider privileged>
<Box display='flex' flexDirection='column' h='100vh'>
<Box is='header' pb='x16' pi='x24' display='flex' flexDirection='row' alignItems='center' justifyContent='space-between'>
<Box color='neutral-800' fontSize='p1' fontWeight='p1' fontWeight='p1' flexShrink={1} withTruncatedText>{t('Administration')}</Box>
<Box color='neutral-800' fontSize='p1' display='flex' flexDirection='row' alignItems='center' fontWeight='p1' fontWeight='p1' flexShrink={1} withTruncatedText>{t('Administration')}<PlanTag></PlanTag></Box>
Comment thread
ggazzo marked this conversation as resolved.
Outdated
<Button square small ghost onClick={closeAdminFlex}><Icon name='cross' size='x20'/></Button>
</Box>
<Scrollable>
Expand Down
45 changes: 45 additions & 0 deletions client/components/basic/PlanTag.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import React, { useMemo, useState } from 'react';
import { Tag, Box } from '@rocket.chat/fuselage';

import { useMethod } from '../../contexts/ServerContext';

function PlanTag() {
const [plans, setPlans] = useState([]);
const [background, setBackground] = useState([]);

const getTags = useMethod('license:getTags');

useMemo(() => {
Comment thread
ggazzo marked this conversation as resolved.
Outdated
const loadTags = async () => {
setPlans(await getTags());

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's a catch here: setPlans can be accidentally called after the component was unmounted, i.e., PlanTag may be already unmounted after the getTags() returned promise was resolved. To avoid that we usually do some kind of semaphore to skip the setPlans calls after unmount, but I've made a custom hook for that:

import { useSafely } from '@rocket.chat/fuselage-hooks';

const [plans, setPlans] = useSafely(useState([]));

So setPlans can be called anytime.

N.B.: Pay attention to possible memory leaks, tough. If the promise never resolves, setPlans will be referenced forever, and the whole component as well.

};
loadTags();
}, [getTags]);

useMemo(() => {
const currBg = [];
plans.forEach((plan, i) => {
switch (plan) {
case 'bronze':
currBg[i] = '#BD5A0B';
break;
case 'silver':
currBg[i] = '#9EA2A8';
break;
case 'gold':
currBg[i] = '#F3BE08';
break;
default:
currBg[i] = '#2F343D';
break;
}
});
setBackground(currBg);
}, [plans]);
Comment thread
ggazzo marked this conversation as resolved.
Outdated

return <Box>
{plans.map((plan, i) => <Tag key={plan} backgroundColor={background[i]} marginInlineStart='x8' color='#fff' textTransform='capitalize' >{plan}</Tag>) }
Comment thread
MartinSchoeler marked this conversation as resolved.
Outdated
</Box>;
}

export default PlanTag;