diff --git a/CHANGELOG.md b/CHANGELOG.md
index 6f57dba1c3d..cec72e55a0d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -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
diff --git a/ui/src/index.tsx b/ui/src/index.tsx
index 4b74caa2c6a..f5e9d220ff7 100644
--- a/ui/src/index.tsx
+++ b/ui/src/index.tsx
@@ -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 {
-
+
+
+
+
+
diff --git a/ui/src/organizations/components/OrgTaskEditPage.tsx b/ui/src/organizations/components/OrgTaskEditPage.tsx
new file mode 100644
index 00000000000..484842b2db4
--- /dev/null
+++ b/ui/src/organizations/components/OrgTaskEditPage.tsx
@@ -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 (
+
+
+
+
+
+
+ )
+ }
+
+ 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) => {
+ 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(
+ mstp,
+ mdtp
+)(OrgTaskEditPage)
diff --git a/ui/src/organizations/components/OrgTaskPage.tsx b/ui/src/organizations/components/OrgTaskPage.tsx
new file mode 100644
index 00000000000..40d589b1312
--- /dev/null
+++ b/ui/src/organizations/components/OrgTaskPage.tsx
@@ -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 (
+
+
+
+
+
+
+ )
+ }
+
+ 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) => {
+ 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(
+ mstp,
+ mdtp
+)(OrgTaskPage)
diff --git a/ui/src/organizations/components/OrgTasksPage.tsx b/ui/src/organizations/components/OrgTasksPage.tsx
index 66c95274de6..04009447520 100644
--- a/ui/src/organizations/components/OrgTasksPage.tsx
+++ b/ui/src/organizations/components/OrgTasksPage.tsx
@@ -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 {
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 {
)
}
+ 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 {
}
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 {
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,
diff --git a/ui/src/organizations/containers/OrganizationView.tsx b/ui/src/organizations/containers/OrganizationView.tsx
index e8792ed3ae6..db1f322d199 100644
--- a/ui/src/organizations/containers/OrganizationView.tsx
+++ b/ui/src/organizations/containers/OrganizationView.tsx
@@ -181,6 +181,7 @@ class OrganizationView extends PureComponent {
diff --git a/ui/src/tasks/actions/v2/index.ts b/ui/src/tasks/actions/v2/index.ts
index 8a33d907f34..889c3855fdc 100644
--- a/ui/src/tasks/actions/v2/index.ts
+++ b/ui/src/tasks/actions/v2/index.ts
@@ -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 => {
@@ -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 => {
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)
diff --git a/ui/src/tasks/containers/TaskEditPage.tsx b/ui/src/tasks/containers/TaskEditPage.tsx
index bbe9080ca2f..1850863b1ea 100644
--- a/ui/src/tasks/containers/TaskEditPage.tsx
+++ b/ui/src/tasks/containers/TaskEditPage.tsx
@@ -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) => {
@@ -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(
mstp,
mdtp
-)(TaskPage)
+)(TaskEditPage)
diff --git a/ui/src/tasks/containers/TaskPage.tsx b/ui/src/tasks/containers/TaskPage.tsx
index 74d2e08bec6..a0ccae902b7 100644
--- a/ui/src/tasks/containers/TaskPage.tsx
+++ b/ui/src/tasks/containers/TaskPage.tsx
@@ -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) => {
@@ -165,9 +165,9 @@ const mstp = ({
const mdtp: ConnectDispatchProps = {
setNewScript,
saveNewScript,
- goToTasks,
setTaskOption,
clearTask,
+ cancel,
}
export default connect(