Skip to content

Commit

Permalink
add: third dashboard panel (Unassigned tours)
Browse files Browse the repository at this point in the history
  • Loading branch information
jimakker authored and alexsegura committed Jun 27, 2023
1 parent 7945e07 commit 9f2162b
Show file tree
Hide file tree
Showing 13 changed files with 402 additions and 35 deletions.
41 changes: 41 additions & 0 deletions features/dispatch.feature
Original file line number Diff line number Diff line change
Expand Up @@ -580,6 +580,47 @@ Feature: Dispatch
}
"""

Scenario: Add/reorder tasks of a tour
Given the fixtures files are loaded:
| dispatch.yml |
And the user "sarah" has role "ROLE_ADMIN"
And the user "sarah" is authenticated
When I add "Content-Type" header equal to "application/ld+json"
And I add "Accept" header equal to "application/ld+json"
And the user "sarah" sends a "PUT" request to "/api/tour/5" with body:
"""
{
"name":"Monday tour",
"tasks":[
"/api/tasks/1",
"/api/tasks/2",
"/api/tasks/3",
]
}
"""
Then the response status code should be 201
And the response should be in JSON
And the JSON should match:
"""
{
"@context":"/api/contexts/Tour",
"@id":"/api/tours/5",
"@type":"Tour",
"name":"Monday tour",
"items":[
"/api/tasks/1",
"/api/tasks/2",
"/api/tasks/3",
],
"distance":@integer@,
"duration":@integer@,
"polyline":@string@,
"createdAt":"@[email protected]()",
"updatedAt":"@[email protected]()"
}
"""


Scenario: Administrator can assign multiple tasks at once
Given the fixtures files are loaded:
| sylius_channels.yml |
Expand Down
4 changes: 3 additions & 1 deletion js/app/dashboard/components/RightPanel.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import UnassignedTasks from './UnassignedTasks'
import TaskLists from './TaskLists'
import ContextMenu from './ContextMenu'
import SearchPanel from './SearchPanel'
import UnassignedTours from './UnassignedTours'

class DashboardApp extends React.Component {

Expand All @@ -41,13 +42,14 @@ class DashboardApp extends React.Component {
onDragStart={ this.props.handleDragStart }
onDragEnd={ this.props.handleDragEnd }>
<Split
sizes={ [ 50, 50 ] }
sizes={ [ 33.33, 33.33, 33.33 ] }
direction={ this.props.splitDirection }
style={{ display: 'flex', flexDirection: this.props.splitDirection === 'vertical' ? 'column' : 'row', width: '100%' }}
// We need to use a "key" prop,
// to force a re-render when the direction has changed
key={ this.props.splitDirection }>
<UnassignedTasks />
<UnassignedTours />
<TaskLists couriersList={ this.props.couriersList } />
</Split>
</DragDropContext>
Expand Down
26 changes: 3 additions & 23 deletions js/app/dashboard/components/UnassignedTasks.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,10 @@ import { useTranslation } from 'react-i18next'

import Task from './Task'
import TaskGroup from './TaskGroup'
import Tour from './Tour'
import RecurrenceRule from './RecurrenceRule'
import UnassignedTasksPopoverContent from './UnassignedTasksPopoverContent'
import { setTaskListGroupMode, openNewTaskModal, toggleSearch, setCurrentRecurrenceRule, openNewRecurrenceRuleModal, deleteGroup, editGroup, showRecurrenceRules } from '../redux/actions'
import { selectGroups, selectStandaloneTasks, selectRecurrenceRules, selectSelectedTasks, selectTours } from '../redux/selectors'
import { selectGroups, selectStandaloneTasks, selectRecurrenceRules, selectSelectedTasks } from '../redux/selectors'

class StandaloneTasks extends React.Component {

Expand Down Expand Up @@ -163,28 +162,10 @@ class UnassignedTasks extends React.Component {
</Draggable>
)
})}
{ _.map(this.props.tours, (tour, index) => {
return (
<Draggable key={ `tour-${tour['@id']}` } draggableId={ `tour:${tour['@id']}` } index={ this.props.groups.length + index }>
{(provided) => (
<div
ref={ provided.innerRef }
{ ...provided.draggableProps }
{ ...provided.dragHandleProps }
>
<Tour
key={ tour['@id'] }
tour={ tour }
tasks={ tour.items }
/>
</div>
)}
</Draggable>
)
})}

<StandaloneTasksWithConnect
tasks={ this.props.standaloneTasks }
offset={ this.props.groups.length + this.props.tours.length } />
offset={ this.props.groups.length } />
{ provided.placeholder }
</div>
)}
Expand All @@ -199,7 +180,6 @@ function mapStateToProps (state) {

return {
groups: selectGroups(state),
tours: selectTours(state),
standaloneTasks: selectStandaloneTasks(state),
recurrenceRules: selectRecurrenceRules(state),
isRecurrenceRulesVisible: state.settings.isRecurrenceRulesVisible,
Expand Down
73 changes: 73 additions & 0 deletions js/app/dashboard/components/UnassignedTour.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import React from 'react'
import { connect } from 'react-redux'
import { withTranslation, useTranslation } from 'react-i18next'
import { Draggable, Droppable } from "react-beautiful-dnd"
import _ from 'lodash'
import Task from './Task'

const UnassignedTour = ({ tour, tasks, username = null, unassignTasks = null, isDropDisabled }) => {

const { t } = useTranslation()

const collapseId = `tour-panel-${tour['@id'].replaceAll('/', '-')}`

return (
<div className="panel panel-default nomargin task__draggable">
<div className="panel-heading" role="tab">
<h4 className="panel-title d-flex align-items-center">
<i className="fa fa-repeat flex-grow-0"></i>
<a role="button" data-toggle="collapse" href={ `#${collapseId}` } className="ml-2 flex-grow-1 text-truncate">
{ tour.name } <span className="badge">{ tasks.length }</span>
</a>
{ username && (
<a
onClick={() => unassignTasks(username, tasks)}
title={ t('ADMIN_DASHBOARD_UNASSIGN_TOUR', { name: tour.name }) }
>
<i className="fa fa-times"></i>
</a>
)}
</h4>
</div>
<div id={ `${collapseId}` } className="panel-collapse collapse" role="tabpanel">
<Droppable isDropDisabled={isDropDisabled} droppableId={ `unassigned_tour:${tour['@id'].replace('/api/tours/', '')}` }>
{(provided) => (
<div className="list-group list-group-padded nomargin taskList__tasks m-0" ref={ provided.innerRef } { ...provided.droppableProps }>
{ _.map(tasks, (task, index) => {
return (
<Draggable key={ `task-${task.id}` } draggableId={ `task:${task.id}` } index={ index }>
{(provided) => (
<div
ref={ provided.innerRef }
{ ...provided.draggableProps }
{ ...provided.dragHandleProps }
>
<Task
key={ task['@id'] }
task={ task }
assigned={ false }
/>
</div>
)}
</Draggable>
)
})}
{ provided.placeholder }
</div>
)}
</Droppable>
</div>
</div>
)
}

function mapStateToProps (state) {

return {
isDropDisabled: state.logistics.ui.unassignedTourTasksDroppableDisabled,
}
}

export default connect(mapStateToProps)(withTranslation()(UnassignedTour))

// export default withTranslation()(UnassignedTour)
60 changes: 60 additions & 0 deletions js/app/dashboard/components/UnassignedTours.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import React from 'react'
import _ from 'lodash'
import { connect } from 'react-redux'
import { withTranslation } from 'react-i18next'
import { Draggable, Droppable } from "react-beautiful-dnd"

import UnassignedTour from './UnassignedTour'
import { selectUnassignedTours } from '../redux/selectors'


class UnassignedTours extends React.Component {

render() {
return (
<div className="dashboard__panel">
<h4 className="d-flex justify-content-between">
<span>{ this.props.t('DASHBOARD_UNASSIGNED_TOURS') }</span>
</h4>
<div className="dashboard__panel__scroll">
<Droppable isDropDisabled={ this.props.isDropDisabled } droppableId="unassigned_tours">
{(provided) => (
<div className="list-group nomargin" ref={ provided.innerRef } { ...provided.droppableProps }>
{ _.map(this.props.tours, (tour, index) => {
return (
<Draggable key={ `tour-${tour['@id']}` } draggableId={ `tour:${tour['@id']}` } index={ index }>
{(provided) => (
<div
ref={ provided.innerRef }
{ ...provided.draggableProps }
{ ...provided.dragHandleProps }
>
<UnassignedTour
key={ tour['@id'] }
tour={ tour }
tasks={ tour.items }
/>
</div>
)}
</Draggable>
)
})}
{ provided.placeholder }
</div>
)}
</Droppable>
</div>
</div>
)
}
}

function mapStateToProps (state) {

return {
tours: selectUnassignedTours(state),
isDropDisabled: state.logistics.ui.unassignedToursDroppableDisabled
}
}

export default connect(mapStateToProps)(withTranslation()(UnassignedTours))
Loading

0 comments on commit 9f2162b

Please sign in to comment.