Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[team7 - FE] 이슈트래커 UI, 이슈 선택 동작, 이슈 생성 페이지 #38

Open
wants to merge 12 commits into
base: team7
Choose a base branch
from
Prev Previous commit
Next Next commit
feat: 이슈 테이블 추가
- 담당자, 레이블, 마일스톤, 작성자 버튼 수정
- 이슈 테이블 레이아웃 추가
adelakim5 committed Jun 16, 2021
commit 55a284816153346f303f53091d4b9f637aeccd95
132 changes: 47 additions & 85 deletions fe/src/components/home/IssueTable.tsx
Original file line number Diff line number Diff line change
@@ -1,117 +1,79 @@
import React, { useEffect } from "react";
import { DataGrid, GridColDef } from "@material-ui/data-grid";
import { IssueType } from "utils/interface";
import { Button, Card, CardActions, CardContent, makeStyles, Typography } from "@material-ui/core";
import { Card, CardContent, makeStyles, Link, Chip } from "@material-ui/core";
import CheckBox from "./styles/CheckBox";
import { selector, useRecoilState, useRecoilValue, atom } from "recoil";
import { selectIssueAll } from "utils/states";
import CardItem from "./styles/CardItem";

// const columns: GridColDef[] = [
// { field: "id", headerName: "#", width: 100 },
// { field: "title", headerName: "제목", width: 100 },
// { field: "assignee", headerName: "담당자", width: 150 },
// { field: "label", headerName: "레이블", width: 150 },
// { field: "milestone", headerName: "마일스톤", width: 150 },
// { field: "author", headerName: "작성자", width: 150 },
// { field: "created_at", headerName: "작성한 시간", width: 150 },
// ];

// const rows = [
// { id: 1, assignee: "adelakim5", author: "adelakim5" },
// { id: 2, assignee: "adelakim5", author: "adelakim5" },
// { id: 3, assignee: "adelakim5", author: "adelakim5" },
// { id: 4, assignee: "adelakim5", author: "adelakim5" },
// { id: 5, assignee: "adelakim5", author: "adelakim5" },
// { id: 6, assignee: "adelakim5", author: "adelakim5" },
// { id: 7, assignee: "adelakim5", author: "adelakim5" },
// { id: 8, assignee: "adelakim5", author: "adelakim5" },
// { id: 9, assignee: "adelakim5", author: "adelakim5" },
// ];
import styled from "styled-components";

interface IssueTableType {
issueListItems: IssueType[];
}

export default function IssueTable({ issueListItems }: IssueTableType) {
const classes = useStyles();
const bull = <span className={classes.bullet}>•</span>;

return (
<div>
{issueListItems.map((item) => (
<Card className={classes.root} variant="outlined">
<CheckBox />
<CardContent>
<Typography className={classes.title} color="textSecondary" gutterBottom>
Word of the Day
</Typography>
<Typography variant="h5" component="h2">
be{bull}nev{bull}o{bull}lent
</Typography>
<Typography className={classes.pos} color="textSecondary">
adjective
</Typography>
<Typography variant="body2" component="p">
well meaning and kindly.
<br />
{'"a benevolent smile"'}
</Typography>
<CardContent className={classes.card}>
<CheckBox />
<CardContentInfo>
<CardHeader>
<Link href={`/${item.id}`} className={classes.title}>
{item.title}
</Link>
{item.label_list.map((label) => (
<Chip className={classes.chip} size="small" label={label} />
))}
</CardHeader>
<CardFooter>
<span>
#{item.id} 이 이슈가 {item.created_at}에 {item.author.name}님에 의해
작성되었습니다.
</span>
<span>{item.milestone.title}</span>
</CardFooter>
</CardContentInfo>
</CardContent>
<CardActions>
<Button size="small">Learn More</Button>
</CardActions>
</Card>
/* <Card className={classes.root}>
<CheckBox
checked={selectedIssueAllState || checkState}
name={`${item.id}`}
onChange={handleChange}
/>
<CardContent>
<Typography className={classes.title} color="textSecondary" gutterBottom>
Word of the Day
</Typography>
<Typography variant="h5" component="h2">
be{bull}nev{bull}o{bull}lent
</Typography>
<Typography className={classes.pos} color="textSecondary">
adjective
</Typography>
<Typography variant="body2" component="p">
well meaning and kindly.
<br />
{'"a benevolent smile"'}
</Typography>
</CardContent>
</Card> */
))}
</div>

// <div>
// {issueListItems.map((item) => (
// <Card>{item.title}</Card>
// ))}
// </div>
);
// <div style={{ height: 400, width: "100%" }}>
// <DataGrid rows={rows} columns={columns} pageSize={5}></DataGrid>
// </div>
}

