Skip to content

Commit

Permalink
feat: integrate with API for suggest changes (#2286)
Browse files Browse the repository at this point in the history
* feat: integrate with API for suggest changes

* fix: suggestions table tabs state (#2287)

* fix: suggestions table tabs state

* fix suggestion header padding

* fix: update snapshots

* fix: pr comments

* fix: revert store change

* fix: revert store fix

Co-authored-by: Tymoteusz Czech <2625371+Tymek@users.noreply.github.com>
  • Loading branch information
FredrikOseberg and Tymek committed Oct 31, 2022
1 parent 9577975 commit 15c22d7
Show file tree
Hide file tree
Showing 14 changed files with 172 additions and 147 deletions.
Expand Up @@ -6,14 +6,16 @@ export const useStyles = makeStyles()(theme => ({
boxShadow: 'none',
},
headerContainer: {
padding: theme.spacing(2, 4),
borderBottomStyle: 'solid',
borderBottomWidth: 1,
borderBottomColor: theme.palette.divider,
[theme.breakpoints.down('md')]: {
padding: '1.5rem 1rem',
},
},
headerPadding: {
padding: theme.spacing(2, 4),
},
bodyContainer: {
padding: theme.spacing(4),
[theme.breakpoints.down('md')]: {
Expand Down
15 changes: 11 additions & 4 deletions frontend/src/component/common/PageContent/PageContent.tsx
Expand Up @@ -19,6 +19,7 @@ interface IPageContentProps extends PaperProps {
disableBorder?: boolean;
disableLoading?: boolean;
bodyClass?: string;
headerClass?: string;
}

const PageContentLoading: FC<{ isLoading: boolean }> = ({
Expand All @@ -40,17 +41,23 @@ export const PageContent: FC<IPageContentProps> = ({
disablePadding = false,
disableBorder = false,
bodyClass = '',
headerClass = '',
isLoading = false,
disableLoading = false,
className,
...rest
}) => {
const { classes: styles } = useStyles();

const headerClasses = classnames('header', styles.headerContainer, {
[styles.paddingDisabled]: disablePadding,
[styles.borderDisabled]: disableBorder,
});
const headerClasses = classnames(
'header',
styles.headerContainer,
headerClass || styles.headerPadding,
{
[styles.paddingDisabled]: disablePadding,
[styles.borderDisabled]: disableBorder,
}
);

const bodyClasses = classnames(
'body',
Expand Down
@@ -1,6 +1,7 @@
import { VFC } from 'react';
import { Chip, styled } from '@mui/material';
import { colors } from '../../../../../themes/colors';
import { TextCell } from '../../../../common/Table/cells/TextCell/TextCell';
import { colors } from 'themes/colors';
import { TextCell } from 'component/common/Table/cells/TextCell/TextCell';
import { Check, CircleOutlined, Close } from '@mui/icons-material';

interface IChangesetStatusCellProps {
Expand Down Expand Up @@ -60,7 +61,10 @@ export const StyledReviewChip = styled(StyledChip)(({ theme }) => ({
color: theme.palette.primary.main,
},
}));
export const ChangesetStatusCell = ({ value }: IChangesetStatusCellProps) => {

export const ChangesetStatusCell: VFC<IChangesetStatusCellProps> = ({
value,
}) => {
const renderState = (state: string) => {
switch (state) {
case SuggestChangesetState.IN_REVIEW:
Expand Down
Expand Up @@ -2,6 +2,7 @@ import { TextCell } from '../../../../common/Table/cells/TextCell/TextCell';
import { Link, styled, Typography } from '@mui/material';
import { Link as RouterLink } from 'react-router-dom';
import { useTheme } from '@mui/system';
import { useRequiredPathParam } from 'hooks/useRequiredPathParam';

interface IChangesetTitleCellProps {
value?: any;
Expand All @@ -18,9 +19,10 @@ export const ChangesetTitleCell = ({
value,
row: { original },
}: IChangesetTitleCellProps) => {
const { id, features: changes, project } = original;
const projectId = useRequiredPathParam('projectId');
const { id, features: changes } = original;
const theme = useTheme();
const path = `projects/${project}/suggest-changes/${id}`;
const path = `/projects/${projectId}/suggest-changes/${id}`;

if (!value) {
return <TextCell />;
Expand Down
@@ -1,8 +1,12 @@
import { makeStyles } from 'tss-react/mui';

export const useStyles = makeStyles()(theme => ({
header: {
padding: theme.spacing(0, 4),
},
tabContainer: {
paddingLeft: 0,
paddingBottom: 0,
},
tabButton: {
textTransform: 'none',
Expand Down
Expand Up @@ -77,7 +77,7 @@ export const SuggestionsTabs = ({
},
];

const [activeTab, setActiveTab] = useState(tabs[0]);
const [activeTab, setActiveTab] = useState(0);

const columns = useMemo(
() => [
Expand Down Expand Up @@ -137,7 +137,7 @@ export const SuggestionsTabs = ({
data: searchedData,
getSearchText,
getSearchContext,
} = useSearch(columns, searchValue, activeTab.data);
} = useSearch(columns, searchValue, tabs[activeTab]?.data);

const data = useMemo(
() => (loading ? featuresPlaceholder : searchedData),
Expand Down Expand Up @@ -206,34 +206,31 @@ export const SuggestionsTabs = ({
setStoredParams({ id: sortBy[0].id, desc: sortBy[0].desc || false });
}, [loading, sortBy, searchValue]); // eslint-disable-line react-hooks/exhaustive-deps

const renderTabs = () => {
return (
<div className={classes.tabContainer}>
<Tabs
value={activeTab?.title}
indicatorColor="primary"
textColor="primary"
>
{tabs.map(tab => (
<Tab
key={tab.title}
label={`${tab.title} (${tab.data.length})`}
value={tab.title}
onClick={() => setActiveTab(tab)}
className={classes.tabButton}
/>
))}
</Tabs>
</div>
);
};

return (
<PageContent
isLoading={loading}
headerClass={classes.header}
header={
<PageHeader
titleElement={renderTabs()}
titleElement={
<div className={classes.tabContainer}>
<Tabs
value={tabs[activeTab]?.title}
indicatorColor="primary"
textColor="primary"
>
{tabs.map((tab, index) => (
<Tab
key={tab.title}
label={`${tab.title} (${tab.data.length})`}
value={tab.title}
onClick={() => setActiveTab(index)}
className={classes.tabButton}
/>
))}
</Tabs>
</div>
}
actions={
<Search
initialValue={searchValue}
Expand Down
Expand Up @@ -16,7 +16,7 @@ export const DraftBanner: VFC<IDraftBannerProps> = ({ project }) => {
const { draft, loading } = useSuggestedChangesDraft(project);
const environment = '';

if (!loading && !draft) {
if (!loading && draft?.length === 0) {
return null;
}

Expand Down
Expand Up @@ -37,8 +37,8 @@ export const SuggestedChangeHeader: FC<{ suggestedChange: any }> = ({
</Typography>
<PlaygroundResultChip
// icon={<ChangesAppliedIcon strokeWidth="0.25" />}
label="Changes applied"
enabled="unknown"
label="Changes approved"
enabled
/>
</Box>
<Box sx={{ display: 'flex', verticalAlign: 'center', gap: 2 }}>
Expand All @@ -60,7 +60,7 @@ export const SuggestedChangeHeader: FC<{ suggestedChange: any }> = ({
</Typography>{' '}
| Updates:{' '}
<Typography display="inline" fontWeight="bold">
{suggestedChange?.changes.length} feature toggles
{suggestedChange?.features.length} feature toggles
</Typography>
</Card>
</Box>
Expand Down
@@ -1,13 +1,38 @@
import { FC } from 'react';
import { Box, Paper } from '@mui/material';
import { Box, Button, Paper } from '@mui/material';
import { useSuggestedChange } from 'hooks/api/getters/useSuggestChange/useSuggestedChange';
import { SuggestedChangeHeader } from './SuggestedChangeHeader/SuggestedChangeHeader';
import { SuggestedChangeTimeline } from './SuggestedChangeTimeline/SuggestedChangeTimeline';
import { SuggestedChangeReviewers } from './SuggestedChangeReviewers/SuggestedChangeReviewers';
import { SuggestedChangeset } from '../SuggestedChangeset/SuggestedChangeset';
import { useRequiredPathParam } from 'hooks/useRequiredPathParam';
import { useSuggestChangeApi } from 'hooks/api/actions/useSuggestChangeApi/useSuggestChangeApi';
import useToast from 'hooks/useToast';
import { formatUnknownError } from 'utils/formatUnknownError';

export const SuggestedChangeOverview: FC = () => {
const { data: suggestedChange } = useSuggestedChange();
const projectId = useRequiredPathParam('projectId');
const id = useRequiredPathParam('id');
const { data: suggestedChange } = useSuggestedChange(projectId, id);
const { applyChanges } = useSuggestChangeApi();
const { setToastData, setToastApiError } = useToast();

if (!suggestedChange) {
return null;
}

const onApplyChanges = async () => {
try {
await applyChanges(projectId, id);
setToastData({
type: 'success',
title: 'Success',
text: 'Changes appplied',
});
} catch (error: unknown) {
setToastApiError(formatUnknownError(error));
}
};

return (
<>
Expand Down Expand Up @@ -40,6 +65,13 @@ export const SuggestedChangeOverview: FC = () => {
})}
>
<SuggestedChangeset suggestedChange={suggestedChange} />
<Button
variant="contained"
sx={{ marginTop: 2 }}
onClick={onApplyChanges}
>
Apply changes
</Button>
</Box>
</Paper>
</Box>
Expand Down
Expand Up @@ -7,6 +7,7 @@ import { PageHeader } from 'component/common/PageHeader/PageHeader';
import { HelpOutline } from '@mui/icons-material';
import { SuggestedChangeset } from '../SuggestedChangeset/SuggestedChangeset';
import { useSuggestedChangesDraft } from 'hooks/api/getters/useSuggestedChangesDraft/useSuggestedChangesDraft';
import { useSuggestChangeApi } from 'hooks/api/actions/useSuggestChangeApi/useSuggestChangeApi';

interface ISuggestedChangesSidebarProps {
open: boolean;
Expand Down Expand Up @@ -45,10 +46,20 @@ export const SuggestedChangesSidebar: VFC<ISuggestedChangesSidebarProps> = ({
project,
onClose,
}) => {
const { draft, loading } = useSuggestedChangesDraft(project);
const {
draft,
loading,
refetch: refetchSuggestedChanges,
} = useSuggestedChangesDraft(project);
const { changeState } = useSuggestChangeApi();

const onReview = async () => {
alert('approve');
const onReview = async (draftId: number) => {
try {
await changeState(project, draftId, { state: 'In review' });
refetchSuggestedChanges();
} catch (e) {
console.log('something went wrong');
}
};
const onDiscard = async () => {
alert('discard');
Expand Down Expand Up @@ -163,7 +174,11 @@ export const SuggestedChangesSidebar: VFC<ISuggestedChangesSidebarProps> = ({
<Button
sx={{ mt: 2, ml: 'auto' }}
variant="contained"
onClick={onReview}
onClick={() =>
onReview(
environmentChangeset.id
)
}
>
Request changes
</Button>
Expand Down
Expand Up @@ -10,7 +10,7 @@ exports[`renders an empty list correctly 1`] = `
className="MuiPaper-root MuiPaper-elevation MuiPaper-rounded MuiPaper-elevation1 css-p9j8ie-MuiPaper-root-container"
>
<div
className="header css-1ywhhai-headerContainer"
className="header css-zq4ve2-headerContainer css-70tvrt-headerPadding"
>
<div
className="css-1ylehva-headerContainer"
Expand Down
Expand Up @@ -10,12 +10,13 @@ interface ISuggestChangeSchema {
payload: string | boolean | object | number;
}

export const useSuggestChangeApi = (project: string) => {
export const useSuggestChangeApi = () => {
const { makeRequest, createRequest, errors, loading } = useAPI({
propagateErrors: true,
});

const addSuggestion = async (
project: string,
environment: string,
payload: ISuggestChangeSchema
) => {
Expand All @@ -26,14 +27,47 @@ export const useSuggestChangeApi = (project: string) => {
});
try {
const response = await makeRequest(req.caller, req.id);
return await response.json();
return response.json();
} catch (e) {
throw e;
}
};

const changeState = async (
project: string,
suggestChangeId: number,
payload: any
) => {
const path = `api/admin/projects/${project}/suggest-changes/${suggestChangeId}/state`;
const req = createRequest(path, {
method: 'PUT',
body: JSON.stringify(payload),
});
try {
const response = await makeRequest(req.caller, req.id);
return response.json();
} catch (e) {
throw e;
}
};

const applyChanges = async (project: string, suggestChangeId: string) => {
const path = `api/admin/projects/${project}/suggest-changes/${suggestChangeId}/apply`;
const req = createRequest(path, {
method: 'PUT',
});
try {
const response = await makeRequest(req.caller, req.id);
return response;
} catch (e) {
throw e;
}
};

return {
addSuggestion,
applyChanges,
changeState,
errors,
loading,
};
Expand Down

0 comments on commit 15c22d7

Please sign in to comment.