@@ -3,9 +3,6 @@ | |||||
"version": "0.1.0", | "version": "0.1.0", | ||||
"private": true, | "private": true, | ||||
"dependencies": { | "dependencies": { | ||||
"@fortawesome/fontawesome-svg-core": "^1.2.35", | |||||
"@fortawesome/free-solid-svg-icons": "^5.15.3", | |||||
"@fortawesome/react-fontawesome": "^0.1.14", | |||||
"@testing-library/jest-dom": "^5.12.0", | "@testing-library/jest-dom": "^5.12.0", | ||||
"@testing-library/react": "^11.2.6", | "@testing-library/react": "^11.2.6", | ||||
"@testing-library/user-event": "^12.8.3", | "@testing-library/user-event": "^12.8.3", | ||||
@@ -13,7 +10,6 @@ | |||||
"@types/node": "^12.20.10", | "@types/node": "^12.20.10", | ||||
"@types/react": "^17.0.3", | "@types/react": "^17.0.3", | ||||
"@types/react-dom": "^17.0.3", | "@types/react-dom": "^17.0.3", | ||||
"font-awesome": "^4.7.0", | |||||
"react": "^17.0.2", | "react": "^17.0.2", | ||||
"react-dom": "^17.0.2", | "react-dom": "^17.0.2", | ||||
"react-icons": "^4.2.0", | "react-icons": "^4.2.0", | ||||
@@ -1,5 +1,7 @@ | |||||
html { | html { | ||||
background-color: #383c4a; | background-color: #383c4a; | ||||
overflow: hidden; | |||||
} | } | ||||
.header { | .header { | ||||
@@ -26,67 +28,85 @@ html { | |||||
text-align: center; | text-align: center; | ||||
flex-direction: column; | flex-direction: column; | ||||
justify-content: flex-start; | justify-content: flex-start; | ||||
float: left; | |||||
width: initial; | |||||
position: relative; | |||||
height: auto; | |||||
flex-grow: inherit; | |||||
max-width: 22vw; | |||||
min-width: 22vw; | |||||
min-height: 25vh; | |||||
border-color: #ddd; | border-color: #ddd; | ||||
border-width: 2px; | border-width: 2px; | ||||
min-width: 300px; | |||||
min-height: 200px; | |||||
max-width: 25%; | |||||
border-style: solid; | border-style: solid; | ||||
color: "orange"; | |||||
color: #eee; | |||||
margin: 5px; | margin: 5px; | ||||
padding: 5px; | padding: 5px; | ||||
flex-wrap: nowrap; | flex-wrap: nowrap; | ||||
overflow-y: auto; | |||||
overflow-x: hidden; | |||||
padding-left: 1px; | |||||
margin-left: 1px; | |||||
margin-right: 1px; | |||||
padding-right: 1px; | |||||
max-height: 88vh; | |||||
} | } | ||||
.taskWrapper { | .taskWrapper { | ||||
display: flex; | display: flex; | ||||
min-height: 100px; | |||||
flex-direction: row; | flex-direction: row; | ||||
align-items: stretch; | |||||
position: relative; | |||||
border-color: #ccc; | |||||
border-width: 2px; | |||||
border-style: solid; | |||||
margin: 2px; | |||||
} | } | ||||
.prioBlock { | .prioBlock { | ||||
order: 1; | order: 1; | ||||
flex: 1; | |||||
flex: 3; | |||||
display: flex; | display: flex; | ||||
overflow: hidden; | overflow: hidden; | ||||
} | } | ||||
.taskText { | .taskText { | ||||
order: 5; | order: 5; | ||||
flex: 5; | |||||
flex: 20; | |||||
height: 100%; | height: 100%; | ||||
overflow: auto; | |||||
} | } | ||||
.actionBlock{ | |||||
.actionBlock { | |||||
order: 10; | order: 10; | ||||
flex: 1; | flex: 1; | ||||
display: flex; | display: flex; | ||||
background-color: purple; | |||||
justify-content: flex-end; | |||||
background-color: #ddd; | |||||
justify-content: flex-start; | |||||
flex-direction: column; | |||||
align-items: flex-end; | |||||
} | |||||
.App { | |||||
display: flex; | |||||
align-items: stretch; | |||||
order: 1; | |||||
flex: 1; | |||||
flex-direction: column; | |||||
min-height: 100vh; | |||||
overflow: hidden; | |||||
} | |||||
.footer { | |||||
display: flex; | |||||
order: 400; | |||||
color: #eee; | |||||
} | } | ||||
.panel { | .panel { | ||||
display: flex; | display: flex; | ||||
flex: 1; | flex: 1; | ||||
order: 1; | |||||
justify-content: flex-start; | |||||
flex-direction: row; | flex-direction: row; | ||||
flex-wrap: nowrap; | flex-wrap: nowrap; | ||||
width: 100%; | width: 100%; | ||||
overflow-x:auto; | |||||
overflow-x: auto; | |||||
overflow-y: hidden; | overflow-y: hidden; | ||||
height: 100%; | |||||
align-items: stretch; | align-items: stretch; | ||||
background-color: lavender; | |||||
background-color: #404552; | |||||
} | } | ||||
.modal { | .modal { | ||||
position: fixed; | position: fixed; | ||||
z-index: 20; | z-index: 20; | ||||
@@ -140,4 +160,3 @@ html { | |||||
.display-none { | .display-none { | ||||
display: none; | display: none; | ||||
} | } | ||||
@@ -120,7 +120,7 @@ class App extends React.Component<{}, State> { | |||||
columns[fromColumnIndex + 1] = toColumn; | columns[fromColumnIndex + 1] = toColumn; | ||||
this.setState({ columns: columns }); | this.setState({ columns: columns }); | ||||
}; | }; | ||||
/* Regresses the task to the column immediately to the left | |||||
/* Regresses the task to the column immediately to the left | |||||
@param columnId: The column which the task is originally hosted at | @param columnId: The column which the task is originally hosted at | ||||
@param taskId: The UID for the task | @param taskId: The UID for the task | ||||
@return void | @return void | ||||
@@ -218,6 +218,10 @@ class App extends React.Component<{}, State> { | |||||
/> | /> | ||||
))} | ))} | ||||
</div> | </div> | ||||
<div className="footer"> | |||||
Not to be taken seriously. Done as a practice React + TS + MobX | |||||
project | |||||
</div> | |||||
</div> | </div> | ||||
); | ); | ||||
} | } | ||||
@@ -66,9 +66,7 @@ class Header extends React.Component<HeaderProps, State> { | |||||
if (target === "titleInput") { | if (target === "titleInput") { | ||||
this.setState({ taskTitle: event.target.value }); | this.setState({ taskTitle: event.target.value }); | ||||
} | } | ||||
if (target === "descInput") { | |||||
this.setState({ taskDesc: event.target.value }); | |||||
} | |||||
if (target === "columnTitle") { | if (target === "columnTitle") { | ||||
this.setState({ columnTitle: event.target.value }); | this.setState({ columnTitle: event.target.value }); | ||||
} | } | ||||
@@ -76,6 +74,9 @@ class Header extends React.Component<HeaderProps, State> { | |||||
this.setState({ columnColor: event.target.value }); | this.setState({ columnColor: event.target.value }); | ||||
} | } | ||||
}; | }; | ||||
handleTextAreaChange = (event: React.ChangeEvent<HTMLTextAreaElement>) => { | |||||
this.setState({ taskDesc: event?.target.value }); | |||||
}; | |||||
handleSelectChange = (event: React.ChangeEvent<HTMLSelectElement>) => { | handleSelectChange = (event: React.ChangeEvent<HTMLSelectElement>) => { | ||||
if (event.target.id === "prioritySelect") { | if (event.target.id === "prioritySelect") { | ||||
@@ -93,6 +94,7 @@ class Header extends React.Component<HeaderProps, State> { | |||||
return ( | return ( | ||||
<div className="header" style={{ height: 60 }}> | <div className="header" style={{ height: 60 }}> | ||||
<h1 | <h1 | ||||
key="Title" | |||||
style={{ | style={{ | ||||
float: "left", | float: "left", | ||||
margin: 0, | margin: 0, | ||||
@@ -102,16 +104,23 @@ class Header extends React.Component<HeaderProps, State> { | |||||
> | > | ||||
Kango Bango | Kango Bango | ||||
</h1> | </h1> | ||||
<Modal show={this.state.showTask} handleClose={this.hideModal}> | |||||
<h3> Add Task</h3> | |||||
<p>{this.props.columns[0] && this.props.columns[0].id}</p> | |||||
<Modal | |||||
show={this.state.showTask} | |||||
handleClose={this.hideModal} | |||||
key="addTask" | |||||
> | |||||
<h3> Add Task 🤔</h3> | |||||
<select | <select | ||||
value={this.state.taskColumnNumber} | value={this.state.taskColumnNumber} | ||||
onChange={this.handleSelectChange} | onChange={this.handleSelectChange} | ||||
id="columnSelect" | id="columnSelect" | ||||
title="columnSelect" | |||||
> | > | ||||
{this.props.columns.map((column) => ( | {this.props.columns.map((column) => ( | ||||
<option value={column.id}>{column.name}</option> | |||||
<option value={column.id} key={column.id}> | |||||
{column.name} | |||||
</option> | |||||
))} | ))} | ||||
; | ; | ||||
</select> | </select> | ||||
@@ -129,11 +138,10 @@ class Header extends React.Component<HeaderProps, State> { | |||||
<label> | <label> | ||||
{" "} | {" "} | ||||
Description: | Description: | ||||
<input | |||||
type="textarea" | |||||
<textarea | |||||
id="descInput" | id="descInput" | ||||
value={this.state.taskDesc} | value={this.state.taskDesc} | ||||
onChange={this.handleInputChange} | |||||
onChange={this.handleTextAreaChange} | |||||
/> | /> | ||||
</label> | </label> | ||||
@@ -145,6 +153,7 @@ class Header extends React.Component<HeaderProps, State> { | |||||
value={this.state.taskPrio} | value={this.state.taskPrio} | ||||
onChange={this.handleSelectChange} | onChange={this.handleSelectChange} | ||||
id="prioritySelect" | id="prioritySelect" | ||||
title="prioSelect" | |||||
> | > | ||||
<option value="normal">Normal</option> | <option value="normal">Normal</option> | ||||
<option value="important">Important</option> | <option value="important">Important</option> | ||||
@@ -172,8 +181,11 @@ class Header extends React.Component<HeaderProps, State> { | |||||
Close | Close | ||||
</button> | </button> | ||||
</Modal> | </Modal> | ||||
<Modal show={this.state.showColumn} handleClose={this.hideModal}> | |||||
<Modal | |||||
show={this.state.showColumn} | |||||
handleClose={this.hideModal} | |||||
key="addColumn" | |||||
> | |||||
<h3>Lets add a column! 🤔</h3> | <h3>Lets add a column! 🤔</h3> | ||||
<label> | <label> | ||||
@@ -219,8 +231,14 @@ class Header extends React.Component<HeaderProps, State> { | |||||
Close | Close | ||||
</button> | </button> | ||||
</Modal> | </Modal> | ||||
<button onClick={this.showTaskModal}> Add task </button> | |||||
<button onClick={this.showColumnModal}> Add column </button> | |||||
<button onClick={this.showTaskModal} key="Task Button"> | |||||
{" "} | |||||
Add task{" "} | |||||
</button> | |||||
<button onClick={this.showColumnModal} key="Column Button"> | |||||
{" "} | |||||
Add column{" "} | |||||
</button> | |||||
</div> | </div> | ||||
); | ); | ||||
} | } | ||||
@@ -39,15 +39,7 @@ class KBColumn extends React.Component<KBColumnProps> { | |||||
} | } | ||||
return ( | return ( | ||||
<div | |||||
style={{ | |||||
borderColor: "#ccc", | |||||
borderWidth: "1px", | |||||
borderStyle: "solid", | |||||
margin: "10px", | |||||
}} | |||||
className="taskWrapper" | |||||
> | |||||
<div key={task.id} className="taskWrapper"> | |||||
<div | <div | ||||
style={{ backgroundColor: bgc, display: "inline" }} | style={{ backgroundColor: bgc, display: "inline" }} | ||||
className="prioBlock" | className="prioBlock" | ||||
@@ -67,14 +59,14 @@ class KBColumn extends React.Component<KBColumnProps> { | |||||
} | } | ||||
/> | /> | ||||
<FaLongArrowAltRight | <FaLongArrowAltRight | ||||
style={{ color: "red", cursor: "pointer" }} | |||||
style={{ color: "red", cursor: "pointer", marginTop: "10px" }} | |||||
onClick={() => | onClick={() => | ||||
this.props.progressTask && | this.props.progressTask && | ||||
this.props.progressTask(this.props.id, task.id) | this.props.progressTask(this.props.id, task.id) | ||||
} | } | ||||
/> | /> | ||||
<FaLongArrowAltLeft | <FaLongArrowAltLeft | ||||
style={{ color: "red", cursor: "pointer" }} | |||||
style={{ color: "red", cursor: "pointer", marginTop: "10px" }} | |||||
onClick={() => | onClick={() => | ||||
this.props.regressTask && | this.props.regressTask && | ||||
this.props.regressTask(this.props.id, task.id) | this.props.regressTask(this.props.id, task.id) | ||||
@@ -88,7 +80,11 @@ class KBColumn extends React.Component<KBColumnProps> { | |||||
render() { | render() { | ||||
return ( | return ( | ||||
<div className="KBColumn" style={{ backgroundColor: this.props.color }}> | |||||
<div | |||||
className="KBColumn" | |||||
style={{ backgroundColor: this.props.color }} | |||||
key={this.props.id} | |||||
> | |||||
<h3>{this.props.title} </h3> | <h3>{this.props.title} </h3> | ||||
{this.getTaskRender()} | {this.getTaskRender()} | ||||
<button | <button | ||||
@@ -96,7 +92,7 @@ class KBColumn extends React.Component<KBColumnProps> { | |||||
this.props.onDelete && this.props.onDelete(this.props.id); | this.props.onDelete && this.props.onDelete(this.props.id); | ||||
}} | }} | ||||
> | > | ||||
Delete | |||||
Delete Column | |||||
</button> | </button> | ||||
</div> | </div> | ||||
); | ); | ||||