function calculteTime(created_at: string) {
const current = new Date().getTime();
const created = new Date(created_at).getTime();
const sec_gap = (current - created) / 1000;
const min_gap = (current - created) / 1000 / 60;
console.log(sec_gap, min_gap);
}

const useStyles = makeStyles({
root: {
minWidth: 275,
},
bullet: {
display: "inline-block",
margin: "0 2px",
transform: "scale(0.8)",
},
card: {
display: "flex",
alignItems: "center",
},
title: {
fontSize: 14,
fontSize: 20,
},
pos: {
marginBottom: 12,
},
chip: {
margin: "0 3px",
},
});

const CardContentInfo = styled.div``;

const CardHeader = styled.div``;

const CardFooter = styled.div`
span {
margin-right: 10px;
}
`;
12 changes: 6 additions & 6 deletions fe/src/components/home/issueAppBar/IssueAppBar.container.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { SimpleAppBarProps } from "utils/interface";
import { IssueRefMenuProps, SimpleAppBarProps } from "utils/interface";
import { useRecoilState } from "recoil";
import IssueAppBarPresenter from "./IssueAppBar.presenter";
import { openState, closeState } from "utils/states";
@@ -17,9 +17,9 @@ export default function IssueAppBarContainer({ openedIssue, closedIssue }: Simpl
setClose(true);
};

