From a7297e3d128570ea11d18a75b849fb43e124d8b2 Mon Sep 17 00:00:00 2001 From: William Petit Date: Thu, 5 Dec 2019 22:37:09 +0100 Subject: [PATCH] Allow issue creation via UI --- client/src/components/BoardPage/BoardPage.jsx | 178 ++++++++++++++---- client/src/components/BoardPage/IssueCard.jsx | 47 +++++ client/src/components/HomePage/HomePage.jsx | 2 +- client/src/components/Modal.jsx | 20 ++ client/src/components/Navbar.jsx | 4 +- client/src/components/Page.jsx | 2 +- client/src/sass/_base.scss | 4 + client/src/sass/_kanboard.scss | 8 +- client/src/sass/_loader.scss | 2 +- client/src/store/actions/issues.js | 10 +- client/src/store/reducers/issues.js | 17 +- client/src/store/reducers/kanboards.js | 1 + client/src/store/sagas/boards.js | 2 - client/src/store/sagas/issues.js | 25 ++- client/src/store/sagas/kanboards.js | 14 +- client/src/store/sagas/root.js | 8 +- client/src/util/gitea.js | 17 ++ 17 files changed, 310 insertions(+), 51 deletions(-) create mode 100644 client/src/components/BoardPage/IssueCard.jsx create mode 100644 client/src/components/Modal.jsx diff --git a/client/src/components/BoardPage/BoardPage.jsx b/client/src/components/BoardPage/BoardPage.jsx index 31c64b1..286a490 100644 --- a/client/src/components/BoardPage/BoardPage.jsx +++ b/client/src/components/BoardPage/BoardPage.jsx @@ -2,13 +2,36 @@ import React from 'react'; import { Page } from '../Page'; import { connect } from 'react-redux'; import Board from '@lourenci/react-kanban'; -import { fetchIssues } from '../../store/actions/issues'; import { fetchBoards } from '../../store/actions/boards'; +import { createIssue } from '../../store/actions/issues'; import { buildKanboard, moveCard } from '../../store/actions/kanboards'; import { Loader } from '../Loader'; +import { IssueCard } from './IssueCard'; +import { Modal } from '../Modal'; export class BoardPage extends React.Component { + state = { + newCardModalActive: false, + newCardLaneID: 0, + newCard: { + title: "", + body: "", + project: "" + } + } + + constructor(props) { + super(props); + this.renderLaneHeader = this.renderLaneHeader.bind(this); + this.onNewCardClick = this.onNewCardClick.bind(this); + this.onNewCardCloseClick = this.onNewCardCloseClick.bind(this); + this.onNewCardTitleChange = this.onNewCardAttrChange.bind(this, 'title'); + this.onNewCardBodyChange = this.onNewCardAttrChange.bind(this, 'body'); + this.onNewCardProjectChange = this.onNewCardAttrChange.bind(this, 'project'); + this.onNewCardSaveClick = this.onNewCardSaveClick.bind(this); + } + render() { return ( @@ -34,54 +57,99 @@ export class BoardPage extends React.Component { onCardDragEnd={this.onCardDragEnd.bind(this)}> {kanboard} + { this.renderNewCardModal() } ); } - renderCard(card) { + renderNewCardModal() { + const { newCardModalActive, newCardLaneID } = this.state; + const { board } = this.props; + if (!board) return null; return ( -
-
-
- { - card.issue.assignee ? -
-
- Image - {`@${card.issue.assignee.login}`} -
+ +
+
+
+

"{board.lanes[newCardLaneID].title}" - Nouveau ticket

+ +
+
+
+
+ +
- : null - } -
-
-

- {`#${card.issue.number}`}  - { card.issue.milestone ? {`- ${card.issue.milestone.title}`} : null } -
- {card.issue.title} -

-
-
-
- - - - - +
+
+ +
+
+
+
+
+
+
-
+
-
- ); + + ) + } + + renderCard(card) { + return ; } renderLaneHeader(lane) { return ( -

{lane.title}

+
+
+
+

{lane.title}

+
+
+ +
+
+
) } @@ -106,6 +174,48 @@ export class BoardPage extends React.Component { this.requestBuildKanboard(); } + onNewCardClick(laneID) { + const { board } = this.props; + this.setState({ + newCardModalActive: true, + newCardLaneID: laneID, + newCard: { + title: "", + body: "", + project: board.projects[0], + } + }); + } + + onNewCardCloseClick() { + this.setState({ newCardModalActive: false }); + } + + onNewCardAttrChange(attrName, evt) { + const value = evt.target.value; + this.setState(state => { + return { + ...state, + newCard: { + ...state.newCard, + [attrName]: value, + } + } + }) + } + + onNewCardSaveClick() { + const { newCard, newCardLaneID } = this.state; + const { board } = this.props; + this.setState({ newCardModalActive: false }); + this.props.dispatch(createIssue( + newCard.project, + newCard.title, + newCard.body, + board.lanes[newCardLaneID].issueLabel + )); + } + componentDidUpdate(prevProps) { if (prevProps.board !== this.props.board) this.requestBuildKanboard(); } diff --git a/client/src/components/BoardPage/IssueCard.jsx b/client/src/components/BoardPage/IssueCard.jsx new file mode 100644 index 0000000..3a2a09d --- /dev/null +++ b/client/src/components/BoardPage/IssueCard.jsx @@ -0,0 +1,47 @@ +import React from 'react'; + +export class IssueCard extends React.PureComponent { + render() { + const { card } = this.props; + return ( +
+
+
+ { + card.issue.assignee ? +
+
+ Image +
+ {`@${card.issue.assignee.login}`} +
+ : null + } +
+
+

+ {`#${card.issue.number}`}  + { card.issue.milestone ? {`- ${card.issue.milestone.title}`} : null } +
+ {card.issue.title} +

+
+
+
+ +
+
+ ); + } +} \ No newline at end of file diff --git a/client/src/components/HomePage/HomePage.jsx b/client/src/components/HomePage/HomePage.jsx index 4a425cd..ba132e8 100644 --- a/client/src/components/HomePage/HomePage.jsx +++ b/client/src/components/HomePage/HomePage.jsx @@ -11,7 +11,7 @@ export class HomePage extends React.Component { return (
-
+
diff --git a/client/src/components/Modal.jsx b/client/src/components/Modal.jsx new file mode 100644 index 0000000..fee86d6 --- /dev/null +++ b/client/src/components/Modal.jsx @@ -0,0 +1,20 @@ +import React from 'react'; + +export class Modal extends React.PureComponent { + render() { + const { children, active, showCloseButton, onClose } = this.props; + return ( +
+
+
+ {children} +
+ { + showCloseButton ? + : + null + } +
+ ); + } +} \ No newline at end of file diff --git a/client/src/components/Navbar.jsx b/client/src/components/Navbar.jsx index bd3caa7..49f7e76 100644 --- a/client/src/components/Navbar.jsx +++ b/client/src/components/Navbar.jsx @@ -1,9 +1,9 @@ import React from 'react'; -export class Navbar extends React.Component { +export class Navbar extends React.PureComponent { render() { return ( -