Skip to content

Commit

Permalink
project creation
Browse files Browse the repository at this point in the history
  • Loading branch information
ciyer committed Nov 10, 2023
1 parent 17d18eb commit 64e796a
Show file tree
Hide file tree
Showing 4 changed files with 158 additions and 51 deletions.
50 changes: 49 additions & 1 deletion client/src/features/projectsV2/new/ProjectV2New.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,10 @@
* limitations under the License.
*/

import { Loader } from "../../../components/Loader";
import FormSchema from "../../../components/formschema/FormSchema";

import { usePostProjectsMutation } from "../api/projectV2.api";
import type { NewProjectV2State } from "./projectV2New.slice";
import { useNewProjectV2Selector } from "./projectV2New.slice";
import ProjectV2NewForm from "./ProjectV2NewForm";
Expand All @@ -42,6 +45,7 @@ function ProjectV2NewHeader({
{currentStep === 0 && <ProjectV2NewMetadataStepHeader />}
{currentStep === 1 && <ProjectV2NewAccessStepHeader />}
{currentStep === 2 && <ProjectV2NewRepositoryStepHeader />}
{currentStep === 3 && <ProjectV2NewProjectCreatingStepHeader />}
</>
);
}
Expand All @@ -55,6 +59,14 @@ function ProjectV2NewMetadataStepHeader() {
);
}

function ProjectV2NewProjectCreatingStepHeader() {
return (
<>
<p>Project is being created...</p>
</>
);
}

function ProjectV2NewRepositoryStepHeader() {
return (
<>
Expand All @@ -67,6 +79,41 @@ function ProjectV2NewRepositoryStepHeader() {
);
}

function ProjectV2BeingCreated() {
const { project } = useNewProjectV2Selector((state) => state);
const [createProject, result] = usePostProjectsMutation();
const newProject = {
name: project.metadata.name,
slug: project.metadata.slug,
description: project.metadata.description,
visibility: project.access.visibility,
repositories: project.content.repositories,
};
if (result == null || result.isUninitialized) {
createProject({ projectPost: newProject });

return (
<div className="d-flex align-items-center">
<Loader className="me-2" />
<span>Creating project...</span>
</div>
);
}
if (result.isLoading) {
return (
<div className="d-flex align-items-center">
<Loader className="me-2" />
<span>Creating project...</span>
</div>
);
}

if (result.isError || result.data == null) {
return <div>Something went wrong...</div>;
}
return <div>Project created</div>;
}

export default function ProjectV2New() {
const { currentStep } = useNewProjectV2Selector((state) => state);
return (
Expand All @@ -75,7 +122,8 @@ export default function ProjectV2New() {
title="New Project (V2)"
description={<ProjectV2NewHeader currentStep={currentStep} />}
>
<ProjectV2NewForm currentStep={currentStep} />
{currentStep < 3 && <ProjectV2NewForm currentStep={currentStep} />}
{currentStep === 3 && <ProjectV2BeingCreated />}
</FormSchema>
);
}
137 changes: 93 additions & 44 deletions client/src/features/projectsV2/new/ProjectV2NewForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,12 @@ import { useDispatch } from "react-redux";
import { Button, Form, FormText, Input, Label } from "reactstrap";

import { slugFromTitle } from "../../../utils/helpers/HelperFunctions";

import styles from "./projectV2New.module.scss";
import type { NewProjectV2State } from "./projectV2New.slice";
import {
setAccess,
setContent,
setCurrentStep,
setMetadata,
useNewProjectV2Selector,
Expand All @@ -50,8 +52,19 @@ function ProjectFormSubmitGroup({ currentStep }: ProjectV2NewFormProps) {
>
Back
</Button>
{currentStep < 2 && <Button type="submit">Next</Button>}
{currentStep === 2 && <Button type="submit">Create</Button>}
<div>
{currentStep === 0 && (
<Button className="me-1" type="submit">
Set Visibility
</Button>
)}
{currentStep === 1 && (
<Button className="me-1" type="submit">
Add repositories
</Button>
)}
{currentStep === 2 && <Button type="submit">Create</Button>}
</div>
</div>
);
}
Expand All @@ -74,12 +87,79 @@ export default function ProjectV2NewForm({
<ProjectV2NewAccessStepForm currentStep={currentStep} />
)}
{currentStep === 2 && (
<ProjectFormSubmitGroup currentStep={currentStep} />
<ProjectV2NewRepositoryStepForm currentStep={currentStep} />
)}
</div>
);
}

