mirror of
https://github.com/rjNemo/ticket_manager
synced 2026-06-10 18:56:39 +00:00
update InputFile; AppFileList
This commit is contained in:
parent
70d1df1e05
commit
12a8e9e289
6 changed files with 252 additions and 95 deletions
|
|
@ -3,6 +3,7 @@ import { AppFile } from "../types/AppFile";
|
|||
import { FileCollection } from "./FileCollection";
|
||||
import { InputFile } from "./InputFile";
|
||||
import { FilterBar } from "./FilterBar";
|
||||
import { Grid, Typography } from "@material-ui/core";
|
||||
|
||||
type IProps = {
|
||||
files: AppFile[];
|
||||
|
|
@ -18,14 +19,20 @@ export const FileList: FC<IProps> = ({ files }) => {
|
|||
};
|
||||
return (
|
||||
<>
|
||||
<div className="row valign-wrapper">
|
||||
<h3>Files</h3>
|
||||
<FilterBar
|
||||
filterText={filterText}
|
||||
handleChange={handleChange}
|
||||
clearFilterText={clearFilterText}
|
||||
/>
|
||||
</div>
|
||||
<Grid container>
|
||||
<Grid item xs>
|
||||
<Typography variant="h4" component="h4">
|
||||
Files
|
||||
</Typography>
|
||||
</Grid>
|
||||
<Grid item xs={4}>
|
||||
<FilterBar
|
||||
filterText={filterText}
|
||||
handleChange={handleChange}
|
||||
clearFilterText={clearFilterText}
|
||||
/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
<InputFile />
|
||||
<FileCollection files={files} filterText={filterText} />
|
||||
</>
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ export const AvatarList: FC<AvatarListProps> = ({ users }) => {
|
|||
<></>
|
||||
) : (
|
||||
<>
|
||||
<AvatarGroup max={2}>
|
||||
<AvatarGroup max={5}>
|
||||
{users.map((user: User, i: number) => (
|
||||
<Link to={`/users/${user.id}`} key={i}>
|
||||
<Avatar src={user.picture} alt={user.fullName} />
|
||||
|
|
|
|||
|
|
@ -1,27 +1,62 @@
|
|||
import React, { FC } from "react";
|
||||
import { CloudUpload } from "@material-ui/icons";
|
||||
import { makeStyles, createStyles, Theme } from "@material-ui/core/styles";
|
||||
import Button from "@material-ui/core/Button";
|
||||
|
||||
export const InputFile: FC = () => {
|
||||
return (
|
||||
<>
|
||||
<form action="/upload">
|
||||
<div className="file-field input-field">
|
||||
<div className="btn indigo lighten-1">
|
||||
<i className="material-icons ">cloud_upload</i>
|
||||
<UploadButton>
|
||||
<CloudUpload />
|
||||
<input
|
||||
type="file"
|
||||
multiple
|
||||
accept=".doc,.docx,.pdf,.md,.gdoc,.zip,image/*"
|
||||
/>
|
||||
</div>
|
||||
<div className="file-path-wrapper">
|
||||
<input
|
||||
className="file-path validate"
|
||||
type="text"
|
||||
placeholder="Upload one or more files"
|
||||
/>
|
||||
</div>
|
||||
</UploadButton>
|
||||
</div>
|
||||
</form>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
const useStyles = makeStyles((theme: Theme) =>
|
||||
createStyles({
|
||||
root: {
|
||||
"& > *": {
|
||||
margin: theme.spacing(1)
|
||||
}
|
||||
},
|
||||
input: {
|
||||
display: "none"
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
const UploadButton: FC = () => {
|
||||
const classes = useStyles();
|
||||
|
||||
return (
|
||||
<div className={classes.root}>
|
||||
<input
|
||||
accept=".doc,.docx,.pdf,.md,.gdoc,.zip,image/*"
|
||||
className={classes.input}
|
||||
id="contained-button-file"
|
||||
multiple
|
||||
type="file"
|
||||
/>
|
||||
<label htmlFor="contained-button-file">
|
||||
<Button
|
||||
variant="contained"
|
||||
color="primary"
|
||||
component="span"
|
||||
startIcon={<CloudUpload />}
|
||||
>
|
||||
Upload files
|
||||
</Button>
|
||||
</label>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
|
|
|||
110
client/src/components/ProjectTabPanel.tsx
Normal file
110
client/src/components/ProjectTabPanel.tsx
Normal file
|
|
@ -0,0 +1,110 @@
|
|||
import React, { FC } from "react";
|
||||
import SwipeableViews from "react-swipeable-views";
|
||||
import { makeStyles, Theme, useTheme } from "@material-ui/core/styles";
|
||||
import AppBar from "@material-ui/core/AppBar";
|
||||
import Tabs from "@material-ui/core/Tabs";
|
||||
import Tab from "@material-ui/core/Tab";
|
||||
import Typography from "@material-ui/core/Typography";
|
||||
import Box from "@material-ui/core/Box";
|
||||
import { Ticket } from "../types/Ticket";
|
||||
import { Project } from "../types/Project";
|
||||
import { FileList } from "./AppFileList";
|
||||
import { TicketList } from "./TicketList";
|
||||
import { AppFile } from "../types/AppFile";
|
||||
|
||||
interface TabProps {
|
||||
children?: React.ReactNode;
|
||||
dir?: string;
|
||||
index: any;
|
||||
value: any;
|
||||
}
|
||||
|
||||
const TabPanel: FC<TabProps> = (props: TabProps) => {
|
||||
const { children, value, index, ...other } = props;
|
||||
|
||||
return (
|
||||
<Typography
|
||||
component="div"
|
||||
role="tabpanel"
|
||||
hidden={value !== index}
|
||||
id={`full-width-tabpanel-${index}`}
|
||||
aria-labelledby={`full-width-tab-${index}`}
|
||||
{...other}
|
||||
>
|
||||
{value === index && <Box p={3}>{children}</Box>}
|
||||
</Typography>
|
||||
);
|
||||
};
|
||||
|
||||
const a11yProps = (index: any) => {
|
||||
return {
|
||||
id: `full-width-tab-${index}`,
|
||||
"aria-controls": `full-width-tabpanel-${index}`
|
||||
};
|
||||
};
|
||||
|
||||
const useStyles = makeStyles((theme: Theme) => ({
|
||||
root: {
|
||||
backgroundColor: "#ffffff",
|
||||
flexGrow: 1
|
||||
}
|
||||
}));
|
||||
|
||||
interface IProps {
|
||||
tickets: Ticket[];
|
||||
remainingDays?: number;
|
||||
tabNames: string[];
|
||||
files: AppFile[];
|
||||
// activities: Activity[];
|
||||
allProjects: Project[];
|
||||
}
|
||||
|
||||
export const ProjectTabPanel: FC<IProps> = ({
|
||||
tickets,
|
||||
tabNames,
|
||||
files
|
||||
// allProjects
|
||||
}) => {
|
||||
const classes = useStyles();
|
||||
const theme = useTheme();
|
||||
const [value, setValue] = React.useState(0);
|
||||
|
||||
const handleChange = (event: React.ChangeEvent<{}>, newValue: number) => {
|
||||
setValue(newValue);
|
||||
};
|
||||
|
||||
const handleChangeIndex = (index: number) => {
|
||||
setValue(index);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className={classes.root}>
|
||||
<AppBar position="static" color="inherit">
|
||||
<Tabs
|
||||
value={value}
|
||||
onChange={handleChange}
|
||||
indicatorColor="primary"
|
||||
textColor="primary"
|
||||
variant="fullWidth"
|
||||
aria-label="full width tabs example"
|
||||
>
|
||||
{tabNames.map((t: string, i: number) => (
|
||||
<Tab key={i} label={t} {...a11yProps({ i })} />
|
||||
))}
|
||||
</Tabs>
|
||||
</AppBar>
|
||||
<SwipeableViews
|
||||
axis={theme.direction === "rtl" ? "x-reverse" : "x"}
|
||||
index={value}
|
||||
onChangeIndex={handleChangeIndex}
|
||||
>
|
||||
<TabPanel value={value} index={0} dir={theme.direction}>
|
||||
<TicketList tickets={tickets} allProjects={[]} addButton={false} />
|
||||
</TabPanel>
|
||||
<TabPanel value={value} index={1} dir={theme.direction}>
|
||||
<FileList files={files} />
|
||||
</TabPanel>
|
||||
</SwipeableViews>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
|
@ -42,58 +42,56 @@ export const TicketList: FC<TicketListProps> = ({
|
|||
);
|
||||
return (
|
||||
<>
|
||||
<div className="row valign-wrapper">
|
||||
<NewTicketModal
|
||||
handleClose={() => {
|
||||
setShowNew(false);
|
||||
}}
|
||||
show={showNew}
|
||||
allProjects={allProjects}
|
||||
/>
|
||||
<NewTicketModal
|
||||
handleClose={() => {
|
||||
setShowNew(false);
|
||||
}}
|
||||
show={showNew}
|
||||
allProjects={allProjects}
|
||||
/>
|
||||
|
||||
<Grid container>
|
||||
<Grid item xs>
|
||||
<Typography variant="h4" component="h4">
|
||||
Tickets
|
||||
</Typography>
|
||||
</Grid>
|
||||
<Grid item xs>
|
||||
{addButton && (
|
||||
<FloatingButton color="primary" size="small" onClick={onClick} />
|
||||
)}
|
||||
</Grid>
|
||||
<Grid item xs={4}>
|
||||
<FilterBar
|
||||
filterText={filterText}
|
||||
handleChange={handleChange}
|
||||
clearFilterText={clearFilterText}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12}>
|
||||
<div className="col s12 grey lighten-1">
|
||||
{filteredTickets.length === 0 ? (
|
||||
<HorizontalCard />
|
||||
) : (
|
||||
filteredTickets.map((t: Ticket) => (
|
||||
<HorizontalCard
|
||||
key={t.id}
|
||||
title={t.title}
|
||||
remainingDays={t.endingDate}
|
||||
link={`/tickets/${t.id}`}
|
||||
validateTicket={async (e: MouseEvent) => {
|
||||
e.preventDefault();
|
||||
await put<HttpResponse<Ticket>>(
|
||||
`${Constants.ticketsURI}/${t.id}/closed`,
|
||||
{}
|
||||
);
|
||||
}}
|
||||
/>
|
||||
))
|
||||
)}
|
||||
</div>
|
||||
</Grid>
|
||||
<Grid container>
|
||||
<Grid item xs>
|
||||
<Typography variant="h4" component="h4">
|
||||
Tickets
|
||||
</Typography>
|
||||
</Grid>
|
||||
</div>
|
||||
<Grid item xs>
|
||||
{addButton && (
|
||||
<FloatingButton color="primary" size="small" onClick={onClick} />
|
||||
)}
|
||||
</Grid>
|
||||
<Grid item xs={4}>
|
||||
<FilterBar
|
||||
filterText={filterText}
|
||||
handleChange={handleChange}
|
||||
clearFilterText={clearFilterText}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12}>
|
||||
<div className="col s12 grey lighten-1">
|
||||
{filteredTickets.length === 0 ? (
|
||||
<HorizontalCard />
|
||||
) : (
|
||||
filteredTickets.map((t: Ticket) => (
|
||||
<HorizontalCard
|
||||
key={t.id}
|
||||
title={t.title}
|
||||
remainingDays={t.endingDate}
|
||||
link={`/tickets/${t.id}`}
|
||||
validateTicket={async (e: MouseEvent) => {
|
||||
e.preventDefault();
|
||||
await put<HttpResponse<Ticket>>(
|
||||
`${Constants.ticketsURI}/${t.id}/closed`,
|
||||
{}
|
||||
);
|
||||
}}
|
||||
/>
|
||||
))
|
||||
)}
|
||||
</div>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -6,6 +6,8 @@ import { ProgressBar } from "../components/ProgressBar";
|
|||
import { TabRouter } from "../components/TabRouter";
|
||||
import { FloatingButton } from "../components/FloatingButton";
|
||||
import { UsersModal } from "../components/UsersModal";
|
||||
import { Container, Grid } from "@material-ui/core";
|
||||
import { ProjectTabPanel } from "../components/ProjectTabPanel";
|
||||
|
||||
interface IProps {
|
||||
viewModel: ProjectVM;
|
||||
|
|
@ -32,38 +34,43 @@ export const ProjectPage: FC<IProps> = ({ viewModel }) => {
|
|||
const [showModal, setShowModal] = useState<boolean>(false);
|
||||
|
||||
return (
|
||||
<div className="section">
|
||||
<div className="container">
|
||||
<Header title={title} description={description} />
|
||||
<div className="row valign-wrapper">
|
||||
<Container maxWidth="md">
|
||||
<Header title={title} description={description} />
|
||||
<UsersModal
|
||||
show={showModal}
|
||||
users={users}
|
||||
allUsers={allUsers}
|
||||
handleClose={() => setShowModal(false)}
|
||||
/>
|
||||
|
||||
<Grid container>
|
||||
<Grid item xs={3}>
|
||||
<AvatarList users={users} />
|
||||
</Grid>
|
||||
<Grid item xs={9}>
|
||||
<FloatingButton
|
||||
icon="add"
|
||||
color="default"
|
||||
size="small"
|
||||
onClick={() => setShowModal(true)}
|
||||
/>
|
||||
<UsersModal
|
||||
show={showModal}
|
||||
users={users}
|
||||
allUsers={allUsers}
|
||||
handleClose={() => setShowModal(false)}
|
||||
/>
|
||||
</div>
|
||||
<ProgressBar
|
||||
value={progression}
|
||||
tasksDone={ticketsDone}
|
||||
tasksTotalCount={ticketsTotalCount}
|
||||
remainingDays={remainingDays}
|
||||
/>
|
||||
<TabRouter
|
||||
tabNames={tabNames}
|
||||
tickets={tickets}
|
||||
files={files}
|
||||
activities={activities}
|
||||
allProjects={allProjects}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</Grid>
|
||||
</Grid>
|
||||
|
||||
<ProgressBar
|
||||
value={progression}
|
||||
tasksDone={ticketsDone}
|
||||
tasksTotalCount={ticketsTotalCount}
|
||||
remainingDays={remainingDays}
|
||||
/>
|
||||
|
||||
<ProjectTabPanel
|
||||
tabNames={tabNames}
|
||||
tickets={tickets}
|
||||
files={files}
|
||||
// activities={activities}
|
||||
allProjects={allProjects}
|
||||
/>
|
||||
</Container>
|
||||
);
|
||||
};
|
||||
|
|
|
|||
Loading…
Reference in a new issue