Pārlūkot izejas kodu

Implement T-Shirt Size selection and showing for the issue.

Oleksandr Korniienko 3 gadi atpakaļ
vecāks
revīzija
c0e8e3c19e

+ 5 - 1
src/components/IssueTracker/Column.tsx

@@ -1,7 +1,7 @@
 import styled from "styled-components";
 import Task from "./Task";
 import { Droppable, DroppableStateSnapshot } from "react-beautiful-dnd";
-import { IColumn, IIssueType, IMember, IStatus, ITask } from "./types";
+import { IColumn, IIssueType, IMember, IStatus, ITask, ITShirtSize } from "./types";
 
 const Container = styled.div`
   margin: 8px;
@@ -31,6 +31,7 @@ const InnerList = (props: {
   tasks: ITask[];
   statuses: IStatus[];
   issueTypes: IIssueType[];
+  tShirtSizes: ITShirtSize[];
   editIssueCallback: (editedTask: ITask, shouldDelete: boolean) => void;
 }) => {
   return (
@@ -43,6 +44,7 @@ const InnerList = (props: {
           members={props.members}
           statuses={props.statuses}
           issueTypes={props.issueTypes}
+          tShirtSizes={props.tShirtSizes}
           editIssueCallback={props.editIssueCallback}
         />
       ))}
@@ -56,6 +58,7 @@ const Column = (props: {
   members: IMember[];
   statuses: IStatus[];
   issueTypes: IIssueType[];
+  tShirtSizes: ITShirtSize[];
   editIssueCallback: (editedTask: ITask, shouldDelete: boolean) => void;
 }) => {
   return (
@@ -74,6 +77,7 @@ const Column = (props: {
               tasks={props.tasks}
               statuses={props.statuses}
               issueTypes={props.issueTypes}
+              tShirtSizes={props.tShirtSizes}
               editIssueCallback={props.editIssueCallback}
             />
             {provided.placeholder}

+ 29 - 2
src/components/IssueTracker/EditIssueModal.tsx

@@ -12,7 +12,7 @@ import {
 } from "@material-ui/core";
 import { useState } from "react";
 import DeleteIcon from "@material-ui/icons/Delete";
-import { IIssueType, IMember, IStatus, ITask } from "./types";
+import { IIssueType, IMember, IStatus, ITask, ITShirtSize } from "./types";
 
 const useStyles = makeStyles((theme: Theme) =>
   createStyles({
@@ -45,6 +45,7 @@ const EditIssueModal = (props: {
   members: IMember[];
   statuses: IStatus[];
   issueTypes: IIssueType[];
+  tShirtSizes: ITShirtSize[];
   editIssueCallback: (updatedTask: ITask, shouldDelete: boolean) => void;
 }) => {
   const classes = useStyles();
@@ -52,9 +53,10 @@ const EditIssueModal = (props: {
 
   const canSave = () => editedTask.title !== "" && editedTask.content !== "";
 
+  const unknownSize = "Unknown";
   return (
     <div className={classes.paper}>
-      <h2 id="new-issue-modal-title">Create Issue</h2>
+      <h2 id="new-issue-modal-title">Update Issue</h2>
       <form className={classes.form} noValidate autoComplete="off">
         <TextField
           fullWidth
@@ -142,6 +144,31 @@ const EditIssueModal = (props: {
             ))}
           </Select>
         </FormControl>
+        <FormControl fullWidth variant="outlined">
+          <InputLabel shrink id="size-select-label">T-Size</InputLabel>
+          <Select
+            labelId="size-select-label"
+            id="size-select"
+            value={editedTask.size ? editedTask.size : unknownSize}
+            onChange={(e) =>
+              setEditedTask((prev) => ({
+                ...prev,
+                size:
+                  (e.target.value as string) === unknownSize
+                    ? ""
+                    : (e.target.value as string),
+              }))
+            }
+            label="Status"
+          >
+            <MenuItem value={unknownSize}>{unknownSize}</MenuItem>
+            {props.tShirtSizes.map((s, i) => (
+              <MenuItem key={i} value={s.id}>
+                {s.title}
+              </MenuItem>
+            ))}
+          </Select>
+        </FormControl>
         <FormControl fullWidth variant="outlined">
           <InputLabel id="assignee-select-label">Assignee</InputLabel>
           <Select

+ 29 - 1
src/components/IssueTracker/NewIssueModal.tsx

@@ -10,7 +10,7 @@ import {
   Theme,
 } from "@material-ui/core";
 import { useState } from "react";
-import { IIssueType, IMember, IStatus, ITask } from "./types";
+import { IIssueType, IMember, IStatus, ITask, ITShirtSize } from "./types";
 
 const useStyles = makeStyles((theme: Theme) =>
   createStyles({
@@ -42,6 +42,7 @@ const NewIssueModal = (props: {
   members: IMember[];
   statuses: IStatus[];
   issueTypes: IIssueType[];
+  tShirtSizes: ITShirtSize[];
   newIssueCallback: (newTask: ITask) => void;
 }) => {
   const classes = useStyles();
@@ -63,6 +64,8 @@ const NewIssueModal = (props: {
     newTask.creatorId &&
     newTask.creatorId !== 0;
 
+  const unknownSize = "Unknown";
+
   return (
     <div className={classes.paper}>
       <h2 id="new-issue-modal-title">Create Issue</h2>
@@ -153,6 +156,31 @@ const NewIssueModal = (props: {
             ))}
           </Select>
         </FormControl>
+        <FormControl fullWidth variant="outlined">
+          <InputLabel id="size-select-label">T-Size</InputLabel>
+          <Select
+            labelId="size-select-label"
+            id="size-select"
+            value={newTask.size ? newTask.size : unknownSize}
+            onChange={(e) =>
+              setNewTask((prev) => ({
+                ...prev,
+                size:
+                  (e.target.value as string) === unknownSize
+                    ? ""
+                    : (e.target.value as string),
+              }))
+            }
+            label="Status"
+          >
+            <MenuItem value={unknownSize}>{unknownSize}</MenuItem>
+            {props.tShirtSizes.map((s, i) => (
+              <MenuItem key={i} value={s.id}>
+                {s.title}
+              </MenuItem>
+            ))}
+          </Select>
+        </FormControl>
         <FormControl required fullWidth variant="outlined">
           <InputLabel id="assignee-select-label">Author</InputLabel>
           <Select

+ 4 - 1
src/components/IssueTracker/Task.tsx

@@ -1,6 +1,6 @@
 import styled from "styled-components";
 import { Draggable, DraggableStateSnapshot } from "react-beautiful-dnd";
-import { IIssueType, IMember, IStatus, ITask } from "./types";
+import { IIssueType, IMember, IStatus, ITask, ITShirtSize } from "./types";
 import moment from "moment";
 import {
   Avatar,
@@ -37,6 +37,7 @@ const Task = (props: {
   members: IMember[];
   statuses: IStatus[];
   issueTypes: IIssueType[];
+  tShirtSizes: ITShirtSize[];
   editIssueCallback: (editedTask: ITask, shouldDelete: boolean) => void;
 }) => {
   const [showEditIssueModal, setShowEditIssueModal] = useState(false);
@@ -144,6 +145,7 @@ const Task = (props: {
             <AssigneeAvatar />
             <div className={classes.chips}>
               <Chip label={props.task.type} />
+              <Chip hidden={!props.task.size} label={props.task.size} />
               <Chip label={`Funded: ${props.task.funded}`} />
               <Chip label={`Priority: ${props.task.priority}`} />
               <Chip label={`Author: ${creatorId()}`} />
@@ -192,6 +194,7 @@ const Task = (props: {
                     members={props.members}
                     issueTypes={props.issueTypes}
                     statuses={props.statuses}
+                    tShirtSizes={props.tShirtSizes}
                     editIssueCallback={(
                       editedTask: ITask,
                       shouldDelete: boolean

+ 6 - 0
src/components/IssueTracker/index.tsx

@@ -30,6 +30,7 @@ import {
   IMember,
   IStatus,
   ITask,
+  ITShirtSize,
 } from "./types";
 import { tasksEndpoint } from "../../config";
 import NewIssueModal from "./NewIssueModal";
@@ -64,6 +65,7 @@ const IssueTracker = () => {
   const [showMembersModal, setShowMembersModal] = useState(false);
   const [statuses, setStatuses] = useState([] as IStatus[]);
   const [issueTypes, setIssueTypes] = useState([] as IIssueType[]);
+  const [tShirtSizes, setTShirtSizes] = useState([] as ITShirtSize[]);
 
   const loadConfig = async () => await axios.get(`${tasksEndpoint}/config`);
   const loadIssues = async () => await axios.get(`${tasksEndpoint}/issues`);
@@ -88,8 +90,10 @@ const IssueTracker = () => {
       }
       const statuses = response.data.statuses as IStatus[];
       const issueTypes = response.data.issueTypes as IIssueType[];
+      const tShirtSizes = response.data.tShirtSizes as IIssueType[];
       setStatuses(statuses);
       setIssueTypes(issueTypes);
+      setTShirtSizes(tShirtSizes);
       const ordered = statuses.sort((a, b) => (a.index > b.index ? 1 : -1));
       let columns = statuses.reduce(function (result, item, index, array) {
         const columnId = (item as IStatus).id;
@@ -375,6 +379,7 @@ const IssueTracker = () => {
               members={members}
               issueTypes={issueTypes}
               statuses={statuses}
+              tShirtSizes={tShirtSizes}
               newIssueCallback={newIssueCallback}
             />
           </Fade>
@@ -426,6 +431,7 @@ const IssueTracker = () => {
                   members={members}
                   issueTypes={issueTypes}
                   statuses={statuses}
+                  tShirtSizes={tShirtSizes}
                   editIssueCallback={editIssueCallback}
                 />
               );

+ 8 - 0
src/components/IssueTracker/types.ts

@@ -10,10 +10,18 @@ export interface IIssueType {
   index: number;
 }
 
+
+export interface ITShirtSize {
+  id: string;
+  title: string;
+  index: number;
+}
+
 export interface ITask {
   id: string;
   title: string;
   content: string;
+  size: string;
   type: string;
   url: string;
   status: string;