mirror of
https://github.com/Unleash/unleash.git
synced 2025-05-03 01:18:43 +02:00
feat: what's new in Unleash (#7497)
https://linear.app/unleash/issue/2-2354/new-in-unleash-section-in-sidebar Add a "New in Unleash" section in the side bar and use it to announce signals and actions.  Inside signals page we're also including a feedback button to try to collect some insights.  --------- Co-authored-by: Nuno Góis <github@nunogois.com>
This commit is contained in:
parent
06971375cb
commit
5832fc7d81
@ -15,6 +15,7 @@ import {
|
|||||||
import { useInitialPathname } from './useInitialPathname';
|
import { useInitialPathname } from './useInitialPathname';
|
||||||
import { useLastViewedProject } from 'hooks/useLastViewedProject';
|
import { useLastViewedProject } from 'hooks/useLastViewedProject';
|
||||||
import { useLastViewedFlags } from 'hooks/useLastViewedFlags';
|
import { useLastViewedFlags } from 'hooks/useLastViewedFlags';
|
||||||
|
import { NewInUnleash } from './NewInUnleash/NewInUnleash';
|
||||||
|
|
||||||
export const MobileNavigationSidebar: FC<{ onClick: () => void }> = ({
|
export const MobileNavigationSidebar: FC<{ onClick: () => void }> = ({
|
||||||
onClick,
|
onClick,
|
||||||
@ -23,6 +24,7 @@ export const MobileNavigationSidebar: FC<{ onClick: () => void }> = ({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
<NewInUnleash onItemClick={onClick} />
|
||||||
<PrimaryNavigationList mode='full' onClick={onClick} />
|
<PrimaryNavigationList mode='full' onClick={onClick} />
|
||||||
<SecondaryNavigationList
|
<SecondaryNavigationList
|
||||||
routes={routes.mainNavRoutes}
|
routes={routes.mainNavRoutes}
|
||||||
@ -67,6 +69,7 @@ export const NavigationSidebar = () => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<StretchContainer>
|
<StretchContainer>
|
||||||
|
<NewInUnleash mode={mode} onMiniModeClick={() => setMode('full')} />
|
||||||
<PrimaryNavigationList
|
<PrimaryNavigationList
|
||||||
mode={mode}
|
mode={mode}
|
||||||
onClick={setActiveItem}
|
onClick={setActiveItem}
|
||||||
|
@ -0,0 +1,161 @@
|
|||||||
|
import type { ReactNode } from 'react';
|
||||||
|
import { useUiFlag } from 'hooks/useUiFlag';
|
||||||
|
import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig';
|
||||||
|
import { useLocalStorageState } from 'hooks/useLocalStorageState';
|
||||||
|
import {
|
||||||
|
Badge,
|
||||||
|
Icon,
|
||||||
|
ListItem,
|
||||||
|
ListItemButton,
|
||||||
|
ListItemIcon,
|
||||||
|
Tooltip,
|
||||||
|
styled,
|
||||||
|
} from '@mui/material';
|
||||||
|
import Signals from '@mui/icons-material/Sensors';
|
||||||
|
import { useNavigate } from 'react-router-dom';
|
||||||
|
import type { NavigationMode } from 'component/layout/MainLayout/NavigationSidebar/NavigationMode';
|
||||||
|
import { NewInUnleashItem } from './NewInUnleashItem';
|
||||||
|
import { usePlausibleTracker } from 'hooks/usePlausibleTracker';
|
||||||
|
|
||||||
|
const StyledNewInUnleash = styled('div')(({ theme }) => ({
|
||||||
|
borderRadius: theme.shape.borderRadiusMedium,
|
||||||
|
[theme.breakpoints.down('lg')]: {
|
||||||
|
margin: theme.spacing(2),
|
||||||
|
marginBottom: theme.spacing(1),
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
|
||||||
|
const StyledNewInUnleashHeader = styled('p')(({ theme }) => ({
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
lineHeight: 1,
|
||||||
|
gap: theme.spacing(1),
|
||||||
|
'& > span': {
|
||||||
|
color: theme.palette.neutral.main,
|
||||||
|
},
|
||||||
|
padding: theme.spacing(1, 2),
|
||||||
|
}));
|
||||||
|
|
||||||
|
const StyledNewInUnleashList = styled('ul')(({ theme }) => ({
|
||||||
|
display: 'flex',
|
||||||
|
flexDirection: 'column',
|
||||||
|
padding: theme.spacing(1),
|
||||||
|
listStyle: 'none',
|
||||||
|
margin: 0,
|
||||||
|
gap: theme.spacing(1),
|
||||||
|
}));
|
||||||
|
|
||||||
|
const StyledMiniItemButton = styled(ListItemButton)(({ theme }) => ({
|
||||||
|
borderRadius: theme.spacing(0.5),
|
||||||
|
borderLeft: `${theme.spacing(0.5)} solid transparent`,
|
||||||
|
'&.Mui-selected': {
|
||||||
|
borderLeft: `${theme.spacing(0.5)} solid ${theme.palette.primary.main}`,
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
|
||||||
|
const StyledMiniItemIcon = styled(ListItemIcon)(({ theme }) => ({
|
||||||
|
minWidth: theme.spacing(4),
|
||||||
|
margin: theme.spacing(0.25, 0),
|
||||||
|
}));
|
||||||
|
|
||||||
|
const StyledSignalsIcon = styled(Signals)(({ theme }) => ({
|
||||||
|
color: theme.palette.primary.main,
|
||||||
|
}));
|
||||||
|
|
||||||
|
type NewItem = {
|
||||||
|
label: string;
|
||||||
|
icon: ReactNode;
|
||||||
|
link: string;
|
||||||
|
show: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
interface INewInUnleashProps {
|
||||||
|
mode?: NavigationMode;
|
||||||
|
onItemClick?: () => void;
|
||||||
|
onMiniModeClick?: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const NewInUnleash = ({
|
||||||
|
mode = 'full',
|
||||||
|
onItemClick,
|
||||||
|
onMiniModeClick,
|
||||||
|
}: INewInUnleashProps) => {
|
||||||
|
const { trackEvent } = usePlausibleTracker();
|
||||||
|
const navigate = useNavigate();
|
||||||
|
const [seenItems, setSeenItems] = useLocalStorageState(
|
||||||
|
'new-in-unleash-seen:v1',
|
||||||
|
new Set(),
|
||||||
|
);
|
||||||
|
const { isEnterprise } = useUiConfig();
|
||||||
|
const signalsEnabled = useUiFlag('signals');
|
||||||
|
|
||||||
|
const items: NewItem[] = [
|
||||||
|
{
|
||||||
|
label: 'Signals & Actions',
|
||||||
|
icon: <StyledSignalsIcon />,
|
||||||
|
link: '/integrations/signals',
|
||||||
|
show: isEnterprise() && signalsEnabled,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const visibleItems = items.filter(
|
||||||
|
(item) => item.show && !seenItems.has(item.label),
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!visibleItems.length) return null;
|
||||||
|
|
||||||
|
if (mode === 'mini' && onMiniModeClick) {
|
||||||
|
return (
|
||||||
|
<ListItem disablePadding onClick={onMiniModeClick}>
|
||||||
|
<StyledMiniItemButton dense>
|
||||||
|
<Tooltip title='New in Unleash' placement='right'>
|
||||||
|
<StyledMiniItemIcon>
|
||||||
|
<Badge
|
||||||
|
badgeContent={visibleItems.length}
|
||||||
|
color='primary'
|
||||||
|
>
|
||||||
|
<Icon>new_releases</Icon>
|
||||||
|
</Badge>
|
||||||
|
</StyledMiniItemIcon>
|
||||||
|
</Tooltip>
|
||||||
|
</StyledMiniItemButton>
|
||||||
|
</ListItem>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<StyledNewInUnleash>
|
||||||
|
<StyledNewInUnleashHeader>
|
||||||
|
<Icon>new_releases</Icon>
|
||||||
|
New in Unleash
|
||||||
|
</StyledNewInUnleashHeader>
|
||||||
|
<StyledNewInUnleashList>
|
||||||
|
{visibleItems.map(({ label, icon, link }) => (
|
||||||
|
<NewInUnleashItem
|
||||||
|
key={label}
|
||||||
|
icon={icon}
|
||||||
|
onClick={() => {
|
||||||
|
trackEvent('new-in-unleash-click', {
|
||||||
|
props: {
|
||||||
|
label,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
navigate(link);
|
||||||
|
onItemClick?.();
|
||||||
|
}}
|
||||||
|
onDismiss={() => {
|
||||||
|
trackEvent('new-in-unleash-dismiss', {
|
||||||
|
props: {
|
||||||
|
label,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
setSeenItems(new Set([...seenItems, label]));
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{label}
|
||||||
|
</NewInUnleashItem>
|
||||||
|
))}
|
||||||
|
</StyledNewInUnleashList>
|
||||||
|
</StyledNewInUnleash>
|
||||||
|
);
|
||||||
|
};
|
@ -0,0 +1,66 @@
|
|||||||
|
import type { ReactNode } from 'react';
|
||||||
|
import {
|
||||||
|
IconButton,
|
||||||
|
ListItem,
|
||||||
|
ListItemButton,
|
||||||
|
Tooltip,
|
||||||
|
styled,
|
||||||
|
} from '@mui/material';
|
||||||
|
import Close from '@mui/icons-material/Close';
|
||||||
|
|
||||||
|
const StyledItemButton = styled(ListItemButton)(({ theme }) => ({
|
||||||
|
justifyContent: 'space-between',
|
||||||
|
outline: `1px solid ${theme.palette.divider}`,
|
||||||
|
borderRadius: theme.shape.borderRadiusMedium,
|
||||||
|
padding: theme.spacing(1),
|
||||||
|
}));
|
||||||
|
|
||||||
|
const StyledItemButtonContent = styled('div')(({ theme }) => ({
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
gap: theme.spacing(1),
|
||||||
|
fontSize: theme.fontSizes.smallBody,
|
||||||
|
}));
|
||||||
|
|
||||||
|
const StyledItemButtonClose = styled(IconButton)(({ theme }) => ({
|
||||||
|
padding: theme.spacing(0.25),
|
||||||
|
}));
|
||||||
|
|
||||||
|
interface INewInUnleashItemProps {
|
||||||
|
icon: ReactNode;
|
||||||
|
onClick: () => void;
|
||||||
|
onDismiss: () => void;
|
||||||
|
children: ReactNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const NewInUnleashItem = ({
|
||||||
|
icon,
|
||||||
|
onClick,
|
||||||
|
onDismiss,
|
||||||
|
children,
|
||||||
|
}: INewInUnleashItemProps) => {
|
||||||
|
const onDismissClick = (e: React.MouseEvent) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
onDismiss();
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ListItem disablePadding onClick={onClick}>
|
||||||
|
<StyledItemButton>
|
||||||
|
<StyledItemButtonContent>
|
||||||
|
{icon}
|
||||||
|
{children}
|
||||||
|
</StyledItemButtonContent>
|
||||||
|
<Tooltip title='Dismiss' arrow>
|
||||||
|
<StyledItemButtonClose
|
||||||
|
aria-label='dismiss'
|
||||||
|
onClick={onDismissClick}
|
||||||
|
size='small'
|
||||||
|
>
|
||||||
|
<Close fontSize='inherit' />
|
||||||
|
</StyledItemButtonClose>
|
||||||
|
</Tooltip>
|
||||||
|
</StyledItemButton>
|
||||||
|
</ListItem>
|
||||||
|
);
|
||||||
|
};
|
@ -3,7 +3,8 @@ import { TablePlaceholder, VirtualizedTable } from 'component/common/Table';
|
|||||||
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
||||||
import useToast from 'hooks/useToast';
|
import useToast from 'hooks/useToast';
|
||||||
import { formatUnknownError } from 'utils/formatUnknownError';
|
import { formatUnknownError } from 'utils/formatUnknownError';
|
||||||
import { Button, useMediaQuery } from '@mui/material';
|
import { Alert, Button, styled, useMediaQuery } from '@mui/material';
|
||||||
|
import ReviewsOutlined from '@mui/icons-material/ReviewsOutlined';
|
||||||
import { useFlexLayout, useSortBy, useTable } from 'react-table';
|
import { useFlexLayout, useSortBy, useTable } from 'react-table';
|
||||||
import { sortTypes } from 'utils/sortTypes';
|
import { sortTypes } from 'utils/sortTypes';
|
||||||
import { TextCell } from 'component/common/Table/cells/TextCell/TextCell';
|
import { TextCell } from 'component/common/Table/cells/TextCell/TextCell';
|
||||||
@ -25,10 +26,18 @@ import { LinkCell } from 'component/common/Table/cells/LinkCell/LinkCell';
|
|||||||
import { SignalEndpointsSignalsModal } from '../SignalEndpointsSignals/SignalEndpointsSignalsModal';
|
import { SignalEndpointsSignalsModal } from '../SignalEndpointsSignals/SignalEndpointsSignalsModal';
|
||||||
import { PageContent } from 'component/common/PageContent/PageContent';
|
import { PageContent } from 'component/common/PageContent/PageContent';
|
||||||
import { PageHeader } from 'component/common/PageHeader/PageHeader';
|
import { PageHeader } from 'component/common/PageHeader/PageHeader';
|
||||||
|
import { PermissionGuard } from 'component/common/PermissionGuard/PermissionGuard';
|
||||||
|
import { ADMIN } from '@server/types/permissions';
|
||||||
|
import PermissionButton from 'component/common/PermissionButton/PermissionButton';
|
||||||
|
import { useFeedback } from 'component/feedbackNew/useFeedback';
|
||||||
|
|
||||||
export const SignalEndpointsTable = () => {
|
export const SignalEndpointsTable = () => {
|
||||||
const { setToastData, setToastApiError } = useToast();
|
const { setToastData, setToastApiError } = useToast();
|
||||||
const { uiConfig } = useUiConfig();
|
const { uiConfig } = useUiConfig();
|
||||||
|
const { openFeedback, hasSubmittedFeedback } = useFeedback(
|
||||||
|
'signals',
|
||||||
|
'automatic',
|
||||||
|
);
|
||||||
|
|
||||||
const { signalEndpoints, refetch } = useSignalEndpoints();
|
const { signalEndpoints, refetch } = useSignalEndpoints();
|
||||||
const { toggleSignalEndpoint, removeSignalEndpoint } =
|
const { toggleSignalEndpoint, removeSignalEndpoint } =
|
||||||
@ -44,6 +53,14 @@ export const SignalEndpointsTable = () => {
|
|||||||
|
|
||||||
const [signalsModalOpen, setSignalsModalOpen] = useState(false);
|
const [signalsModalOpen, setSignalsModalOpen] = useState(false);
|
||||||
|
|
||||||
|
const StyledAlert = styled(Alert)(({ theme }) => ({
|
||||||
|
marginBottom: theme.spacing(3),
|
||||||
|
}));
|
||||||
|
|
||||||
|
const StyledParagraph = styled('p')(({ theme }) => ({
|
||||||
|
marginBottom: theme.spacing(2),
|
||||||
|
}));
|
||||||
|
|
||||||
const onToggleSignalEndpoint = async (
|
const onToggleSignalEndpoint = async (
|
||||||
{ id, name }: ISignalEndpoint,
|
{ id, name }: ISignalEndpoint,
|
||||||
enabled: boolean,
|
enabled: boolean,
|
||||||
@ -227,69 +244,143 @@ export const SignalEndpointsTable = () => {
|
|||||||
<PageHeader
|
<PageHeader
|
||||||
title={`Signal endpoints (${signalEndpoints.length})`}
|
title={`Signal endpoints (${signalEndpoints.length})`}
|
||||||
actions={
|
actions={
|
||||||
<Button
|
<>
|
||||||
variant='contained'
|
<ConditionallyRender
|
||||||
color='primary'
|
condition={!hasSubmittedFeedback}
|
||||||
onClick={() => {
|
show={
|
||||||
setSelectedSignalEndpoint(undefined);
|
<Button
|
||||||
setModalOpen(true);
|
startIcon={<ReviewsOutlined />}
|
||||||
}}
|
variant='outlined'
|
||||||
>
|
onClick={() => {
|
||||||
New signal endpoint
|
openFeedback({
|
||||||
</Button>
|
title: 'Do you find signals and actions easy to use?',
|
||||||
|
positiveLabel:
|
||||||
|
'What do you like most about signals and actions?',
|
||||||
|
areasForImprovementsLabel:
|
||||||
|
'What needs to change to use signals and actions the way you want?',
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Provide feedback
|
||||||
|
</Button>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<PermissionButton
|
||||||
|
variant='contained'
|
||||||
|
color='primary'
|
||||||
|
permission={ADMIN}
|
||||||
|
onClick={() => {
|
||||||
|
setSelectedSignalEndpoint(undefined);
|
||||||
|
setModalOpen(true);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
New signal endpoint
|
||||||
|
</PermissionButton>
|
||||||
|
</>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<VirtualizedTable
|
<StyledAlert severity='info'>
|
||||||
rows={rows}
|
<StyledParagraph>
|
||||||
headerGroups={headerGroups}
|
Signals and actions allow you to respond to events in your
|
||||||
prepareRow={prepareRow}
|
real-time monitoring system by automating tasks such as
|
||||||
/>
|
disabling a beta feature in response to an increase in
|
||||||
<ConditionallyRender
|
errors or a drop in conversion rates.
|
||||||
condition={rows.length === 0}
|
</StyledParagraph>
|
||||||
show={
|
|
||||||
<TablePlaceholder>
|
<StyledParagraph>
|
||||||
No signal endpoints available. Get started by adding
|
<ul>
|
||||||
one.
|
<li>
|
||||||
</TablePlaceholder>
|
<b>Signal endpoints</b> are used to send signals to
|
||||||
}
|
Unleash. This allows you to integrate Unleash with
|
||||||
/>
|
any external tool.
|
||||||
<SignalEndpointsModal
|
</li>
|
||||||
signalEndpoint={selectedSignalEndpoint}
|
|
||||||
open={modalOpen}
|
<li>
|
||||||
setOpen={setModalOpen}
|
<b>Actions</b>, which are configured inside
|
||||||
newToken={(token: string, signalEndpoint: ISignalEndpoint) => {
|
projects, allow you to react to those signals and
|
||||||
setNewToken(token);
|
enable or disable flags based on certain conditions.
|
||||||
setSelectedSignalEndpoint(signalEndpoint);
|
</li>
|
||||||
setTokenDialog(true);
|
</ul>
|
||||||
}}
|
</StyledParagraph>
|
||||||
onOpenSignals={() => {
|
|
||||||
setModalOpen(false);
|
<StyledParagraph>
|
||||||
setSignalsModalOpen(true);
|
Read more about these features in our documentation:{' '}
|
||||||
}}
|
<a
|
||||||
/>
|
href='https://docs.getunleash.io/reference/signals'
|
||||||
<SignalEndpointsSignalsModal
|
target='_blank'
|
||||||
signalEndpoint={selectedSignalEndpoint}
|
rel='noreferrer'
|
||||||
open={signalsModalOpen}
|
>
|
||||||
setOpen={setSignalsModalOpen}
|
Signals
|
||||||
onOpenConfiguration={() => {
|
</a>{' '}
|
||||||
setSignalsModalOpen(false);
|
and{' '}
|
||||||
setModalOpen(true);
|
<a
|
||||||
}}
|
href='https://docs.getunleash.io/reference/actions'
|
||||||
/>
|
target='_blank'
|
||||||
<SignalEndpointsTokensDialog
|
rel='noreferrer'
|
||||||
open={tokenDialog}
|
>
|
||||||
setOpen={setTokenDialog}
|
Actions
|
||||||
token={newToken}
|
</a>
|
||||||
signalEndpoint={selectedSignalEndpoint}
|
</StyledParagraph>
|
||||||
/>
|
</StyledAlert>
|
||||||
<SignalEndpointsDeleteDialog
|
|
||||||
signalEndpoint={selectedSignalEndpoint}
|
<PermissionGuard permissions={ADMIN}>
|
||||||
open={deleteOpen}
|
<>
|
||||||
setOpen={setDeleteOpen}
|
<VirtualizedTable
|
||||||
onConfirm={onDeleteConfirm}
|
rows={rows}
|
||||||
/>
|
headerGroups={headerGroups}
|
||||||
|
prepareRow={prepareRow}
|
||||||
|
/>
|
||||||
|
<ConditionallyRender
|
||||||
|
condition={rows.length === 0}
|
||||||
|
show={
|
||||||
|
<TablePlaceholder>
|
||||||
|
No signal endpoints available. Get started by
|
||||||
|
adding one.
|
||||||
|
</TablePlaceholder>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<SignalEndpointsModal
|
||||||
|
signalEndpoint={selectedSignalEndpoint}
|
||||||
|
open={modalOpen}
|
||||||
|
setOpen={setModalOpen}
|
||||||
|
newToken={(
|
||||||
|
token: string,
|
||||||
|
signalEndpoint: ISignalEndpoint,
|
||||||
|
) => {
|
||||||
|
setNewToken(token);
|
||||||
|
setSelectedSignalEndpoint(signalEndpoint);
|
||||||
|
setTokenDialog(true);
|
||||||
|
}}
|
||||||
|
onOpenSignals={() => {
|
||||||
|
setModalOpen(false);
|
||||||
|
setSignalsModalOpen(true);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<SignalEndpointsSignalsModal
|
||||||
|
signalEndpoint={selectedSignalEndpoint}
|
||||||
|
open={signalsModalOpen}
|
||||||
|
setOpen={setSignalsModalOpen}
|
||||||
|
onOpenConfiguration={() => {
|
||||||
|
setSignalsModalOpen(false);
|
||||||
|
setModalOpen(true);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<SignalEndpointsTokensDialog
|
||||||
|
open={tokenDialog}
|
||||||
|
setOpen={setTokenDialog}
|
||||||
|
token={newToken}
|
||||||
|
signalEndpoint={selectedSignalEndpoint}
|
||||||
|
/>
|
||||||
|
<SignalEndpointsDeleteDialog
|
||||||
|
signalEndpoint={selectedSignalEndpoint}
|
||||||
|
open={deleteOpen}
|
||||||
|
setOpen={setDeleteOpen}
|
||||||
|
onConfirm={onDeleteConfirm}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
</PermissionGuard>
|
||||||
</PageContent>
|
</PageContent>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
import { ADMIN } from 'component/providers/AccessProvider/permissions';
|
|
||||||
import { PermissionGuard } from 'component/common/PermissionGuard/PermissionGuard';
|
|
||||||
import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig';
|
import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig';
|
||||||
import { PremiumFeature } from 'component/common/PremiumFeature/PremiumFeature';
|
import { PremiumFeature } from 'component/common/PremiumFeature/PremiumFeature';
|
||||||
import { SignalEndpointsTable } from './SignalEndpointsTable/SignalEndpointsTable';
|
import { SignalEndpointsTable } from './SignalEndpointsTable/SignalEndpointsTable';
|
||||||
@ -11,11 +9,5 @@ export const Signals = () => {
|
|||||||
return <PremiumFeature feature='signals' />;
|
return <PremiumFeature feature='signals' />;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return <SignalEndpointsTable />;
|
||||||
<div>
|
|
||||||
<PermissionGuard permissions={ADMIN}>
|
|
||||||
<SignalEndpointsTable />
|
|
||||||
</PermissionGuard>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
@ -62,7 +62,9 @@ export type CustomEvents =
|
|||||||
| 'many-strategies'
|
| 'many-strategies'
|
||||||
| 'sdk-banner'
|
| 'sdk-banner'
|
||||||
| 'feature-lifecycle'
|
| 'feature-lifecycle'
|
||||||
| 'command-bar';
|
| 'command-bar'
|
||||||
|
| 'new-in-unleash-click'
|
||||||
|
| 'new-in-unleash-dismiss';
|
||||||
|
|
||||||
export const usePlausibleTracker = () => {
|
export const usePlausibleTracker = () => {
|
||||||
const plausible = useContext(PlausibleContext);
|
const plausible = useContext(PlausibleContext);
|
||||||
|
@ -4,7 +4,8 @@ export type IFeedbackCategory =
|
|||||||
| 'search'
|
| 'search'
|
||||||
| 'insights'
|
| 'insights'
|
||||||
| 'applicationOverview'
|
| 'applicationOverview'
|
||||||
| 'newProjectOverview';
|
| 'newProjectOverview'
|
||||||
|
| 'signals';
|
||||||
|
|
||||||
export const useUserSubmittedFeedback = (category: IFeedbackCategory) => {
|
export const useUserSubmittedFeedback = (category: IFeedbackCategory) => {
|
||||||
const key = `unleash-userSubmittedFeedback:${category}`;
|
const key = `unleash-userSubmittedFeedback:${category}`;
|
||||||
|
Loading…
Reference in New Issue
Block a user