mirror of
				https://github.com/Unleash/unleash.git
				synced 2025-10-27 11:02:16 +01:00 
			
		
		
		
	feat: get suggested changeset draft (#2274)
* feat: get suggested changeset draft * fix: update routes snapshot
This commit is contained in:
		
							parent
							
								
									c6c873d67d
								
							
						
					
					
						commit
						b7183fdf98
					
				| @ -30,12 +30,16 @@ import StatusChip from 'component/common/StatusChip/StatusChip'; | ||||
| import { FeatureNotFound } from 'component/feature/FeatureView/FeatureNotFound/FeatureNotFound'; | ||||
| import { useRequiredPathParam } from 'hooks/useRequiredPathParam'; | ||||
| import { FeatureArchiveDialog } from '../../common/FeatureArchiveDialog/FeatureArchiveDialog'; | ||||
| import { DraftBanner } from 'component/suggestChanges/DraftBanner/DraftBanner'; | ||||
| import { MainLayout } from 'component/layout/MainLayout/MainLayout'; | ||||
| import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig'; | ||||
| 
 | ||||
| export const FeatureView = () => { | ||||
|     const projectId = useRequiredPathParam('projectId'); | ||||
|     const featureId = useRequiredPathParam('featureId'); | ||||
|     const { refetch: projectRefetch } = useProject(projectId); | ||||
|     const { refetchFeature } = useFeature(projectId, featureId); | ||||
|     const { uiConfig } = useUiConfig(); | ||||
| 
 | ||||
|     const [openTagDialog, setOpenTagDialog] = useState(false); | ||||
|     const [showDelDialog, setShowDelDialog] = useState(false); | ||||
| @ -81,123 +85,145 @@ export const FeatureView = () => { | ||||
|     } | ||||
| 
 | ||||
|     return ( | ||||
|         <ConditionallyRender | ||||
|             condition={error === undefined} | ||||
|             show={ | ||||
|                 <div ref={ref}> | ||||
|                     <div className={styles.header}> | ||||
|                         <div className={styles.innerContainer}> | ||||
|                             <div className={styles.toggleInfoContainer}> | ||||
|                                 <h1 | ||||
|                                     className={styles.featureViewHeader} | ||||
|                                     data-loading | ||||
|                                 > | ||||
|                                     {feature.name}{' '} | ||||
|                                 </h1> | ||||
|                                 <ConditionallyRender | ||||
|                                     condition={!smallScreen} | ||||
|                                     show={<StatusChip stale={feature?.stale} />} | ||||
|                                 /> | ||||
|                             </div> | ||||
| 
 | ||||
|                             <div className={styles.toolbarContainer}> | ||||
|                                 <PermissionIconButton | ||||
|                                     permission={CREATE_FEATURE} | ||||
|                                     projectId={projectId} | ||||
|                                     data-loading | ||||
|                                     component={Link} | ||||
|                                     to={`/projects/${projectId}/features/${featureId}/strategies/copy`} | ||||
|                                     tooltipProps={{ | ||||
|                                         title: 'Copy feature toggle', | ||||
|                                     }} | ||||
|                                 > | ||||
|                                     <FileCopy /> | ||||
|                                 </PermissionIconButton> | ||||
|                                 <PermissionIconButton | ||||
|                                     permission={DELETE_FEATURE} | ||||
|                                     projectId={projectId} | ||||
|                                     tooltipProps={{ | ||||
|                                         title: 'Archive feature toggle', | ||||
|                                     }} | ||||
|                                     data-loading | ||||
|                                     onClick={() => setShowDelDialog(true)} | ||||
|                                 > | ||||
|                                     <Archive /> | ||||
|                                 </PermissionIconButton> | ||||
|                                 <PermissionIconButton | ||||
|                                     onClick={() => setOpenStaleDialog(true)} | ||||
|                                     permission={UPDATE_FEATURE} | ||||
|                                     projectId={projectId} | ||||
|                                     tooltipProps={{ | ||||
|                                         title: 'Toggle stale state', | ||||
|                                     }} | ||||
|                                     data-loading | ||||
|                                 > | ||||
|                                     <WatchLater /> | ||||
|                                 </PermissionIconButton> | ||||
|                                 <PermissionIconButton | ||||
|                                     onClick={() => setOpenTagDialog(true)} | ||||
|                                     permission={UPDATE_FEATURE} | ||||
|                                     projectId={projectId} | ||||
|                                     tooltipProps={{ title: 'Add tag' }} | ||||
|                                     data-loading | ||||
|                                 > | ||||
|                                     <Label /> | ||||
|                                 </PermissionIconButton> | ||||
|                             </div> | ||||
|                         </div> | ||||
|                         <div className={styles.separator} /> | ||||
|                         <div className={styles.tabContainer}> | ||||
|                             <Tabs | ||||
|                                 value={activeTab.path} | ||||
|                                 indicatorColor="primary" | ||||
|                                 textColor="primary" | ||||
|                             > | ||||
|                                 {tabData.map(tab => ( | ||||
|                                     <Tab | ||||
|                                         key={tab.title} | ||||
|                                         label={tab.title} | ||||
|                                         value={tab.path} | ||||
|                                         onClick={() => navigate(tab.path)} | ||||
|                                         className={styles.tabButton} | ||||
|                                     /> | ||||
|                                 ))} | ||||
|                             </Tabs> | ||||
|                         </div> | ||||
|                     </div> | ||||
|                     <Routes> | ||||
|                         <Route path="metrics" element={<FeatureMetrics />} /> | ||||
|                         <Route path="logs" element={<FeatureLog />} /> | ||||
|                         <Route path="variants" element={<FeatureVariants />} /> | ||||
|                         <Route path="settings" element={<FeatureSettings />} /> | ||||
|                         <Route path="*" element={<FeatureOverview />} /> | ||||
|                     </Routes> | ||||
|                     <FeatureArchiveDialog | ||||
|                         isOpen={showDelDialog} | ||||
|                         onConfirm={() => { | ||||
|                             projectRefetch(); | ||||
|                             navigate(`/projects/${projectId}`); | ||||
|                         }} | ||||
|                         onClose={() => setShowDelDialog(false)} | ||||
|                         projectId={projectId} | ||||
|                         featureId={featureId} | ||||
|                     /> | ||||
|                     <FeatureStaleDialog | ||||
|                         isStale={feature.stale} | ||||
|                         isOpen={openStaleDialog} | ||||
|                         onClose={() => { | ||||
|                             setOpenStaleDialog(false); | ||||
|                             refetchFeature(); | ||||
|                         }} | ||||
|                         featureId={featureId} | ||||
|                         projectId={projectId} | ||||
|                     /> | ||||
|                     <AddTagDialog | ||||
|                         open={openTagDialog} | ||||
|                         setOpen={setOpenTagDialog} | ||||
|                     /> | ||||
|                 </div> | ||||
|         <MainLayout | ||||
|             ref={ref} | ||||
|             subheader={ | ||||
|                 uiConfig?.flags?.suggestChanges ? ( | ||||
|                     <DraftBanner project={projectId} /> | ||||
|                 ) : null | ||||
|             } | ||||
|         /> | ||||
|         > | ||||
|             <ConditionallyRender | ||||
|                 condition={error === undefined} | ||||
|                 show={ | ||||
|                     <div ref={ref}> | ||||
|                         <div className={styles.header}> | ||||
|                             <div className={styles.innerContainer}> | ||||
|                                 <div className={styles.toggleInfoContainer}> | ||||
|                                     <h1 | ||||
|                                         className={styles.featureViewHeader} | ||||
|                                         data-loading | ||||
|                                     > | ||||
|                                         {feature.name}{' '} | ||||
|                                     </h1> | ||||
|                                     <ConditionallyRender | ||||
|                                         condition={!smallScreen} | ||||
|                                         show={ | ||||
|                                             <StatusChip | ||||
|                                                 stale={feature?.stale} | ||||
|                                             /> | ||||
|                                         } | ||||
|                                     /> | ||||
|                                 </div> | ||||
| 
 | ||||
|                                 <div className={styles.toolbarContainer}> | ||||
|                                     <PermissionIconButton | ||||
|                                         permission={CREATE_FEATURE} | ||||
|                                         projectId={projectId} | ||||
|                                         data-loading | ||||
|                                         component={Link} | ||||
|                                         to={`/projects/${projectId}/features/${featureId}/strategies/copy`} | ||||
|                                         tooltipProps={{ | ||||
|                                             title: 'Copy feature toggle', | ||||
|                                         }} | ||||
|                                     > | ||||
|                                         <FileCopy /> | ||||
|                                     </PermissionIconButton> | ||||
|                                     <PermissionIconButton | ||||
|                                         permission={DELETE_FEATURE} | ||||
|                                         projectId={projectId} | ||||
|                                         tooltipProps={{ | ||||
|                                             title: 'Archive feature toggle', | ||||
|                                         }} | ||||
|                                         data-loading | ||||
|                                         onClick={() => setShowDelDialog(true)} | ||||
|                                     > | ||||
|                                         <Archive /> | ||||
|                                     </PermissionIconButton> | ||||
|                                     <PermissionIconButton | ||||
|                                         onClick={() => setOpenStaleDialog(true)} | ||||
|                                         permission={UPDATE_FEATURE} | ||||
|                                         projectId={projectId} | ||||
|                                         tooltipProps={{ | ||||
|                                             title: 'Toggle stale state', | ||||
|                                         }} | ||||
|                                         data-loading | ||||
|                                     > | ||||
|                                         <WatchLater /> | ||||
|                                     </PermissionIconButton> | ||||
|                                     <PermissionIconButton | ||||
|                                         onClick={() => setOpenTagDialog(true)} | ||||
|                                         permission={UPDATE_FEATURE} | ||||
|                                         projectId={projectId} | ||||
|                                         tooltipProps={{ title: 'Add tag' }} | ||||
|                                         data-loading | ||||
|                                     > | ||||
|                                         <Label /> | ||||
|                                     </PermissionIconButton> | ||||
|                                 </div> | ||||
|                             </div> | ||||
|                             <div className={styles.separator} /> | ||||
|                             <div className={styles.tabContainer}> | ||||
|                                 <Tabs | ||||
|                                     value={activeTab.path} | ||||
|                                     indicatorColor="primary" | ||||
|                                     textColor="primary" | ||||
|                                 > | ||||
|                                     {tabData.map(tab => ( | ||||
|                                         <Tab | ||||
|                                             key={tab.title} | ||||
|                                             label={tab.title} | ||||
|                                             value={tab.path} | ||||
|                                             onClick={() => navigate(tab.path)} | ||||
|                                             className={styles.tabButton} | ||||
|                                         /> | ||||
|                                     ))} | ||||
|                                 </Tabs> | ||||
|                             </div> | ||||
|                         </div> | ||||
|                         <Routes> | ||||
|                             <Route | ||||
|                                 path="metrics" | ||||
|                                 element={<FeatureMetrics />} | ||||
|                             /> | ||||
|                             <Route path="logs" element={<FeatureLog />} /> | ||||
|                             <Route | ||||
|                                 path="variants" | ||||
|                                 element={<FeatureVariants />} | ||||
|                             /> | ||||
|                             <Route | ||||
|                                 path="settings" | ||||
|                                 element={<FeatureSettings />} | ||||
|                             /> | ||||
|                             <Route path="*" element={<FeatureOverview />} /> | ||||
|                         </Routes> | ||||
|                         <FeatureArchiveDialog | ||||
|                             isOpen={showDelDialog} | ||||
|                             onConfirm={() => { | ||||
|                                 projectRefetch(); | ||||
|                                 navigate(`/projects/${projectId}`); | ||||
|                             }} | ||||
|                             onClose={() => setShowDelDialog(false)} | ||||
|                             projectId={projectId} | ||||
|                             featureId={featureId} | ||||
|                         /> | ||||
|                         <FeatureStaleDialog | ||||
|                             isStale={feature.stale} | ||||
|                             isOpen={openStaleDialog} | ||||
|                             onClose={() => { | ||||
|                                 setOpenStaleDialog(false); | ||||
|                                 refetchFeature(); | ||||
|                             }} | ||||
|                             featureId={featureId} | ||||
|                             projectId={projectId} | ||||
|                         /> | ||||
|                         <AddTagDialog | ||||
|                             open={openTagDialog} | ||||
|                             setOpen={setOpenTagDialog} | ||||
|                         /> | ||||
|                     </div> | ||||
|                 } | ||||
|             /> | ||||
|         </MainLayout> | ||||
|     ); | ||||
| }; | ||||
|  | ||||
| @ -54,6 +54,7 @@ exports[`returns all baseRoutes 1`] = ` | ||||
|   }, | ||||
|   { | ||||
|     "component": [Function], | ||||
|     "isStandalone": true, | ||||
|     "menu": {}, | ||||
|     "parent": "/projects", | ||||
|     "path": "/projects/:projectId/features/:featureId/*", | ||||
|  | ||||
| @ -121,6 +121,7 @@ export const routes: IRoute[] = [ | ||||
|         title: 'FeatureView', | ||||
|         component: FeatureView, | ||||
|         type: 'protected', | ||||
|         isStandalone: true, | ||||
|         menu: {}, | ||||
|     }, | ||||
|     { | ||||
|  | ||||
| @ -117,7 +117,11 @@ const Project = () => { | ||||
|     return ( | ||||
|         <MainLayout | ||||
|             ref={ref} | ||||
|             subheader={uiConfig?.flags?.suggestChanges ? <DraftBanner /> : null} | ||||
|             subheader={ | ||||
|                 uiConfig?.flags?.suggestChanges ? ( | ||||
|                     <DraftBanner project={projectId} /> | ||||
|                 ) : null | ||||
|             } | ||||
|         > | ||||
|             <div className={styles.header}> | ||||
|                 <div className={styles.innerContainer}> | ||||
|  | ||||
| @ -4,14 +4,21 @@ import { useStyles as useAppStyles } from 'component/App.styles'; | ||||
| import WarningAmberIcon from '@mui/icons-material/WarningAmber'; | ||||
| import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender'; | ||||
| import { SuggestedChangesSidebar } from '../SuggestedChangesSidebar/SuggestedChangesSidebar'; | ||||
| import { useSuggestedChangesDraft } from 'hooks/api/getters/useSuggestedChangesDraft/useSuggestedChangesDraft'; | ||||
| 
 | ||||
| interface IDraftBannerProps { | ||||
|     environment?: string; | ||||
|     project: string; | ||||
| } | ||||
| 
 | ||||
| export const DraftBanner: VFC<IDraftBannerProps> = ({ environment }) => { | ||||
| export const DraftBanner: VFC<IDraftBannerProps> = ({ project }) => { | ||||
|     const { classes } = useAppStyles(); | ||||
|     const [isSidebarOpen, setIsSidebarOpen] = useState(false); | ||||
|     const { draft, loading } = useSuggestedChangesDraft(project); | ||||
|     const environment = ''; | ||||
| 
 | ||||
|     if (!loading && !draft) { | ||||
|         return null; | ||||
|     } | ||||
| 
 | ||||
|     return ( | ||||
|         <Box | ||||
| @ -63,6 +70,7 @@ export const DraftBanner: VFC<IDraftBannerProps> = ({ environment }) => { | ||||
|                 </Box> | ||||
|             </Box> | ||||
|             <SuggestedChangesSidebar | ||||
|                 project={project} | ||||
|                 open={isSidebarOpen} | ||||
|                 onClose={() => { | ||||
|                     setIsSidebarOpen(false); | ||||
|  | ||||
| @ -1,14 +1,16 @@ | ||||
| import React, { useState, VFC } from 'react'; | ||||
| import { VFC } from 'react'; | ||||
| import { Box, Button, Typography, styled, Tooltip } from '@mui/material'; | ||||
| import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender'; | ||||
| import { SidebarModal } from 'component/common/SidebarModal/SidebarModal'; | ||||
| import { PageContent } from 'component/common/PageContent/PageContent'; | ||||
| import { PageHeader } from 'component/common/PageHeader/PageHeader'; | ||||
| import { HelpOutline } from '@mui/icons-material'; | ||||
| import { useSuggestedChange } from 'hooks/api/getters/useSuggestChange/useSuggestedChange'; | ||||
| import { SuggestedChangeset } from '../SuggestedChangeset/SuggestedChangeset'; | ||||
| import { useSuggestedChangesDraft } from 'hooks/api/getters/useSuggestedChangesDraft/useSuggestedChangesDraft'; | ||||
| 
 | ||||
| interface ISuggestedChangesSidebarProps { | ||||
|     open: boolean; | ||||
|     project: string; | ||||
|     onClose: () => void; | ||||
| } | ||||
| const StyledPageContent = styled(PageContent)(({ theme }) => ({ | ||||
| @ -26,11 +28,13 @@ const StyledPageContent = styled(PageContent)(({ theme }) => ({ | ||||
|     }, | ||||
|     borderRadius: `${theme.spacing(1.5, 0, 0, 1.5)} !important`, | ||||
| })); | ||||
| 
 | ||||
| const StyledHelpOutline = styled(HelpOutline)(({ theme }) => ({ | ||||
|     fontSize: theme.fontSizes.mainHeader, | ||||
|     marginLeft: '0.3rem', | ||||
|     color: theme.palette.grey[700], | ||||
| })); | ||||
| 
 | ||||
| const StyledHeaderHint = styled('div')(({ theme }) => ({ | ||||
|     color: theme.palette.text.secondary, | ||||
|     fontSize: theme.fontSizes.smallBody, | ||||
| @ -38,23 +42,43 @@ const StyledHeaderHint = styled('div')(({ theme }) => ({ | ||||
| 
 | ||||
| export const SuggestedChangesSidebar: VFC<ISuggestedChangesSidebarProps> = ({ | ||||
|     open, | ||||
|     project, | ||||
|     onClose, | ||||
| }) => { | ||||
|     const { data: suggestedChange } = useSuggestedChange(); | ||||
|     const { draft, loading } = useSuggestedChangesDraft(project); | ||||
| 
 | ||||
|     const onReview = async () => { | ||||
|         console.log('approve'); | ||||
|         alert('approve'); | ||||
|     }; | ||||
|     const onDiscard = async () => { | ||||
|         console.log('discard'); | ||||
|         alert('discard'); | ||||
|     }; | ||||
|     const onApply = async () => { | ||||
|         try { | ||||
|             console.log('apply'); | ||||
|             alert('apply'); | ||||
|         } catch (e) { | ||||
|             console.log(e); | ||||
|         } | ||||
|     }; | ||||
| 
 | ||||
|     if (!loading && !draft) { | ||||
|         return ( | ||||
|             <SidebarModal open={open} onClose={onClose} label="Review changes"> | ||||
|                 <StyledPageContent | ||||
|                     header={ | ||||
|                         <PageHeader | ||||
|                             secondary | ||||
|                             titleElement="Review your changes" | ||||
|                         ></PageHeader> | ||||
|                     } | ||||
|                 > | ||||
|                     There are no changes to review. | ||||
|                     {/* FIXME: empty state */} | ||||
|                 </StyledPageContent> | ||||
|             </SidebarModal> | ||||
|         ); | ||||
|     } | ||||
| 
 | ||||
|     return ( | ||||
|         <SidebarModal open={open} onClose={onClose} label="Review changes"> | ||||
|             <StyledPageContent | ||||
| @ -80,55 +104,82 @@ export const SuggestedChangesSidebar: VFC<ISuggestedChangesSidebarProps> = ({ | ||||
|                     ></PageHeader> | ||||
|                 } | ||||
|             > | ||||
|                 {/* TODO: multiple environments (changesets) */} | ||||
|                 <Typography>{suggestedChange?.state}</Typography> | ||||
|                 <br /> | ||||
|                 <SuggestedChangeset suggestedChange={suggestedChange} /> | ||||
|                 <Box sx={{ display: 'flex' }}> | ||||
|                     <ConditionallyRender | ||||
|                         condition={suggestedChange?.state === 'APPROVED'} | ||||
|                         show={<Typography>Applied</Typography>} | ||||
|                     /> | ||||
|                     <ConditionallyRender | ||||
|                         condition={suggestedChange?.state === 'CLOSED'} | ||||
|                         show={<Typography>Applied</Typography>} | ||||
|                     /> | ||||
|                     <ConditionallyRender | ||||
|                         condition={suggestedChange?.state === 'APPROVED'} | ||||
|                         show={ | ||||
|                             <> | ||||
|                                 <Button | ||||
|                                     sx={{ mt: 2 }} | ||||
|                                     variant="contained" | ||||
|                                     onClick={onApply} | ||||
|                                 > | ||||
|                                     Apply changes | ||||
|                                 </Button> | ||||
|                             </> | ||||
|                         } | ||||
|                     /> | ||||
|                     <ConditionallyRender | ||||
|                         condition={suggestedChange?.state === 'CREATED'} | ||||
|                         show={ | ||||
|                             <> | ||||
|                                 <Button | ||||
|                                     sx={{ mt: 2, ml: 'auto' }} | ||||
|                                     variant="contained" | ||||
|                                     onClick={onReview} | ||||
|                                 > | ||||
|                                     Request changes | ||||
|                                 </Button> | ||||
|                                 <Button | ||||
|                                     sx={{ mt: 2, ml: 2 }} | ||||
|                                     variant="outlined" | ||||
|                                     onClick={onDiscard} | ||||
|                                 > | ||||
|                                     Discard changes | ||||
|                                 </Button> | ||||
|                             </> | ||||
|                         } | ||||
|                     /> | ||||
|                 </Box> | ||||
|                 {draft?.map(environmentChangeset => ( | ||||
|                     <Box | ||||
|                         key={environmentChangeset.id} | ||||
|                         sx={{ | ||||
|                             padding: 2, | ||||
|                             border: '2px solid', | ||||
|                             borderColor: theme => theme.palette.neutral.light, | ||||
|                             borderRadius: theme => | ||||
|                                 `${theme.shape.borderRadiusLarge}px`, | ||||
|                         }} | ||||
|                     > | ||||
|                         <Typography> | ||||
|                             env: {environmentChangeset?.environment} | ||||
|                         </Typography> | ||||
|                         <Typography> | ||||
|                             state: {environmentChangeset?.state} | ||||
|                         </Typography> | ||||
|                         <hr /> | ||||
|                         <SuggestedChangeset | ||||
|                             suggestedChange={environmentChangeset} | ||||
|                         /> | ||||
|                         <Box sx={{ display: 'flex' }}> | ||||
|                             <ConditionallyRender | ||||
|                                 condition={ | ||||
|                                     environmentChangeset?.state === 'APPROVED' | ||||
|                                 } | ||||
|                                 show={<Typography>Applied</Typography>} | ||||
|                             /> | ||||
|                             <ConditionallyRender | ||||
|                                 condition={ | ||||
|                                     environmentChangeset?.state === 'CLOSED' | ||||
|                                 } | ||||
|                                 show={<Typography>Applied</Typography>} | ||||
|                             /> | ||||
|                             <ConditionallyRender | ||||
|                                 condition={ | ||||
|                                     environmentChangeset?.state === 'APPROVED' | ||||
|                                 } | ||||
|                                 show={ | ||||
|                                     <> | ||||
|                                         <Button | ||||
|                                             sx={{ mt: 2 }} | ||||
|                                             variant="contained" | ||||
|                                             onClick={onApply} | ||||
|                                         > | ||||
|                                             Apply changes | ||||
|                                         </Button> | ||||
|                                     </> | ||||
|                                 } | ||||
|                             /> | ||||
|                             <ConditionallyRender | ||||
|                                 condition={ | ||||
|                                     environmentChangeset?.state === 'Draft' | ||||
|                                 } | ||||
|                                 show={ | ||||
|                                     <> | ||||
|                                         <Button | ||||
|                                             sx={{ mt: 2, ml: 'auto' }} | ||||
|                                             variant="contained" | ||||
|                                             onClick={onReview} | ||||
|                                         > | ||||
|                                             Request changes | ||||
|                                         </Button> | ||||
|                                         <Button | ||||
|                                             sx={{ mt: 2, ml: 2 }} | ||||
|                                             variant="outlined" | ||||
|                                             onClick={onDiscard} | ||||
|                                         > | ||||
|                                             Discard changes | ||||
|                                         </Button> | ||||
|                                     </> | ||||
|                                 } | ||||
|                             /> | ||||
|                         </Box> | ||||
|                     </Box> | ||||
|                 ))} | ||||
|             </StyledPageContent> | ||||
|         </SidebarModal> | ||||
|     ); | ||||
|  | ||||
| @ -4,38 +4,39 @@ import { SuggestedFeatureToggleChange } from '../SuggestedChangeOverview/Suggest | ||||
| import { objectId } from 'utils/objectId'; | ||||
| import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender'; | ||||
| import { ToggleStatusChange } from '../SuggestedChangeOverview/SuggestedFeatureToggleChange/ToggleStatusChange'; | ||||
| import { | ||||
|     StrategyAddedChange, | ||||
|     StrategyDeletedChange, | ||||
|     StrategyEditedChange, | ||||
| } from '../SuggestedChangeOverview/SuggestedFeatureToggleChange/StrategyChange'; | ||||
| import { | ||||
|     formatStrategyName, | ||||
|     GetFeatureStrategyIcon, | ||||
| } from 'utils/strategyNames'; | ||||
| // import {
 | ||||
| //     StrategyAddedChange,
 | ||||
| //     StrategyDeletedChange,
 | ||||
| //     StrategyEditedChange,
 | ||||
| // } from '../SuggestedChangeOverview/SuggestedFeatureToggleChange/StrategyChange';
 | ||||
| // import {
 | ||||
| //     formatStrategyName,
 | ||||
| //     GetFeatureStrategyIcon,
 | ||||
| // } from 'utils/strategyNames';
 | ||||
| import type { ISuggestChangesResponse } from 'hooks/api/getters/useSuggestedChangesDraft/useSuggestedChangesDraft'; | ||||
| 
 | ||||
| export const SuggestedChangeset: FC<{ suggestedChange: any }> = ({ | ||||
|     suggestedChange, | ||||
| }) => { | ||||
| export const SuggestedChangeset: FC<{ | ||||
|     suggestedChange: ISuggestChangesResponse; | ||||
| }> = ({ suggestedChange }) => { | ||||
|     return ( | ||||
|         <Box> | ||||
|             Changes | ||||
|             {suggestedChange.changes?.map((featureToggleChange: any) => ( | ||||
|             {suggestedChange.features?.map(featureToggleChange => ( | ||||
|                 <SuggestedFeatureToggleChange | ||||
|                     key={featureToggleChange.feature} | ||||
|                     featureToggleName={featureToggleChange.feature} | ||||
|                     key={featureToggleChange.name} | ||||
|                     featureToggleName={featureToggleChange.name} | ||||
|                 > | ||||
|                     {featureToggleChange.changeSet.map((change: any) => ( | ||||
|                     {featureToggleChange.changes.map(change => ( | ||||
|                         <Box key={objectId(change)}> | ||||
|                             <ConditionallyRender | ||||
|                                 condition={change.action === 'updateEnabled'} | ||||
|                                 show={ | ||||
|                                     <ToggleStatusChange | ||||
|                                         enabled={change?.payload?.data?.data} | ||||
|                                         enabled={change?.payload?.enabled} | ||||
|                                     /> | ||||
|                                 } | ||||
|                             /> | ||||
|                             <ConditionallyRender | ||||
|                             {/* <ConditionallyRender | ||||
|                                 condition={change.action === 'addStrategy'} | ||||
|                                 show={ | ||||
|                                     <StrategyAddedChange> | ||||
| @ -55,7 +56,7 @@ export const SuggestedChangeset: FC<{ suggestedChange: any }> = ({ | ||||
|                             <ConditionallyRender | ||||
|                                 condition={change.action === 'updateStrategy'} | ||||
|                                 show={<StrategyEditedChange />} | ||||
|                             /> | ||||
|                             /> */} | ||||
|                         </Box> | ||||
|                     ))} | ||||
|                 </SuggestedFeatureToggleChange> | ||||
|  | ||||
| @ -80,6 +80,9 @@ const data: any = { | ||||
|     ], | ||||
| }; | ||||
| 
 | ||||
| /** | ||||
|  * @deprecated for draft: useSuggestedChangesDraft | ||||
|  */ | ||||
| export const useSuggestedChange = () => { | ||||
|     // const { data, error, mutate } = useSWR(
 | ||||
|     //     formatApiPath(`api/admin/suggest-changes/${id}`),
 | ||||
|  | ||||
| @ -0,0 +1,58 @@ | ||||
| import useSWR from 'swr'; | ||||
| import { useMemo } from 'react'; | ||||
| import { formatApiPath } from 'utils/formatPath'; | ||||
| import handleErrorResponses from '../httpErrorResponseHandler'; | ||||
| 
 | ||||
| interface IChange { | ||||
|     id: number; | ||||
|     action: string; | ||||
|     payload: { | ||||
|         enabled: boolean; // FIXME: add other action types
 | ||||
|     }; | ||||
|     createdAt: Date; | ||||
|     createdBy: { | ||||
|         id: number; | ||||
|         username?: any; | ||||
|         imageUrl?: any; | ||||
|     }; | ||||
| } | ||||
| 
 | ||||
| export interface ISuggestChangesResponse { | ||||
|     id: number; | ||||
|     environment: string; | ||||
|     state: string; | ||||
|     project: string; | ||||
|     createdBy: { | ||||
|         id: number; | ||||
|         username?: any; | ||||
|         imageUrl?: any; | ||||
|     }; | ||||
|     createdAt: Date; | ||||
|     features: Array<{ | ||||
|         name: string; | ||||
|         changes: IChange[]; | ||||
|     }>; | ||||
| } | ||||
| 
 | ||||
| const fetcher = (path: string) => { | ||||
|     return fetch(path) | ||||
|         .then(handleErrorResponses('SuggestedChanges')) | ||||
|         .then(res => res.json()); | ||||
| }; | ||||
| 
 | ||||
| export const useSuggestedChangesDraft = (project: string) => { | ||||
|     const { data, error, mutate } = useSWR<ISuggestChangesResponse[]>( | ||||
|         formatApiPath(`api/admin/projects/${project}/suggest-changes/draft`), | ||||
|         fetcher | ||||
|     ); | ||||
| 
 | ||||
|     return useMemo( | ||||
|         () => ({ | ||||
|             draft: data, | ||||
|             loading: !error && !data, | ||||
|             refetch: () => mutate(), | ||||
|             error, | ||||
|         }), | ||||
|         [data, error, mutate] | ||||
|     ); | ||||
| }; | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user