function ProjectV2NewAccessStepForm({ currentStep }: ProjectV2NewFormProps) {
const dispatch = useDispatch();
const { project } = useNewProjectV2Selector((state) => state);
const {
control,
formState: { errors },
handleSubmit,
} = useForm<NewProjectV2State["project"]["access"]>({
defaultValues: project.access,
});

const onSubmit = useCallback(
(data: NewProjectV2State["project"]["access"]) => {
dispatch(setAccess(data));
const nextStep = (currentStep + 1) as typeof currentStep;
dispatch(setCurrentStep(nextStep));
},
[currentStep, dispatch]
);
return (
<Form
className="form-rk-green"
noValidate
onSubmit={handleSubmit(onSubmit)}
>
<div className="mb-3">
<Label className="form-label" for="projectV2NewForm-name">
Visibility
</Label>
<Controller
control={control}
name="visibility"
render={({ field }) => (
<Input
className={cx("form-control", errors.visibility && "is-invalid")}
id="projectV2NewForm-visibility"
type="select"
{...field}
>
<option>Public</option>
<option>Private</option>
</Input>
)}
rules={{ required: true }}
/>
{errors.visibility ? null : (
<FormText className="input-hint">
Should the project be visible to everyone or only to members?
</FormText>
)}
<div className="invalid-feedback">Please select a visibility</div>
</div>
<div className="mb-3">
<Label className="form-label" for="projectV2NewForm-name">
Users
</Label>

<FormText className="input-hint">
Who has access to the project?
</FormText>
<div className="invalid-feedback">Please select users</div>
</div>
<ProjectFormSubmitGroup currentStep={currentStep} />
</Form>
);
}

