mirror of
https://github.com/rjNemo/ticket_manager
synced 2026-06-12 03:36:39 +00:00
added manage user layout to project page
This commit is contained in:
parent
6cf52b256b
commit
d6d46f2850
7 changed files with 129 additions and 29 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -7,4 +7,5 @@ app.db*
|
||||||
.DS_Store
|
.DS_Store
|
||||||
app.db
|
app.db
|
||||||
client/node_modules
|
client/node_modules
|
||||||
|
client/src/pages/TestPage.tsx
|
||||||
Scripts/
|
Scripts/
|
||||||
|
|
|
||||||
25
README.md
25
README.md
|
|
@ -33,15 +33,16 @@
|
||||||
|
|
||||||
## TO DO
|
## TO DO
|
||||||
|
|
||||||
- Write API tests using Postman: request + test, environment variables, mock server
|
- [ ] Write API tests using Postman: request + test, environment variables, mock server
|
||||||
- Annotate API request in controllers
|
- [ ] Annotate API request in controllers
|
||||||
- Annotate Properties in Models
|
- [ ] Annotate Properties in Models
|
||||||
- Write backend tests
|
- [ ] Write backend tests
|
||||||
- Have a Look at typeahead component
|
- [ ] Have a Look at typeahead component
|
||||||
- Ensure Tickets Edits belong to Project Edits
|
- [ ] Ensure Tickets Edits belong to Project Edits
|
||||||
- Ensure Tickets Files belong to Project Files
|
- [ ] Ensure Tickets Files belong to Project Files
|
||||||
- Async model methods ?
|
- [ ] Async model methods ?
|
||||||
- update assignments automatically from context
|
- [ ] update assignments automatically from context
|
||||||
- use PATCH instead of PUT
|
- [ ] use PATCH instead of PUT
|
||||||
- logging
|
- [ ] logging
|
||||||
- check useRef, useReducer, dispatch
|
- [ ] check useRef, useReducer, dispatch
|
||||||
|
- [ ] error page redirect when offline.
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ export const FilterBar: FC<IProps> = ({
|
||||||
clearFilterText
|
clearFilterText
|
||||||
}) => {
|
}) => {
|
||||||
const { url } = useRouteMatch();
|
const { url } = useRouteMatch();
|
||||||
const placeholder: string = url.split("/")[3];
|
const placeholder: string = url.split("/")[3] || "users";
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="nav-wrapper">
|
<div className="nav-wrapper">
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,24 @@
|
||||||
import React, { FC } from "react";
|
import React, { FC, useState, CSSProperties } from "react";
|
||||||
|
|
||||||
export const Modal: FC = () => {
|
interface IProps {
|
||||||
|
handleClose: () => void;
|
||||||
|
show: boolean;
|
||||||
|
}
|
||||||
|
export const Modal: FC<IProps> = ({ handleClose, show, children }) => {
|
||||||
|
const showHideStyle: CSSProperties = show
|
||||||
|
? { display: "block", zIndex: 10 }
|
||||||
|
: { display: "none", zIndex: 10 };
|
||||||
return (
|
return (
|
||||||
<div id="modal1" className="modal">
|
<div className="modal" style={showHideStyle}>
|
||||||
<div className="modal-content">
|
<div className="modal-content">{children}</div>
|
||||||
<h4>Modal Header</h4>
|
{/* <div className="modal-footer">
|
||||||
<p>A bunch of text</p>
|
<button
|
||||||
</div>
|
className="modal-close waves-effect waves-green btn-flat"
|
||||||
<div className="modal-footer">
|
onClick={handleClose}
|
||||||
<a href="#!" className="modal-close waves-effect waves-green btn-flat">
|
>
|
||||||
Agree
|
close
|
||||||
</a>
|
</button>
|
||||||
</div>
|
</div> */}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
73
client/src/components/UsersModal.tsx
Normal file
73
client/src/components/UsersModal.tsx
Normal file
|
|
@ -0,0 +1,73 @@
|
||||||
|
import React, { FC, useState, ChangeEvent } from "react";
|
||||||
|
import { Modal } from "./Modal";
|
||||||
|
import { AvatarList } from "./AvatarList";
|
||||||
|
import { User } from "../types/User";
|
||||||
|
import { FilterBar } from "./FilterBar";
|
||||||
|
|
||||||
|
interface IProps {
|
||||||
|
show: boolean;
|
||||||
|
handleClose: () => void;
|
||||||
|
users: User[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export const UsersModal: FC<IProps> = ({ show, handleClose, users }) => {
|
||||||
|
const [filterText, setFilterText] = useState<string>("");
|
||||||
|
const handleChange: (e: ChangeEvent<HTMLInputElement>) => void = (
|
||||||
|
e: ChangeEvent<HTMLInputElement>
|
||||||
|
) => {
|
||||||
|
setFilterText(e.target.value);
|
||||||
|
};
|
||||||
|
return (
|
||||||
|
<Modal show={show} handleClose={handleClose}>
|
||||||
|
<div className="row valign-wrapper blue">
|
||||||
|
<div className="col s10">
|
||||||
|
<h4 className="white-text">Manage users</h4>
|
||||||
|
</div>
|
||||||
|
<div className="col s2">
|
||||||
|
<i
|
||||||
|
className="right material-icons blue lighten-3 circle"
|
||||||
|
onClick={handleClose}
|
||||||
|
>
|
||||||
|
close
|
||||||
|
</i>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="center">
|
||||||
|
<AvatarList users={users} />
|
||||||
|
<FilterBar
|
||||||
|
filterText={filterText}
|
||||||
|
clearFilterText={() => setFilterText("")}
|
||||||
|
handleChange={handleChange}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<form>
|
||||||
|
<ul>
|
||||||
|
{users.map((u: User) => (
|
||||||
|
<li key={u.id}>
|
||||||
|
<div className="row">
|
||||||
|
<input
|
||||||
|
id={u.id}
|
||||||
|
type="checkbox"
|
||||||
|
name="active"
|
||||||
|
value="true"
|
||||||
|
onChange={() => false}
|
||||||
|
// checked
|
||||||
|
/>
|
||||||
|
<span>
|
||||||
|
{u.fullName}
|
||||||
|
<img
|
||||||
|
className="circle"
|
||||||
|
src={u.picture}
|
||||||
|
width="32vh"
|
||||||
|
height="32vh"
|
||||||
|
alt={u.fullName}
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
</form>
|
||||||
|
</Modal>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
@ -1,15 +1,16 @@
|
||||||
import React, { FC } from "react";
|
import React, { FC, useState } from "react";
|
||||||
|
import ProjectVM from "../VM/ProjectVM";
|
||||||
import { Header } from "../components/Header";
|
import { Header } from "../components/Header";
|
||||||
import { AvatarList } from "../components/AvatarList";
|
import { AvatarList } from "../components/AvatarList";
|
||||||
import { ProgressBar } from "../components/ProgressBar";
|
import { ProgressBar } from "../components/ProgressBar";
|
||||||
import ProjectVM from "../VM/ProjectVM";
|
|
||||||
import { TabRouter } from "../components/TabRouter";
|
import { TabRouter } from "../components/TabRouter";
|
||||||
import { FloatingButton } from "../components/FloatingButton";
|
import { FloatingButton } from "../components/FloatingButton";
|
||||||
import { Modal } from "../components/Modal";
|
import { UsersModal } from "../components/UsersModal";
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
viewModel: ProjectVM;
|
viewModel: ProjectVM;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const ProjectPage: FC<IProps> = ({ viewModel }) => {
|
export const ProjectPage: FC<IProps> = ({ viewModel }) => {
|
||||||
const {
|
const {
|
||||||
title,
|
title,
|
||||||
|
|
@ -23,7 +24,9 @@ export const ProjectPage: FC<IProps> = ({ viewModel }) => {
|
||||||
files,
|
files,
|
||||||
activities
|
activities
|
||||||
} = viewModel;
|
} = viewModel;
|
||||||
|
|
||||||
const tabNames: string[] = ["Tickets", "Files", "Activity"];
|
const tabNames: string[] = ["Tickets", "Files", "Activity"];
|
||||||
|
const [showModal, setShowModal] = useState<boolean>(false);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="section">
|
<div className="section">
|
||||||
|
|
@ -31,7 +34,17 @@ export const ProjectPage: FC<IProps> = ({ viewModel }) => {
|
||||||
<Header title={title} description={description} />
|
<Header title={title} description={description} />
|
||||||
<div className="row valign-wrapper">
|
<div className="row valign-wrapper">
|
||||||
<AvatarList users={users} />
|
<AvatarList users={users} />
|
||||||
<FloatingButton icon="add" color="grey" size="small" />
|
<FloatingButton
|
||||||
|
icon="add"
|
||||||
|
color="grey"
|
||||||
|
size="small"
|
||||||
|
onClick={() => setShowModal(true)}
|
||||||
|
/>
|
||||||
|
<UsersModal
|
||||||
|
show={showModal}
|
||||||
|
users={users}
|
||||||
|
handleClose={() => setShowModal(false)}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<ProgressBar
|
<ProgressBar
|
||||||
value={value}
|
value={value}
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ import * as creacteHistory from "history";
|
||||||
// import { HomeController } from "../controllers/HomeController";
|
// import { HomeController } from "../controllers/HomeController";
|
||||||
import { ProjectController } from "../controllers/ProjectController";
|
import { ProjectController } from "../controllers/ProjectController";
|
||||||
import { NotFoundPage } from "../pages/NotFoundPage";
|
import { NotFoundPage } from "../pages/NotFoundPage";
|
||||||
|
import { TestPage } from "../pages/TestPage";
|
||||||
// import { UserController } from "../controllers/UserController";
|
// import { UserController } from "../controllers/UserController";
|
||||||
// import { TicketController } from "../controllers/TicketController";
|
// import { TicketController } from "../controllers/TicketController";
|
||||||
|
|
||||||
|
|
@ -21,6 +22,10 @@ export const AppRouter = () => {
|
||||||
<Router history={history}>
|
<Router history={history}>
|
||||||
<div className="grey lighten-4">
|
<div className="grey lighten-4">
|
||||||
<Switch>
|
<Switch>
|
||||||
|
<Route exact path="/">
|
||||||
|
<TestPage />
|
||||||
|
</Route>
|
||||||
|
|
||||||
{/* <Route path="/">
|
{/* <Route path="/">
|
||||||
<HomeController />
|
<HomeController />
|
||||||
</Route>
|
</Route>
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue