diff --git a/src/components/BuildList/index.tsx b/src/components/BuildList/index.tsx index 4c6e8627..27ec31fd 100644 --- a/src/components/BuildList/index.tsx +++ b/src/components/BuildList/index.tsx @@ -23,6 +23,7 @@ import { useBuildDispatch, deleteBuild, selectBuild, + modifyBuild, stopBuild, getBuildList, useProjectState, @@ -31,9 +32,10 @@ import { BuildStatusChip } from "../BuildStatusChip"; import { SkeletonList } from "../SkeletonList"; import { formatDateTime } from "../../_helpers/format.helper"; import { useSnackbar } from "notistack"; +import { TextValidator } from "react-material-ui-form-validator"; +import { Pagination } from "@material-ui/lab"; import { Build } from "../../types"; import { BaseModal } from "../BaseModal"; -import { Pagination } from "@material-ui/lab"; const useStyles = makeStyles((theme: Theme) => createStyles({ @@ -60,8 +62,10 @@ const BuildList: FunctionComponent = () => { const { enqueueSnackbar } = useSnackbar(); const { selectedProjectId } = useProjectState(); const [deleteDialogOpen, setDeleteDialogOpen] = React.useState(false); + const [editDialogOpen, setEditDialogOpen] = React.useState(false); const [anchorEl, setAnchorEl] = React.useState(null); const [menuBuild, setMenuBuild] = React.useState(); + const [newCiBuildId, setNewCiBuildId] = React.useState(""); const handleMenuClick = ( event: React.MouseEvent, @@ -80,6 +84,10 @@ const BuildList: FunctionComponent = () => { setDeleteDialogOpen(!deleteDialogOpen); }; + const toggleEditDialogOpen = () => { + setEditDialogOpen(!editDialogOpen); + }; + React.useEffect(() => { if (!selectedBuild && buildList.length > 0) { selectBuild(buildDispatch, buildList[0].id); @@ -204,9 +212,56 @@ const BuildList: FunctionComponent = () => { Stop )} + Edit CI Build Delete )} + {menuBuild && ( + + {`Edit the ci build id for build: #${ + menuBuild.number || menuBuild.id + }`} + + setNewCiBuildId((event.target as HTMLInputElement).value), + "data-testid": "newCiBuildId", + }} + /> + + } + onSubmit={() => { + modifyBuild(buildDispatch, menuBuild.id, { + ciBuildId: newCiBuildId, + }) + .then((b) => { + toggleEditDialogOpen(); + }) + .catch((err) => + enqueueSnackbar(err, { + variant: "error", + }) + ); + handleMenuClose(); + }} + /> + )} {menuBuild && ( { + return buildsService.update(id, { "isRunning": false }).then((build) => { dispatch({ type: "update", payload: build }); return build; }); } +async function modifyBuild(dispatch: Dispatch, id: string, body: object) { + return buildsService.update(id, body); +} + async function selectBuild(dispatch: Dispatch, id: string | null) { if (id === null) { dispatch({ type: "select", payload: null }); @@ -207,5 +211,6 @@ export { selectBuild, addBuild, updateBuild, + modifyBuild, stopBuild, }; diff --git a/src/services/builds.service.ts b/src/services/builds.service.ts index 1b4fff6a..c8e190cc 100644 --- a/src/services/builds.service.ts +++ b/src/services/builds.service.ts @@ -1,6 +1,7 @@ import { Build, PaginatedData } from "../types"; import { handleResponse, authHeader } from "../_helpers/service.helpers"; import { API_URL } from "../_config/env.config"; +import {BuildDto} from "../types/dto/build.dto"; const ENDPOINT_URL = "/builds"; @@ -42,10 +43,11 @@ async function remove(id: string): Promise { ); } -async function stop(id: string): Promise { +async function update(id: string, body: BuildDto): Promise { const requestOptions = { method: "PATCH", - headers: authHeader(), + headers: { "Content-Type": "application/json", ...authHeader() }, + body: JSON.stringify(body) }; return fetch(`${API_URL}${ENDPOINT_URL}/${id}`, requestOptions).then( @@ -70,5 +72,5 @@ export const buildsService = { getList, approve, remove, - stop, + update, }; diff --git a/src/types/dto/build.dto.ts b/src/types/dto/build.dto.ts new file mode 100644 index 00000000..7958eec5 --- /dev/null +++ b/src/types/dto/build.dto.ts @@ -0,0 +1,4 @@ +export interface BuildDto { + ciBuildId?: string; + isRunning?: boolean; +}