mirror of
				https://github.com/Unleash/unleash.git
				synced 2025-10-27 11:02:16 +01:00 
			
		
		
		
	feat: merge feature toggle details with feature meta info box (#6977)
 --------- Signed-off-by: andreas-unleash <andreas@getunleash.ai> Co-authored-by: andreas-unleash <andreas@getunleash.ai>
This commit is contained in:
		
							parent
							
								
									2c05f1a0ce
								
							
						
					
					
						commit
						233b882c7b
					
				| @ -1,4 +1,4 @@ | ||||
| import { StyledLink } from './StyledRow'; | ||||
| import { StyledLink } from '../FeatureOverviewSidePanel/FeatureOverviewSidePanelDetails/StyledRow'; | ||||
| import { TooltipLink } from 'component/common/TooltipLink/TooltipLink'; | ||||
| import type { FC } from 'react'; | ||||
| 
 | ||||
| @ -2,7 +2,12 @@ import { ConditionallyRender } from 'component/common/ConditionallyRender/Condit | ||||
| import { AddDependencyDialogue } from 'component/feature/Dependencies/AddDependencyDialogue'; | ||||
| import type { IFeatureToggle } from 'interfaces/featureToggle'; | ||||
| import { type FC, useState } from 'react'; | ||||
| import { FlexRow, StyledDetail, StyledLabel, StyledLink } from './StyledRow'; | ||||
| import { | ||||
|     FlexRow, | ||||
|     StyledDetail, | ||||
|     StyledLabel, | ||||
|     StyledLink, | ||||
| } from '../FeatureOverviewSidePanel/FeatureOverviewSidePanelDetails/StyledRow'; | ||||
| import { DependencyActions } from './DependencyActions'; | ||||
| import { useDependentFeaturesApi } from 'hooks/api/actions/useDependentFeaturesApi/useDependentFeaturesApi'; | ||||
| import { useFeature } from 'hooks/api/getters/useFeature/useFeature'; | ||||
| @ -1,10 +1,11 @@ | ||||
| import { screen } from '@testing-library/react'; | ||||
| import userEvent from '@testing-library/user-event'; | ||||
| import { render } from 'utils/testRenderer'; | ||||
| import { FeatureOverviewSidePanelDetails } from './FeatureOverviewSidePanelDetails'; | ||||
| import type { IDependency, IFeatureToggle } from 'interfaces/featureToggle'; | ||||
| import FeatureOverviewMetaData from './FeatureOverviewMetaData'; | ||||
| import { testServerRoute, testServerSetup } from 'utils/testServer'; | ||||
| import { Route, Routes } from 'react-router-dom'; | ||||
| import type { IDependency, IFeatureToggle } from 'interfaces/featureToggle'; | ||||
| import ToastRenderer from 'component/common/ToastRenderer/ToastRenderer'; | ||||
| import userEvent from '@testing-library/user-event'; | ||||
| 
 | ||||
| const server = testServerSetup(); | ||||
| 
 | ||||
| @ -14,7 +15,6 @@ const setupApi = () => { | ||||
|             current: { oss: 'irrelevant', enterprise: 'some value' }, | ||||
|         }, | ||||
|     }); | ||||
|     testServerRoute(server, '/api/admin/projects/default/features/feature', {}); | ||||
|     testServerRoute( | ||||
|         server, | ||||
|         '/api/admin/projects/default/features/feature/parents', | ||||
| @ -54,36 +54,43 @@ const setupChangeRequestApi = () => { | ||||
|     ); | ||||
|     testServerRoute( | ||||
|         server, | ||||
|         'api/admin/projects/default/change-requests/pending', | ||||
|         '/api/admin/projects/default/change-requests/pending', | ||||
|         [], | ||||
|     ); | ||||
|     testServerRoute( | ||||
|         server, | ||||
|         'api/admin/projects/default/environments/development/change-requests', | ||||
|         '/api/admin/projects/default/environments/development/change-requests', | ||||
|         {}, | ||||
|         'post', | ||||
|         200, | ||||
|     ); | ||||
| }; | ||||
| 
 | ||||
| const setupFeatureApi = (feature: IFeatureToggle) => { | ||||
|     testServerRoute( | ||||
|         server, | ||||
|         '/api/admin/projects/default/features/feature', | ||||
|         feature, | ||||
|     ); | ||||
| }; | ||||
| 
 | ||||
| beforeEach(() => { | ||||
|     setupApi(); | ||||
| }); | ||||
| 
 | ||||
