Migration du client sur Typescript
This commit is contained in:
242
client/src/components/BoardPage/BoardPage.tsx
Normal file
242
client/src/components/BoardPage/BoardPage.tsx
Normal file
@ -0,0 +1,242 @@
|
||||
import React from 'react';
|
||||
import { Page } from '../Page';
|
||||
import { connect } from 'react-redux';
|
||||
import Board from '@lourenci/react-kanban';
|
||||
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() {
|
||||
const { board } = this.props;
|
||||
return (
|
||||
<Page title={`${board ? (board.title + ' - ') : ''}GenGitKan`}>
|
||||
<div className="container is-fluid">
|
||||
{this.renderBoard()}
|
||||
</div>
|
||||
</Page>
|
||||
);
|
||||
}
|
||||
|
||||
renderBoard() {
|
||||
const { kanboard } = this.props;
|
||||
|
||||
if (!kanboard) {
|
||||
return <Loader></Loader>
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="kanboard-container is-fullheight">
|
||||
<Board disableLaneDrag={true}
|
||||
renderCard={this.renderCard}
|
||||
renderLaneHeader={this.renderLaneHeader}
|
||||
onCardDragEnd={this.onCardDragEnd.bind(this)}>
|
||||
{kanboard}
|
||||
</Board>
|
||||
{ this.renderNewCardModal() }
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
renderNewCardModal() {
|
||||
const { newCardModalActive, newCardLaneID } = this.state;
|
||||
const { board } = this.props;
|
||||
if (!board || !newCardLaneID) return null;
|
||||
return (
|
||||
<Modal active={newCardModalActive}>
|
||||
<div className="new-card-modal">
|
||||
<article className="message">
|
||||
<div className="message-header">
|
||||
<p><span>"{board.lanes[newCardLaneID].title}" - Nouveau ticket</span></p>
|
||||
<button className="delete" aria-label="delete" onClick={this.onNewCardCloseClick}></button>
|
||||
</div>
|
||||
<div className="message-body">
|
||||
<div className="field">
|
||||
<div className="control">
|
||||
<input className="input is-medium" type="text"
|
||||
placeholder="Titre de votre ticket..."
|
||||
value={this.state.newCard.title}
|
||||
onChange={this.onNewCardTitleChange} />
|
||||
</div>
|
||||
</div>
|
||||
<div className="field">
|
||||
<div className="control">
|
||||
<textarea className="textarea"
|
||||
placeholder="Description du nouveau ticket..."
|
||||
value={this.state.newCard.body}
|
||||
onChange={this.onNewCardBodyChange}
|
||||
rows="10">
|
||||
</textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div className="field">
|
||||
<div className="control is-expanded">
|
||||
<div className="select is-fullwidth"
|
||||
value={this.state.newCard.project}
|
||||
onChange={this.onNewCardProjectChange}>
|
||||
<select>
|
||||
{
|
||||
board.projects.map((p, i) => {
|
||||
return <option key={`new-card-project-${i}`} value={p}>{p}</option>
|
||||
})
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="field is-grouped is-grouped-right">
|
||||
<p className="control">
|
||||
<a className="button is-light"
|
||||
onClick={this.onNewCardCloseClick}>
|
||||
Annuler
|
||||
</a>
|
||||
</p>
|
||||
<p className="control">
|
||||
<a className="button is-primary"
|
||||
onClick={this.onNewCardSaveClick}>
|
||||
Enregistrer
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
</div>
|
||||
</Modal>
|
||||
)
|
||||
}
|
||||
|
||||
renderCard(card) {
|
||||
return <IssueCard card={card} />;
|
||||
}
|
||||
|
||||
renderLaneHeader(lane) {
|
||||
return (
|
||||
<div className="kanboard-lane">
|
||||
<div className="level">
|
||||
<div className="level-left">
|
||||
<h3 className="level-item is-size-3">{lane.title}</h3>
|
||||
</div>
|
||||
<div className="level-right">
|
||||
<button className="button is-light level-item is-medium"
|
||||
onClick={this.onNewCardClick.bind(this, lane.id)}>
|
||||
<span className="icon">
|
||||
<i className="fas fa-plus" aria-hidden="true"></i>
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
onCardDragEnd(source, dest) {
|
||||
const { board } = this.props;
|
||||
this.props.dispatch(moveCard(
|
||||
board.id,
|
||||
source.fromLaneId,
|
||||
source.fromPosition,
|
||||
dest.toLaneId,
|
||||
dest.toPosition
|
||||
));
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
const { board } = this.props;
|
||||
if (!board) {
|
||||
this.requestBoardsUpdate();
|
||||
return
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
requestBoardsUpdate() {
|
||||
this.props.dispatch(fetchBoards());
|
||||
}
|
||||
|
||||
requestBuildKanboard() {
|
||||
const { board } = this.props;
|
||||
if (!board) return;
|
||||
this.props.dispatch(buildKanboard(board));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export const ConnectedBoardPage = connect(function(state, props) {
|
||||
const boardID = props.match.params.id;
|
||||
return {
|
||||
board: state.boards.byID[boardID],
|
||||
kanboard: state.kanboards.byID[boardID]
|
||||
};
|
||||
})(BoardPage);
|
Reference in New Issue
Block a user