handled project selector in newticketform

This commit is contained in:
Ruidy Nemausat 2020-03-04 10:54:35 +01:00
parent ec53a6edb6
commit 61d189b3d3
16 changed files with 97 additions and 35 deletions

View file

@ -1,7 +1,3 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Hosting;

View file

@ -50,3 +50,4 @@
- [<span style="color:red">X</span>] write dtos without circular dependencies. - [<span style="color:red">X</span>] write dtos without circular dependencies.
- [ ] use dtoRequest for PutProjects - [ ] use dtoRequest for PutProjects
- [ ] render avatarlist after UserModal Update - [ ] render avatarlist after UserModal Update
- [ ] Form validators

View file

@ -4,10 +4,11 @@ namespace TicketManager.Resources
{ {
public class NewAppUserDTO public class NewAppUserDTO
{ {
[Required]
public string FirstName { get; set; } public string FirstName { get; set; }
public string LastName { get; set; } public string LastName { get; set; }
public string Presentation { get; set; } public string Presentation { get; set; }
[Required]
[DataType(DataType.EmailAddress)] [DataType(DataType.EmailAddress)]
public string Email { get; set; } public string Email { get; set; }

View file

@ -8,7 +8,9 @@ namespace TicketManager.Resources
[Required] [Required]
public string Title { get; set; } public string Title { get; set; }
public string Description { get; set; } public string Description { get; set; }
[Required]
public DateTime EndingDate { get; set; } public DateTime EndingDate { get; set; }
[Required]
public Guid ManagerId { get; set; } public Guid ManagerId { get; set; }
} }
} }

View file

@ -8,10 +8,11 @@ namespace TicketManager.Resources
{ {
public class NewTicketDTO public class NewTicketDTO
{ {
[Required]
public string Title { get; set; } public string Title { get; set; }
[Required]
public string Description { get; set; } public string Description { get; set; }
[Required]
[DataType(DataType.Date)] [DataType(DataType.Date)]
public DateTime EndingDate { get; set; } public DateTime EndingDate { get; set; }
@ -20,8 +21,9 @@ namespace TicketManager.Resources
public string Difficulty { get; set; } public string Difficulty { get; set; }
public string Category { get; set; } public string Category { get; set; }
[Required]
public Guid CreatorId { get; set; } public Guid CreatorId { get; set; }
[Required]
public int ProjectId { get; set; } public int ProjectId { get; set; }
} }
} }

View file

