Commit 044c7f83 authored by jerasmus's avatar jerasmus Committed by Thong Kuah

Add frontend integration for cluster environments

Added frontend integration for cluster environments
parent 6feb0312
...@@ -39,6 +39,7 @@ export default class Clusters { ...@@ -39,6 +39,7 @@ export default class Clusters {
updateKnativePath, updateKnativePath,
installPrometheusPath, installPrometheusPath,
managePrometheusPath, managePrometheusPath,
clusterEnvironmentsPath,
hasRbac, hasRbac,
clusterType, clusterType,
clusterStatus, clusterStatus,
...@@ -79,6 +80,7 @@ export default class Clusters { ...@@ -79,6 +80,7 @@ export default class Clusters {
installJupyterEndpoint: installJupyterPath, installJupyterEndpoint: installJupyterPath,
installKnativeEndpoint: installKnativePath, installKnativeEndpoint: installKnativePath,
updateKnativeEndpoint: updateKnativePath, updateKnativeEndpoint: updateKnativePath,
clusterEnvironmentsEndpoint: clusterEnvironmentsPath,
}); });
this.installApplication = this.installApplication.bind(this); this.installApplication = this.installApplication.bind(this);
...@@ -109,6 +111,10 @@ export default class Clusters { ...@@ -109,6 +111,10 @@ export default class Clusters {
this.initApplications(clusterType); this.initApplications(clusterType);
this.initEnvironments(); this.initEnvironments();
if (clusterEnvironmentsPath) {
this.fetchEnvironments();
}
this.updateContainer(null, this.store.state.status, this.store.state.statusReason); this.updateContainer(null, this.store.state.status, this.store.state.statusReason);
this.addListeners(); this.addListeners();
...@@ -162,6 +168,7 @@ export default class Clusters { ...@@ -162,6 +168,7 @@ export default class Clusters {
render(createElement) { render(createElement) {
return createElement(Environments, { return createElement(Environments, {
props: { props: {
isFetching: this.state.fetchingEnvironments,
environments: this.state.environments, environments: this.state.environments,
environmentsHelpPath: this.state.environmentsHelpPath, environmentsHelpPath: this.state.environmentsHelpPath,
clustersHelpPath: this.state.clustersHelpPath, clustersHelpPath: this.state.clustersHelpPath,
...@@ -172,6 +179,18 @@ export default class Clusters { ...@@ -172,6 +179,18 @@ export default class Clusters {
}); });
} }
fetchEnvironments() {
this.store.toggleFetchEnvironments(true);
this.service
.fetchClusterEnvironments()
.then(data => {
this.store.toggleFetchEnvironments(false);
this.store.updateEnvironments(data.data);
})
.catch(() => Clusters.handleError());
}
static initDismissableCallout() { static initDismissableCallout() {
const callout = document.querySelector('.js-cluster-security-warning'); const callout = document.querySelector('.js-cluster-security-warning');
PersistentUserCallout.factory(callout); PersistentUserCallout.factory(callout);
......
...@@ -33,6 +33,10 @@ export default class ClusterService { ...@@ -33,6 +33,10 @@ export default class ClusterService {
return axios.delete(this.appInstallEndpointMap[appId], params); return axios.delete(this.appInstallEndpointMap[appId], params);
} }
fetchClusterEnvironments() {
return axios.get(this.options.clusterEnvironmentsEndpoint);
}
static updateCluster(endpoint, data) { static updateCluster(endpoint, data) {
return axios.put(endpoint, data); return axios.put(endpoint, data);
} }
......
...@@ -84,6 +84,7 @@ export default class ClusterStore { ...@@ -84,6 +84,7 @@ export default class ClusterStore {
}, },
}, },
environments: [], environments: [],
fetchingEnvironments: false,
}; };
} }
...@@ -206,6 +207,10 @@ export default class ClusterStore { ...@@ -206,6 +207,10 @@ export default class ClusterStore {
}); });
} }
toggleFetchEnvironments(isFetching) {
this.state.fetchingEnvironments = isFetching;
}
updateEnvironments(environments = []) { updateEnvironments(environments = []) {
this.state.environments = environments.map(environment => ({ this.state.environments = environments.map(environment => ({
name: environment.name, name: environment.name,
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
install_jupyter_path: clusterable.install_applications_cluster_path(@cluster, :jupyter), install_jupyter_path: clusterable.install_applications_cluster_path(@cluster, :jupyter),
install_knative_path: clusterable.install_applications_cluster_path(@cluster, :knative), install_knative_path: clusterable.install_applications_cluster_path(@cluster, :knative),
update_knative_path: clusterable.update_applications_cluster_path(@cluster, :knative), update_knative_path: clusterable.update_applications_cluster_path(@cluster, :knative),
cluster_environments_path: clusterable.environments_cluster_path(@cluster),
toggle_status: @cluster.enabled? ? 'true': 'false', toggle_status: @cluster.enabled? ? 'true': 'false',
has_rbac: has_rbac_enabled?(@cluster) ? 'true': 'false', has_rbac: has_rbac_enabled?(@cluster) ? 'true': 'false',
cluster_type: @cluster.cluster_type, cluster_type: @cluster.cluster_type,
......
<script> <script>
import { GlTable, GlLink, GlEmptyState } from '@gitlab/ui'; import { GlTable, GlLink, GlEmptyState, GlLoadingIcon } from '@gitlab/ui';
import { __, sprintf } from '~/locale'; import { __, sprintf } from '~/locale';
import Icon from '~/vue_shared/components/icon.vue'; import Icon from '~/vue_shared/components/icon.vue';
import TimeAgo from '~/vue_shared/components/time_ago_tooltip.vue'; import TimeAgo from '~/vue_shared/components/time_ago_tooltip.vue';
...@@ -11,9 +11,14 @@ export default { ...@@ -11,9 +11,14 @@ export default {
GlLink, GlLink,
Icon, Icon,
TimeAgo, TimeAgo,
GlLoadingIcon,
deploymentInstance: () => import('ee_component/vue_shared/components/deployment_instance.vue'), deploymentInstance: () => import('ee_component/vue_shared/components/deployment_instance.vue'),
}, },
props: { props: {
isFetching: {
type: Boolean,
required: true,
},
environments: { environments: {
type: Array, type: Array,
required: true, required: true,
...@@ -33,7 +38,7 @@ export default { ...@@ -33,7 +38,7 @@ export default {
}, },
computed: { computed: {
isEmpty() { isEmpty() {
return this.environments.length === 0; return !this.isFetching && this.environments.length === 0;
}, },
tableEmptyStateText() { tableEmptyStateText() {
const text = __( const text = __(
...@@ -57,7 +62,9 @@ export default { ...@@ -57,7 +62,9 @@ export default {
let podsInUse = 0; let podsInUse = 0;
this.environments.forEach(environment => { this.environments.forEach(environment => {
if (this.hasInstances(environment.rolloutStatus)) {
podsInUse += environment.rolloutStatus.instances.length; podsInUse += environment.rolloutStatus.instances.length;
}
}); });
return podsInUse; return podsInUse;
...@@ -76,6 +83,9 @@ export default { ...@@ -76,6 +83,9 @@ export default {
}, },
]; ];
}, },
methods: {
hasInstances: rolloutStatus => rolloutStatus.instances && rolloutStatus.instances.length,
},
}; };
</script> </script>
...@@ -90,7 +100,12 @@ export default { ...@@ -90,7 +100,12 @@ export default {
<div slot="description" v-html="tableEmptyStateText"></div> <div slot="description" v-html="tableEmptyStateText"></div>
</gl-empty-state> </gl-empty-state>
<gl-table v-else :fields="$options.fields" :items="environments" head-variant="white"> <gl-table
v-if="!isFetching && !isEmpty"
:fields="$options.fields"
:items="environments"
head-variant="white"
>
<!-- column: Project --> <!-- column: Project -->
<template slot="project" slot-scope="data"> <template slot="project" slot-scope="data">
<a :href="`/${data.value.path_with_namespace}`">{{ data.value.name }}</a> <a :href="`/${data.value.path_with_namespace}`">{{ data.value.name }}</a>
...@@ -112,7 +127,7 @@ export default { ...@@ -112,7 +127,7 @@ export default {
</template> </template>
<template slot="rolloutStatus" slot-scope="row"> <template slot="rolloutStatus" slot-scope="row">
<div v-if="row.item.rolloutStatus.instances.length" class="d-flex flex-wrap flex-row"> <div v-if="hasInstances(row.item.rolloutStatus)" class="d-flex flex-wrap flex-row">
<template v-for="(instance, i) in row.item.rolloutStatus.instances"> <template v-for="(instance, i) in row.item.rolloutStatus.instances">
<deployment-instance <deployment-instance
:key="i" :key="i"
...@@ -141,5 +156,7 @@ export default { ...@@ -141,5 +156,7 @@ export default {
<time-ago :time="data.value" /> <time-ago :time="data.value" />
</template> </template>
</gl-table> </gl-table>
<gl-loading-icon v-if="isFetching" :size="2" class="mt-3" />
</div> </div>
</template> </template>
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
- is_group_type = @cluster.cluster_type.in? 'group_type' - is_group_type = @cluster.cluster_type.in? 'group_type'
- is_creating = @cluster.status_name.in? %i/scheduled creating/ - is_creating = @cluster.status_name.in? %i/scheduled creating/
- if is_group_type && !is_creating && Feature.enabled?(:view_group_cluster_deployments) - if is_group_type && !is_creating
.js-toggle-container .js-toggle-container
%ul.nav-links.mobile-separator.nav.nav-tabs{ role: 'tablist' } %ul.nav-links.mobile-separator.nav.nav-tabs{ role: 'tablist' }
%li.nav-item{ role: 'presentation' } %li.nav-item{ role: 'presentation' }
......
...@@ -17,6 +17,7 @@ describe('Environments', () => { ...@@ -17,6 +17,7 @@ describe('Environments', () => {
environmentsHelpPath: 'path/to/environments', environmentsHelpPath: 'path/to/environments',
clustersHelpPath: 'path/to/clusters', clustersHelpPath: 'path/to/clusters',
deployBoardsHelpPath: 'path/to/clusters', deployBoardsHelpPath: 'path/to/clusters',
isFetching: false,
}; };
wrapper = mount(Component, { wrapper = mount(Component, {
......
...@@ -152,6 +152,7 @@ describe('Clusters Store', () => { ...@@ -152,6 +152,7 @@ describe('Clusters Store', () => {
}, },
}, },
environments: [], environments: [],
fetchingEnvironments: false,
}); });
}); });
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment