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 ## Features
1. [11677](https://github.com/influxdata/influxdb/pull/11677): Add instructions button to view `$INFLUX_TOKEN` setup for telegraf configs 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. [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 ## Bug Fixes
1. [11678](https://github.com/influxdata/influxdb/pull/11678): Update the System Telegraf Plugin bundle to include the swap plugin 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 TasksPage from 'src/tasks/containers/TasksPage'
import OrganizationsIndex from 'src/organizations/containers/OrganizationsIndex' import OrganizationsIndex from 'src/organizations/containers/OrganizationsIndex'
import OrganizationView from 'src/organizations/containers/OrganizationView' 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 TaskEditPage from 'src/tasks/containers/TaskEditPage'
import DashboardPage from 'src/dashboards/components/DashboardPage' import DashboardPage from 'src/dashboards/components/DashboardPage'
import DashboardsIndex from 'src/dashboards/components/dashboard_index/DashboardsIndex' import DashboardsIndex from 'src/dashboards/components/dashboard_index/DashboardsIndex'
@ -101,10 +103,20 @@ class Root extends PureComponent {
<IndexRoute component={MePage} /> <IndexRoute component={MePage} />
<Route path="organizations"> <Route path="organizations">
<IndexRoute component={OrganizationsIndex} /> <IndexRoute component={OrganizationsIndex} />
<Route <Route path=":orgID">
path=":orgID/:tab" <Route
component={OrganizationView} path="tasks_tab/new"
/> component={OrgTaskPage}
/>
<Route
path="tasks_tab/:id"
component={OrgTaskEditPage}
/>
<Route
path=":tab"
component={OrganizationView}
/>
</Route>
</Route> </Route>
<Route path="tasks"> <Route path="tasks">
<IndexRoute component={TasksPage} /> <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 { interface PassedInProps {
tasks: Task[] tasks: Task[]
orgName: string orgName: string
orgID: string
onChange: () => void onChange: () => void
router: InjectedRouter router: InjectedRouter
} }
@ -123,7 +124,7 @@ class OrgTasksPage extends PureComponent<Props, State> {
onDelete={this.handleDelete} onDelete={this.handleDelete}
onCreate={this.handleCreateTask} onCreate={this.handleCreateTask}
onClone={this.handleClone} onClone={this.handleClone}
onSelect={selectTask} onSelect={this.handleSelectTask}
onAddTaskLabels={onAddTaskLabels} onAddTaskLabels={onAddTaskLabels}
onRemoveTaskLabels={onRemoveTaskLabels} 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() { private get filteredTasks() {
const {tasks, showInactive} = this.props const {tasks, showInactive} = this.props
if (showInactive) { if (showInactive) {
@ -175,9 +182,9 @@ class OrgTasksPage extends PureComponent<Props, State> {
} }
private handleCreateTask = () => { private handleCreateTask = () => {
const {router} = this.props const {router, orgID} = this.props
router.push('/tasks/new') router.push(`/organizations/${orgID}/tasks_tab/new`)
} }
private handleToggleOverlay = () => { private handleToggleOverlay = () => {
@ -209,6 +216,7 @@ class OrgTasksPage extends PureComponent<Props, State> {
this.props.setSearchTerm(e.target.value) this.props.setSearchTerm(e.target.value)
} }
} }
const mstp = ({ const mstp = ({
tasks: {searchTerm, showInactive}, tasks: {searchTerm, showInactive},
orgs, orgs,
@ -219,6 +227,7 @@ const mstp = ({
orgs, orgs,
} }
} }
const mdtp: ConnectedDispatchProps = { const mdtp: ConnectedDispatchProps = {
updateTaskStatus, updateTaskStatus,
deleteTask, deleteTask,
@ -230,6 +239,7 @@ const mdtp: ConnectedDispatchProps = {
onRemoveTaskLabels: removeTaskLabelsAsync, onRemoveTaskLabels: removeTaskLabelsAsync,
onAddTaskLabels: addTaskLabelsAsync, onAddTaskLabels: addTaskLabelsAsync,
} }
export default connect< export default connect<
ConnectedStateProps, ConnectedStateProps,
ConnectedDispatchProps, ConnectedDispatchProps,

View File

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

View File

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

View File

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

View File

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