summaryrefslogtreecommitdiff
path: root/app/assets/javascripts/clusters/agents/components
diff options
context:
space:
mode:
Diffstat (limited to 'app/assets/javascripts/clusters/agents/components')
-rw-r--r--app/assets/javascripts/clusters/agents/components/agent_integration_status_row.vue66
-rw-r--r--app/assets/javascripts/clusters/agents/components/integration_status.vue98
-rw-r--r--app/assets/javascripts/clusters/agents/components/show.vue19
-rw-r--r--app/assets/javascripts/clusters/agents/components/token_table.vue7
4 files changed, 186 insertions, 4 deletions
diff --git a/app/assets/javascripts/clusters/agents/components/agent_integration_status_row.vue b/app/assets/javascripts/clusters/agents/components/agent_integration_status_row.vue
new file mode 100644
index 00000000000..59de6df1e49
--- /dev/null
+++ b/app/assets/javascripts/clusters/agents/components/agent_integration_status_row.vue
@@ -0,0 +1,66 @@
+<script>
+import { GlLink, GlIcon, GlBadge } from '@gitlab/ui';
+import { s__ } from '~/locale';
+import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
+
+export default {
+ components: {
+ GlLink,
+ GlIcon,
+ GlBadge,
+ },
+ mixins: [glFeatureFlagMixin()],
+ i18n: {
+ premiumTitle: s__('ClusterAgents|Premium'),
+ },
+ props: {
+ text: {
+ required: true,
+ type: String,
+ },
+ icon: {
+ required: false,
+ type: String,
+ default: 'information',
+ },
+ iconClass: {
+ required: false,
+ type: String,
+ default: 'text-info',
+ },
+ helpUrl: {
+ required: false,
+ type: String,
+ default: null,
+ },
+ featureName: {
+ required: false,
+ type: String,
+ default: null,
+ },
+ },
+ computed: {
+ showPremiumBadge() {
+ return this.featureName && !this.glFeatures[this.featureName];
+ },
+ },
+};
+</script>
+
+<template>
+ <li class="gl-mb-3">
+ <gl-icon :name="icon" :size="16" :class="iconClass" class="gl-mr-2" />
+
+ <gl-link v-if="helpUrl" :href="helpUrl">{{ text }}</gl-link>
+ <span v-else>{{ text }}</span>
+
+ <gl-badge
+ v-if="showPremiumBadge"
+ size="md"
+ class="gl-ml-2 gl-vertical-align-middle"
+ icon="license"
+ variant="tier"
+ >{{ $options.i18n.premiumTitle }}</gl-badge
+ >
+ </li>
+</template>
diff --git a/app/assets/javascripts/clusters/agents/components/integration_status.vue b/app/assets/javascripts/clusters/agents/components/integration_status.vue
new file mode 100644
index 00000000000..68a77dfbc8e
--- /dev/null
+++ b/app/assets/javascripts/clusters/agents/components/integration_status.vue
@@ -0,0 +1,98 @@
+<script>
+import { GlCollapse, GlButton, GlIcon } from '@gitlab/ui';
+import { s__ } from '~/locale';
+import { AGENT_STATUSES } from '~/clusters_list/constants';
+import { getAgentLastContact, getAgentStatus } from '~/clusters_list/clusters_util';
+import {
+ INTEGRATION_STATUS_VALID_TOKEN,
+ INTEGRATION_STATUS_NO_TOKEN,
+ INTEGRATION_STATUS_RESTRICTED_CI_CD,
+} from '../constants';
+import AgentIntegrationStatusRow from './agent_integration_status_row.vue';
+
+export default {
+ components: {
+ GlCollapse,
+ GlButton,
+ GlIcon,
+ AgentIntegrationStatusRow,
+ },
+ i18n: {
+ title: s__('ClusterAgents|Integration Status'),
+ },
+ AGENT_STATUSES,
+ props: {
+ tokens: {
+ required: true,
+ type: Array,
+ },
+ },
+ data() {
+ return {
+ isVisible: false,
+ };
+ },
+ computed: {
+ chevronIcon() {
+ return this.isVisible ? 'chevron-down' : 'chevron-right';
+ },
+ agentStatus() {
+ const lastContact = getAgentLastContact(this.tokens);
+ return getAgentStatus(lastContact);
+ },
+ integrationStatuses() {
+ const statuses = [];
+
+ if (this.agentStatus === 'active') {
+ statuses.push(INTEGRATION_STATUS_VALID_TOKEN);
+ }
+
+ if (!this.tokens.length) {
+ statuses.push(INTEGRATION_STATUS_NO_TOKEN);
+ }
+
+ statuses.push(INTEGRATION_STATUS_RESTRICTED_CI_CD);
+
+ return statuses;
+ },
+ },
+ methods: {
+ toggleCollapse() {
+ this.isVisible = !this.isVisible;
+ },
+ },
+};
+</script>
+
+<template>
+ <div>
+ <gl-button
+ :icon="chevronIcon"
+ variant="link"
+ size="small"
+ class="gl-mr-3"
+ @click="toggleCollapse"
+ >
+ {{ $options.i18n.title }} </gl-button
+ ><span data-testid="agent-status">
+ <gl-icon
+ :name="$options.AGENT_STATUSES[agentStatus].icon"
+ :class="$options.AGENT_STATUSES[agentStatus].class"
+ class="gl-mr-2"
+ />{{ $options.AGENT_STATUSES[agentStatus].name }}
+ </span>
+ <gl-collapse v-model="isVisible" class="gl-ml-5 gl-mt-5">
+ <ul class="gl-list-style-none gl-pl-2 gl-mb-0">
+ <agent-integration-status-row
+ v-for="(status, index) in integrationStatuses"
+ :key="index"
+ :icon="status.icon"
+ :icon-class="status.iconClass"
+ :text="status.text"
+ :help-url="status.helpUrl"
+ :feature-name="status.featureName"
+ />
+ </ul>
+ </gl-collapse>
+ </div>
+</template>
diff --git a/app/assets/javascripts/clusters/agents/components/show.vue b/app/assets/javascripts/clusters/agents/components/show.vue
index e3de8339325..f1bd36b4a63 100644
--- a/app/assets/javascripts/clusters/agents/components/show.vue
+++ b/app/assets/javascripts/clusters/agents/components/show.vue
@@ -14,6 +14,7 @@ import { MAX_LIST_COUNT, TOKEN_STATUS_ACTIVE } from '../constants';
import getClusterAgentQuery from '../graphql/queries/get_cluster_agent.query.graphql';
import TokenTable from './token_table.vue';
import ActivityEvents from './activity_events_list.vue';
+import IntegrationStatus from './integration_status.vue';
export default {
i18n: {
@@ -51,6 +52,7 @@ export default {
TimeAgoTooltip,
TokenTable,
ActivityEvents,
+ IntegrationStatus,
},
inject: ['agentName', 'projectPath'],
data() {
@@ -105,11 +107,11 @@ export default {
<template>
<section>
- <h2>{{ agentName }}</h2>
+ <h1>{{ agentName }}</h1>
<gl-loading-icon v-if="isLoading && clusterAgent == null" size="lg" class="gl-m-3" />
- <div v-else-if="clusterAgent">
+ <template v-else-if="clusterAgent">
<p data-testid="cluster-agent-create-info">
<gl-sprintf :message="$options.i18n.installedInfo">
<template #name>
@@ -122,7 +124,16 @@ export default {
</gl-sprintf>
</p>
- <gl-tabs sync-active-tab-with-query-params lazy>
+ <integration-status
+ :tokens="tokens"
+ class="gl-py-5 gl-border-t-1 gl-border-t-solid gl-border-t-gray-100"
+ />
+
+ <gl-tabs
+ sync-active-tab-with-query-params
+ lazy
+ class="gl-border-t-1 gl-border-t-solid gl-border-t-gray-100"
+ >
<gl-tab :title="$options.i18n.activity" query-param-value="activity">
<activity-events :agent-name="agentName" :project-path="projectPath" />
</gl-tab>
@@ -151,7 +162,7 @@ export default {
</div>
</gl-tab>
</gl-tabs>
- </div>
+ </template>
<gl-alert v-else variant="danger" :dismissible="false">
{{ $options.i18n.loadingError }}
diff --git a/app/assets/javascripts/clusters/agents/components/token_table.vue b/app/assets/javascripts/clusters/agents/components/token_table.vue
index f74d66f6b8f..667d10e1753 100644
--- a/app/assets/javascripts/clusters/agents/components/token_table.vue
+++ b/app/assets/javascripts/clusters/agents/components/token_table.vue
@@ -44,36 +44,43 @@ export default {
},
computed: {
fields() {
+ const tdClass = 'gl-vertical-align-middle!';
return [
{
key: 'name',
label: this.$options.i18n.name,
tdAttr: { 'data-testid': 'agent-token-name' },
+ tdClass,
},
{
key: 'lastUsed',
label: this.$options.i18n.lastUsed,
tdAttr: { 'data-testid': 'agent-token-used' },
+ tdClass,
},
{
key: 'createdAt',
label: this.$options.i18n.dateCreated,
tdAttr: { 'data-testid': 'agent-token-created-time' },
+ tdClass,
},
{
key: 'createdBy',
label: this.$options.i18n.createdBy,
tdAttr: { 'data-testid': 'agent-token-created-user' },
+ tdClass,
},
{
key: 'description',
label: this.$options.i18n.description,
tdAttr: { 'data-testid': 'agent-token-description' },
+ tdClass,
},
{
key: 'actions',
label: '',
tdAttr: { 'data-testid': 'agent-token-revoke' },
+ tdClass,
},
];
},