function ProjectV2NewMetadataStepForm({ currentStep }: ProjectV2NewFormProps) {
const dispatch = useDispatch();
const { project } = useNewProjectV2Selector((state) => state);
Expand All @@ -95,7 +175,6 @@ function ProjectV2NewMetadataStepForm({ currentStep }: ProjectV2NewFormProps) {
const onSubmit = useCallback(
(data: NewProjectV2State["project"]["metadata"]) => {
dispatch(setMetadata(data));
if (currentStep > 1) return;
const nextStep = (currentStep + 1) as typeof currentStep;
dispatch(setCurrentStep(nextStep));
},
Expand All @@ -118,6 +197,7 @@ function ProjectV2NewMetadataStepForm({ currentStep }: ProjectV2NewFormProps) {
render={({ field }) => (
<Input
className={cx("form-control", errors.name && "is-invalid")}
data-cy="project-name-input"
id="projectV2NewForm-name"
type="text"
{...field}
Expand Down Expand Up @@ -147,6 +227,7 @@ function ProjectV2NewMetadataStepForm({ currentStep }: ProjectV2NewFormProps) {
render={({ field }) => (
<Input
className={cx("form-control", errors.slug && "is-invalid")}
data-cy="project-slug-input"
id="projectV2NewForm-slug"
type="text"
{...field}
Expand Down Expand Up @@ -195,21 +276,18 @@ function ProjectV2NewMetadataStepForm({ currentStep }: ProjectV2NewFormProps) {
);
}

function ProjectV2NewAccessStepForm({ currentStep }: ProjectV2NewFormProps) {
function ProjectV2NewRepositoryStepForm({
currentStep,
}: ProjectV2NewFormProps) {
const dispatch = useDispatch();
const { project } = useNewProjectV2Selector((state) => state);
const {
control,
formState: { errors },
handleSubmit,
} = useForm<NewProjectV2State["project"]["access"]>({
defaultValues: project.access,
const { handleSubmit } = useForm<NewProjectV2State["project"]["content"]>({
defaultValues: project.content,
});

const onSubmit = useCallback(
(data: NewProjectV2State["project"]["access"]) => {
dispatch(setAccess(data));
if (currentStep > 1) return;
(data: NewProjectV2State["project"]["content"]) => {
dispatch(setContent(data));
const nextStep = (currentStep + 1) as typeof currentStep;
dispatch(setCurrentStep(nextStep));
},
Expand All @@ -223,40 +301,11 @@ function ProjectV2NewAccessStepForm({ currentStep }: ProjectV2NewFormProps) {
>
<div className="mb-3">
<Label className="form-label" for="projectV2NewForm-name">
Visibility
Repositories
</Label>
<Controller
control={control}
name="visibility"
render={({ field }) => (
<Input
className={cx("form-control", errors.visibility && "is-invalid")}
id="projectV2NewForm-visibility"
type="select"
{...field}
>
<option>Public</option>
<option>Private</option>
</Input>
)}
rules={{ required: true }}
/>
{errors.visibility ? null : (
<FormText className="input-hint">
Should the project be visible to everyone or only to members?
</FormText>
)}
<div className="invalid-feedback">Please select a visibility</div>
</div>
<div className="mb-3">
<Label className="form-label" for="projectV2NewForm-name">
Users
</Label>

<FormText className="input-hint">
Who has access to the project?
</FormText>
<div className="invalid-feedback">Please select a visibility</div>
</div>
<ProjectFormSubmitGroup currentStep={currentStep} />
</Form>
Expand Down
7 changes: 5 additions & 2 deletions client/src/features/projectsV2/new/projectV2New.slice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import { createSlice, PayloadAction } from "@reduxjs/toolkit";
import { createSliceSelector } from "../../../utils/customHooks/UseSliceSelector";
import type { Project } from "../projectV2.types";

type NewProjectV2Step = 0 | 1 | 2;
type NewProjectV2Step = 0 | 1 | 2 | 3;

export interface NewProjectV2State {
project: Project;
Expand Down Expand Up @@ -53,6 +53,9 @@ export const projectV2NewSlice = createSlice({
setAccess: (state, action: PayloadAction<Project["access"]>) => {
state.project.access = action.payload;
},
setContent: (state, action: PayloadAction<Project["content"]>) => {
state.project.content = action.payload;
},
setCurrentStep: (state, action: PayloadAction<NewProjectV2Step>) => {
state.currentStep = action.payload;
},
Expand All @@ -63,6 +66,6 @@ export const projectV2NewSlice = createSlice({
},
});

export const { setAccess, setCurrentStep, setMetadata, reset } =
export const { setAccess, setContent, setCurrentStep, setMetadata, reset } =
projectV2NewSlice.actions;
export const useNewProjectV2Selector = createSliceSelector(projectV2NewSlice);
15 changes: 11 additions & 4 deletions tests/cypress/e2e/projectV2.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,15 +30,22 @@ describe("Add new v2 project", () => {
cy.visit("projectV2/new");
});

it("create a new project that should change name", () => {
it("create a new project", () => {
fixtures
.templates()
.createProject()
.project(newProjectPath, "getNewProject", "projects/project.json", false)
.updateProject(newProjectPath);
cy.contains("New Project (V2)").should("be.visible");
// cy.createProject(newProjectTitle);
// cy.wait("@getTemplates");
//cy.wait("@createProject");
cy.getDataCy("project-name-input").clear().type("new project");
cy.getDataCy("project-slug-input").should("have.value", slug);
cy.contains("Set Visibility").click();
cy.contains("Add repositories").click();

// cy.createProject(newProjectTitle);
// cy.wait("@getTemplates");
// cy.wait("@createProject");
});

// TODO: test validation
});

0 comments on commit 64e796a

Please sign in to comment.