diff --git a/src/app/applications/components/application-creation-wizard/application-creation-wizard.tsx b/src/app/applications/components/application-creation-wizard/application-creation-wizard.tsx index a139933..87ffee2 100644 --- a/src/app/applications/components/application-creation-wizard/application-creation-wizard.tsx +++ b/src/app/applications/components/application-creation-wizard/application-creation-wizard.tsx @@ -1,10 +1,13 @@ -import { MockupList } from 'argo-ui'; +import { MockupList, NotificationType } from 'argo-ui'; import * as path from 'path'; +import * as PropTypes from 'prop-types'; import * as React from 'react'; import { BehaviorSubject } from 'rxjs'; +import { ErrorNotification } from '../../../shared/components'; +import { AppContext } from '../../../shared/context'; import * as models from '../../../shared/models'; -import { ArgoApp, services } from '../../../shared/services'; +import { services } from '../../../shared/services'; import { AppParams, AppsList, EnvironmentsList, NewAppParams, RepositoryList } from './steps'; @@ -16,10 +19,11 @@ interface StepInfo { title: string | React.ReactNode; canNext(): boolean; next() interface State { repos: models.Repository[]; clusters: models.Cluster[]; - apps: ArgoApp[]; + apps: models.AppInfo[]; envs: { [key: string]: models.KsonnetEnvironment; }; selectedRepo: string; - selectedApp: ArgoApp; + selectedApp: models.AppInfo; + selectedAppDetails: models.AppDetails; selectedEnv: string; appParams: NewAppParams; appParamsValid: boolean; @@ -33,6 +37,9 @@ export interface WizardProps { onStateChanged: (state: WizardStepState) => any; export interface WizardStepState { nextTitle: string; next?: () => any; prev?: () => any; } export class ApplicationCreationWizardContainer extends React.Component { + public static contextTypes = { + apis: PropTypes.object, + }; private submitAppParamsForm = new BehaviorSubject(null); @@ -43,9 +50,10 @@ export class ApplicationCreationWizardContainer extends React.Componentspecify drop-in YAML directory ), canNext: () => !!this.state.selectedApp, - next: () => { - if (this.state.selectedApp.ksonnet) { - this.updateState({ envs: this.state.selectedApp.ksonnet.environments, step: Step.SelectEnvironments}); - } else { - this.updateState({ appParams: { - applicationName: this.state.selectedApp.helm.name, - repoURL: this.state.selectedRepo, - environment: '', - clusterURL: '', - namespace: '', - path: path.dirname(this.state.selectedApp.helm.path), - project: this.state.projects[0], - }, step: Step.SetParams }); + next: async () => { + try { + this.updateState({ loading: true }); + const selectedAppDetails = await services.reposService.appDetails(this.state.selectedRepo, this.state.selectedApp.path); + + if (selectedAppDetails.ksonnet) { + this.updateState({ selectedAppDetails, envs: selectedAppDetails.ksonnet.environments || {}, step: Step.SelectEnvironments}); + } else { + this.updateState({ selectedAppDetails, appParams: { + applicationName: selectedAppDetails.helm.name, + repoURL: this.state.selectedRepo, + environment: '', + clusterURL: '', + namespace: '', + path: path.dirname(selectedAppDetails.helm.path), + project: this.state.projects[0], + }, step: Step.SetParams }); + } + } catch (e) { + this.appContext.apis.notifications.show({type: NotificationType.Error, content: }); + } finally { + this.updateState({ loading: false }); } }, canPrev: () => true, prev: () => this.updateState({ step: Step.SelectRepo }), render: () => this.state.apps ? ( - this.updateState({ selectedApp: app })}/> + this.updateState({ selectedApp })}/> ) : ( ), @@ -130,12 +147,12 @@ export class ApplicationCreationWizardContainer extends React.Component this.submitAppParamsForm.next({}), canPrev: () => true, prev: async () => { - if (this.state.selectedApp && this.state.selectedApp.ksonnet) { + if (this.state.selectedAppDetails && this.state.selectedAppDetails.ksonnet) { this.updateState({ step: Step.SelectEnvironments }); } else { this.updateState({ step: Step.SelectApp }); @@ -161,7 +178,7 @@ export class ApplicationCreationWizardContainer extends React.Component ( any, + apps: models.AppInfo[], + selectedApp: models.AppInfo, + onAppSelected: (app: models.AppInfo) => any, }) => ( props.apps.length === 0 ? (
@@ -23,18 +22,14 @@ export const AppsList = (props: {
TYPE
-
APPLICATION NAME
-
PATH
-
ENVIRONMENTS COUNT
+
PATH
{props.apps.map((item, i) => (
props.onAppSelected(item)}>
-
{item.ksonnet && 'Ksonnet' || 'Helm'}
-
{(item.ksonnet || item.helm).name}
-
{(item.ksonnet || item.helm).path}
-
{item.ksonnet ? Object.keys(item.ksonnet.environments).length : 0}
+
{item.type}
+
{item.path}
))} @@ -84,6 +79,9 @@ export const EnvironmentsList = (props: { onEnvsSelectionChanged: (env: string) => any; }) => { const environments = Object.keys(props.envs).map((name) => Object.assign(props.envs[name], {name})); + if (environments.length === 0) { + return

Application has no environments

; + } return (
diff --git a/src/app/shared/models.ts b/src/app/shared/models.ts index de84f27..034cf0b 100644 --- a/src/app/shared/models.ts +++ b/src/app/shared/models.ts @@ -279,6 +279,13 @@ export interface KsonnetAppSpec { environments: { [key: string]: KsonnetEnvironment; }; } +export interface AppDetails { type: string; path: string; ksonnet?: KsonnetAppSpec; helm?: HelmAppSpec; } + +export interface AppInfo { + type: string; + path: string; +} + export interface HelmAppSpec { name: string; path: string; diff --git a/src/app/shared/services/index.ts b/src/app/shared/services/index.ts index 75c61ef..2d2b453 100644 --- a/src/app/shared/services/index.ts +++ b/src/app/shared/services/index.ts @@ -25,5 +25,3 @@ export const services: Services = { projects: new ProjectsService(), viewPreferences: new ViewPreferencesService(), }; - -export { ArgoApp } from './repo-service'; diff --git a/src/app/shared/services/repo-service.ts b/src/app/shared/services/repo-service.ts index b94a1ee..cb516e8 100644 --- a/src/app/shared/services/repo-service.ts +++ b/src/app/shared/services/repo-service.ts @@ -1,8 +1,6 @@ import * as models from '../models'; import requests from './requests'; -export interface ArgoApp { ksonnet?: models.KsonnetAppSpec; helm?: models.HelmAppSpec; } - export class RepositoriesService { public list(): Promise { return requests.get('/repositories').then((res) => res.body as models.RepositoryList).then((list) => list.items || []); @@ -16,13 +14,13 @@ export class RepositoriesService { return requests.delete(`/repositories/${encodeURIComponent(url)}`).send().then((res) => res.body as models.Repository); } - public apps(repo: string): Promise { + public apps(repo: string): Promise { return requests.get(`/repositories/${encodeURIComponent(repo)}/apps`) - .then((res) => { - const body = res.body as { ksonnetApps: models.KsonnetAppSpec[], helmApps: models.HelmAppSpec[] }; - const ksonnet = (body.ksonnetApps || []).map((item) => ({ ksonnet: item, helm: null })); - const helm = (body.helmApps || []).map((item) => ({ ksonnet: null, helm: item })); - return ksonnet.concat(helm); - }); + .then((res) => res.body.items as models.AppInfo[]); + } + + public appDetails(repo: string, path: string): Promise { + return requests.get(`/repositories/${encodeURIComponent(repo)}/apps/${encodeURIComponent(path)}`) + .then((res) => res.body as models.AppDetails); } }