Update routes to create, update and select task from org page

Co-authored-by: Iris Scholten <ischolten.is@gmail.com>
pull/11739/head
Palak Bhojani 2019-02-06 15:52:44 -08:00
parent 3636784016
commit 078ff6db09
9 changed files with 436 additions and 35 deletions

View File

@ -3,6 +3,7 @@
## Features
1. [11677](https://github.com/influxdata/influxdb/pull/11677): Add instructions button to view `$INFLUX_TOKEN` setup for telegraf configs
1. [11693](https://github.com/influxdata/influxdb/pull/11693): Save the $INFLUX_TOKEN environmental variable in telegraf configs
1. [11700](https://github.com/influxdata/influxdb/pull/11700): Update Tasks tab on Org page to look like Tasks Page
## Bug Fixes
1. [11678](https://github.com/influxdata/influxdb/pull/11678): Update the System Telegraf Plugin bundle to include the swap plugin

View File

@ -25,6 +25,8 @@ import TaskPage from 'src/tasks/containers/TaskPage'
import TasksPage from 'src/tasks/containers/TasksPage'
import OrganizationsIndex from 'src/organizations/containers/OrganizationsIndex'
import OrganizationView from 'src/organizations/containers/OrganizationView'
import OrgTaskPage from 'src/organizations/components/OrgTaskPage'
import OrgTaskEditPage from 'src/organizations/components/OrgTaskEditPage'
import TaskEditPage from 'src/tasks/containers/TaskEditPage'
import DashboardPage from 'src/dashboards/components/DashboardPage'
import DashboardsIndex from 'src/dashboards/components/dashboard_index/DashboardsIndex'
@ -101,10 +103,20 @@ class Root extends PureComponent {
<IndexRoute component={MePage} />
<Route path="organizations">
<IndexRoute component={OrganizationsIndex} />
<Route
path=":orgID/:tab"
component={OrganizationView}
/>
<Route path=":orgID">
<Route
path="tasks_tab/new"
component={OrgTaskPage}
/>
<Route
path="tasks_tab/:id"
component={OrgTaskEditPage}
/>
<Route
path=":tab"
component={OrganizationView}
/>
</Route>
</Route>
<Route path="tasks">
<IndexRoute component={TasksPage} />

View File

@ -0,0 +1,189 @@
// Libraries
import _ from 'lodash'
import React, {PureComponent, ChangeEvent} from 'react'
import {InjectedRouter} from 'react-router'
import {connect} from 'react-redux'
// Components
import TaskForm from 'src/tasks/components/TaskForm'
import TaskHeader from 'src/tasks/components/TaskHeader'
import {Page} from 'src/pageLayout'
import FluxEditor from 'src/shared/components/FluxEditor'
// Actions
import {
updateScript,
selectTaskByID,
setCurrentScript,
cancel,
setTaskOption,
clearTask,
setAllTaskOptions,
} from 'src/tasks/actions/v2'
// Types
import {Organization} from '@influxdata/influx'
import {Links} from 'src/types/v2/links'
import {State as TasksState} from 'src/tasks/reducers/v2'
import {
TaskOptions,
TaskOptionKeys,
TaskSchedule,
} from 'src/utils/taskOptionsToFluxScript'
import {Task} from 'src/tasks/containers/TasksPage'
interface PassedInProps {
router: InjectedRouter
params: {id: string; orgID: string}
}
interface ConnectStateProps {
orgs: Organization[]
taskOptions: TaskOptions
currentTask: Task
currentScript: string
tasksLink: string
}
interface ConnectDispatchProps {
setTaskOption: typeof setTaskOption
setCurrentScript: typeof setCurrentScript
updateScript: typeof updateScript
cancel: typeof cancel
selectTaskByID: typeof selectTaskByID
clearTask: typeof clearTask
setAllTaskOptions: typeof setAllTaskOptions
}
class OrgTaskEditPage extends PureComponent<
PassedInProps & ConnectStateProps & ConnectDispatchProps
> {
constructor(props) {
super(props)
}
public async componentDidMount() {
const {
params: {id, orgID},
} = this.props
await this.props.selectTaskByID(id, `organizations/${orgID}/tasks_tab/`)
const {currentTask} = this.props
this.props.setAllTaskOptions(currentTask)
}
public componentWillUnmount() {
this.props.clearTask()
}
public render(): JSX.Element {
const {currentScript, taskOptions, orgs} = this.props
return (
<Page titleTag={`Edit ${taskOptions.name}`}>
<TaskHeader
title="Update Task"
canSubmit={this.isFormValid}
onCancel={this.handleCancel}
onSave={this.handleSave}
/>
<Page.Contents fullWidth={true} scrollable={false}>
<div className="task-form">
<div className="task-form--options">
<TaskForm
orgs={orgs}
canSubmit={this.isFormValid}
taskOptions={taskOptions}
onChangeInput={this.handleChangeInput}
onChangeScheduleType={this.handleChangeScheduleType}
onChangeTaskOrgID={this.handleChangeTaskOrgID}
/>
</div>
<div className="task-form--editor">
<FluxEditor
script={currentScript}
onChangeScript={this.handleChangeScript}
visibility="visible"
status={{text: '', type: ''}}
suggestions={[]}
/>
</div>
</div>
</Page.Contents>
</Page>
)
}
private get isFormValid(): boolean {
const {
taskOptions: {name, cron, interval},
currentScript,
} = this.props
const hasSchedule = !!cron || !!interval
return hasSchedule && !!name && !!currentScript
}
private handleChangeScript = (script: string) => {
this.props.setCurrentScript(script)
}
private handleChangeScheduleType = (schedule: TaskSchedule) => {
this.props.setTaskOption({key: 'taskScheduleType', value: schedule})
}
private handleSave = () => {
const {params} = this.props
this.props.updateScript(`organizations/${params.orgID}/tasks_tab/`)
}
private handleCancel = () => {
this.props.cancel()
}
private handleChangeInput = (e: ChangeEvent<HTMLInputElement>) => {
const {name, value} = e.target
const key = name as TaskOptionKeys
this.props.setTaskOption({key, value})
}
private handleChangeTaskOrgID = (orgID: string) => {
this.props.setTaskOption({key: 'orgID', value: orgID})
}
}
const mstp = ({
tasks,
links,
orgs,
}: {
tasks: TasksState
links: Links
orgs: Organization[]
}): ConnectStateProps => {
return {
orgs,
taskOptions: tasks.taskOptions,
currentScript: tasks.currentScript,
tasksLink: links.tasks,
currentTask: tasks.currentTask,
}
}
const mdtp: ConnectDispatchProps = {
setTaskOption,
setCurrentScript,
updateScript,
cancel,
selectTaskByID,
setAllTaskOptions,
clearTask,
}
export default connect<ConnectStateProps, ConnectDispatchProps, {}>(
mstp,
mdtp
)(OrgTaskEditPage)

View File

@ -0,0 +1,181 @@
import _ from 'lodash'
import React, {PureComponent, ChangeEvent} from 'react'
import {InjectedRouter} from 'react-router'
import {connect} from 'react-redux'
// components
import TaskForm from 'src/tasks/components/TaskForm'
import TaskHeader from 'src/tasks/components/TaskHeader'
import FluxEditor from 'src/shared/components/FluxEditor'
import {Page} from 'src/pageLayout'
// actions
import {State as TasksState} from 'src/tasks/reducers/v2'
import {
setNewScript,
saveNewScript,
setTaskOption,
clearTask,
cancel,
} from 'src/tasks/actions/v2'
// types
import {Links} from 'src/types/v2/links'
import {Organization} from 'src/types/v2'
import {
TaskOptions,
TaskOptionKeys,
TaskSchedule,
} from 'src/utils/taskOptionsToFluxScript'
// Styles
import 'src/tasks/components/TaskForm.scss'
interface PassedInProps {
router: InjectedRouter
params: {orgID: string}
}
interface ConnectStateProps {
orgs: Organization[]
taskOptions: TaskOptions
newScript: string
tasksLink: string
}
interface ConnectDispatchProps {
setNewScript: typeof setNewScript
saveNewScript: typeof saveNewScript
setTaskOption: typeof setTaskOption
clearTask: typeof clearTask
cancel: typeof cancel
}
class OrgTaskPage extends PureComponent<
PassedInProps & ConnectStateProps & ConnectDispatchProps
> {
constructor(props) {
super(props)
}
public componentDidMount() {
this.props.setTaskOption({
key: 'taskScheduleType',
value: TaskSchedule.interval,
})
}
public componentWillUnmount() {
this.props.clearTask()
}
public render(): JSX.Element {
const {newScript, taskOptions, orgs} = this.props
return (
<Page titleTag="Create Task">
<TaskHeader
title="Create Task"
canSubmit={this.isFormValid}
onCancel={this.handleCancel}
onSave={this.handleSave}
/>
<Page.Contents fullWidth={true} scrollable={false}>
<div className="task-form">
<div className="task-form--options">
<TaskForm
orgs={orgs}
canSubmit={this.isFormValid}
taskOptions={taskOptions}
onChangeInput={this.handleChangeInput}
onChangeScheduleType={this.handleChangeScheduleType}
onChangeTaskOrgID={this.handleChangeTaskOrgID}
/>
</div>
<div className="task-form--editor">
<FluxEditor
script={newScript}
onChangeScript={this.handleChangeScript}
visibility="visible"
status={{text: '', type: ''}}
suggestions={[]}
/>
</div>
</div>
</Page.Contents>
</Page>
)
}
private get isFormValid(): boolean {
const {
taskOptions: {name, cron, interval},
newScript,
} = this.props
const hasSchedule = !!cron || !!interval
return hasSchedule && !!name && !!newScript
}
private handleChangeScript = (script: string) => {
this.props.setNewScript(script)
}
private handleChangeScheduleType = (schedule: TaskSchedule) => {
this.props.setTaskOption({key: 'taskScheduleType', value: schedule})
}
private handleSave = () => {
const {params, newScript, taskOptions} = this.props
this.props.saveNewScript(
newScript,
taskOptions,
`organizations/${params.orgID}/tasks_tab/`
)
}
private handleCancel = () => {
this.props.cancel()
}
private handleChangeInput = (e: ChangeEvent<HTMLInputElement>) => {
const {name, value} = e.target
const key = name as TaskOptionKeys
this.props.setTaskOption({key, value})
}
private handleChangeTaskOrgID = (orgID: string) => {
this.props.setTaskOption({key: 'orgID', value: orgID})
}
}
const mstp = ({
tasks,
links,
orgs,
}: {
tasks: TasksState
links: Links
orgs: Organization[]
}): ConnectStateProps => {
return {
orgs,
taskOptions: tasks.taskOptions,
newScript: tasks.newScript,
tasksLink: links.tasks,
}
}
const mdtp: ConnectDispatchProps = {
setNewScript,
saveNewScript,
setTaskOption,
clearTask,
cancel,
}
export default connect<ConnectStateProps, ConnectDispatchProps, {}>(
mstp,
mdtp
)(OrgTaskPage)

View File

@ -35,6 +35,7 @@ import {AppState} from 'src/types/v2'
interface PassedInProps {
tasks: Task[]
orgName: string
orgID: string
onChange: () => void
router: InjectedRouter
}
@ -123,7 +124,7 @@ class OrgTasksPage extends PureComponent<Props, State> {
onDelete={this.handleDelete}
onCreate={this.handleCreateTask}
onClone={this.handleClone}
onSelect={selectTask}
onSelect={this.handleSelectTask}
onAddTaskLabels={onAddTaskLabels}
onRemoveTaskLabels={onRemoveTaskLabels}
/>
@ -135,6 +136,12 @@ class OrgTasksPage extends PureComponent<Props, State> {
)
}
private handleSelectTask = (task: Task) => {
const {selectTask, orgID} = this.props
selectTask(task, `organizations/${orgID}/tasks_tab/${task.id}`)
}
private get filteredTasks() {
const {tasks, showInactive} = this.props
if (showInactive) {
@ -175,9 +182,9 @@ class OrgTasksPage extends PureComponent<Props, State> {
}
private handleCreateTask = () => {
const {router} = this.props
const {router, orgID} = this.props
router.push('/tasks/new')
router.push(`/organizations/${orgID}/tasks_tab/new`)
}
private handleToggleOverlay = () => {
@ -209,6 +216,7 @@ class OrgTasksPage extends PureComponent<Props, State> {
this.props.setSearchTerm(e.target.value)
}
}
const mstp = ({
tasks: {searchTerm, showInactive},
orgs,
@ -219,6 +227,7 @@ const mstp = ({
orgs,
}
}
const mdtp: ConnectedDispatchProps = {
updateTaskStatus,
deleteTask,
@ -230,6 +239,7 @@ const mdtp: ConnectedDispatchProps = {
onRemoveTaskLabels: removeTaskLabelsAsync,
onAddTaskLabels: addTaskLabelsAsync,
}
export default connect<
ConnectedStateProps,
ConnectedDispatchProps,

View File

@ -181,6 +181,7 @@ class OrganizationView extends PureComponent<Props> {
<OrgTasksPage
tasks={tasks}
orgName={org.name}
orgID={org.id}
onChange={fetch}
router={router}
/>

View File

@ -1,5 +1,5 @@
// Libraries
import {push} from 'react-router-redux'
import {push, goBack} from 'react-router-redux'
import _ from 'lodash'
// APIs
@ -288,7 +288,7 @@ export const populateTasks = () => async (
}
}
export const selectTaskByID = (id: string) => async (
export const selectTaskByID = (id: string, route?: string) => async (
dispatch,
getState: GetStateFunc
): Promise<void> => {
@ -301,26 +301,37 @@ export const selectTaskByID = (id: string) => async (
return dispatch(setCurrentTask({...task, organization: org}))
} catch (e) {
console.error(e)
dispatch(goToTasks())
dispatch(goToTasks(route))
const message = getErrorMessage(e)
dispatch(notify(taskNotFound(message)))
}
}
export const selectTask = (task: Task) => async dispatch => {
export const selectTask = (task: Task, route?: string) => async dispatch => {
if (route) {
dispatch(push(route))
return
}
dispatch(push(`/tasks/${task.id}`))
}
export const goToTasks = () => async dispatch => {
export const goToTasks = (route?: string) => async dispatch => {
if (route) {
dispatch(push(route))
return
}
dispatch(push('/tasks'))
}
export const cancelUpdateTask = () => async dispatch => {
export const cancel = () => async dispatch => {
dispatch(setCurrentTask(null))
dispatch(goToTasks())
dispatch(goBack())
}
export const updateScript = () => async (dispatch, getState: GetStateFunc) => {
export const updateScript = (route?: string) => async (
dispatch,
getState: GetStateFunc
) => {
try {
const {
tasks: {currentScript: script, currentTask: task, taskOptions},
@ -341,7 +352,7 @@ export const updateScript = () => async (dispatch, getState: GetStateFunc) => {
await client.tasks.update(task.id, updatedTask)
dispatch(setCurrentTask(null))
dispatch(goToTasks())
dispatch(goToTasks(route))
dispatch(notify(taskUpdateSuccess()))
} catch (e) {
console.error(e)
@ -352,7 +363,8 @@ export const updateScript = () => async (dispatch, getState: GetStateFunc) => {
export const saveNewScript = (
script: string,
taskOptions: TaskOptions
taskOptions: TaskOptions,
route?: string
) => async (dispatch, getState: GetStateFunc): Promise<void> => {
try {
const {orgs} = await getState()
@ -375,8 +387,8 @@ export const saveNewScript = (
dispatch(setNewScript(''))
dispatch(clearTask())
dispatch(goToTasks())
dispatch(populateTasks())
dispatch(goToTasks(route))
dispatch(notify(taskCreatedSuccess()))
} catch (e) {
console.error(e)

View File

@ -15,14 +15,14 @@ import {
updateScript,
selectTaskByID,
setCurrentScript,
cancelUpdateTask,
cancel,
setTaskOption,
clearTask,
setAllTaskOptions,
} from 'src/tasks/actions/v2'
// Types
import {Task as TaskAPI, User, Organization} from '@influxdata/influx'
import {Organization} from '@influxdata/influx'
import {Links} from 'src/types/v2/links'
import {State as TasksState} from 'src/tasks/reducers/v2'
import {
@ -30,12 +30,7 @@ import {
TaskOptionKeys,
TaskSchedule,
} from 'src/utils/taskOptionsToFluxScript'
interface Task extends TaskAPI {
organization: Organization
owner?: User
offset?: string
}
import {Task} from 'src/tasks/containers/TasksPage'
interface PassedInProps {
router: InjectedRouter
@ -54,13 +49,13 @@ interface ConnectDispatchProps {
setTaskOption: typeof setTaskOption
setCurrentScript: typeof setCurrentScript
updateScript: typeof updateScript
cancelUpdateTask: typeof cancelUpdateTask
cancel: typeof cancel
selectTaskByID: typeof selectTaskByID
clearTask: typeof clearTask
setAllTaskOptions: typeof setAllTaskOptions
}
class TaskPage extends PureComponent<
class TaskEditPage extends PureComponent<
PassedInProps & ConnectStateProps & ConnectDispatchProps
> {
constructor(props) {
@ -143,7 +138,7 @@ class TaskPage extends PureComponent<
}
private handleCancel = () => {
this.props.cancelUpdateTask()
this.props.cancel()
}
private handleChangeInput = (e: ChangeEvent<HTMLInputElement>) => {
@ -180,7 +175,7 @@ const mdtp: ConnectDispatchProps = {
setTaskOption,
setCurrentScript,
updateScript,
cancelUpdateTask,
cancel,
selectTaskByID,
setAllTaskOptions,
clearTask,
@ -189,4 +184,4 @@ const mdtp: ConnectDispatchProps = {
export default connect<ConnectStateProps, ConnectDispatchProps, {}>(
mstp,
mdtp
)(TaskPage)
)(TaskEditPage)

View File

@ -14,9 +14,9 @@ import {State as TasksState} from 'src/tasks/reducers/v2'
import {
setNewScript,
saveNewScript,
goToTasks,
setTaskOption,
clearTask,
cancel,
} from 'src/tasks/actions/v2'
// types
import {Links} from 'src/types/v2/links'
@ -44,9 +44,9 @@ interface ConnectStateProps {
interface ConnectDispatchProps {
setNewScript: typeof setNewScript
saveNewScript: typeof saveNewScript
goToTasks: typeof goToTasks
setTaskOption: typeof setTaskOption
clearTask: typeof clearTask
cancel: typeof cancel
}
class TaskPage extends PureComponent<
@ -130,7 +130,7 @@ class TaskPage extends PureComponent<
}
private handleCancel = () => {
this.props.goToTasks()
this.props.cancel()
}
private handleChangeInput = (e: ChangeEvent<HTMLInputElement>) => {
@ -165,9 +165,9 @@ const mstp = ({
const mdtp: ConnectDispatchProps = {
setNewScript,
saveNewScript,
goToTasks,
setTaskOption,
clearTask,
cancel,
}
export default connect<ConnectStateProps, ConnectDispatchProps, {}>(