const issueRefArray = [
const issueRefArray: IssueRefMenuProps[] = [
{
buttonTitle: "담당자",
buttonTitle: "assignee",
listItems: [
{ id: 0, title: "Adela" },
{ id: 1, title: "Bibi" },
@@ -29,15 +29,15 @@ export default function IssueAppBarContainer({ openedIssue, closedIssue }: Simpl
],
},
{
buttonTitle: "레이블",
buttonTitle: "label",
listItems: [
{ id: 0, title: "fe" },
{ id: 1, title: "be" },
{ id: 2, title: "ios" },
],
},
{
buttonTitle: "마일스톤",
buttonTitle: "milestone",
listItems: [
{ id: 0, title: "마스터즈코스" },
{ id: 1, title: "프론트엔드" },
@@ -46,7 +46,7 @@ export default function IssueAppBarContainer({ openedIssue, closedIssue }: Simpl
],
},
{
buttonTitle: "작성자",
buttonTitle: "author",
listItems: [
{ id: 0, title: "Adela" },
{ id: 1, title: "Bibi" },
4 changes: 2 additions & 2 deletions fe/src/components/home/issueAppBar/IssueAppBar.presenter.tsx
Original file line number Diff line number Diff line change
@@ -2,8 +2,8 @@ import { createStyles, makeStyles, Theme } from "@material-ui/core/styles";
import { AppBar, Toolbar, Tabs, Tab } from "@material-ui/core";
import { IssueRefMenuProps } from "utils/interface";
import IssueRefMenuContainer from "../issueRefMenu/IssueRefMenu.container";
import { selector, useRecoilState, useRecoilValue } from "recoil";
import { openState, selectIssueAll } from "utils/states";
import { selector, useRecoilValue } from "recoil";
import { openState } from "utils/states";
import { SimpleAppBarProps } from "utils/interface";
import IssueTable from "../IssueTable";
import CheckBoxAppBar from "../styles/CheckBox.AppBar";
25 changes: 14 additions & 11 deletions fe/src/components/home/issueRefMenu/IssueRefMenu.container.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,22 @@
import React, { useState } from "react";
import IssueRefMenuPresenter from "./IssueRefMenu.presenter";
import { IssueRefMenuProps } from "utils/interface";
import { IssueRefMenuProps, UsefulObjectType } from "utils/interface";

export default function IssueRefMenuContainer({ buttonTitle, listItems }: IssueRefMenuProps) {
const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null);
const [selectState, setSelectState] = useState<UsefulObjectType>({
assignee: "",
author: "",
milestone: "",
label: "",
});

const handleClick = (event: React.MouseEvent<HTMLElement>) => {
setAnchorEl(event.currentTarget);
const handleChange = (event: React.ChangeEvent<UsefulObjectType>) => {
const name = event.target.name as keyof typeof selectState;
setSelectState({
...selectState,
[name]: event.target.value,
});
};

const handleClose = () => {
setAnchorEl(null);
};

return (
<IssueRefMenuPresenter {...{ buttonTitle, listItems, handleClick, handleClose, anchorEl }} />
);
return <IssueRefMenuPresenter {...{ buttonTitle, listItems, handleChange, selectState }} />;
}
99 changes: 40 additions & 59 deletions fe/src/components/home/issueRefMenu/IssueRefMenu.presenter.tsx
Original file line number Diff line number Diff line change
@@ -1,73 +1,54 @@
import React from "react";
import { withStyles } from "@material-ui/core/styles";
import { Button, ListItemText, MenuItem } from "@material-ui/core";
import Menu, { MenuProps } from "@material-ui/core/Menu";
import { IssueRefMenuProps } from "utils/interface";
import { createStyles, makeStyles, Theme } from "@material-ui/core/styles";
import InputLabel from "@material-ui/core/InputLabel";
import FormControl from "@material-ui/core/FormControl";
import Select from "@material-ui/core/Select";
import { IssueRefMenuProps, UsefulObjectType } from "utils/interface";

interface IssueRefMenuPresenterProps extends IssueRefMenuProps {
handleClick: (event: React.MouseEvent<HTMLElement>) => void;
handleClose: () => void;
anchorEl: null | HTMLElement;
handleChange: (event: React.ChangeEvent<{}>) => void;
selectState: UsefulObjectType;
}

export default function IssueRefMenuPresenter(props: IssueRefMenuPresenterProps) {
const { buttonTitle, listItems, handleClick, handleClose, anchorEl } = props;
const { buttonTitle, listItems, handleChange, selectState } = props;
const classes = useStyles();

return (
<div>
<Button
aria-controls="customized-menu"
aria-haspopup="true"
variant="contained"
color="primary"
onClick={handleClick}
>
{buttonTitle}
</Button>
<StyledMenu
id="customized-menu"
anchorEl={anchorEl}
keepMounted
open={Boolean(anchorEl)}
onClose={handleClose}
>
{listItems.map((item) => (
<StyledMenuItem>
<ListItemText primary={item.title} />
</StyledMenuItem>
))}
</StyledMenu>
<FormControl variant="outlined" className={classes.formControl}>
<InputLabel className={classes.select}>{buttonTitle}</InputLabel>
<Select
native
value={selectState[buttonTitle]}
onChange={handleChange}
label={buttonTitle}
inputProps={{
name: `${buttonTitle}`,
id: `outlined-${buttonTitle}-native-simple`,
}}
>
<option aria-label="None" value="" />
{listItems.map((item) => (
<option value={item.title}>{item.title}</option>
))}
</Select>
</FormControl>
</div>
);
}

const StyledMenu = withStyles({
paper: {
border: "1px solid #d3d4d5",
},
})((props: MenuProps) => (
<Menu
elevation={0}
getContentAnchorEl={null}
anchorOrigin={{
vertical: "bottom",
horizontal: "center",
}}
transformOrigin={{
vertical: "top",
horizontal: "center",
}}
{...props}
/>
));

const StyledMenuItem = withStyles((theme) => ({
root: {
"&:focus": {
backgroundColor: theme.palette.primary.main,
"& .MuiListItemIcon-root, & .MuiListItemText-primary": {
color: theme.palette.common.white,
},
const useStyles = makeStyles((theme: Theme) =>
createStyles({
formControl: {
margin: theme.spacing(1),
minWidth: 120,
},
selectEmpty: {
marginTop: theme.spacing(2),
},
select: {
color: "white",
},
},
}))(MenuItem);
})
);
4 changes: 2 additions & 2 deletions fe/src/components/home/styles/CheckBox.AppBar.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React, { useState } from "react";
import React from "react";
import FormGroup from "@material-ui/core/FormGroup";
import FormControlLabel from "@material-ui/core/FormControlLabel";
import { selector, useRecoilState, useRecoilValue, useSetRecoilState } from "recoil";
import { useRecoilState, useSetRecoilState } from "recoil";
import { selectIssueAll, selectCheckBoxAppBar } from "utils/states";
import { GreenCheckbox } from "./CheckBox.style";

41 changes: 0 additions & 41 deletions fe/src/components/home/styles/CheckBox.tmp.tsx

This file was deleted.

13 changes: 12 additions & 1 deletion fe/src/utils/interface.ts
Original file line number Diff line number Diff line change
@@ -20,13 +20,24 @@ export interface filterOptionType {
key: string;
}

export interface UsefulObjectType {
[key: string]: string;
}

interface ListItemsType {
id: number;
title: string;
}

export interface IssueRefStateType {
assignee: string;
author: string;
milestone: string;
label: string;
}

export interface IssueRefMenuProps {
buttonTitle: string;
buttonTitle: keyof IssueRefStateType;
listItems: ListItemsType[];
}