/*
Copyright (C) 2017 Cloudbase Solutions SRL
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see .
*/
import React from 'react'
import { observer } from 'mobx-react'
import styled from 'styled-components'
import TaskItem from '@src/components/modules/TransferModule/TaskItem/TaskItem'
import type { Task } from '@src/@types/Task'
import { ThemePalette, ThemeProps } from '@src/components/Theme'
import StatusImage from '@src/components/ui/StatusComponents/StatusImage/StatusImage'
const ColumnWidths = ['26%', '18%', '36%', '20%']
const Wrapper = styled.div``
const ContentWrapper = styled.div`
background: ${ThemePalette.grayscale[1]};
`
const LoadingWrapper = styled.div`
display: flex;
align-items: center;
justify-content: center;
padding: 64px;
`
const Header = styled.div`
display: flex;
border-bottom: 1px solid ${ThemePalette.grayscale[5]};
padding: 4px 8px;
`
const HeaderData = styled.div`
width: ${props => props.width};
font-size: 10px;
color: ${ThemePalette.grayscale[5]};
font-weight: ${ThemeProps.fontWeights.medium};
text-transform: uppercase;
`
const Body = styled.div``
type Props = {
items: Task[],
loading?: boolean,
}
type State = {
openedItems: Task[],
}
@observer
class Tasks extends React.Component {
state: State = {
openedItems: [],
}
dragStartPosition: { x: number, y: number } | null = null
UNSAFE_componentWillMount() {
this.UNSAFE_componentWillReceiveProps(this.props)
}
UNSAFE_componentWillReceiveProps(props: Props) {
this.setState(prevState => {
let openedItems = prevState.openedItems
props.items.forEach(item => {
if (item.status === 'RUNNING') {
openedItems.push(item)
return
}
// Close items that were previously in RUNNING state, but they no longer are
const oldItem = this.props.items.find(i => i.id === item.id)
if (oldItem && oldItem.status === 'RUNNING') {
openedItems = openedItems.filter(i => i.id !== oldItem.id)
}
})
return { openedItems }
})
}
get isLoading() {
return this.props.loading || this.props.items.length === 0
}
handleItemMouseDown(e: React.MouseEvent) {
this.dragStartPosition = { x: e.screenX, y: e.screenY }
}
handleItemMouseUp(e: React.MouseEvent, item: Task) {
this.dragStartPosition = this.dragStartPosition || { x: e.screenX, y: e.screenY }
if (this.dragStartPosition
&& Math.abs(this.dragStartPosition.x - e.screenX) < 3
&& Math.abs(this.dragStartPosition.y - e.screenY) < 3) {
this.toggleItem(item)
}
this.dragStartPosition = null
}
handleDependsOnClick(id: string) {
const item = this.props.items.find(i => i.id === id)
if (item) this.toggleItem(item)
}
toggleItem(item: Task) {
this.setState(prevState => {
let openedItems = prevState.openedItems
if (openedItems.find(i => i.id === item.id)) {
openedItems = openedItems.filter(i => i.id !== item.id)
} else {
openedItems = openedItems.filter(i => i.status === 'RUNNING')
openedItems.push(item)
}
return { openedItems }
})
}
renderLoading() {
return (
)
}
renderHeader() {
return (
Task
Instance
Latest Message
Timestamp
)
}
renderBody() {
return (
{this.props.items.map(item => (
this.handleItemMouseDown(e)}
onMouseUp={e => this.handleItemMouseUp(e, item)}
key={item.id}
item={item}
columnWidths={ColumnWidths}
open={Boolean(this.state.openedItems.find(i => i.id === item.id))}
onDependsOnClick={id => { this.handleDependsOnClick(id) }}
data-test-id={`tasks-item-${item.id}`}
/>
))}
)
}
renderContent() {
return (
{this.renderHeader()}
{this.renderBody()}
)
}
render() {
return (
{!this.isLoading ? this.renderContent() : null}
{this.isLoading ? this.renderLoading() : null}
)
}
}
export default Tasks