Skip to content

Commit a409eaa

Browse files
authored
1 parent 45abbb1 commit a409eaa

File tree

6 files changed

+143
-55
lines changed

6 files changed

+143
-55
lines changed

src/components/ProjectForm.tsx

Lines changed: 100 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,18 @@
1+
import {
2+
FormControl,
3+
FormControlLabel,
4+
InputLabel,
5+
MenuItem,
6+
Select,
7+
Switch,
8+
} from "@material-ui/core";
19
import React from "react";
210
import { TextValidator } from "react-material-ui-form-validator";
11+
import { ProjectDto } from "../types";
12+
import { ImageComparison } from "../types/imageComparison";
313

414
interface IProps {
5-
projectState: [
6-
{
7-
id: string;
8-
name: string;
9-
mainBranchName: string;
10-
},
11-
React.Dispatch<
12-
React.SetStateAction<{
13-
id: string;
14-
name: string;
15-
mainBranchName: string;
16-
}>
17-
>
18-
];
15+
projectState: [ProjectDto, React.Dispatch<React.SetStateAction<ProjectDto>>];
1916
}
2017

2118
export const ProjectForm: React.FunctionComponent<IProps> = ({
@@ -54,10 +51,98 @@ export const ProjectForm: React.FunctionComponent<IProps> = ({
5451
fullWidth
5552
required
5653
value={project.mainBranchName}
57-
onChange={(event) => {
54+
onChange={(event) =>
5855
setProject({
5956
...project,
6057
mainBranchName: (event.target as HTMLInputElement).value,
58+
})
59+
}
60+
/>
61+
<FormControl fullWidth>
62+
<InputLabel id="imageComparisonSelect">
63+
Image comparison library
64+
</InputLabel>
65+
<Select
66+
id="imageComparisonSelect"
67+
labelId="imageComparisonSelect"
68+
value={project.imageComparison}
69+
onChange={(event) =>
70+
setProject({
71+
...project,
72+
imageComparison: event.target.value as ImageComparison,
73+
})
74+
}
75+
>
76+
<MenuItem value={ImageComparison.pixelmatch}>
77+
{ImageComparison.pixelmatch}
78+
</MenuItem>
79+
</Select>
80+
</FormControl>
81+
<FormControlLabel
82+
label="Auto approve feature"
83+
control={
84+
<Switch
85+
checked={project.autoApproveFeature}
86+
onChange={(event, checked) =>
87+
setProject({
88+
...project,
89+
autoApproveFeature: checked,
90+
})
91+
}
92+
color="primary"
93+
name="autoApproveFeature"
94+
/>
95+
}
96+
/>
97+
<FormControlLabel
98+
label="Allow diff dimentions"
99+
control={
100+
<Switch
101+
checked={project.diffDimensionsFeature}
102+
onChange={(event, checked) =>
103+
setProject({
104+
...project,
105+
diffDimensionsFeature: checked,
106+
})
107+
}
108+
color="primary"
109+
name="diffDimensionsFeature"
110+
/>
111+
}
112+
/>
113+
<FormControlLabel
114+
label="Ignore anti-alliasing"
115+
control={
116+
<Switch
117+
checked={project.ignoreAntialiasing}
118+
onChange={(event, checked) =>
119+
setProject({
120+
...project,
121+
ignoreAntialiasing: checked,
122+
})
123+
}
124+
color="primary"
125+
name="ignoreAntialiasing"
126+
/>
127+
}
128+
/>
129+
<TextValidator
130+
name="threshold"
131+
validators={["minNumber:0", "maxNumber:1"]}
132+
errorMessages={["Enter greater than 0", "Enter less than 1"]}
133+
InputProps={{ inputProps: { min: 0, max: 1, step: 0.001 } }}
134+
margin="dense"
135+
id="threshold"
136+
label="Pixel diff threshold"
137+
type="number"
138+
fullWidth
139+
required
140+
value={project.threshold}
141+
onChange={(event) => {
142+
const value = (event.target as HTMLInputElement).value;
143+
setProject({
144+
...project,
145+
threshold: parseFloat(value),
61146
});
62147
}}
63148
/>

src/contexts/project.context.tsx

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import * as React from "react";
2-
import { Project } from "../types";
2+
import { Project, ProjectDto } from "../types";
33
import { projectsService } from "../services";
44
import { useSnackbar } from "notistack";
55
import { useAuthState } from "./auth.context";
@@ -118,10 +118,7 @@ async function selectProject(dispatch: Dispatch, id: string) {
118118
dispatch({ type: "select", payload: id });
119119
}
120120

121-
async function createProject(
122-
dispatch: Dispatch,
123-
project: { name: string; mainBranchName: string }
124-
) {
121+
async function createProject(dispatch: Dispatch, project: ProjectDto) {
125122
dispatch({ type: "request" });
126123

127124
return projectsService.create(project).then((project: Project) => {
@@ -130,10 +127,7 @@ async function createProject(
130127
});
131128
}
132129

133-
async function updateProject(
134-
dispatch: Dispatch,
135-
project: { id: string; name: string; mainBranchName: string }
136-
) {
130+
async function updateProject(dispatch: Dispatch, project: ProjectDto) {
137131
dispatch({ type: "request" });
138132

139133
return projectsService.update(project).then((project: Project) => {

src/pages/ProjectListPage.tsx

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,19 @@ import { formatDateTime } from "../_helpers/format.helper";
2424
import { ProjectForm } from "../components/ProjectForm";
2525
import { useSnackbar } from "notistack";
2626
import { BaseModal } from "../components/BaseModal";
27+
import { ProjectDto } from "../types";
28+
import { ImageComparison } from "../types/imageComparison";
29+
30+
const defaultProject: ProjectDto = {
31+
id: "",
32+
name: "",
33+
mainBranchName: "",
34+
ignoreAntialiasing: true,
35+
autoApproveFeature: true,
36+
diffDimensionsFeature: true,
37+
threshold: 0.1,
38+
imageComparison: ImageComparison.pixelmatch,
39+
};
2740

2841
const ProjectsListPage = () => {
2942
const { enqueueSnackbar } = useSnackbar();
@@ -33,15 +46,7 @@ const ProjectsListPage = () => {
3346
const [createDialogOpen, setCreateDialogOpen] = React.useState(false);
3447
const [updateDialogOpen, setUpdateDialogOpen] = React.useState(false);
3548
const [deleteDialogOpen, setDeleteDialogOpen] = React.useState(false);
36-
const [project, setProject] = React.useState<{
37-
id: string;
38-
name: string;
39-
mainBranchName: string;
40-
}>({
41-
id: "",
42-
name: "",
43-
mainBranchName: "",
44-
});
49+
const [project, setProject] = React.useState(defaultProject);
4550

4651
const toggleCreateDialogOpen = () => {
4752
setCreateDialogOpen(!createDialogOpen);
@@ -70,11 +75,7 @@ const ProjectsListPage = () => {
7075
aria-label="add"
7176
onClick={() => {
7277
toggleCreateDialogOpen();
73-
setProject({
74-
id: "",
75-
name: "",
76-
mainBranchName: "",
77-
});
78+
setProject(defaultProject);
7879
}}
7980
>
8081
<Add />

src/services/projects.service.ts

Lines changed: 12 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2,51 +2,46 @@ import { Project } from "../types";
22
import { handleResponse, authHeader } from "../_helpers/service.helpers";
33
import { API_URL } from "../_config/env.config";
44

5-
function getAll(): Promise<Project[]> {
5+
async function getAll(): Promise<Project[]> {
66
const requestOptions = {
77
method: "GET",
88
headers: authHeader(),
99
};
1010

11-
return fetch(`${API_URL}/projects`, requestOptions).then(handleResponse);
11+
const response = await fetch(`${API_URL}/projects`, requestOptions);
12+
return handleResponse(response);
1213
}
1314

14-
function remove(id: string): Promise<Project> {
15+
async function remove(id: string): Promise<Project> {
1516
const requestOptions = {
1617
method: "DELETE",
1718
headers: authHeader(),
1819
};
1920

20-
return fetch(`${API_URL}/projects/${id}`, requestOptions).then(
21-
handleResponse
22-
);
21+
const response = await fetch(`${API_URL}/projects/${id}`, requestOptions);
22+
return handleResponse(response);
2323
}
2424

25-
function create(project: {
26-
name: string;
27-
mainBranchName: string;
28-
}): Promise<Project> {
25+
async function create(project: Partial<Project>): Promise<Project> {
2926
const requestOptions = {
3027
method: "POST",
3128
headers: { "Content-Type": "application/json", ...authHeader() },
3229
body: JSON.stringify(project),
3330
};
3431

35-
return fetch(`${API_URL}/projects`, requestOptions).then(handleResponse);
32+
const response = await fetch(`${API_URL}/projects`, requestOptions);
33+
return handleResponse(response);
3634
}
3735

38-
function update(project: {
39-
id: string;
40-
name: string;
41-
mainBranchName: string;
42-
}): Promise<Project> {
36+
async function update(project: Partial<Project>): Promise<Project> {
4337
const requestOptions = {
4438
method: "PUT",
4539
headers: { "Content-Type": "application/json", ...authHeader() },
4640
body: JSON.stringify(project),
4741
};
4842

49-
return fetch(`${API_URL}/projects`, requestOptions).then(handleResponse);
43+
const response = await fetch(`${API_URL}/projects`, requestOptions);
44+
return handleResponse(response);
5045
}
5146

5247
export const projectsService = {

src/types/imageComparison.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
export enum ImageComparison {
2+
pixelmatch = "pixelmatch",
3+
lookSame = "lookSame",
4+
odiff = "odiff",
5+
}

src/types/project.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { Build } from "./build";
2+
import { ImageComparison } from "./imageComparison";
23

34
export interface Project {
45
id: string;
@@ -7,4 +8,11 @@ export interface Project {
78
builds: Build[];
89
updatedAt: string;
910
createdAt: string;
11+
autoApproveFeature: boolean;
12+
diffDimensionsFeature: boolean;
13+
ignoreAntialiasing: boolean;
14+
threshold: number;
15+
imageComparison: ImageComparison;
1016
}
17+
18+
export type ProjectDto = Omit<Project, "updatedAt" | "createdAt" | "builds">;

0 commit comments

Comments
 (0)