mirror of
https://github.com/rjNemo/ticket_manager
synced 2026-06-11 19:26:40 +00:00
Default placeholder for empty ticket and file lists. Pick a random color Indigo as main
This commit is contained in:
parent
50d2b8b86a
commit
86fd097481
10 changed files with 129 additions and 87 deletions
|
|
@ -46,7 +46,7 @@
|
||||||
- [ ] logging
|
- [ ] logging
|
||||||
- [ ] check useRef, useReducer, dispatch
|
- [ ] check useRef, useReducer, dispatch
|
||||||
- [ ] error page redirect when offline.
|
- [ ] error page redirect when offline.
|
||||||
- [ ] ticket/files/activities list placeholders when empty
|
- [x] ticket/files/activities list placeholders when empty
|
||||||
- [ ] think about public/private DTO's constructor, getters and setters
|
- [ ] think about public/private DTO's constructor, getters and setters
|
||||||
- [x] write dtos without circular dependencies
|
- [x] write dtos without circular dependencies
|
||||||
- [ ] use dtoRequest for PutProjects
|
- [ ] use dtoRequest for PutProjects
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
import React, { FC } from "react";
|
import React, { FC } from "react";
|
||||||
import { Activity } from "../types/Activity";
|
import { Activity } from "../types/Activity";
|
||||||
|
import { act } from "react-dom/test-utils";
|
||||||
|
|
||||||
type IProps = {
|
type IProps = {
|
||||||
activities: Activity[];
|
activities: Activity[];
|
||||||
|
|
@ -12,38 +13,58 @@ export const ActivityCollection: FC<IProps> = ({ activities, filterText }) => {
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
<ul className="collection">
|
<ul className="collection">
|
||||||
{activities
|
{activities.length === 0 ? (
|
||||||
.filter(
|
<ActivityEntry />
|
||||||
a =>
|
) : (
|
||||||
a.description.toLowerCase().includes(filterText.toLowerCase()) ||
|
activities
|
||||||
a.user.firstName
|
.filter(
|
||||||
.toLowerCase()
|
a =>
|
||||||
.includes(filterText.toLowerCase()) ||
|
a.description
|
||||||
a.ticket.title.toLowerCase().includes(filterText.toLowerCase())
|
.toLowerCase()
|
||||||
)
|
.includes(filterText.toLowerCase()) ||
|
||||||
.map((activity: Activity) => (
|
a.user.firstName
|
||||||
<li key={activity.id} className="collection-item avatar">
|
.toLowerCase()
|
||||||
<ActivityEntry activity={activity} />
|
.includes(filterText.toLowerCase()) ||
|
||||||
</li>
|
a.ticket.title.toLowerCase().includes(filterText.toLowerCase())
|
||||||
))}
|
)
|
||||||
|
.map((activity: Activity) => (
|
||||||
|
<ActivityEntry activity={activity} key={activity.id} />
|
||||||
|
))
|
||||||
|
)}
|
||||||
</ul>
|
</ul>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
type IFProps = {
|
type IFProps = {
|
||||||
activity: Activity;
|
activity?: Activity;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const ActivityEntry: FC<IFProps> = ({ activity }) => {
|
export const ActivityEntry: FC<IFProps> = ({ activity }) => {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<img src={activity.user.picture} alt="" className="circle" />
|
<li className="collection-item avatar">
|
||||||
{/* <i className="material-icons circle">folder</i> */}
|
{/* <img
|
||||||
<span className="title">
|
src={
|
||||||
{activity.user.firstName} {activity.description} {activity.ticket.title}
|
activity
|
||||||
</span>
|
? activity.user.picture
|
||||||
<p>{activity.date.toDateString()}</p>
|
: "https://previews.123rf.com/images/vikpit/vikpit1604/vikpit160400034/54976526-welcome-sign-symbol-word-welcome-hand-lettering-calligraphic-font-letters-and-shade-isolated-on-whit.jpg"
|
||||||
|
}
|
||||||
|
alt=""
|
||||||
|
height="32vh"
|
||||||
|
width="32vh"
|
||||||
|
className="circle"
|
||||||
|
/> */}
|
||||||
|
<i className="material-icons circle indigo lighten-1">folder</i>
|
||||||
|
<span className="title">
|
||||||
|
{activity ? activity.user.firstName : "Ruidy"}
|
||||||
|
{activity ? activity.description : " welcomes you "}
|
||||||
|
{activity ? activity.ticket.title : "here"}
|
||||||
|
</span>
|
||||||
|
<p>
|
||||||
|
{activity ? activity.date.toDateString() : new Date().toDateString()}
|
||||||
|
</p>
|
||||||
|
</li>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -7,35 +7,38 @@ type IProps = {
|
||||||
};
|
};
|
||||||
|
|
||||||
export const FileCollection: FC<IProps> = ({ files, filterText }) => {
|
export const FileCollection: FC<IProps> = ({ files, filterText }) => {
|
||||||
|
console.log();
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<ul className="collection">
|
<ul className="collection">
|
||||||
{files
|
{files.length === 0 ? (
|
||||||
.filter(
|
<FileEntry />
|
||||||
f =>
|
) : (
|
||||||
f.name.toLowerCase().includes(filterText.toLowerCase()) ||
|
files
|
||||||
f.format.toLowerCase().includes(filterText.toLowerCase())
|
.filter(
|
||||||
)
|
f =>
|
||||||
.map((file: AppFile) => (
|
f.name.toLowerCase().includes(filterText.toLowerCase()) ||
|
||||||
<FileEntry file={file} key={file.id} />
|
f.format.toLowerCase().includes(filterText.toLowerCase())
|
||||||
))}
|
)
|
||||||
|
.map((file: AppFile) => <FileEntry file={file} key={file.id} />)
|
||||||
|
)}
|
||||||
</ul>
|
</ul>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
type IFProps = {
|
type IFProps = {
|
||||||
file: AppFile;
|
file?: AppFile;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const FileEntry: FC<IFProps> = ({ file }) => {
|
export const FileEntry: FC<IFProps> = ({ file }) => {
|
||||||
return (
|
return (
|
||||||
<li className="collection-item avatar">
|
<li className="collection-item avatar">
|
||||||
{/* <img src={require("../images/user_1.jpg")} alt="" className="circle" /> */}
|
{/* <img src={require("../images/user_1.jpg")} alt="" className="circle" /> */}
|
||||||
<i className="material-icons circle">folder</i>
|
<i className="material-icons circle indigo lighten-1">folder</i>
|
||||||
<span className="title">{file.name}</span>
|
<span className="title">{file ? file.name : "Add your first file"}</span>
|
||||||
<p>
|
<p>
|
||||||
{file.size}kb {file.format}
|
{file ? file.size : 0}kb {file ? file.format : "pdf"}
|
||||||
</p>
|
</p>
|
||||||
<a href="#!" className="secondary-content">
|
<a href="#!" className="secondary-content">
|
||||||
<i className="material-icons">more_vert</i>
|
<i className="material-icons">more_vert</i>
|
||||||
|
|
|
||||||
|
|
@ -3,9 +3,9 @@ import { Link } from "react-router-dom";
|
||||||
import { getRemainingdays } from "../utils/methods";
|
import { getRemainingdays } from "../utils/methods";
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
title: string;
|
title?: string;
|
||||||
remainingDays: string;
|
remainingDays?: string;
|
||||||
validateTicket: (event: MouseEvent) => void;
|
validateTicket?: (event: MouseEvent) => void;
|
||||||
// archiveTicket: (event: MouseEvent) => void;
|
// archiveTicket: (event: MouseEvent) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -16,33 +16,45 @@ export const HorizontalCard: FC<IProps> = ({
|
||||||
validateTicket
|
validateTicket
|
||||||
}) => {
|
}) => {
|
||||||
return (
|
return (
|
||||||
<div className="card horizontal">
|
<li>
|
||||||
<div className="card-stacked">
|
<div className="card horizontal">
|
||||||
<div className="card-content">
|
<div className="card-stacked">
|
||||||
<div className="row">
|
<div className="card-content">
|
||||||
<div className="card-title">
|
<div className="row">
|
||||||
<h6>
|
<div className="card-title">
|
||||||
|
<h6>
|
||||||
|
<Link to="#">
|
||||||
|
<b>{title ?? "Nothing to do"}</b>
|
||||||
|
</Link>
|
||||||
|
</h6>
|
||||||
|
</div>
|
||||||
|
<span>
|
||||||
|
Due{" "}
|
||||||
|
{remainingDays ? (
|
||||||
|
getRemainingdays(remainingDays)
|
||||||
|
) : (
|
||||||
|
<span>
|
||||||
|
<del>Too much</del> 0
|
||||||
|
</span>
|
||||||
|
)}{" "}
|
||||||
|
days
|
||||||
|
</span>
|
||||||
|
<div className="right">
|
||||||
<Link to="#">
|
<Link to="#">
|
||||||
<b>{title}</b>
|
<i className="material-icons" onClick={validateTicket}>
|
||||||
|
check
|
||||||
|
</i>
|
||||||
</Link>
|
</Link>
|
||||||
</h6>
|
{/* <Link to="#">
|
||||||
</div>
|
|
||||||
<span>Due {getRemainingdays(remainingDays)} days</span>
|
|
||||||
<div className="right">
|
|
||||||
<Link to="#">
|
|
||||||
<i className="material-icons" onClick={validateTicket}>
|
|
||||||
check
|
|
||||||
</i>
|
|
||||||
</Link>
|
|
||||||
{/* <Link to="#">
|
|
||||||
<i className="material-icons" onClick={archiveTicket}>
|
<i className="material-icons" onClick={archiveTicket}>
|
||||||
archive
|
archive
|
||||||
</i>
|
</i>
|
||||||
</Link> */}
|
</Link> */}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</li>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ export const InputFile: FC<IProps> = () => {
|
||||||
<>
|
<>
|
||||||
<form action="/upload">
|
<form action="/upload">
|
||||||
<div className="file-field input-field">
|
<div className="file-field input-field">
|
||||||
<div className="btn">
|
<div className="btn indigo lighten-1">
|
||||||
<i className="material-icons ">cloud_upload</i>
|
<i className="material-icons ">cloud_upload</i>
|
||||||
<input
|
<input
|
||||||
type="file"
|
type="file"
|
||||||
|
|
|
||||||
|
|
@ -16,11 +16,12 @@ export const ProgressBar: FC<ProgressBarProps> = ({
|
||||||
remainingDays
|
remainingDays
|
||||||
}) => {
|
}) => {
|
||||||
const styleString: CSSProperties = { width: `${value}%` };
|
const styleString: CSSProperties = { width: `${value}%` };
|
||||||
|
const barColor: string = value < 75 ? "red" : "";
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="row">
|
<div className="row">
|
||||||
<div className="progress">
|
<div className="progress">
|
||||||
<div className="determinate" style={styleString}></div>
|
<div className={`determinate ${barColor}`} style={styleString}></div>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<i className="left material-icons">playlist_add_check</i>
|
<i className="left material-icons">playlist_add_check</i>
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ export const TabRouterHeader: FC<IProps> = ({
|
||||||
const nTabs = tabNames.length;
|
const nTabs = tabNames.length;
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<ul className="tabs z-depth-1">
|
<ul className="tabs">
|
||||||
{tabNames.map((name, i) => (
|
{tabNames.map((name, i) => (
|
||||||
<TabUnit
|
<TabUnit
|
||||||
key={i}
|
key={i}
|
||||||
|
|
@ -27,7 +27,7 @@ export const TabRouterHeader: FC<IProps> = ({
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
<li
|
<li
|
||||||
className="indicator"
|
className="indicator indigo lighten-2"
|
||||||
style={{
|
style={{
|
||||||
left: `${(isActive / nTabs) * 100}%`,
|
left: `${(isActive / nTabs) * 100}%`,
|
||||||
right: `${(1 - (isActive + 1) / nTabs) * 100}%`
|
right: `${(1 - (isActive + 1) / nTabs) * 100}%`
|
||||||
|
|
@ -68,7 +68,11 @@ const TabUnit: FC<TabUnitProps> = ({
|
||||||
<Link
|
<Link
|
||||||
to={`${url}/${text}`}
|
to={`${url}/${text}`}
|
||||||
id={value}
|
id={value}
|
||||||
className={isActive === parseInt(value) ? "active pink lighten-5" : ""}
|
className={
|
||||||
|
isActive === parseInt(value)
|
||||||
|
? "active indigo lighten-5 indigo-text"
|
||||||
|
: "indigo-text"
|
||||||
|
}
|
||||||
onClick={() => setIsActive(parseInt(value))}
|
onClick={() => setIsActive(parseInt(value))}
|
||||||
>
|
>
|
||||||
{text}
|
{text}
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,11 @@ export const TicketList: FC<TicketListProps> = ({ tickets }) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
const [showNew, setShowNew] = useState(false);
|
const [showNew, setShowNew] = useState(false);
|
||||||
|
let filteredTickets = tickets.filter(
|
||||||
|
t =>
|
||||||
|
t.status !== "Done" &&
|
||||||
|
t.title.toLowerCase().includes(filterText.toLowerCase())
|
||||||
|
);
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="row valign-wrapper">
|
<div className="row valign-wrapper">
|
||||||
|
|
@ -42,7 +46,7 @@ export const TicketList: FC<TicketListProps> = ({ tickets }) => {
|
||||||
/>
|
/>
|
||||||
<h3>Tickets</h3>
|
<h3>Tickets</h3>
|
||||||
<FloatingButton
|
<FloatingButton
|
||||||
color=" blue-grey lighten-4"
|
color="indigo lighten-1"
|
||||||
size="small"
|
size="small"
|
||||||
onClick={onClick}
|
onClick={onClick}
|
||||||
/>
|
/>
|
||||||
|
|
@ -54,28 +58,25 @@ export const TicketList: FC<TicketListProps> = ({ tickets }) => {
|
||||||
</div>
|
</div>
|
||||||
<div className="col s12 grey">
|
<div className="col s12 grey">
|
||||||
<ul>
|
<ul>
|
||||||
{tickets
|
{filteredTickets.length === 0 ? (
|
||||||
.filter(
|
<HorizontalCard />
|
||||||
t =>
|
) : (
|
||||||
t.status !== "Done" &&
|
filteredTickets.map((t: Ticket) => (
|
||||||
t.title.toLowerCase().includes(filterText.toLowerCase())
|
<HorizontalCard
|
||||||
)
|
key={t.id}
|
||||||
.map((t: Ticket) => (
|
title={t.title}
|
||||||
<li key={t.id}>
|
remainingDays={t.plannedEnding}
|
||||||
<HorizontalCard
|
validateTicket={async (e: MouseEvent) => {
|
||||||
title={t.title}
|
e.preventDefault();
|
||||||
remainingDays={t.plannedEnding}
|
await put<HttpResponse<Ticket>>(
|
||||||
validateTicket={async (e: MouseEvent) => {
|
`${Constants.ticketsURI}/${t.id}/closed`,
|
||||||
e.preventDefault();
|
{}
|
||||||
await put<HttpResponse<Ticket>>(
|
);
|
||||||
`${Constants.ticketsURI}/${t.id}/closed`,
|
}}
|
||||||
{}
|
// archiveTicket={archiveTicket}
|
||||||
);
|
/>
|
||||||
}}
|
))
|
||||||
// archiveTicket={archiveTicket}
|
)}
|
||||||
/>
|
|
||||||
</li>
|
|
||||||
))}
|
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,7 @@ export const ProjectPage: FC<IProps> = ({ viewModel }) => {
|
||||||
<AvatarList users={users} />
|
<AvatarList users={users} />
|
||||||
<FloatingButton
|
<FloatingButton
|
||||||
icon="add"
|
icon="add"
|
||||||
color="grey"
|
color="indigo lighten-1"
|
||||||
size="small"
|
size="small"
|
||||||
onClick={() => setShowModal(true)}
|
onClick={() => setShowModal(true)}
|
||||||
/>
|
/>
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ export const history = creacteHistory.createBrowserHistory();
|
||||||
export const AppRouter = () => {
|
export const AppRouter = () => {
|
||||||
return (
|
return (
|
||||||
<Router history={history}>
|
<Router history={history}>
|
||||||
<div className="grey lighten-4">
|
<div className="grey lighten-3">
|
||||||
<Switch>
|
<Switch>
|
||||||
<Route exact path="/">
|
<Route exact path="/">
|
||||||
<TestPage />
|
<TestPage />
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue