Skip to content

Commit e227192

Browse files
authored
Merge pull request #12910 from influxdata/feat/templates-clone
Add the ability to clone a template
2 parents c65af3c + aa79a26 commit e227192

File tree

7 files changed

+115
-26
lines changed

7 files changed

+115
-26
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
1. [12821](https://github.com/influxdata/influxdb/pull/12821): Allow variables to be re-ordered within control bar on a dashboard.
1515
1. [12888](https://github.com/influxdata/influxdb/pull/12888): Add the ability to delete a template
1616
1. [12901](https://github.com/influxdata/influxdb/pull/12901): Save user preference for variable control bar visibility and default to visible
17+
1. [12910](https://github.com/influxdata/influxdb/pull/12910): Add the ability to clone a template
1718

1819
### Bug Fixes
1920

ui/package-lock.json

+33-14
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

ui/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@
137137
},
138138
"dependencies": {
139139
"@influxdata/clockface": "0.0.5",
140-
"@influxdata/influx": "0.2.50",
140+
"@influxdata/influx": "0.2.52",
141141
"@influxdata/react-custom-scrollbars": "4.3.8",
142142
"axios": "^0.18.0",
143143
"babel-polyfill": "^6.26.0",

ui/src/shared/copy/notifications.ts

+10
Original file line numberDiff line numberDiff line change
@@ -855,6 +855,16 @@ export const deleteTemplateSuccess = (): Notification => ({
855855
message: 'Template was deleted successfully',
856856
})
857857

858+
export const cloneTemplateFailed = (error: string): Notification => ({
859+
...defaultErrorNotification,
860+
message: `Failed to clone template: ${error}`,
861+
})
862+
863+
export const cloneTemplateSuccess = (): Notification => ({
864+
...defaultSuccessNotification,
865+
message: 'Template cloned successfully',
866+
})
867+
858868
export const resourceSavedAsTemplate = (
859869
resourceName: string
860870
): Notification => ({

ui/src/templates/actions/index.ts

+43-10
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,27 @@ export enum ActionTypes {
2222
SetTemplatesStatus = 'SET_TEMPLATES_STATUS',
2323
SetExportTemplate = 'SET_EXPORT_TEMPLATE',
2424
RemoveTemplateSummary = 'REMOVE_TEMPLATE_SUMMARY',
25+
AddTemplateSummary = 'ADD_TEMPLATE_SUMMARY',
2526
}
2627

2728
export type Actions =
2829
| PopulateTemplateSummaries
2930
| SetTemplatesStatus
3031
| SetExportTemplate
3132
| RemoveTemplateSummary
33+
| AddTemplateSummary
34+
35+
export interface AddTemplateSummary {
36+
type: ActionTypes.AddTemplateSummary
37+
payload: {item: TemplateSummary}
38+
}
39+
40+
export const addTemplateSummary = (
41+
item: TemplateSummary
42+
): AddTemplateSummary => ({
43+
type: ActionTypes.AddTemplateSummary,
44+
payload: {item},
45+
})
3246

3347
export interface PopulateTemplateSummaries {
3448
type: ActionTypes.PopulateTemplateSummaries
@@ -68,6 +82,16 @@ export const setExportTemplate = (
6882
payload: {status, item, orgID},
6983
})
7084

85+
interface RemoveTemplateSummary {
86+
type: ActionTypes.RemoveTemplateSummary
87+
payload: {templateID: string}
88+
}
89+
90+
const removeTemplateSummary = (templateID: string): RemoveTemplateSummary => ({
91+
type: ActionTypes.RemoveTemplateSummary,
92+
payload: {templateID},
93+
})
94+
7195
export const getTemplatesForOrg = (orgName: string) => async dispatch => {
7296
dispatch(setTemplatesStatus(RemoteDataState.Loading))
7397
const items = await client.templates.getAll(orgName)
@@ -104,16 +128,6 @@ export const clearExportTemplate = () => async dispatch => {
104128
dispatch(setExportTemplate(RemoteDataState.NotStarted, null))
105129
}
106130

107-
interface RemoveTemplateSummary {
108-
type: ActionTypes.RemoveTemplateSummary
109-
payload: {templateID: string}
110-
}
111-
112-
const removeTemplateSummary = (templateID: string): RemoveTemplateSummary => ({
113-
type: ActionTypes.RemoveTemplateSummary,
114-
payload: {templateID},
115-
})
116-
117131
export const deleteTemplate = (templateID: string) => async (
118132
dispatch
119133
): Promise<void> => {
@@ -126,3 +140,22 @@ export const deleteTemplate = (templateID: string) => async (
126140
dispatch(notify(copy.deleteTemplateFailed(e)))
127141
}
128142
}
143+
144+
export const cloneTemplate = (templateID: string, orgID: string) => async (
145+
dispatch
146+
): Promise<void> => {
147+
try {
148+
const createdTemplate = await client.templates.clone(templateID, orgID)
149+
150+
dispatch(
151+
addTemplateSummary({
152+
...createdTemplate,
153+
labels: createdTemplate.labels || [],
154+
})
155+
)
156+
dispatch(notify(copy.cloneTemplateSuccess()))
157+
} catch (e) {
158+
console.error(e)
159+
dispatch(notify(copy.cloneTemplateFailed(e)))
160+
}
161+
}

ui/src/templates/components/TemplateCard.tsx

+18-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import {withRouter, WithRouterProps} from 'react-router'
77
import {ResourceList, Context, IconFont} from 'src/clockface'
88

99
// Actions
10-
import {deleteTemplate} from 'src/templates/actions'
10+
import {deleteTemplate, cloneTemplate} from 'src/templates/actions'
1111

1212
// Types
1313
import {TemplateSummary} from '@influxdata/influx'
@@ -23,6 +23,7 @@ interface OwnProps {
2323

2424
interface DispatchProps {
2525
onDelete: typeof deleteTemplate
26+
onClone: typeof cloneTemplate
2627
}
2728

2829
type Props = DispatchProps & OwnProps
@@ -60,6 +61,12 @@ export class TemplateCard extends PureComponent<Props & WithRouterProps> {
6061
} = this.props
6162
return (
6263
<Context>
64+
<Context.Menu
65+
icon={IconFont.Duplicate}
66+
color={ComponentColor.Secondary}
67+
>
68+
<Context.Item label="Clone" action={this.handleClone} value={id} />
69+
</Context.Menu>
6370
<Context.Menu
6471
icon={IconFont.Trash}
6572
color={ComponentColor.Danger}
@@ -76,6 +83,15 @@ export class TemplateCard extends PureComponent<Props & WithRouterProps> {
7683
)
7784
}
7885

86+
private handleClone = () => {
87+
const {
88+
template: {id},
89+
params: {orgID},
90+
onClone,
91+
} = this.props
92+
onClone(id, orgID)
93+
}
94+
7995
private handleNameClick = (e: MouseEvent<HTMLAnchorElement>) => {
8096
e.preventDefault()
8197
this.handleExport()
@@ -93,6 +109,7 @@ export class TemplateCard extends PureComponent<Props & WithRouterProps> {
93109

94110
const mdtp: DispatchProps = {
95111
onDelete: deleteTemplate,
112+
onClone: cloneTemplate,
96113
}
97114

98115
export default connect<{}, DispatchProps, OwnProps>(

ui/src/templates/reducers/index.ts

+9
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,15 @@ const templatesReducer = (
6969

7070
return
7171
}
72+
73+
case ActionTypes.AddTemplateSummary: {
74+
const {item} = action.payload
75+
const {items} = draftState
76+
77+
draftState.items = [...items, item]
78+
79+
return
80+
}
7281
}
7382
})
7483

0 commit comments

Comments
 (0)