Default placeholder for empty ticket and file lists. Pick a random color Indigo as main

This commit is contained in:
Ruidy Nemausat 2020-02-29 14:07:26 +01:00
parent 50d2b8b86a
commit 86fd097481
10 changed files with 129 additions and 87 deletions

View file

@ -46,7 +46,7 @@
- [ ] logging
- [ ] check useRef, useReducer, dispatch
- [ ] 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
- [x] write dtos without circular dependencies
- [ ] use dtoRequest for PutProjects

View file

@ -1,5 +1,6 @@
import React, { FC } from "react";
import { Activity } from "../types/Activity";
import { act } from "react-dom/test-utils";
type IProps = {
activities: Activity[];
@ -12,38 +13,58 @@ export const ActivityCollection: FC<IProps> = ({ activities, filterText }) => {
) : (
<>
<ul className="collection">
{activities
.filter(
a =>
a.description.toLowerCase().includes(filterText.toLowerCase()) ||
a.user.firstName
.toLowerCase()
.includes(filterText.toLowerCase()) ||
a.ticket.title.toLowerCase().includes(filterText.toLowerCase())
)
.map((activity: Activity) => (
<li key={activity.id} className="collection-item avatar">
<ActivityEntry activity={activity} />
</li>
))}
{activities.length === 0 ? (
<ActivityEntry />
) : (
activities
.filter(
a =>
a.description
.toLowerCase()
.includes(filterText.toLowerCase()) ||
a.user.firstName
.toLowerCase()
.includes(filterText.toLowerCase()) ||
a.ticket.title.toLowerCase().includes(filterText.toLowerCase())
)
.map((activity: Activity) => (
<ActivityEntry activity={activity} key={activity.id} />
))
)}
</ul>
</>
);
};
type IFProps = {
activity: Activity;
activity?: Activity;
};
export const ActivityEntry: FC<IFProps> = ({ activity }) => {
return (
<>
<img src={activity.user.picture} alt="" className="circle" />
{/* <i className="material-icons circle">folder</i> */}
<span className="title">
{activity.user.firstName} {activity.description} {activity.ticket.title}
</span>
<p>{activity.date.toDateString()}</p>
<li className="collection-item avatar">
{/* <img
src={
activity
? activity.user.picture
: "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>
</>
);
};

View file

@ -7,35 +7,38 @@ type IProps = {
};
export const FileCollection: FC<IProps> = ({ files, filterText }) => {
console.log();
return (
<>
<ul className="collection">
{files
.filter(
f =>
f.name.toLowerCase().includes(filterText.toLowerCase()) ||
f.format.toLowerCase().includes(filterText.toLowerCase())
)
.map((file: AppFile) => (
<FileEntry file={file} key={file.id} />
))}
{files.length === 0 ? (
<FileEntry />
) : (
files
.filter(
f =>
f.name.toLowerCase().includes(filterText.toLowerCase()) ||
f.format.toLowerCase().includes(filterText.toLowerCase())
)
.map((file: AppFile) => <FileEntry file={file} key={file.id} />)
)}
</ul>
</>
);
};
type IFProps = {
file: AppFile;
file?: AppFile;
};
export const FileEntry: FC<IFProps> = ({ file }) => {
return (
<li className="collection-item avatar">
{/* <img src={require("../images/user_1.jpg")} alt="" className="circle" /> */}
<i className="material-icons circle">folder</i>
<span className="title">{file.name}</span>
<i className="material-icons circle indigo lighten-1">folder</i>
<span className="title">{file ? file.name : "Add your first file"}</span>
<p>
{file.size}kb {file.format}
{file ? file.size : 0}kb {file ? file.format : "pdf"}
</p>
<a href="#!" className="secondary-content">
<i className="material-icons">more_vert</i>

View file

@ -3,9 +3,9 @@ import { Link } from "react-router-dom";
import { getRemainingdays } from "../utils/methods";
interface IProps {
title: string;
remainingDays: string;
validateTicket: (event: MouseEvent) => void;
title?: string;
remainingDays?: string;
validateTicket?: (event: MouseEvent) => void;
// archiveTicket: (event: MouseEvent) => void;
}
@ -16,33 +16,45 @@ export const HorizontalCard: FC<IProps> = ({
validateTicket
}) => {
return (
<div className="card horizontal">
<div className="card-stacked">
<div className="card-content">
<div className="row">
<div className="card-title">
<h6>
<li>
<div className="card horizontal">
<div className="card-stacked">
<div className="card-content">
<div className="row">
<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="#">
<b>{title}</b>
<i className="material-icons" onClick={validateTicket}>
check
</i>
</Link>
</h6>
</div>
<span>Due {getRemainingdays(remainingDays)} days</span>
<div className="right">
<Link to="#">
<i className="material-icons" onClick={validateTicket}>
check
</i>
</Link>
{/* <Link to="#">
{/* <Link to="#">
<i className="material-icons" onClick={archiveTicket}>
archive
</i>
</Link> */}
</div>
</div>
</div>
</div>
</div>
</div>
</li>
);
};

View file

@ -7,7 +7,7 @@ export const InputFile: FC<IProps> = () => {
<>
<form action="/upload">
<div className="file-field input-field">
<div className="btn">
<div className="btn indigo lighten-1">
<i className="material-icons ">cloud_upload</i>
<input
type="file"

View file

@ -16,11 +16,12 @@ export const ProgressBar: FC<ProgressBarProps> = ({
remainingDays
}) => {
const styleString: CSSProperties = { width: `${value}%` };
const barColor: string = value < 75 ? "red" : "";
return (
<>
<div className="row">
<div className="progress">
<div className="determinate" style={styleString}></div>
<div className={`determinate ${barColor}`} style={styleString}></div>
</div>
<div>
<i className="left material-icons">playlist_add_check</i>

View file

@ -14,7 +14,7 @@ export const TabRouterHeader: FC<IProps> = ({
const nTabs = tabNames.length;
return (
<>
<ul className="tabs z-depth-1">
<ul className="tabs">
{tabNames.map((name, i) => (
<TabUnit
key={i}
@ -27,7 +27,7 @@ export const TabRouterHeader: FC<IProps> = ({
/>
))}
<li
className="indicator"
className="indicator indigo lighten-2"
style={{
left: `${(isActive / nTabs) * 100}%`,
right: `${(1 - (isActive + 1) / nTabs) * 100}%`
@ -68,7 +68,11 @@ const TabUnit: FC<TabUnitProps> = ({
<Link
to={`${url}/${text}`}
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))}
>
{text}

View file

@ -30,7 +30,11 @@ export const TicketList: FC<TicketListProps> = ({ tickets }) => {
};
const [showNew, setShowNew] = useState(false);
let filteredTickets = tickets.filter(
t =>
t.status !== "Done" &&
t.title.toLowerCase().includes(filterText.toLowerCase())
);
return (
<>
<div className="row valign-wrapper">
@ -42,7 +46,7 @@ export const TicketList: FC<TicketListProps> = ({ tickets }) => {
/>
<h3>Tickets</h3>
<FloatingButton
color=" blue-grey lighten-4"
color="indigo lighten-1"
size="small"
onClick={onClick}
/>
@ -54,28 +58,25 @@ export const TicketList: FC<TicketListProps> = ({ tickets }) => {
</div>
<div className="col s12 grey">
<ul>
{tickets
.filter(
t =>
t.status !== "Done" &&
t.title.toLowerCase().includes(filterText.toLowerCase())
)
.map((t: Ticket) => (
<li key={t.id}>
<HorizontalCard
title={t.title}
remainingDays={t.plannedEnding}
validateTicket={async (e: MouseEvent) => {
e.preventDefault();
await put<HttpResponse<Ticket>>(
`${Constants.ticketsURI}/${t.id}/closed`,
{}
);
}}
// archiveTicket={archiveTicket}
/>
</li>
))}
{filteredTickets.length === 0 ? (
<HorizontalCard />
) : (
filteredTickets.map((t: Ticket) => (
<HorizontalCard
key={t.id}
title={t.title}
remainingDays={t.plannedEnding}
validateTicket={async (e: MouseEvent) => {
e.preventDefault();
await put<HttpResponse<Ticket>>(
`${Constants.ticketsURI}/${t.id}/closed`,
{}
);
}}
// archiveTicket={archiveTicket}
/>
))
)}
</ul>
</div>
</>

View file

@ -37,7 +37,7 @@ export const ProjectPage: FC<IProps> = ({ viewModel }) => {
<AvatarList users={users} />
<FloatingButton
icon="add"
color="grey"
color="indigo lighten-1"
size="small"
onClick={() => setShowModal(true)}
/>

View file

@ -20,7 +20,7 @@ export const history = creacteHistory.createBrowserHistory();
export const AppRouter = () => {
return (
<Router history={history}>
<div className="grey lighten-4">
<div className="grey lighten-3">
<Switch>
<Route exact path="/">
<TestPage />