Refonte de l'UI des tableaux

This commit is contained in:
2020-06-05 16:18:53 +02:00
parent 94bfb77d87
commit 832cca1c66
8 changed files with 202 additions and 98 deletions

View File

@ -1,7 +1,7 @@
import React, { Fragment } from 'react';
import { Page } from '../Page';
import { connect, DispatchProp } from 'react-redux';
import Board from '@lourenci/react-kanban';
import Board, { addColumn } from '@lourenci/react-kanban';
import { fetchBoards } from '../../store/actions/boards';
import { createIssue } from '../../store/actions/issues';
import { buildKanboard, moveCard } from '../../store/actions/kanboards';
@ -13,6 +13,7 @@ export interface BoardPageProps extends DispatchProp {
board: any
kanboard: any
}
export class BoardPage extends React.Component<BoardPageProps> {
state = {
@ -24,6 +25,7 @@ export class BoardPage extends React.Component<BoardPageProps> {
project: ""
},
compactMode: true,
hasError: false,
}
onNewCardTitleChange: (evt: any) => void;
@ -41,19 +43,22 @@ export class BoardPage extends React.Component<BoardPageProps> {
this.onNewCardSaveClick = this.onNewCardSaveClick.bind(this);
}
componentDidCatch(error, errorInfo) {
// You can also log the error to an error reporting service
console.error(error, errorInfo);
}
render() {
const { board } = this.props;
return (
<Page title={`${board ? (board.title + ' - ') : ''}GenGitKan`}>
<div className="container is-fluid">
{this.renderBoard()}
</div>
{this.renderBoard()}
</Page>
);
}
renderBoard() {
const { kanboard } = this.props;
const { kanboard, board } = this.props;
if (!kanboard) {
return <Loader></Loader>
@ -61,28 +66,35 @@ export class BoardPage extends React.Component<BoardPageProps> {
return (
<Fragment>
<div className="is-clearfix has-margin-top-normal">
<div className="is-pulled-right">
<div className="field">
<input id="compactMode"
checked={this.state.compactMode}
onChange={this.onCompactModeChange.bind(this)}
type="checkbox"
className="switch is-rtl"
name="compactMode"
/>
<label htmlFor="compactMode">Mode compact</label>
<nav className="navbar is-info">
<div className="container is-fluid">
<div className="navbar-start">
<div className="navbar-item">
{board.title}
</div>
</div>
<div className="navbar-end">
<a href={`#/boards/${board.id}/edit`} className="navbar-item">
<span className="icon">
<i className="fa fa-edit fa-fw"></i>
</span>
<span>Modifier le tableau</span>
</a>
</div>
</div>
</div>
<div className="kanboard-container is-fullheight">
<Board disableLaneDrag={true}
renderCard={this.renderCard.bind(this)}
renderLaneHeader={this.renderLaneHeader}
onCardDragEnd={this.onCardDragEnd.bind(this)}>
{kanboard}
</Board>
{ this.renderNewCardModal() }
</nav>
<div className="container is-fluid">
<div className="kanboard-container is-fullheight">
<Board
initialBoard={kanboard}
renderCard={this.renderCard.bind(this)}
renderColumnHeader={this.renderLaneHeader.bind(this)}
onCardDragEnd={this.onCardDragEnd.bind(this)}
disableColumnDrag={true}
/>
{ this.renderNewCardModal() }
</div>
</div>
</Fragment>
@ -167,28 +179,39 @@ export class BoardPage extends React.Component<BoardPageProps> {
<div className="kanboard-lane">
<div className="level">
<div className="level-left">
<h3 className="level-item is-size-3">{lane.title}</h3>
<div className="level-item">
<span className="tag is-primary is-light is-normal">{lane.cards.length}</span>
</div>
<h3 className="level-item is-size-5">
{lane.title}
</h3>
</div>
<div className="level-right">
<button className="button is-light level-item is-medium"
<button className="button is-light level-item is-small"
onClick={this.onNewCardClick.bind(this, lane.id)}>
<span className="icon">
<i className="fas fa-plus" aria-hidden="true"></i>
</span>
</button>
<button className="button is-light level-item is-small"
onClick={this.onNewCardClick.bind(this, lane.id)}>
<span className="icon">
<i className="fas fa-chevron-left" aria-hidden="true"></i>
</span>
</button>
</div>
</div>
</div>
)
}
onCardDragEnd(source: any, dest: any) {
onCardDragEnd(b: any, card: any, source: any, dest: any) {
const { board } = this.props;
this.props.dispatch(moveCard(
board.id,
source.fromLaneId,
source.fromColumnId,
source.fromPosition,
dest.toLaneId,
dest.toColumnId,
dest.toPosition
));
}

View File

@ -16,41 +16,43 @@ export class IssueCard extends React.PureComponent<IssueCardProps> {
return (
<div className="kanboard-card">
<div className={`box ${compact ? 'has-padding-small': ''}`}>
<div className="box has-padding-small is-radiusless">
<div className="media">
{
card.issue.assignee && !compact ?
<div className="media-left">
<figure className="image is-64x64">
<img src={card.issue.assignee.avatar_url} alt="Image" />
</figure>
<small>{`@${card.issue.assignee.login}`}</small>
</div>
: null
}
<div className="media-content">
<div className="content">
<p>
<a target="_blank" href={issueURL}><strong>{`#${card.issue.number}`}</strong></a>&nbsp;
{ !compact && card.issue.milestone ? <small>{`- ${card.issue.milestone.title}`}</small> : null }
{ !compact ? <br /> : ' - ' }
<span className="is-size-6">{card.issue.title}</span>
</p>
<nav className="level">
<div className="level-left">
<div className="level-item">
<a target="_blank" href={issueURL}><strong>{`#${card.issue.number}`}</strong></a>
</div>
<div className="level-item">
<a target="_blank" href={projectURL}>{card.project}</a>
</div>
</div>
<div className="level-right">
{
card.issue.assignee ?
<div className="level-item">
<small>{`@${card.issue.assignee.login}`}</small>
</div>
: null
}
</div>
</nav>
<span>{card.issue.title}</span>
</div>
{
<nav className="level">
<div className="level-left"></div>
<div className="level-right">
<div className="level-item is-size-7">
{card.issue.milestone.title}
</div>
</div>
</nav>
}
</div>
</div>
{
!compact ?
<div className="level is-mobile" style={{marginTop:'1rem'}}>
<div className="level-left">
<small className="level-item"><a href={projectURL}>{card.project}</a></small>
</div>
<div className="level-right">
</div>
</div> :
null
}
</div>
</div>
);

View File

@ -1,5 +1,6 @@
@import 'bulma/bulma.sass';
@import '../../node_modules/@lourenci/react-kanban/dist/styles.css';
@import 'bulma-switch/dist/css/bulma-switch.sass';
@import '_base.scss';
@import '_loader.scss';
@import '_kanboard.scss';
@import '_kanboard.scss';

View File

@ -44,6 +44,10 @@
.kanboard-lane {
margin-bottom: $size-small;
background: $white;
position: sticky;
position: -webkit-sticky;
top: 0;
}
}
@ -51,4 +55,79 @@
justify-content: center;
align-items: center;
width: 50% !important;
}
.react-kanban-board {
max-height: calc(100vh - calc(52px * 2));
overflow: hidden;
overflow-x: scroll;
scrollbar-color: $grey-lighter, #f1f1f1;
scrollbar-width: 5px;
&::-webkit-scrollbar {
width: 5px;
height: 5px;
}
/* Track */
&::-webkit-scrollbar-track {
background: #f1f1f1;
}
/* Handle */
&::-webkit-scrollbar-thumb {
background: $grey-lighter;
}
/* Handle on hover */
&::-webkit-scrollbar-thumb:hover {
background: $green;
}
}
.react-kanban-column {
max-width: 305px;
min-width: 305px;
position: relative;
max-height: 100%;
overflow-x: hidden;
overflow-y: scroll;
scrollbar-color: $grey-lighter, #f1f1f1;
scrollbar-width: 5px;
&.minimized {
max-width: 30px;
min-width: 30px;
}
&::-webkit-scrollbar {
width: 5px;
}
/* Track */
&::-webkit-scrollbar-track {
background: #f1f1f1;
}
/* Handle */
&::-webkit-scrollbar-thumb {
background: $grey-lighter;
}
/* Handle on hover */
&::-webkit-scrollbar-thumb:hover {
background: $green;
}
}
.react-kanban-card__title {
position: sticky;
position: -webkit-sticky;
}
.react-kanban-column {
background: white !important;
}

View File

@ -37,7 +37,7 @@ function handleMoveCard(state: any, action: any) {
const kanboard = state.byID[boardID];
const lanes = [ ...kanboard.lanes ];
const lanes = [ ...kanboard.columns ];
const fromLane = lanes[fromLaneID];
const toLane = lanes[toLaneID];
const card = fromLane.cards[fromPosition];

View File

@ -145,7 +145,7 @@ function createKanboard(board: Board, issues: any) {
const kanboard = {
id: board.id,
lanes: createKanboardLanes(board, issues),
columns: createKanboardLanes(board, issues),
};
return kanboard;