Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore(ui): refactored dashboards client API to oats generated types and API #16438

Merged
merged 2 commits into from
Jan 13, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions ui/cypress/e2e/explorer.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -456,11 +456,11 @@ describe('DataExplorer', () => {
.click()
.focused()
.type(
`from(bucket: "defbuck")
`from(bucket: "defbuck")
|> range(start: -10s)
|> filter(fn: (r) => r._measurement == "no exist")`,
{force: true, delay: TYPE_DELAY}
)
{force: true, delay: TYPE_DELAY}
)
cy.getByTestID('time-machine-submit-button').click()
})

Expand All @@ -475,11 +475,11 @@ describe('DataExplorer', () => {
.click()
.focused()
.type(
`from(bucket: "defbuck")
`from(bucket: "defbuck")
|> range(start: -15m, stop: now())
|> filter(fn: (r) => r._measurement == `,
{force: true, delay: TYPE_DELAY}
)
{force: true, delay: TYPE_DELAY}
)
})

cy.getByTestID('toolbar-tab').click()
Expand Down
6 changes: 3 additions & 3 deletions ui/cypress/e2e/tasks.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -319,9 +319,9 @@ http.post(
cy.get<Bucket>('@bucket').then(bucket => {
cy.getByTestID('flux-editor').within(() => {
cy.get('.react-monaco-editor-container')
.click()
.focused()
.type(flux(bucket), {force: true, delay: 2})
.click()
.focused()
.type(flux(bucket), {force: true, delay: 2})
})
})
cy.getByTestID('task-save-btn').click()
Expand Down
202 changes: 165 additions & 37 deletions ui/src/dashboards/actions/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,16 @@ import {
getView as getViewAJAX,
updateView as updateViewAJAX,
} from 'src/dashboards/apis'
import {getVariables as apiGetVariables} from 'src/client'
import {
getVariables as apiGetVariables,
getDashboard as apiGetDashboard,
postDashboard as apiPostDashboard,
postDashboardsCell as apiPostDashboardsCell,
postDashboardsLabel as apiPostDashboardsLabel,
deleteDashboardsLabel as apiDeleteDashboardsLabel,
patchDashboardsCellsView as apiPatchDashboardsCellsView,
getDashboardsCellsView as apiGetDashboardsCellsView,
} from 'src/client'
import {createDashboardFromTemplate as createDashboardFromTemplateAJAX} from 'src/templates/api'

// Actions
Expand Down Expand Up @@ -50,20 +59,18 @@ import {
getClonedDashboardCell,
} from 'src/dashboards/utils/cellGetters'
import {dashboardToTemplate} from 'src/shared/utils/resourceToTemplate'
import {client} from 'src/utils/api'
import {exportVariables} from 'src/variables/utils/exportVariables'
import {getSaveableView} from 'src/timeMachine/selectors'
import {incrementCloneName} from 'src/utils/naming'
import {isLimitError} from 'src/cloud/utils/limits'
import {getOrg} from 'src/organizations/selectors'
import {addLabelDefaults} from 'src/labels/utils'

// Constants
import * as copy from 'src/shared/copy/notifications'
import {DEFAULT_DASHBOARD_NAME} from 'src/dashboards/constants/index'

// Types
import {RemoteDataState} from 'src/types'
import {CreateCell} from '@influxdata/influx'
import {
Dashboard,
NewView,
Expand All @@ -72,7 +79,36 @@ import {
View,
DashboardTemplate,
Label,
RemoteDataState,
NewCell,
} from 'src/types'
import {
Dashboard as IDashboard,
Cell as ICell,
DashboardWithViewProperties,
} from 'src/client'

export const addDashboardIDToCells = (
cells: ICell[],
dashboardID: string
): Cell[] => {
return cells.map(c => {
return {...c, dashboardID}
})
}

export const addDashboardDefaults = (
dashboard: IDashboard | DashboardWithViewProperties
): Dashboard => {
return {
...dashboard,
cells: addDashboardIDToCells(dashboard.cells, dashboard.id) || [],
id: dashboard.id || '',
labels: (dashboard.labels || []).map(addLabelDefaults),
name: dashboard.name || '',
orgID: dashboard.orgID || '',
}
}

export enum ActionTypes {
SetDashboards = 'SET_DASHBOARDS',
Expand All @@ -81,8 +117,8 @@ export enum ActionTypes {
DeleteDashboardFailed = 'DELETE_DASHBOARD_FAILED',
EditDashboard = 'EDIT_DASHBOARD',
RemoveCell = 'REMOVE_CELL',
AddDashboardLabels = 'ADD_DASHBOARD_LABELS',
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

unpluralized these to accurately reflect their functionality

RemoveDashboardLabels = 'REMOVE_DASHBOARD_LABELS',
AddDashboardLabel = 'ADD_DASHBOARD_LABEL',
RemoveDashboardLabel = 'REMOVE_DASHBOARD_LABEL',
}

export type Action =
Expand All @@ -94,8 +130,8 @@ export type Action =
| SetViewAction
| DeleteTimeRangeAction
| DeleteDashboardFailedAction
| AddDashboardLabelsAction
| RemoveDashboardLabelsAction
| AddDashboardLabelAction
| RemoveDashboardLabelAction

interface RemoveCellAction {
type: ActionTypes.RemoveCell
Expand Down Expand Up @@ -141,19 +177,19 @@ interface SetDashboardAction {
}
}

interface AddDashboardLabelsAction {
type: ActionTypes.AddDashboardLabels
interface AddDashboardLabelAction {
type: ActionTypes.AddDashboardLabel
payload: {
dashboardID: string
labels: Label[]
label: Label
}
}

interface RemoveDashboardLabelsAction {
type: ActionTypes.RemoveDashboardLabels
interface RemoveDashboardLabelAction {
type: ActionTypes.RemoveDashboardLabel
payload: {
dashboardID: string
labels: Label[]
label: Label
}
}

Expand Down Expand Up @@ -217,20 +253,20 @@ export const removeCell = (
payload: {dashboard, cell},
})

export const addDashboardLabels = (
export const addDashboardLabel = (
dashboardID: string,
labels: Label[]
): AddDashboardLabelsAction => ({
type: ActionTypes.AddDashboardLabels,
payload: {dashboardID, labels},
label: Label
): AddDashboardLabelAction => ({
type: ActionTypes.AddDashboardLabel,
payload: {dashboardID, label},
})

export const removeDashboardLabels = (
export const removeDashboardLabel = (
dashboardID: string,
labels: Label[]
): RemoveDashboardLabelsAction => ({
type: ActionTypes.RemoveDashboardLabels,
payload: {dashboardID, labels},
label: Label
): RemoveDashboardLabelAction => ({
type: ActionTypes.RemoveDashboardLabel,
payload: {dashboardID, label},
})

// Thunks
Expand Down Expand Up @@ -262,6 +298,46 @@ export const createDashboard = () => async (
}
}

export const cloneUtilFunc = async (dash: Dashboard, id: string) => {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this utility function is based on the client-api:

https://github.com/influxdata/influxdb-client-js/blob/master/src/wrappers/dashboards.ts#L247-L248

My first attempt at this refactor tried to flatten these into a synchronous progression, but the functionality was buggy.

const cells = dash.cells
const pendingViews = cells.map(cell =>
apiGetDashboardsCellsView({
dashboardID: dash.id,
cellID: cell.id,
}).then(res => {
return {
...res,
cellID: cell.id,
}
})
)
const views = await Promise.all(pendingViews)

if (views.length > 0 && views.some(v => v.status !== 200)) {
throw new Error('An error occurred cloning the dashboard')
}

return views.map(async v => {
const view = v.data as View
const cell = cells.find(c => c.id === view.id)

if (cell && id) {
const newCell = await apiPostDashboardsCell({
dashboardID: id,
data: cell,
})
if (newCell.status !== 201) {
throw new Error('An error occurred cloning the dashboard')
}
return apiPatchDashboardsCellsView({
dashboardID: id,
cellID: newCell.data.id,
data: view,
})
}
})
}

export const cloneDashboard = (dashboard: Dashboard) => async (
dispatch,
getState: GetState
Expand All @@ -274,10 +350,49 @@ export const cloneDashboard = (dashboard: Dashboard) => async (

const clonedName = incrementCloneName(allDashboardNames, dashboard.name)

const data = await client.dashboards.clone(dashboard.id, clonedName, org.id)
const getResp = await apiGetDashboard({dashboardID: dashboard.id})

if (getResp.status !== 200) {
throw new Error(getResp.data.message)
}

const dash = addDashboardDefaults(getResp.data)

const postResp = await apiPostDashboard({
data: {
orgID: org.id,
name: clonedName,
description: dash.description || '',
},
})

if (postResp.status !== 201) {
throw new Error(postResp.data.message)
}

const pendingLabels = dash.labels.map(l =>
apiPostDashboardsLabel({
dashboardID: postResp.data.id,
data: {labelID: l.id},
})
)

const mappedLabels = await Promise.all(pendingLabels)

if (mappedLabels.length > 0 && mappedLabels.some(l => l.status !== 201)) {
throw new Error('An error occurred cloning the labels for this dashboard')
}

const clonedViews = await cloneUtilFunc(dash, postResp.data.id)

const newViews = await Promise.all(clonedViews)

if (newViews.length > 0 && newViews.some(v => v.status !== 200)) {
throw new Error('An error occurred cloning the dashboard')
}

dispatch(checkDashboardLimits())
dispatch(push(`/orgs/${org.id}/dashboards/${data.id}`))
dispatch(push(`/orgs/${org.id}/dashboards/${postResp.data.id}`))
} catch (error) {
console.error(error)
if (isLimitError(error)) {
Expand Down Expand Up @@ -414,7 +529,7 @@ export const createCellWithView = (
dashboard = await getDashboardAJAX(dashboardID)
}

const cell: CreateCell = getNewDashboardCell(dashboard, clonedCell)
const cell: NewCell = getNewDashboardCell(dashboard, clonedCell)

// Create the cell
const createdCell = await addCellAJAX(dashboardID, cell)
Expand Down Expand Up @@ -519,31 +634,44 @@ export const copyDashboardCellAsync = (dashboard: Dashboard, cell: Cell) => (
}
}

export const addDashboardLabelsAsync = (
export const addDashboardLabelAsync = (
dashboardID: string,
labels: Label[]
label: Label
) => async (dispatch: Dispatch<Action | PublishNotificationAction>) => {
try {
const newLabels = await client.dashboards.addLabels(
const resp = await apiPostDashboardsLabel({
dashboardID,
labels.map(l => l.id)
)
data: {labelID: label.id},
})

if (resp.status !== 201) {
throw new Error(resp.data.message)
}

const lab = addLabelDefaults(resp.data.label)

dispatch(addDashboardLabels(dashboardID, newLabels))
dispatch(addDashboardLabel(dashboardID, lab))
} catch (error) {
console.error(error)
dispatch(notify(copy.addDashboardLabelFailed()))
}
}

export const removeDashboardLabelsAsync = (
export const removeDashboardLabelAsync = (
dashboardID: string,
labels: Label[]
label: Label
) => async (dispatch: Dispatch<Action | PublishNotificationAction>) => {
try {
await client.dashboards.removeLabels(dashboardID, labels.map(l => l.id))
const resp = await apiDeleteDashboardsLabel({
dashboardID,
labelID: label.id,
})

if (resp.status !== 204) {
throw new Error(resp.data.message)
}

dispatch(removeDashboardLabels(dashboardID, labels))
dispatch(removeDashboardLabel(dashboardID, label))
} catch (error) {
console.error(error)
dispatch(notify(copy.removedDashboardLabelFailed()))
Expand Down
Loading