diff --git a/CHANGELOG.md b/CHANGELOG.md index cc819699e0d..6d94ad02bc3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ 1. [12826](https://github.com/influxdata/influxdb/pull/12826): Enable copying error messages to the clipboard from dashboard cells 1. [12876](https://github.com/influxdata/influxdb/pull/12876): Add the ability to update token's status in Token list 1. [12821](https://github.com/influxdata/influxdb/pull/12821): Allow variables to be re-ordered within control bar on a dashboard. +1. [12888](https://github.com/influxdata/influxdb/pull/12888): Add the ability to delete a template ### Bug Fixes diff --git a/ui/package-lock.json b/ui/package-lock.json index d65da8c8b8f..c300a349f44 100644 --- a/ui/package-lock.json +++ b/ui/package-lock.json @@ -985,9 +985,9 @@ } }, "@influxdata/influx": { - "version": "0.2.48", - "resolved": "https://registry.npmjs.org/@influxdata/influx/-/influx-0.2.48.tgz", - "integrity": "sha512-CIqUd3hdKa6qQrsqQR3x2+r4r0guETnfTrMWXZ6EDOU5rWwyc2kdrgCJGRviy3RCvtV7+wtrQ1FYd8KSHUR82w==", + "version": "0.2.49", + "resolved": "https://registry.npmjs.org/@influxdata/influx/-/influx-0.2.49.tgz", + "integrity": "sha512-Gt5mEyokQ/WxrYK1EhmuYSIWvCnG+X83RblmPFaGKZyhoeBk8G1F8lNoH0bWZzVMnMt9RcnvJmWcDq2L2iGpJw==", "requires": { "axios": "^0.18.0" } diff --git a/ui/package.json b/ui/package.json index 9731d12ac11..c3bf73b323a 100644 --- a/ui/package.json +++ b/ui/package.json @@ -137,7 +137,7 @@ }, "dependencies": { "@influxdata/clockface": "0.0.5", - "@influxdata/influx": "0.2.48", + "@influxdata/influx": "0.2.49", "@influxdata/react-custom-scrollbars": "4.3.8", "axios": "^0.18.0", "babel-polyfill": "^6.26.0", diff --git a/ui/src/shared/copy/notifications.ts b/ui/src/shared/copy/notifications.ts index bf7b9849905..16c3c24db16 100644 --- a/ui/src/shared/copy/notifications.ts +++ b/ui/src/shared/copy/notifications.ts @@ -845,6 +845,16 @@ export const createTemplateFailed = (error: string): Notification => ({ message: `Failed to export resource as template: ${error}`, }) +export const deleteTemplateFailed = (error: string): Notification => ({ + ...defaultErrorNotification, + message: `Failed to delete template: ${error}`, +}) + +export const deleteTemplateSuccess = (): Notification => ({ + ...defaultSuccessNotification, + message: 'Template was deleted successfully', +}) + export const resourceSavedAsTemplate = ( resourceName: string ): Notification => ({ diff --git a/ui/src/templates/actions/index.ts b/ui/src/templates/actions/index.ts index d8e8ecdb1ac..443cd8734d2 100644 --- a/ui/src/templates/actions/index.ts +++ b/ui/src/templates/actions/index.ts @@ -21,12 +21,14 @@ export enum ActionTypes { PopulateTemplateSummaries = 'POPULATE_TEMPLATE_SUMMARIES', SetTemplatesStatus = 'SET_TEMPLATES_STATUS', SetExportTemplate = 'SET_EXPORT_TEMPLATE', + RemoveTemplateSummary = 'REMOVE_TEMPLATE_SUMMARY', } export type Actions = | PopulateTemplateSummaries | SetTemplatesStatus | SetExportTemplate + | RemoveTemplateSummary export interface PopulateTemplateSummaries { type: ActionTypes.PopulateTemplateSummaries @@ -72,8 +74,14 @@ export const getTemplatesForOrg = (orgName: string) => async dispatch => { dispatch(populateTemplateSummaries(items)) } -export const createTemplate = async (template: DocumentCreate) => { - await client.templates.create(template) +export const createTemplate = (template: DocumentCreate) => async dispatch => { + try { + await client.templates.create(template) + dispatch(notify(copy.importTemplateSucceeded())) + } catch (e) { + console.error(e) + dispatch(notify(copy.importTemplateFailed(e))) + } } export const convertToTemplate = (id: string) => async ( @@ -95,3 +103,26 @@ export const convertToTemplate = (id: string) => async ( export const clearExportTemplate = () => async dispatch => { dispatch(setExportTemplate(RemoteDataState.NotStarted, null)) } + +interface RemoveTemplateSummary { + type: ActionTypes.RemoveTemplateSummary + payload: {templateID: string} +} + +const removeTemplateSummary = (templateID: string): RemoveTemplateSummary => ({ + type: ActionTypes.RemoveTemplateSummary, + payload: {templateID}, +}) + +export const deleteTemplate = (templateID: string) => async ( + dispatch +): Promise => { + try { + await client.templates.delete(templateID) + dispatch(removeTemplateSummary(templateID)) + dispatch(notify(copy.deleteTemplateSuccess())) + } catch (e) { + console.error(e) + dispatch(notify(copy.deleteTemplateFailed(e))) + } +} diff --git a/ui/src/templates/components/TemplateCard.tsx b/ui/src/templates/components/TemplateCard.tsx index 9b8170c94e8..a30dd41580b 100644 --- a/ui/src/templates/components/TemplateCard.tsx +++ b/ui/src/templates/components/TemplateCard.tsx @@ -1,23 +1,32 @@ // Libraries import React, {PureComponent, MouseEvent} from 'react' +import {connect} from 'react-redux' import {withRouter, WithRouterProps} from 'react-router' // Components -import {ResourceList} from 'src/clockface' +import {ResourceList, Context, IconFont} from 'src/clockface' // Actions +import {deleteTemplate} from 'src/templates/actions' // Types import {TemplateSummary} from '@influxdata/influx' +import {ComponentColor} from '@influxdata/clockface' // Constants import {DEFAULT_TEMPLATE_NAME} from 'src/templates/constants' -interface Props { +interface OwnProps { template: TemplateSummary onFilterChange: (searchTerm: string) => void } +interface DispatchProps { + onDelete: typeof deleteTemplate +} + +type Props = DispatchProps & OwnProps + export class TemplateCard extends PureComponent { public render() { const {template} = this.props @@ -45,7 +54,26 @@ export class TemplateCard extends PureComponent { private doNothing = () => {} private get contextMenu(): JSX.Element { - return null + const { + template: {id}, + onDelete, + } = this.props + return ( + + + + + + ) } private handleNameClick = (e: MouseEvent) => { @@ -63,4 +91,11 @@ export class TemplateCard extends PureComponent { } } -export default withRouter(TemplateCard) +const mdtp: DispatchProps = { + onDelete: deleteTemplate, +} + +export default connect<{}, DispatchProps, OwnProps>( + null, + mdtp +)(withRouter(TemplateCard)) diff --git a/ui/src/templates/components/TemplateImportOverlay.tsx b/ui/src/templates/components/TemplateImportOverlay.tsx index c5640b931d7..f90ffed283d 100644 --- a/ui/src/templates/components/TemplateImportOverlay.tsx +++ b/ui/src/templates/components/TemplateImportOverlay.tsx @@ -12,12 +12,6 @@ import { } from 'src/templates/actions' import {notify as notifyAction} from 'src/shared/actions/notifications' -//Constants -import { - importTemplateSucceeded, - importTemplateFailed, -} from 'src/shared/copy/notifications' - // Types import {AppState, Organization} from 'src/types/v2' import {RemoteDataState} from 'src/types' @@ -58,16 +52,12 @@ class TemplateImportOverlay extends PureComponent { private handleImportTemplate = () => async ( importString: string ): Promise => { - const {createTemplate, notify} = this.props + const {createTemplate} = this.props const {setTemplatesStatus} = this.props - try { - const template = JSON.parse(importString) - await createTemplate(template) - notify(importTemplateSucceeded()) - setTemplatesStatus(RemoteDataState.NotStarted) - } catch (error) { - notify(importTemplateFailed(error)) - } + + const template = JSON.parse(importString) + await createTemplate(template) + setTemplatesStatus(RemoteDataState.NotStarted) this.onDismiss() } diff --git a/ui/src/templates/reducers/index.ts b/ui/src/templates/reducers/index.ts index 23220a83fd5..31bf5c05510 100644 --- a/ui/src/templates/reducers/index.ts +++ b/ui/src/templates/reducers/index.ts @@ -59,6 +59,16 @@ const templatesReducer = ( } return } + + case ActionTypes.RemoveTemplateSummary: { + const {templateID} = action.payload + const {items} = draftState + draftState.items = items.filter(l => { + return l.id !== templateID + }) + + return + } } })