feat(ui/labels): display labels in task row
parent
21c996383c
commit
4f96333b52
|
@ -3951,6 +3951,7 @@ components:
|
|||
description: The Flux script to run for this task.
|
||||
type: string
|
||||
Task:
|
||||
type: object
|
||||
properties:
|
||||
id:
|
||||
readOnly: true
|
||||
|
@ -3970,6 +3971,8 @@ components:
|
|||
- inactive
|
||||
owner:
|
||||
$ref: "#/components/schemas/User"
|
||||
labels:
|
||||
$ref: "#/components/schemas/Labels"
|
||||
flux:
|
||||
description: The Flux script to run for this task.
|
||||
type: string
|
||||
|
@ -3980,8 +3983,13 @@ components:
|
|||
description: A task repetition schedule in the form '* * * * * *'; parsed from Flux.
|
||||
type: string
|
||||
offset:
|
||||
description: How long to wait before running the task
|
||||
description: Duration to delay after the schedule, before executing the task; parsed from flux.
|
||||
type: string
|
||||
latest_completed:
|
||||
description: Timestamp of latest scheduled, completed run, RFC3339.
|
||||
type: string
|
||||
format: date-time
|
||||
readOnly: true
|
||||
links:
|
||||
type: object
|
||||
readOnly: true
|
||||
|
|
|
@ -9,7 +9,7 @@ import {
|
|||
TemplateValueType,
|
||||
} from 'src/types'
|
||||
import {Links} from 'src/types/v2/links'
|
||||
import {Task, TaskStatus} from 'src/types/v2/tasks'
|
||||
import {Task} from 'src/types/v2/tasks'
|
||||
import {OnboardingStepProps} from 'src/onboarding/containers/OnboardingWizard'
|
||||
import {WithRouterProps} from 'react-router'
|
||||
import {ConfigurationState} from 'src/types/v2/dataLoaders'
|
||||
|
@ -24,6 +24,8 @@ import {
|
|||
TelegrafPluginInputNet,
|
||||
TelegrafPluginInputProcstat,
|
||||
TelegrafPluginInputDocker,
|
||||
Task as TaskApi,
|
||||
Label,
|
||||
} from 'src/api'
|
||||
|
||||
export const links: Links = {
|
||||
|
@ -215,6 +217,25 @@ export const dashboard: Dashboard = {
|
|||
labels: [],
|
||||
}
|
||||
|
||||
export const labels: Label[] = [
|
||||
{
|
||||
resourceID: 'dashboard-mock-label-a',
|
||||
name: 'Trogdor',
|
||||
properties: {
|
||||
color: '#44ffcc',
|
||||
description: 'Burninating the countryside',
|
||||
},
|
||||
},
|
||||
{
|
||||
resourceID: 'dashboard-mock-label-b',
|
||||
name: 'Strawberry',
|
||||
properties: {
|
||||
color: '#ff0054',
|
||||
description: 'It is a great fruit',
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
export const dashboardWithLabels: Dashboard = {
|
||||
id: '1',
|
||||
cells: [],
|
||||
|
@ -227,24 +248,7 @@ export const dashboardWithLabels: Dashboard = {
|
|||
createdAt: '2019-01-08T11:57:31.562044-08:00',
|
||||
updatedAt: '2019-01-08T12:57:31.562048-08:00',
|
||||
},
|
||||
labels: [
|
||||
{
|
||||
resourceID: 'dashboard-mock-label-a',
|
||||
name: 'Trogdor',
|
||||
properties: {
|
||||
color: '#44ffcc',
|
||||
description: 'Burninating the countryside',
|
||||
},
|
||||
},
|
||||
{
|
||||
resourceID: 'dashboard-mock-label-b',
|
||||
name: 'Strawberry',
|
||||
properties: {
|
||||
color: '#ff0054',
|
||||
description: 'It is a great fruit',
|
||||
},
|
||||
},
|
||||
],
|
||||
labels,
|
||||
}
|
||||
|
||||
export const cell: Cell = {
|
||||
|
@ -265,7 +269,7 @@ export const tasks: Task[] = [
|
|||
id: '02ef9deff2141000',
|
||||
organizationID: '02ee9e2a29d73000',
|
||||
name: 'pasdlak',
|
||||
status: TaskStatus.Active,
|
||||
status: TaskApi.StatusEnum.Active,
|
||||
owner: {id: '02ee9e2a19d73000', name: ''},
|
||||
flux:
|
||||
'option task = {\n name: "pasdlak",\n cron: "2 0 * * *"\n}\nfrom(bucket: "inbucket") \n|> range(start: -1h)',
|
||||
|
@ -282,12 +286,13 @@ export const tasks: Task[] = [
|
|||
id: '02ee9e2a29d73000',
|
||||
name: 'RadicalOrganization',
|
||||
},
|
||||
labels: [],
|
||||
},
|
||||
{
|
||||
id: '02f12c50dba72000',
|
||||
organizationID: '02ee9e2a29d73000',
|
||||
name: 'somename',
|
||||
status: TaskStatus.Active,
|
||||
status: TaskApi.StatusEnum.Active,
|
||||
owner: {id: '02ee9e2a19d73000', name: ''},
|
||||
flux:
|
||||
'option task = {\n name: "somename",\n every: 1m,\n}\nfrom(bucket: "inbucket") \n|> range(start: -task.every)',
|
||||
|
@ -304,6 +309,7 @@ export const tasks: Task[] = [
|
|||
id: '02ee9e2a29d73000',
|
||||
name: 'RadicalOrganization',
|
||||
},
|
||||
labels,
|
||||
},
|
||||
]
|
||||
|
||||
|
|
|
@ -2672,6 +2672,12 @@ export interface Task {
|
|||
* @memberof Task
|
||||
*/
|
||||
owner?: User;
|
||||
/**
|
||||
*
|
||||
* @type {Array<Label>}
|
||||
* @memberof Task
|
||||
*/
|
||||
labels?: Array<Label>;
|
||||
/**
|
||||
* The Flux script to run for this task.
|
||||
* @type {string}
|
||||
|
@ -2691,11 +2697,17 @@ export interface Task {
|
|||
*/
|
||||
cron?: string;
|
||||
/**
|
||||
* How long to wait before running the task
|
||||
* Duration to delay after the schedule, before executing the task; parsed from flux.
|
||||
* @type {string}
|
||||
* @memberof Task
|
||||
*/
|
||||
offset?: string;
|
||||
/**
|
||||
* Timestamp of latest scheduled, completed run, RFC3339.
|
||||
* @type {Date}
|
||||
* @memberof Task
|
||||
*/
|
||||
latestCompleted?: Date;
|
||||
/**
|
||||
*
|
||||
* @type {TaskLinks}
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
// Libraries
|
||||
import React from 'react'
|
||||
import {shallow} from 'enzyme'
|
||||
|
||||
// Components
|
||||
import {TaskRow} from 'src/tasks/components/TaskRow'
|
||||
|
||||
// Types
|
||||
import {Label} from 'src/clockface'
|
||||
|
||||
// Constants
|
||||
import {tasks, withRouterProps} from 'mocks/dummyData'
|
||||
|
||||
const setup = (override = {}) => {
|
||||
const props = {
|
||||
...withRouterProps,
|
||||
task: tasks[0],
|
||||
onActivate: jest.fn(),
|
||||
onDelete: jest.fn(),
|
||||
onSelect: jest.fn(),
|
||||
...override,
|
||||
}
|
||||
|
||||
const wrapper = shallow(<TaskRow {...props} />)
|
||||
|
||||
return {wrapper}
|
||||
}
|
||||
|
||||
describe('Tasks.Components.TaskRow', () => {
|
||||
it('renders', () => {
|
||||
const {wrapper} = setup()
|
||||
expect(wrapper.exists()).toBe(true)
|
||||
expect(wrapper).toMatchSnapshot()
|
||||
})
|
||||
|
||||
describe('if task has labels', () => {
|
||||
it('renders with labels', () => {
|
||||
const {wrapper} = setup({task: tasks[1]})
|
||||
|
||||
const labelContainer = wrapper.find(Label.Container)
|
||||
const labels = wrapper.find(Label)
|
||||
|
||||
expect(labelContainer.exists()).toBe(true)
|
||||
expect(labels.length).toBe(tasks[1].labels.length)
|
||||
})
|
||||
})
|
||||
})
|
|
@ -11,16 +11,16 @@ import {
|
|||
SlideToggle,
|
||||
IndexList,
|
||||
ConfirmationButton,
|
||||
Stack,
|
||||
Label,
|
||||
} from 'src/clockface'
|
||||
|
||||
// Utils
|
||||
import {downloadTextFile} from 'src/shared/utils/download'
|
||||
import {Task as TaskAPI, User, Organization} from 'src/api'
|
||||
import {Task as TaskAPI, Organization} from 'src/api'
|
||||
|
||||
interface Task extends TaskAPI {
|
||||
organization: Organization
|
||||
owner?: User
|
||||
offset?: string
|
||||
}
|
||||
|
||||
// Constants
|
||||
|
@ -33,16 +33,19 @@ interface Props {
|
|||
onSelect: (task: Task) => void
|
||||
}
|
||||
|
||||
class TaskRow extends PureComponent<Props & WithRouterProps> {
|
||||
export class TaskRow extends PureComponent<Props & WithRouterProps> {
|
||||
public render() {
|
||||
const {task, onDelete} = this.props
|
||||
|
||||
return (
|
||||
<IndexList.Row disabled={!this.isTaskActive}>
|
||||
<IndexList.Cell>
|
||||
<a href="#" onClick={this.handleClick}>
|
||||
{task.name}
|
||||
</a>
|
||||
<ComponentSpacer stackChildren={Stack.Rows} align={Alignment.Left}>
|
||||
<a href="#" onClick={this.handleClick}>
|
||||
{task.name}
|
||||
</a>
|
||||
{this.labels}
|
||||
</ComponentSpacer>
|
||||
</IndexList.Cell>
|
||||
<IndexList.Cell>
|
||||
<SlideToggle
|
||||
|
@ -94,6 +97,27 @@ class TaskRow extends PureComponent<Props & WithRouterProps> {
|
|||
router.push(`/organizations/${task.organization.id}/members_tab`)
|
||||
}
|
||||
|
||||
private get labels(): JSX.Element {
|
||||
const {task} = this.props
|
||||
if (!task.labels.length) {
|
||||
return
|
||||
}
|
||||
|
||||
return (
|
||||
<Label.Container limitChildCount={4}>
|
||||
{task.labels.map(label => (
|
||||
<Label
|
||||
key={label.resourceID}
|
||||
id={label.resourceID}
|
||||
colorHex={label.properties.color}
|
||||
name={label.name}
|
||||
description={label.properties.description}
|
||||
/>
|
||||
))}
|
||||
</Label.Container>
|
||||
)
|
||||
}
|
||||
|
||||
private get isTaskActive(): boolean {
|
||||
const {task} = this.props
|
||||
if (task.status === TaskAPI.StatusEnum.Active) {
|
||||
|
|
|
@ -0,0 +1,114 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`Tasks.Components.TaskRow renders 1`] = `
|
||||
<IndexListRow
|
||||
disabled={false}
|
||||
>
|
||||
<IndexListRowCell
|
||||
alignment="left"
|
||||
revealOnHover={false}
|
||||
>
|
||||
<ComponentSpacer
|
||||
align="left"
|
||||
stackChildren="rows"
|
||||
>
|
||||
<a
|
||||
href="#"
|
||||
onClick={[Function]}
|
||||
>
|
||||
pasdlak
|
||||
</a>
|
||||
</ComponentSpacer>
|
||||
</IndexListRowCell>
|
||||
<IndexListRowCell
|
||||
alignment="left"
|
||||
revealOnHover={false}
|
||||
>
|
||||
<SlideToggle
|
||||
active={true}
|
||||
color="primary"
|
||||
disabled={false}
|
||||
onChange={[Function]}
|
||||
size="xs"
|
||||
tooltipText=""
|
||||
/>
|
||||
</IndexListRowCell>
|
||||
<IndexListRowCell
|
||||
alignment="left"
|
||||
revealOnHover={false}
|
||||
>
|
||||
2 0 * * *
|
||||
</IndexListRowCell>
|
||||
<IndexListRowCell
|
||||
alignment="left"
|
||||
revealOnHover={false}
|
||||
>
|
||||
<a
|
||||
href=""
|
||||
onClick={[Function]}
|
||||
>
|
||||
RadicalOrganization
|
||||
</a>
|
||||
</IndexListRowCell>
|
||||
<IndexListRowCell
|
||||
alignment="right"
|
||||
revealOnHover={true}
|
||||
>
|
||||
<ComponentSpacer
|
||||
align="right"
|
||||
>
|
||||
<Button
|
||||
active={false}
|
||||
color="default"
|
||||
icon="export"
|
||||
onClick={[Function]}
|
||||
shape="none"
|
||||
size="xs"
|
||||
status="default"
|
||||
text="Export"
|
||||
type="button"
|
||||
/>
|
||||
<ConfirmationButton
|
||||
confirmText="Confirm"
|
||||
onConfirm={[MockFunction]}
|
||||
returnValue={
|
||||
Object {
|
||||
"cron": "2 0 * * *",
|
||||
"flux": "option task = {
|
||||
name: \\"pasdlak\\",
|
||||
cron: \\"2 0 * * *\\"
|
||||
}
|
||||
from(bucket: \\"inbucket\\")
|
||||
|> range(start: -1h)",
|
||||
"id": "02ef9deff2141000",
|
||||
"labels": Array [],
|
||||
"name": "pasdlak",
|
||||
"organization": Object {
|
||||
"id": "02ee9e2a29d73000",
|
||||
"links": Object {
|
||||
"buckets": "/api/v2/buckets?org=RadicalOrganization",
|
||||
"dashboards": "/api/v2/dashboards?org=RadicalOrganization",
|
||||
"log": "/api/v2/orgs/02ee9e2a29d73000/log",
|
||||
"members": "/api/v2/orgs/02ee9e2a29d73000/members",
|
||||
"self": "/api/v2/orgs/02ee9e2a29d73000",
|
||||
"tasks": "/api/v2/tasks?org=RadicalOrganization",
|
||||
},
|
||||
"name": "RadicalOrganization",
|
||||
},
|
||||
"organizationID": "02ee9e2a29d73000",
|
||||
"owner": Object {
|
||||
"id": "02ee9e2a19d73000",
|
||||
"name": "",
|
||||
},
|
||||
"status": "active",
|
||||
}
|
||||
}
|
||||
shape="none"
|
||||
size="xs"
|
||||
status="default"
|
||||
text="Delete"
|
||||
/>
|
||||
</ComponentSpacer>
|
||||
</IndexListRowCell>
|
||||
</IndexListRow>
|
||||
`;
|
|
@ -63,6 +63,7 @@ exports[`TasksList rendering renders 1`] = `
|
|||
from(bucket: \\"inbucket\\")
|
||||
|> range(start: -1h)",
|
||||
"id": "02ef9deff2141000",
|
||||
"labels": Array [],
|
||||
"name": "pasdlak",
|
||||
"organization": Object {
|
||||
"id": "02ee9e2a29d73000",
|
||||
|
@ -92,6 +93,24 @@ from(bucket: \\"inbucket\\")
|
|||
from(bucket: \\"inbucket\\")
|
||||
|> range(start: -task.every)",
|
||||
"id": "02f12c50dba72000",
|
||||
"labels": Array [
|
||||
Object {
|
||||
"name": "Trogdor",
|
||||
"properties": Object {
|
||||
"color": "#44ffcc",
|
||||
"description": "Burninating the countryside",
|
||||
},
|
||||
"resourceID": "dashboard-mock-label-a",
|
||||
},
|
||||
Object {
|
||||
"name": "Strawberry",
|
||||
"properties": Object {
|
||||
"color": "#ff0054",
|
||||
"description": "It is a great fruit",
|
||||
},
|
||||
"resourceID": "dashboard-mock-label-b",
|
||||
},
|
||||
],
|
||||
"name": "somename",
|
||||
"organization": Object {
|
||||
"id": "02ee9e2a29d73000",
|
||||
|
|
|
@ -63,6 +63,7 @@ exports[`TasksList rendering renders 1`] = `
|
|||
from(bucket: \\"inbucket\\")
|
||||
|> range(start: -1h)",
|
||||
"id": "02ef9deff2141000",
|
||||
"labels": Array [],
|
||||
"name": "pasdlak",
|
||||
"organization": Object {
|
||||
"id": "02ee9e2a29d73000",
|
||||
|
@ -92,6 +93,24 @@ from(bucket: \\"inbucket\\")
|
|||
from(bucket: \\"inbucket\\")
|
||||
|> range(start: -task.every)",
|
||||
"id": "02f12c50dba72000",
|
||||
"labels": Array [
|
||||
Object {
|
||||
"name": "Trogdor",
|
||||
"properties": Object {
|
||||
"color": "#44ffcc",
|
||||
"description": "Burninating the countryside",
|
||||
},
|
||||
"resourceID": "dashboard-mock-label-a",
|
||||
},
|
||||
Object {
|
||||
"name": "Strawberry",
|
||||
"properties": Object {
|
||||
"color": "#ff0054",
|
||||
"description": "It is a great fruit",
|
||||
},
|
||||
"resourceID": "dashboard-mock-label-b",
|
||||
},
|
||||
],
|
||||
"name": "somename",
|
||||
"organization": Object {
|
||||
"id": "02ee9e2a29d73000",
|
||||
|
|
|
@ -1,22 +1,6 @@
|
|||
import {Organization} from 'src/types/v2/orgs'
|
||||
import {Task as TaskAPI} from 'src/api'
|
||||
|
||||
export interface Task {
|
||||
every?: string
|
||||
cron?: string
|
||||
offset?: string
|
||||
id: string
|
||||
name: string
|
||||
status: TaskStatus
|
||||
organizationID: string
|
||||
export interface Task extends TaskAPI {
|
||||
organization: Organization
|
||||
owner: {
|
||||
id: string
|
||||
name: string
|
||||
}
|
||||
flux?: string
|
||||
}
|
||||
|
||||
export enum TaskStatus {
|
||||
Active = 'active',
|
||||
Inactive = 'inactive',
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue