From 70b7287c9e8ba7f0f1c3b0430c29bfcff2e5c6a9 Mon Sep 17 00:00:00 2001 From: Bucky Schwarz Date: Mon, 24 Aug 2020 11:04:54 -0700 Subject: [PATCH] chore(community-templates): remove github file restriction --- ...ate.test.ts => communityTemplates.test.ts} | 12 ---- ui/src/templates/actions/creators.ts | 13 +++- .../CommunityTemplateImportOverlay.tsx | 64 +++++++------------ .../containers/CommunityTemplatesIndex.tsx | 20 ++++-- ui/src/templates/reducers/index.test.ts | 2 + ui/src/templates/reducers/index.ts | 19 ++++-- ui/src/templates/utils/index.test.ts | 43 +++++++++++++ ui/src/templates/utils/index.ts | 8 +++ ui/src/types/templates.ts | 1 + 9 files changed, 114 insertions(+), 68 deletions(-) rename ui/cypress/e2e/{communityTemplate.test.ts => communityTemplates.test.ts} (94%) diff --git a/ui/cypress/e2e/communityTemplate.test.ts b/ui/cypress/e2e/communityTemplates.test.ts similarity index 94% rename from ui/cypress/e2e/communityTemplate.test.ts rename to ui/cypress/e2e/communityTemplates.test.ts index 1851090819..0befeda2d6 100644 --- a/ui/cypress/e2e/communityTemplate.test.ts +++ b/ui/cypress/e2e/communityTemplates.test.ts @@ -32,19 +32,7 @@ describe('Community Templates', () => { cy.getByTestID('lookup-template-button').click() cy.getByTestID('notification-error').should('be.visible') - //lookup template errors on bad url - cy.getByTestID('lookup-template-input').type('www.badURL.com') - cy.getByTestID('lookup-template-button').click() - cy.getByTestID('notification-error').should('be.visible') - - //lookup template errors on bad file type - cy.getByTestID('lookup-template-input').clear() - cy.getByTestID('lookup-template-input').type('variables.html') - cy.getByTestID('lookup-template-button').click() - cy.getByTestID('notification-error').should('be.visible') - //lookup template errors on github folder - cy.getByTestID('lookup-template-input').clear() cy.getByTestID('lookup-template-input').type( 'https://github.com/influxdata/community-templates/tree/master/kafka' ) diff --git a/ui/src/templates/actions/creators.ts b/ui/src/templates/actions/creators.ts index 187ff0bc6c..691d868dca 100644 --- a/ui/src/templates/actions/creators.ts +++ b/ui/src/templates/actions/creators.ts @@ -13,8 +13,8 @@ export const ADD_TEMPLATE_SUMMARY = 'ADD_TEMPLATE_SUMMARY' export const GET_TEMPLATE_SUMMARIES_FOR_ORG = 'GET_TEMPLATE_SUMMARIES_FOR_ORG' export const POPULATE_TEMPLATE_SUMMARIES = 'POPULATE_TEMPLATE_SUMMARIES' export const REMOVE_TEMPLATE_SUMMARY = 'REMOVE_TEMPLATE_SUMMARY' -export const SET_COMMUNITY_TEMPLATE_TO_INSTALL = - 'SET_COMMUNITY_TEMPLATE_TO_INSTALL' +export const SET_STAGED_TEMPLATE = 'SET_STAGED_TEMPLATE' +export const SET_STAGED_TEMPLATE_URL = 'SET_STAGED_TEMPLATE_URL' export const SET_EXPORT_TEMPLATE = 'SET_EXPORT_TEMPLATE' export const SET_TEMPLATE_SUMMARY = 'SET_TEMPLATE_SUMMARY' export const SET_TEMPLATES_STATUS = 'SET_TEMPLATES_STATUS' @@ -32,6 +32,7 @@ export type Action = | ReturnType | ReturnType | ReturnType + | ReturnType | ReturnType | ReturnType | ReturnType @@ -93,10 +94,16 @@ export const setTemplateSummary = ( export const setStagedCommunityTemplate = (template: CommunityTemplate) => ({ - type: SET_COMMUNITY_TEMPLATE_TO_INSTALL, + type: SET_STAGED_TEMPLATE, template, } as const) +export const setStagedTemplateUrl = (templateUrl: string) => + ({ + type: SET_STAGED_TEMPLATE_URL, + templateUrl, + } as const) + export const toggleTemplateResourceInstall = ( resourceType: string, templateMetaName: string, diff --git a/ui/src/templates/components/CommunityTemplateImportOverlay.tsx b/ui/src/templates/components/CommunityTemplateImportOverlay.tsx index dc2384072a..06ef9f64a8 100644 --- a/ui/src/templates/components/CommunityTemplateImportOverlay.tsx +++ b/ui/src/templates/components/CommunityTemplateImportOverlay.tsx @@ -18,7 +18,7 @@ import {ComponentStatus} from '@influxdata/clockface' // Utils import {getByID} from 'src/resources/selectors' -import {getGithubUrlFromTemplateDetails} from 'src/templates/utils' +import {getTemplateNameFromUrl} from 'src/templates/utils' import {reportError} from 'src/shared/utils/errors' import { @@ -41,11 +41,9 @@ interface State { type ReduxProps = ConnectedProps type RouterProps = RouteComponentProps<{ - directory: string orgID: string - templateName: string - templateExtension: string }> + type Props = ReduxProps & RouterProps class UnconnectedTemplateImportOverlay extends PureComponent { @@ -54,12 +52,13 @@ class UnconnectedTemplateImportOverlay extends PureComponent { } public componentDidMount() { - const {directory, org, templateExtension, templateName} = this.props + if (!this.props.stagedTemplateUrl) { + this.onDismiss() + return + } this.reviewTemplateResources( - org.id, - directory, - templateName, - templateExtension + this.props.org.id, + this.props.stagedTemplateUrl ) } @@ -70,26 +69,18 @@ class UnconnectedTemplateImportOverlay extends PureComponent { onInstall={this.handleInstallTemplate} resourceCount={this.props.resourceCount} status={this.state.status} - templateName={this.props.templateName} + templateName={getTemplateNameFromUrl(this.props.stagedTemplateUrl).name} updateStatus={this.updateOverlayStatus} /> ) } private reviewTemplateResources = async ( - orgID, - directory, - templateName, - templateExtension + orgID: string, + templateUrl: string ) => { - const yamlLocation = getGithubUrlFromTemplateDetails( - directory, - templateName, - templateExtension - ) - try { - const summary = await reviewTemplate(orgID, yamlLocation) + const summary = await reviewTemplate(orgID, templateUrl) this.props.setStagedCommunityTemplate(summary) return summary @@ -102,28 +93,18 @@ class UnconnectedTemplateImportOverlay extends PureComponent { } private onDismiss = () => { - const {history} = this.props - - history.goBack() + this.props.history.push(`/orgs/${this.props.org.id}/settings/templates`) } private updateOverlayStatus = (status: ComponentStatus) => this.setState(() => ({status})) private handleInstallTemplate = async () => { - const {directory, org, templateExtension, templateName} = this.props - - const yamlLocation = getGithubUrlFromTemplateDetails( - directory, - templateName, - templateExtension - ) - let summary try { summary = await installTemplate( - org.id, - yamlLocation, + this.props.org.id, + this.props.stagedTemplateUrl, this.props.resourcesToSkip ) } catch (err) { @@ -132,16 +113,19 @@ class UnconnectedTemplateImportOverlay extends PureComponent { } try { - await updateStackName(summary.stackID, templateName) + const templateDetails = getTemplateNameFromUrl( + this.props.stagedTemplateUrl + ) + await updateStackName(summary.stackID, templateDetails.name) - event('template_install', {templateName: templateName}) + event('template_install', {templateName: templateDetails.name}) - this.props.notify(communityTemplateInstallSucceeded(templateName)) + this.props.notify(communityTemplateInstallSucceeded(templateDetails.name)) } catch (err) { this.props.notify(communityTemplateRenameFailed()) reportError(err, {name: 'The community template rename failed'}) } finally { - this.props.fetchAndSetStacks(org.id) + this.props.fetchAndSetStacks(this.props.org.id) this.onDismiss() } } @@ -156,15 +140,13 @@ const mstp = (state: AppState, props: RouterProps) => { return { org, - directory: props.match.params.directory, - templateName: props.match.params.templateName, - templateExtension: props.match.params.templateExtension, flags: state.flags.original, resourceCount: getTotalResourceCount( state.resources.templates.stagedCommunityTemplate.summary ), resourcesToSkip: state.resources.templates.stagedCommunityTemplate.resourcesToSkip, + stagedTemplateUrl: state.resources.templates.stagedTemplateUrl, } } diff --git a/ui/src/templates/containers/CommunityTemplatesIndex.tsx b/ui/src/templates/containers/CommunityTemplatesIndex.tsx index 8210f20e7c..b07b9466f3 100644 --- a/ui/src/templates/containers/CommunityTemplatesIndex.tsx +++ b/ui/src/templates/containers/CommunityTemplatesIndex.tsx @@ -35,15 +35,18 @@ import {communityTemplatesImportPath} from 'src/templates/containers/TemplatesIn import GetResources from 'src/resources/components/GetResources' import {getOrg} from 'src/organizations/selectors' +import {setStagedTemplateUrl} from 'src/templates/actions/creators' + // Utils import {pageTitleSuffixer} from 'src/shared/utils/pageTitles' import { getGithubUrlFromTemplateDetails, - getTemplateDetails, + getTemplateNameFromUrl, } from 'src/templates/utils' import {reportError} from 'src/shared/utils/errors' import {communityTemplateUnsupportedFormatError} from 'src/shared/copy/notifications' + // Types import {AppState, ResourceType} from 'src/types' @@ -168,7 +171,7 @@ class UnconnectedTemplatesIndex extends Component { @@ -183,12 +186,14 @@ class UnconnectedTemplatesIndex extends Component { } try { - const {directory, templateExtension, templateName} = getTemplateDetails( - this.state.templateUrl - ) - event('template_click_lookup', {templateName: templateName}) + this.props.setStagedTemplateUrl(this.state.templateUrl) + + event('template_click_lookup', { + templateName: getTemplateNameFromUrl(this.state.templateUrl).name, + }) + this.props.history.push( - `/orgs/${this.props.org.id}/settings/templates/import/${directory}/${templateName}/${templateExtension}` + `/orgs/${this.props.org.id}/settings/templates/import` ) } catch (err) { this.props.notify(communityTemplateUnsupportedFormatError()) @@ -217,6 +222,7 @@ const mstp = (state: AppState) => { const mdtp = { notify, + setStagedTemplateUrl, } const connector = connect(mstp, mdtp) diff --git a/ui/src/templates/reducers/index.test.ts b/ui/src/templates/reducers/index.test.ts index 43186cdd6f..f9aa2a7369 100644 --- a/ui/src/templates/reducers/index.test.ts +++ b/ui/src/templates/reducers/index.test.ts @@ -46,6 +46,7 @@ const stagedCommunityTemplate: CommunityTemplate = {} const initialState = () => ({ stagedCommunityTemplate, + stagedTemplateUrl: '', status, byID: { ['1']: templateSummary, @@ -99,6 +100,7 @@ describe('templates reducer', () => { allIDs, exportTemplate, stagedCommunityTemplate, + stagedTemplateUrl: '', stacks: [], } const actual = reducer(state, removeTemplateSummary(state.allIDs[1])) diff --git a/ui/src/templates/reducers/index.ts b/ui/src/templates/reducers/index.ts index c66b3c9328..5ba2092f21 100644 --- a/ui/src/templates/reducers/index.ts +++ b/ui/src/templates/reducers/index.ts @@ -4,12 +4,13 @@ import { ADD_TEMPLATE_SUMMARY, POPULATE_TEMPLATE_SUMMARIES, REMOVE_TEMPLATE_SUMMARY, - SET_COMMUNITY_TEMPLATE_TO_INSTALL, SET_EXPORT_TEMPLATE, - SET_TEMPLATE_SUMMARY, - SET_TEMPLATES_STATUS, - TOGGLE_TEMPLATE_RESOURCE_INSTALL, SET_STACKS, + SET_STAGED_TEMPLATE, + SET_STAGED_TEMPLATE_URL, + SET_TEMPLATES_STATUS, + SET_TEMPLATE_SUMMARY, + TOGGLE_TEMPLATE_RESOURCE_INSTALL, } from 'src/templates/actions/creators' import { CommunityTemplate, @@ -37,6 +38,7 @@ const defaultCommunityTemplate = (): CommunityTemplate => { export const defaultState = (): TemplatesState => ({ stagedCommunityTemplate: defaultCommunityTemplate(), + stagedTemplateUrl: '', status: RemoteDataState.NotStarted, byID: {}, allIDs: [], @@ -75,7 +77,14 @@ export const templatesReducer = ( return } - case SET_COMMUNITY_TEMPLATE_TO_INSTALL: { + case SET_STAGED_TEMPLATE_URL: { + const {templateUrl} = action + + draftState.stagedTemplateUrl = templateUrl + return + } + + case SET_STAGED_TEMPLATE: { const {template} = action const stagedCommunityTemplate = { diff --git a/ui/src/templates/utils/index.test.ts b/ui/src/templates/utils/index.test.ts index 224422be91..0b78db9772 100644 --- a/ui/src/templates/utils/index.test.ts +++ b/ui/src/templates/utils/index.test.ts @@ -1,4 +1,5 @@ import { + getTemplateNameFromUrl, findIncludedsFromRelationships, findIncludedFromRelationship, findIncludedVariables, @@ -46,3 +47,45 @@ describe('Templates utils', () => { }) }) }) + +describe('the Community Template url utilities', () => { + it('returns the template name and extension from an arbitrary url', () => { + const {name, extension} = getTemplateNameFromUrl( + 'https://github.com/influxdata/influxdb/blob/master/pkger/testdata/dashboard_params.yml' + ) + expect(name).toBe('dashboard_params') + expect(extension).toBe('yml') + }) + + it('returns the template name and extension from the official community templates github repo', () => { + const {name, extension} = getTemplateNameFromUrl( + 'https://github.com/influxdata/community-templates/blob/master/csgo/csgo.yml' + ) + expect(name).toBe('csgo') + expect(extension).toBe('yml') + }) + + it('returns the template name and extension from the official community templates github repo when the extension is not yml', () => { + const {name, extension} = getTemplateNameFromUrl( + 'https://github.com/influxdata/community-templates/blob/master/csgo/csgo.json' + ) + expect(name).toBe('csgo') + expect(extension).toBe('json') + }) + + it('returns the template name and extension from arbitrary urls', () => { + const {name, extension} = getTemplateNameFromUrl( + 'https://www.example.com/csgo/csgo.json' + ) + expect(name).toBe('csgo') + expect(extension).toBe('json') + }) + + it('handles non secure arbitrary urls', () => { + const {name, extension} = getTemplateNameFromUrl( + 'http://www.example.com/blog/cats/catstuff/memes/csgo/downsampling.yml' + ) + expect(name).toBe('downsampling') + expect(extension).toBe('yml') + }) +}) diff --git a/ui/src/templates/utils/index.ts b/ui/src/templates/utils/index.ts index 8cea2e56e4..2b47c7bfd2 100644 --- a/ui/src/templates/utils/index.ts +++ b/ui/src/templates/utils/index.ts @@ -101,6 +101,14 @@ const getTemplateDetailsFromFileSource = (_source: string): TemplateDetails => { } } +export const getTemplateNameFromUrl = ( + url: string +): {name: string; extension: string} => { + const fullName = url.split('/').pop() + const [name, extension] = fullName.split('.') + return {name, extension} +} + export const getTemplateDetails = (source: string): TemplateDetails => { if (source.includes('https')) { return getTemplateDetailsFromGithubSource(source) diff --git a/ui/src/types/templates.ts b/ui/src/types/templates.ts index 7d666fdd49..64d4df2874 100644 --- a/ui/src/types/templates.ts +++ b/ui/src/types/templates.ts @@ -36,6 +36,7 @@ export type CommunityTemplate = any export interface TemplatesState extends NormalizedState { exportTemplate: {status: RemoteDataState; item: DocumentCreate} stagedCommunityTemplate: CommunityTemplate + stagedTemplateUrl: string stacks: InstalledStack[] }