@ -6,7 +6,7 @@ import { User } from "../types/User";
import { getRemainingdays } from "../utils/methods"; import { getRemainingdays } from "../utils/methods";
export default class ProjectVM { export default class ProjectVM {
// public id: number; public id: number;
public title: string; public title: string;
public description: string; public description: string;
public creationDate: string; public creationDate: string;
@ -22,9 +22,14 @@ export default class ProjectVM {
public ticketsTotalCount: number; public ticketsTotalCount: number;
public ticketsDone: number; public ticketsDone: number;
public remainingDays: number; public remainingDays: number;
public allProjects: Project[];
public constructor(project: Project, allUsers: User[]) { public constructor(
// this.id = project.id; project: Project,
allUsers: User[],
allProjects: Project[]
) {
this.id = project.id;
this.title = project.title; this.title = project.title;
this.description = project.description; this.description = project.description;
this.creationDate = project.creationDate; this.creationDate = project.creationDate;
@ -44,5 +49,6 @@ export default class ProjectVM {
? 0 ? 0
: this.tickets.filter(t => t.status === "Done").length; : this.tickets.filter(t => t.status === "Done").length;
this.remainingDays = getRemainingdays(project.endingDate); this.remainingDays = getRemainingdays(project.endingDate);
this.allProjects = allProjects;
} }
} }

View file

@ -6,7 +6,13 @@ interface IProps {
export const Avatar: FC<IProps> = ({ picture }) => { export const Avatar: FC<IProps> = ({ picture }) => {
return ( return (
<> <>
<img className="circle" src={picture} height="100vh" width="100vh" /> <img
className="circle"
src={picture}
height="100vh"
width="100vh"
alt="user avatar"
/>
</> </>
); );
}; };

View file

@ -1,4 +1,5 @@
import React, { FC } from "react"; import React, { FC } from "react";
import { Project } from "../types/Project";
interface IProps { interface IProps {
title: string; title: string;
@ -7,6 +8,9 @@ interface IProps {
setDescription: React.Dispatch<React.SetStateAction<string>>; setDescription: React.Dispatch<React.SetStateAction<string>>;
endingDate: string; endingDate: string;
setEndingDate: React.Dispatch<React.SetStateAction<string>>; setEndingDate: React.Dispatch<React.SetStateAction<string>>;
allProjects: Project[];
projectId: string;
setProjectId: React.Dispatch<React.SetStateAction<string>>;
} }
export const NewTicketForm: FC<IProps> = ({ export const NewTicketForm: FC<IProps> = ({
@ -15,7 +19,10 @@ export const NewTicketForm: FC<IProps> = ({
description, description,
setDescription, setDescription,
endingDate, endingDate,
setEndingDate setEndingDate,
allProjects,
projectId,
setProjectId
}) => { }) => {
return ( return (
<> <>
@ -62,13 +69,23 @@ export const NewTicketForm: FC<IProps> = ({
</div> </div>
<div className="input-field"> <div className="input-field">
<select id="project" className="browser-default"> <select
<option value="" disabled selected> id="project"
className="browser-default"
value={projectId}
onChange={(e: React.ChangeEvent<HTMLSelectElement>) => {
e.preventDefault();
setProjectId(e.target.value);
}}
>
<option value={0} disabled>
Project Project
</option> </option>
<option value="1">Option 1</option> {allProjects.map(p => (
<option value="2">Option 2</option> <option key={p.id} value={p.id}>
<option value="3">Option 3</option> {p.title}
</option>
))}
</select> </select>
</div> </div>
</div> </div>

View file

@ -5,16 +5,23 @@ import { post } from "../utils/http";
import { Constants } from "../utils/Constants"; import { Constants } from "../utils/Constants";
import { HttpResponse } from "../types/HttpResponse"; import { HttpResponse } from "../types/HttpResponse";
import { NewTicketForm } from "./NewTicketForm"; import { NewTicketForm } from "./NewTicketForm";
import { Project } from "../types/Project";
interface IProps { interface IProps {
show: boolean; show: boolean;
handleClose(): void; handleClose(): void;
allProjects: Project[];
} }
export const NewTicketModal: FC<IProps> = ({ show, handleClose }) => { export const NewTicketModal: FC<IProps> = ({
show,
handleClose,
allProjects
}) => {
const [title, setTitle] = useState(""); const [title, setTitle] = useState("");
const [description, setDescription] = useState(""); const [description, setDescription] = useState("");
const [endingDate, setEndingDate] = useState(""); const [endingDate, setEndingDate] = useState("");
const [projectId, setProjectId] = useState("0");
const handleSubmit: (event: FormEvent<HTMLFormElement>) => void = async ( const handleSubmit: (event: FormEvent<HTMLFormElement>) => void = async (
e: FormEvent e: FormEvent
@ -25,7 +32,7 @@ export const NewTicketModal: FC<IProps> = ({ show, handleClose }) => {
description: description, description: description,
endingDate: new Date(endingDate).toISOString(), endingDate: new Date(endingDate).toISOString(),
creatorId: "20bf4b2a-7209-4826-96cd-29c2bc937a94", creatorId: "20bf4b2a-7209-4826-96cd-29c2bc937a94",
projectId: 1 projectId: parseInt(projectId)
}; };
// console.log(newTicket); // console.log(newTicket);
const response: HttpResponse<Ticket> = await post<Ticket>( const response: HttpResponse<Ticket> = await post<Ticket>(
@ -63,6 +70,9 @@ export const NewTicketModal: FC<IProps> = ({ show, handleClose }) => {
setDescription={setDescription} setDescription={setDescription}
endingDate={endingDate} endingDate={endingDate}
setEndingDate={setEndingDate} setEndingDate={setEndingDate}
allProjects={allProjects}
projectId={projectId}
setProjectId={setProjectId}
/> />
</div> </div>

View file

@ -1,7 +1,6 @@
import React, { FC } from "react"; import React, { FC } from "react";
import { useRouteMatch } from "react-router-dom"; import { useRouteMatch } from "react-router-dom";
import { TabRouterHeader } from "./TabRouterHeader"; import { TabRouterHeader } from "./TabRouterHeader";
import { NewTicketForm } from "./NewTicketForm";
interface IProps { interface IProps {
tabNames: string[]; tabNames: string[];
@ -28,14 +27,14 @@ export const NewTicketTabRouter: FC<IProps> = ({
<div className="row"> <div className="row">
<TabRouterHeader tabNames={tabNames} /> <TabRouterHeader tabNames={tabNames} />
<NewTicketForm {/* <NewTicketForm
title={title} title={title}
setTitle={setTitle} setTitle={setTitle}
description={description} description={description}
setDescription={setDescription} setDescription={setDescription}
endingDate={endingDate} endingDate={endingDate}
setEndingDate={setEndingDate} setEndingDate={setEndingDate}
/> /> */}
</div> </div>
</> </>
); );

View file

@ -7,6 +7,7 @@ import { FileList } from "./AppFileList";
import { Ticket } from "../types/Ticket"; import { Ticket } from "../types/Ticket";
import { AppFile } from "../types/AppFile"; import { AppFile } from "../types/AppFile";
import { Activity } from "../types/Activity"; import { Activity } from "../types/Activity";
import { Project } from "../types/Project";
interface IProps { interface IProps {
tickets: Ticket[]; tickets: Ticket[];
@ -14,13 +15,15 @@ interface IProps {
tabNames: string[]; tabNames: string[];
files: AppFile[]; files: AppFile[];
activities: Activity[]; activities: Activity[];
allProjects: Project[];
} }
export const TabRouter: FC<IProps> = ({ export const TabRouter: FC<IProps> = ({
tickets, tickets,
tabNames, tabNames,
files, files,
activities activities,
allProjects
}) => { }) => {
const { url } = useRouteMatch(); const { url } = useRouteMatch();
@ -32,7 +35,7 @@ export const TabRouter: FC<IProps> = ({
<Redirect from={url} to={`${url}/tickets`} /> <Redirect from={url} to={`${url}/tickets`} />
<Route path={`${url}/tickets`}> <Route path={`${url}/tickets`}>
<TicketList tickets={tickets} /> <TicketList tickets={tickets} allProjects={allProjects} />
</Route> </Route>
<Route path={`${url}/files`}> <Route path={`${url}/files`}>

View file

@ -7,12 +7,14 @@ import { HttpResponse } from "../types/HttpResponse";
import { put } from "../utils/http"; import { put } from "../utils/http";
import { Constants } from "../utils/Constants"; import { Constants } from "../utils/Constants";
import { NewTicketModal } from "./NewTicketModal"; import { NewTicketModal } from "./NewTicketModal";
import { Project } from "../types/Project";
type TicketListProps = { type TicketListProps = {
tickets: Ticket[]; tickets: Ticket[];
allProjects: Project[];
}; };
export const TicketList: FC<TicketListProps> = ({ tickets }) => { export const TicketList: FC<TicketListProps> = ({ tickets, allProjects }) => {
const [filterText, setFilterText] = useState<string>(""); const [filterText, setFilterText] = useState<string>("");
const clearFilterText: (e: MouseEvent) => void = (e: MouseEvent) => { const clearFilterText: (e: MouseEvent) => void = (e: MouseEvent) => {
setFilterText(""); setFilterText("");
@ -42,6 +44,7 @@ export const TicketList: FC<TicketListProps> = ({ tickets }) => {
setShowNew(false); setShowNew(false);
}} }}
show={showNew} show={showNew}
allProjects={allProjects}
/> />
<h3>Tickets</h3> <h3>Tickets</h3>
<FloatingButton <FloatingButton

View file

@ -4,6 +4,7 @@ import { TabRouterHeader } from "./TabRouterHeader";
import { ProjectList } from "./ProjectList"; import { ProjectList } from "./ProjectList";
import { Ticket } from "../types/Ticket"; import { Ticket } from "../types/Ticket";
import { Project } from "../types/Project"; import { Project } from "../types/Project";
import { TicketList } from "./TicketList";
interface IProps { interface IProps {
tabNames: string[]; tabNames: string[];
@ -25,9 +26,9 @@ export const UserTabRouter: FC<IProps> = ({ tickets, tabNames, projects }) => {
<ProjectList projects={projects} /> <ProjectList projects={projects} />
</Route> </Route>
{/* <Route path={`${url}/tickets`}> <Route path={`${url}/tickets`}>
<TicketList tickets={tickets} /> <TicketList tickets={tickets} allProjects={[]} />
</Route> */} </Route>
</div> </div>
</> </>
); );

View file

@ -13,6 +13,7 @@ import { User } from "../types/User";
export const ProjectController: FC = () => { export const ProjectController: FC = () => {
const [project, setProject] = useState<Project>({} as Project); const [project, setProject] = useState<Project>({} as Project);
const [allUsers, setAllUsers] = useState<User[]>([]); const [allUsers, setAllUsers] = useState<User[]>([]);
const [allProjects, setAllProjects] = useState<Project[]>([]);
const [isLoading, setIsLoading] = useState(true); const [isLoading, setIsLoading] = useState(true);
const [hasError, setHasError] = useState(false); const [hasError, setHasError] = useState(false);
const [error, setError] = useState(""); const [error, setError] = useState("");
@ -48,10 +49,25 @@ export const ProjectController: FC = () => {
} }
} }
async function httpGetAllProjects(): Promise<void> {
try {
const response: HttpResponse<Project> = await get<Project>(
`${Constants.projectsURI}`
);
if (response.parsedBody !== undefined) {
setAllProjects((response.parsedBody as unknown) as Project[]);
}
} catch (ex) {
setHasError(true);
setError(ex);
}
}
useEffect(() => { useEffect(() => {
if (id !== undefined) { if (id !== undefined) {
httpGetProjects(id); httpGetProjects(id);
httpGetAllUsers(); httpGetAllUsers();
httpGetAllProjects();
} else { } else {
setHasError(true); setHasError(true);
setError("Bad Request"); setError("Bad Request");
@ -61,6 +77,6 @@ export const ProjectController: FC = () => {
if (hasError) { if (hasError) {
return <ErrorController error={error} />; return <ErrorController error={error} />;
} }
const viewModel = new ProjectVM(project, allUsers); const viewModel = new ProjectVM(project, allUsers, allProjects);
return isLoading ? <Preloader /> : <ProjectPage viewModel={viewModel} />; return isLoading ? <Preloader /> : <ProjectPage viewModel={viewModel} />;
}; };

View file

@ -13,6 +13,7 @@ interface IProps {
export const ProjectPage: FC<IProps> = ({ viewModel }) => { export const ProjectPage: FC<IProps> = ({ viewModel }) => {
const { const {
// id,
title, title,
description, description,
users, users,
@ -23,7 +24,8 @@ export const ProjectPage: FC<IProps> = ({ viewModel }) => {
ticketsTotalCount, ticketsTotalCount,
remainingDays, remainingDays,
files, files,
activities activities,
allProjects
} = viewModel; } = viewModel;
const tabNames: string[] = ["Tickets", "Files"]; //, "Activity"]; const tabNames: string[] = ["Tickets", "Files"]; //, "Activity"];
@ -59,6 +61,7 @@ export const ProjectPage: FC<IProps> = ({ viewModel }) => {
tickets={tickets} tickets={tickets}
files={files} files={files}
activities={activities} activities={activities}
allProjects={allProjects}
/> />
</div> </div>
</div> </div>

View file

@ -23,10 +23,6 @@ export const UserPage: FC<IProps> = ({ viewModel }) => {
tickets={tickets} tickets={tickets}
/> />
</div> </div>
{/* // <TabView>
// <CardList>
// <CardList>
// </TabView> */}
</div> </div>
); );
}; };