| const route = '/projects/default/features/feature'; | ||||
| 
 | ||||
| test('show dependency dialogue', async () => { | ||||
|     setupFeatureApi(feature); | ||||
|     render( | ||||
|         <FeatureOverviewSidePanelDetails | ||||
|             feature={ | ||||
|                 { | ||||
|                     name: 'feature', | ||||
|                     project: 'default', | ||||
|                     dependencies: [] as Array<{ feature: string }>, | ||||
|                     children: [] as string[], | ||||
|                 } as IFeatureToggle | ||||
|             } | ||||
|             header={''} | ||||
|         />, | ||||
|         <Routes> | ||||
|             <Route | ||||
|                 path={'/projects/:projectId/features/:featureId'} | ||||
|                 element={<FeatureOverviewMetaData />} | ||||
|             /> | ||||
|         </Routes>, | ||||
|         { | ||||
|             route, | ||||
|             permissions: [ | ||||
|                 { permission: 'UPDATE_FEATURE_DEPENDENCY', project: 'default' }, | ||||
|             ], | ||||
| @ -101,19 +108,21 @@ test('show dependency dialogue', async () => { | ||||
| 
 | ||||
| test('show dependency dialogue for OSS with dependencies', async () => { | ||||
|     setupOssWithExistingDependencies(); | ||||
|     setupFeatureApi({ | ||||
|         name: 'feature', | ||||
|         project: 'default', | ||||
|         dependencies: [] as Array<{ feature: string }>, | ||||
|         children: [] as string[], | ||||
|     } as IFeatureToggle); | ||||
|     render( | ||||
|         <FeatureOverviewSidePanelDetails | ||||
|             feature={ | ||||
|                 { | ||||
|                     name: 'feature', | ||||
|                     project: 'default', | ||||
|                     dependencies: [] as Array<{ feature: string }>, | ||||
|                     children: [] as string[], | ||||
|                 } as IFeatureToggle | ||||
|             } | ||||
|             header={''} | ||||
|         />, | ||||
|         <Routes> | ||||
|             <Route | ||||
|                 path={'/projects/:projectId/features/:featureId'} | ||||
|                 element={<FeatureOverviewMetaData />} | ||||
|             /> | ||||
|         </Routes>, | ||||
|         { | ||||
|             route, | ||||
|             permissions: [ | ||||
|                 { permission: 'UPDATE_FEATURE_DEPENDENCY', project: 'default' }, | ||||
|             ], | ||||
| @ -130,18 +139,20 @@ test('show dependency dialogue for OSS with dependencies', async () => { | ||||
| }); | ||||
| 
 | ||||
| test('show child', async () => { | ||||
|     setupFeatureApi({ | ||||
|         name: 'feature', | ||||
|         project: 'default', | ||||
|         dependencies: [] as Array<{ feature: string }>, | ||||
|         children: ['some_child'], | ||||
|     } as IFeatureToggle); | ||||
|     render( | ||||
|         <FeatureOverviewSidePanelDetails | ||||
|             feature={ | ||||
|                 { | ||||
|                     name: 'feature', | ||||
|                     project: 'default', | ||||
|                     dependencies: [] as Array<{ feature: string }>, | ||||
|                     children: ['some_child'], | ||||
|                 } as IFeatureToggle | ||||
|             } | ||||
|             header={''} | ||||
|         />, | ||||
|         <Routes> | ||||
|             <Route | ||||
|                 path={'/projects/:projectId/features/:featureId'} | ||||
|                 element={<FeatureOverviewMetaData />} | ||||
|             /> | ||||
|         </Routes>, | ||||
|         { route }, | ||||
|     ); | ||||
| 
 | ||||
|     await screen.findByText('Children:'); | ||||
| @ -149,18 +160,20 @@ test('show child', async () => { | ||||
| }); | ||||
| 
 | ||||
| test('show children', async () => { | ||||
|     setupFeatureApi({ | ||||
|         name: 'feature', | ||||
|         project: 'default', | ||||
|         dependencies: [] as Array<{ feature: string }>, | ||||
|         children: ['some_child', 'some_other_child'], | ||||
|     } as IFeatureToggle); | ||||
|     render( | ||||
|         <FeatureOverviewSidePanelDetails | ||||
|             feature={ | ||||
|                 { | ||||
|                     name: 'feature', | ||||
|                     project: 'default', | ||||
|                     dependencies: [] as Array<{ feature: string }>, | ||||
|                     children: ['some_child', 'some_other_child'], | ||||
|                 } as IFeatureToggle | ||||
|             } | ||||
|             header={''} | ||||
|         />, | ||||
|         <Routes> | ||||
|             <Route | ||||
|                 path={'/projects/:projectId/features/:featureId'} | ||||
|                 element={<FeatureOverviewMetaData />} | ||||
|             /> | ||||
|         </Routes>, | ||||
|         { route }, | ||||
|     ); | ||||
| 
 | ||||
|     await screen.findByText('Children:'); | ||||
| @ -175,18 +188,22 @@ const feature = { | ||||
| } as IFeatureToggle; | ||||
| 
 | ||||
| test('delete dependency', async () => { | ||||
|     setupFeatureApi({ | ||||
|         ...feature, | ||||
|         dependencies: [{ feature: 'some_parent' }], | ||||
|     }); | ||||
|     render( | ||||
|         <> | ||||
|             <ToastRenderer /> | ||||
|             <FeatureOverviewSidePanelDetails | ||||
|                 feature={{ | ||||
|                     ...feature, | ||||
|                     dependencies: [{ feature: 'some_parent' }], | ||||
|                 }} | ||||
|                 header={''} | ||||
|             /> | ||||
|             <Routes> | ||||
|                 <Route | ||||
|                     path={'/projects/:projectId/features/:featureId'} | ||||
|                     element={<FeatureOverviewMetaData />} | ||||
|                 /> | ||||
|             </Routes> | ||||
|         </>, | ||||
|         { | ||||
|             route, | ||||
|             permissions: [ | ||||
|                 { permission: 'UPDATE_FEATURE_DEPENDENCY', project: 'default' }, | ||||
|             ], | ||||
| @ -209,18 +226,22 @@ test('delete dependency', async () => { | ||||
| 
 | ||||
| test('delete dependency with change request', async () => { | ||||
|     setupChangeRequestApi(); | ||||
|     setupFeatureApi({ | ||||
|         ...feature, | ||||
|         dependencies: [{ feature: 'some_parent' }], | ||||
|     }); | ||||
|     render( | ||||
|         <> | ||||
|             <ToastRenderer /> | ||||
|             <FeatureOverviewSidePanelDetails | ||||
|                 feature={{ | ||||
|                     ...feature, | ||||
|                     dependencies: [{ feature: 'some_parent' }], | ||||
|                 }} | ||||
|                 header={''} | ||||
|             /> | ||||
|             <Routes> | ||||
|                 <Route | ||||
|                     path={'/projects/:projectId/features/:featureId'} | ||||
|                     element={<FeatureOverviewMetaData />} | ||||
|                 /> | ||||
|             </Routes> | ||||
|         </>, | ||||
|         { | ||||
|             route, | ||||
|             permissions: [ | ||||
|                 /* deliberately no permissions */ | ||||
|             ], | ||||
| @ -242,15 +263,19 @@ test('delete dependency with change request', async () => { | ||||
| }); | ||||
| 
 | ||||
| test('edit dependency', async () => { | ||||
|     setupFeatureApi({ | ||||
|         ...feature, | ||||
|         dependencies: [{ feature: 'some_parent', enabled: false }], | ||||
|     }); | ||||
|     render( | ||||
|         <FeatureOverviewSidePanelDetails | ||||
|             feature={{ | ||||
|                 ...feature, | ||||
|                 dependencies: [{ feature: 'some_parent', enabled: false }], | ||||
|             }} | ||||
|             header={''} | ||||
|         />, | ||||
|         <Routes> | ||||
|             <Route | ||||
|                 path={'/projects/:projectId/features/:featureId'} | ||||
|                 element={<FeatureOverviewMetaData />} | ||||
|             /> | ||||
|         </Routes>, | ||||
|         { | ||||
|             route, | ||||
|             permissions: [ | ||||
|                 { permission: 'UPDATE_FEATURE_DEPENDENCY', project: 'default' }, | ||||
|             ], | ||||
| @ -274,20 +299,24 @@ test('edit dependency', async () => { | ||||
| }); | ||||
| 
 | ||||
| test('show variant dependencies', async () => { | ||||
|     setupFeatureApi({ | ||||
|         ...feature, | ||||
|         dependencies: [ | ||||
|             { | ||||
|                 feature: 'some_parent', | ||||
|                 enabled: true, | ||||
|                 variants: ['variantA', 'variantB'], | ||||
|             }, | ||||
|         ], | ||||
|     }); | ||||
|     render( | ||||
|         <FeatureOverviewSidePanelDetails | ||||
|             feature={{ | ||||
|                 ...feature, | ||||
|                 dependencies: [ | ||||
|                     { | ||||
|                         feature: 'some_parent', | ||||
|                         enabled: true, | ||||
|                         variants: ['variantA', 'variantB'], | ||||
|                     }, | ||||
|                 ], | ||||
|             }} | ||||
|             header={''} | ||||
|         />, | ||||
|         <Routes> | ||||
|             <Route | ||||
|                 path={'/projects/:projectId/features/:featureId'} | ||||
|                 element={<FeatureOverviewMetaData />} | ||||
|             /> | ||||
|         </Routes>, | ||||
|         { route }, | ||||
|     ); | ||||
| 
 | ||||
|     const variants = await screen.findByText('2 variants'); | ||||
| @ -299,39 +328,47 @@ test('show variant dependencies', async () => { | ||||
| }); | ||||
| 
 | ||||
| test('show variant dependency', async () => { | ||||
|     setupFeatureApi({ | ||||
|         ...feature, | ||||
|         dependencies: [ | ||||
|             { | ||||
|                 feature: 'some_parent', | ||||
|                 enabled: true, | ||||
|                 variants: ['variantA'], | ||||
|             }, | ||||
|         ], | ||||
|     }); | ||||
|     render( | ||||
|         <FeatureOverviewSidePanelDetails | ||||
|             feature={{ | ||||
|                 ...feature, | ||||
|                 dependencies: [ | ||||
|                     { | ||||
|                         feature: 'some_parent', | ||||
|                         enabled: true, | ||||
|                         variants: ['variantA'], | ||||
|                     }, | ||||
|                 ], | ||||
|             }} | ||||
|             header={''} | ||||
|         />, | ||||
|         <Routes> | ||||
|             <Route | ||||
|                 path={'/projects/:projectId/features/:featureId'} | ||||
|                 element={<FeatureOverviewMetaData />} | ||||
|             /> | ||||
|         </Routes>, | ||||
|         { route }, | ||||
|     ); | ||||
| 
 | ||||
|     await screen.findByText('variantA'); | ||||
| }); | ||||
| 
 | ||||
| test('show disabled dependency', async () => { | ||||
|     setupFeatureApi({ | ||||
|         ...feature, | ||||
|         dependencies: [ | ||||
|             { | ||||
|                 feature: 'some_parent', | ||||
|                 enabled: false, | ||||
|             }, | ||||
|         ], | ||||
|     }); | ||||
|     render( | ||||
|         <FeatureOverviewSidePanelDetails | ||||
|             feature={{ | ||||
|                 ...feature, | ||||
|                 dependencies: [ | ||||
|                     { | ||||
|                         feature: 'some_parent', | ||||
|                         enabled: false, | ||||
|                     }, | ||||
|                 ], | ||||
|             }} | ||||
|             header={''} | ||||
|         />, | ||||
|         <Routes> | ||||
|             <Route | ||||
|                 path={'/projects/:projectId/features/:featureId'} | ||||
|                 element={<FeatureOverviewMetaData />} | ||||
|             /> | ||||
|         </Routes>, | ||||
|         { route }, | ||||
|     ); | ||||
| 
 | ||||
|     await screen.findByText('disabled'); | ||||
| @ -15,6 +15,14 @@ import { useState } from 'react'; | ||||
| import { FeatureArchiveNotAllowedDialog } from 'component/common/FeatureArchiveDialog/FeatureArchiveNotAllowedDialog'; | ||||
| import { populateCurrentStage } from '../FeatureLifecycle/populateCurrentStage'; | ||||
| import useFeatureLifecycleApi from 'hooks/api/actions/useFeatureLifecycleApi/useFeatureLifecycleApi'; | ||||
| import { StyledDetail } from '../FeatureOverviewSidePanel/FeatureOverviewSidePanelDetails/StyledRow'; | ||||
| import { formatDateYMD } from 'utils/formatDate'; | ||||
| import { parseISO } from 'date-fns'; | ||||
| import { FeatureEnvironmentSeen } from '../../FeatureEnvironmentSeen/FeatureEnvironmentSeen'; | ||||
| import { DependencyRow } from './DependencyRow'; | ||||
| import { useLocationSettings } from 'hooks/useLocationSettings'; | ||||
| import { useShowDependentFeatures } from './useShowDependentFeatures'; | ||||
| import type { ILastSeenEnvironments } from 'interfaces/featureToggle'; | ||||
| 
 | ||||
| const StyledContainer = styled('div')(({ theme }) => ({ | ||||
|     borderRadius: theme.shape.borderRadiusLarge, | ||||
| @ -68,6 +76,12 @@ const StyledDescriptionContainer = styled('div')(({ theme }) => ({ | ||||
|     alignItems: 'center', | ||||
| })); | ||||
| 
 | ||||
| const StyledDetailsContainer = styled('div')(({ theme }) => ({ | ||||
|     display: 'flex', | ||||
|     alignItems: 'center', | ||||
|     justifyContent: 'space-between', | ||||
| })); | ||||
| 
 | ||||
| const StyledDescription = styled('p')({ | ||||
|     wordBreak: 'break-word', | ||||
| }); | ||||
| @ -87,6 +101,15 @@ const FeatureOverviewMetaData = () => { | ||||
|         useFeatureLifecycleApi(); | ||||
|     const navigate = useNavigate(); | ||||
|     const [showDelDialog, setShowDelDialog] = useState(false); | ||||
|     const { locationSettings } = useLocationSettings(); | ||||
|     const showDependentFeatures = useShowDependentFeatures(feature.project); | ||||
| 
 | ||||
|     const lastSeenEnvironments: ILastSeenEnvironments[] = | ||||
|         feature.environments?.map((env) => ({ | ||||
|             name: env.name, | ||||
|             lastSeenAt: env.lastSeenAt, | ||||
|             enabled: env.enabled, | ||||
|         })); | ||||
| 
 | ||||
|     const IconComponent = getFeatureTypeIcons(type); | ||||
| 
 | ||||
| @ -189,6 +212,29 @@ const FeatureOverviewMetaData = () => { | ||||
|                             </span> | ||||
|                         } | ||||
|                     /> | ||||
|                     <StyledBodyItem> | ||||
|                         <StyledDetailsContainer> | ||||
|                             <StyledDetail> | ||||
|                                 <StyledLabel>Created at:</StyledLabel> | ||||
|                                 <span> | ||||
|                                     {formatDateYMD( | ||||
|                                         parseISO(feature.createdAt), | ||||
|                                         locationSettings.locale, | ||||
|                                     )} | ||||
|                                 </span> | ||||
|                             </StyledDetail> | ||||
| 
 | ||||
|                             <FeatureEnvironmentSeen | ||||
|                                 featureLastSeen={feature.lastSeenAt} | ||||
|                                 environments={lastSeenEnvironments} | ||||
|                                 sx={{ p: 0 }} | ||||
|                             /> | ||||
|                         </StyledDetailsContainer> | ||||
|                     </StyledBodyItem> | ||||
|                     <ConditionallyRender | ||||
|                         condition={showDependentFeatures} | ||||
|                         show={<DependencyRow feature={feature} />} | ||||
|                     /> | ||||
|                 </StyledBody> | ||||
|             </StyledPaddingContainerTop> | ||||
|             <ConditionallyRender | ||||
|  | ||||
| @ -2,7 +2,6 @@ import { Box, Divider, styled } from '@mui/material'; | ||||
| import { HelpIcon } from 'component/common/HelpIcon/HelpIcon'; | ||||
| import { useFeature } from 'hooks/api/getters/useFeature/useFeature'; | ||||
| import { useRequiredPathParam } from 'hooks/useRequiredPathParam'; | ||||
| import { FeatureOverviewSidePanelDetails } from './FeatureOverviewSidePanelDetails/FeatureOverviewSidePanelDetails'; | ||||
| import { FeatureOverviewSidePanelEnvironmentSwitches } from './FeatureOverviewSidePanelEnvironmentSwitches/FeatureOverviewSidePanelEnvironmentSwitches'; | ||||
| import { FeatureOverviewSidePanelTags } from './FeatureOverviewSidePanelTags/FeatureOverviewSidePanelTags'; | ||||
| import { Sticky } from 'component/common/Sticky/Sticky'; | ||||
| @ -77,15 +76,6 @@ export const FeatureOverviewSidePanel = ({ | ||||
|                 setHiddenEnvironments={setHiddenEnvironments} | ||||
|             /> | ||||
|             <Divider /> | ||||
|             <FeatureOverviewSidePanelDetails | ||||
|                 header={ | ||||
|                     <StyledHeader data-loading> | ||||
|                         Feature toggle details | ||||
|                     </StyledHeader> | ||||
|                 } | ||||
|                 feature={feature} | ||||
|             /> | ||||
|             <Divider /> | ||||
|             <FeatureOverviewSidePanelTags | ||||
|                 header={ | ||||
|                     <StyledHeader data-loading> | ||||
|  | ||||
| @ -1,67 +0,0 @@ | ||||
| import type { | ||||
|     IFeatureToggle, | ||||
|     ILastSeenEnvironments, | ||||
| } from 'interfaces/featureToggle'; | ||||
| import { styled } from '@mui/material'; | ||||
| import { useLocationSettings } from 'hooks/useLocationSettings'; | ||||
| import { formatDateYMD } from 'utils/formatDate'; | ||||
| import { parseISO } from 'date-fns'; | ||||
| import { FeatureEnvironmentSeen } from '../../../FeatureEnvironmentSeen/FeatureEnvironmentSeen'; | ||||
| import { DependencyRow } from './DependencyRow'; | ||||
| import { FlexRow, StyledDetail, StyledLabel } from './StyledRow'; | ||||
| import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender'; | ||||
| import { useShowDependentFeatures } from './useShowDependentFeatures'; | ||||
| 
 | ||||
| const StyledContainer = styled('div')(({ theme }) => ({ | ||||
|     display: 'flex', | ||||
|     flexDirection: 'column', | ||||
|     justifyItems: 'center', | ||||
|     padding: theme.spacing(3), | ||||
|     fontSize: theme.fontSizes.smallBody, | ||||
| })); | ||||
| 
 | ||||
| interface IFeatureOverviewSidePanelDetailsProps { | ||||
|     feature: IFeatureToggle; | ||||
|     header: React.ReactNode; | ||||
| } | ||||
| export const FeatureOverviewSidePanelDetails = ({ | ||||
|     feature, | ||||
|     header, | ||||
| }: IFeatureOverviewSidePanelDetailsProps) => { | ||||
|     const { locationSettings } = useLocationSettings(); | ||||
|     const showDependentFeatures = useShowDependentFeatures(feature.project); | ||||
| 
 | ||||
|     const lastSeenEnvironments: ILastSeenEnvironments[] = | ||||
|         feature.environments?.map((env) => ({ | ||||
|             name: env.name, | ||||
|             lastSeenAt: env.lastSeenAt, | ||||
|             enabled: env.enabled, | ||||
|         })); | ||||
| 
 | ||||
|     return ( | ||||
|         <StyledContainer> | ||||
|             {header} | ||||
|             <FlexRow> | ||||
|                 <StyledDetail> | ||||
|                     <StyledLabel>Created at:</StyledLabel> | ||||
|                     <span> | ||||
|                         {formatDateYMD( | ||||
|                             parseISO(feature.createdAt), | ||||
|                             locationSettings.locale, | ||||
|                         )} | ||||
|                     </span> | ||||
|                 </StyledDetail> | ||||
| 
 | ||||
|                 <FeatureEnvironmentSeen | ||||
|                     featureLastSeen={feature.lastSeenAt} | ||||
|                     environments={lastSeenEnvironments} | ||||
|                     sx={{ p: 0 }} | ||||
|                 /> | ||||
|             </FlexRow> | ||||
|             <ConditionallyRender | ||||
|                 condition={showDependentFeatures} | ||||
|                 show={<DependencyRow feature={feature} />} | ||||
|             /> | ||||
|         </StyledContainer> | ||||
|     ); | ||||
| }; | ||||
| @ -45,7 +45,7 @@ import { useFavoriteFeaturesApi } from 'hooks/api/actions/useFavoriteFeaturesApi | ||||
| import { FavoriteIconButton } from 'component/common/FavoriteIconButton/FavoriteIconButton'; | ||||
| import { ReactComponent as ChildLinkIcon } from 'assets/icons/link-child.svg'; | ||||
| import { ReactComponent as ParentLinkIcon } from 'assets/icons/link-parent.svg'; | ||||
| import { ChildrenTooltip } from './FeatureOverview/FeatureOverviewSidePanel/FeatureOverviewSidePanelDetails/ChildrenTooltip'; | ||||
| import { ChildrenTooltip } from './FeatureOverview/FeatureOverviewMetaData/ChildrenTooltip'; | ||||
| import copy from 'copy-to-clipboard'; | ||||
| import useToast from 'hooks/useToast'; | ||||
| 
 | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user