diff options
Diffstat (limited to 'app/assets/javascripts/clusters_list/components/install_agent_modal.vue')
-rw-r--r-- | app/assets/javascripts/clusters_list/components/install_agent_modal.vue | 325 |
1 files changed, 231 insertions, 94 deletions
diff --git a/app/assets/javascripts/clusters_list/components/install_agent_modal.vue b/app/assets/javascripts/clusters_list/components/install_agent_modal.vue index 6eb2e85ecea..5eef76252bd 100644 --- a/app/assets/javascripts/clusters_list/components/install_agent_modal.vue +++ b/app/assets/javascripts/clusters_list/components/install_agent_modal.vue @@ -9,22 +9,48 @@ import { GlSprintf, } from '@gitlab/ui'; import { helpPagePath } from '~/helpers/help_page_helper'; -import ClipboardButton from '~/vue_shared/components/clipboard_button.vue'; +import ModalCopyButton from '~/vue_shared/components/modal_copy_button.vue'; import CodeBlock from '~/vue_shared/components/code_block.vue'; +import Tracking from '~/tracking'; import { generateAgentRegistrationCommand } from '../clusters_util'; -import { INSTALL_AGENT_MODAL_ID, I18N_INSTALL_AGENT_MODAL } from '../constants'; -import { addAgentToStore } from '../graphql/cache_update'; +import { + INSTALL_AGENT_MODAL_ID, + I18N_AGENT_MODAL, + KAS_DISABLED_ERROR, + EVENT_LABEL_MODAL, + EVENT_ACTIONS_OPEN, + EVENT_ACTIONS_SELECT, + EVENT_ACTIONS_CLICK, + MODAL_TYPE_EMPTY, + MODAL_TYPE_REGISTER, +} from '../constants'; +import { addAgentToStore, addAgentConfigToStore } from '../graphql/cache_update'; import createAgent from '../graphql/mutations/create_agent.mutation.graphql'; import createAgentToken from '../graphql/mutations/create_agent_token.mutation.graphql'; import getAgentsQuery from '../graphql/queries/get_agents.query.graphql'; +import agentConfigurations from '../graphql/queries/agent_configurations.query.graphql'; import AvailableAgentsDropdown from './available_agents_dropdown.vue'; +const trackingMixin = Tracking.mixin({ label: EVENT_LABEL_MODAL }); + export default { modalId: INSTALL_AGENT_MODAL_ID, - i18n: I18N_INSTALL_AGENT_MODAL, + EVENT_ACTIONS_OPEN, + EVENT_ACTIONS_CLICK, + EVENT_LABEL_MODAL, + basicInstallPath: helpPagePath('user/clusters/agent/install/index', { + anchor: 'install-the-agent-into-the-cluster', + }), + advancedInstallPath: helpPagePath('user/clusters/agent/install/index', { + anchor: 'advanced-installation', + }), + enableKasPath: helpPagePath('administration/clusters/kas'), + installAgentPath: helpPagePath('user/clusters/agent/install/index'), + registerAgentPath: helpPagePath('user/clusters/agent/install/index', { + anchor: 'register-an-agent-with-gitlab', + }), components: { AvailableAgentsDropdown, - ClipboardButton, CodeBlock, GlAlert, GlButton, @@ -33,8 +59,10 @@ export default { GlLink, GlModal, GlSprintf, + ModalCopyButton, }, - inject: ['projectPath', 'kasAddress'], + mixins: [trackingMixin], + inject: ['projectPath', 'kasAddress', 'emptyStateImage'], props: { defaultBranchName: { default: '.noBranch', @@ -46,6 +74,22 @@ export default { type: Number, }, }, + apollo: { + agents: { + query: agentConfigurations, + variables() { + return { + projectPath: this.projectPath, + }; + }, + update(data) { + this.populateAvailableAgents(data); + }, + error(error) { + this.kasDisabled = error?.message?.indexOf(KAS_DISABLED_ERROR) >= 0; + }, + }, + }, data() { return { registering: false, @@ -53,6 +97,8 @@ export default { agentToken: null, error: null, clusterAgent: null, + availableAgents: [], + kasDisabled: false, }; }, computed: { @@ -63,19 +109,11 @@ export default { return !this.registering && this.agentName !== null; }, canCancel() { - return !this.registered && !this.registering; + return !this.registered && !this.registering && this.isAgentRegistrationModal; }, agentRegistrationCommand() { return generateAgentRegistrationCommand(this.agentToken, this.kasAddress); }, - basicInstallPath() { - return helpPagePath('user/clusters/agent/install/index', { - anchor: 'install-the-agent-into-the-cluster', - }); - }, - advancedInstallPath() { - return helpPagePath('user/clusters/agent/install/index', { anchor: 'advanced-installation' }); - }, getAgentsQueryVariables() { return { defaultBranchName: this.defaultBranchName, @@ -84,10 +122,31 @@ export default { projectPath: this.projectPath, }; }, + i18n() { + return I18N_AGENT_MODAL[this.modalType]; + }, + repositoryPath() { + return `/${this.projectPath}`; + }, + modalType() { + return !this.availableAgents?.length && !this.registered + ? MODAL_TYPE_EMPTY + : MODAL_TYPE_REGISTER; + }, + modalSize() { + return this.isEmptyStateModal ? 'sm' : 'md'; + }, + isEmptyStateModal() { + return this.modalType === MODAL_TYPE_EMPTY; + }, + isAgentRegistrationModal() { + return this.modalType === MODAL_TYPE_REGISTER; + }, }, methods: { setAgentName(name) { this.agentName = name; + this.track(EVENT_ACTIONS_SELECT); }, closeModal() { this.$refs.modal.hide(); @@ -96,8 +155,16 @@ export default { this.registering = false; this.agentName = null; this.agentToken = null; + this.clusterAgent = null; this.error = null; }, + populateAvailableAgents(data) { + const installedAgents = data?.project?.clusterAgents?.nodes.map((agent) => agent.name) ?? []; + const configuredAgents = + data?.project?.agentConfigurations?.nodes.map((config) => config.agentName) ?? []; + + this.availableAgents = configuredAgents.filter((agent) => !installedAgents.includes(agent)); + }, createAgentMutation() { return this.$apollo .mutate({ @@ -117,7 +184,9 @@ export default { ); }, }) - .then(({ data: { createClusterAgent } }) => createClusterAgent); + .then(({ data: { createClusterAgent } }) => { + return createClusterAgent; + }); }, createAgentTokenMutation(agendId) { return this.$apollo @@ -129,6 +198,17 @@ export default { name: this.agentName, }, }, + update: (store, { data: { clusterAgentTokenCreate } }) => { + addAgentConfigToStore( + store, + clusterAgentTokenCreate, + this.clusterAgent, + agentConfigurations, + { + projectPath: this.projectPath, + }, + ); + }, }) .then(({ data: { clusterAgentTokenCreate } }) => clusterAgentTokenCreate); }, @@ -158,7 +238,7 @@ export default { if (error) { this.error = error.message; } else { - this.error = this.$options.i18n.unknownError; + this.error = this.i18n.unknownError; } } finally { this.registering = false; @@ -172,115 +252,172 @@ export default { <gl-modal ref="modal" :modal-id="$options.modalId" - :title="$options.i18n.modalTitle" + :title="i18n.modalTitle" + :size="modalSize" static lazy @hidden="resetModal" + @show="track($options.EVENT_ACTIONS_OPEN, { property: modalType })" > - <template v-if="!registered"> - <p> - <strong>{{ $options.i18n.selectAgentTitle }}</strong> - </p> + <template v-if="isAgentRegistrationModal"> + <template v-if="!registered"> + <p> + <strong>{{ i18n.selectAgentTitle }}</strong> + </p> - <p> - <gl-sprintf :message="$options.i18n.selectAgentBody"> - <template #link="{ content }"> - <gl-link :href="basicInstallPath" target="_blank"> {{ content }}</gl-link> - </template> - </gl-sprintf> - </p> + <p class="gl-mb-0">{{ i18n.selectAgentBody }}</p> + <p> + <gl-link :href="$options.registerAgentPath"> {{ i18n.learnMoreLink }}</gl-link> + </p> - <form> - <gl-form-group label-for="agent-name"> - <available-agents-dropdown - class="gl-w-70p" - :is-registering="registering" - @agentSelected="setAgentName" - /> - </gl-form-group> - </form> + <form> + <gl-form-group label-for="agent-name"> + <available-agents-dropdown + class="gl-w-70p" + :is-registering="registering" + :available-agents="availableAgents" + @agentSelected="setAgentName" + /> + </gl-form-group> + </form> - <p v-if="error"> - <gl-alert - :title="$options.i18n.registrationErrorTitle" - variant="danger" - :dismissible="false" - > - {{ error }} - </gl-alert> - </p> - </template> + <p v-if="error"> + <gl-alert :title="i18n.registrationErrorTitle" variant="danger" :dismissible="false"> + {{ error }} + </gl-alert> + </p> + </template> - <template v-else> - <p> - <strong>{{ $options.i18n.tokenTitle }}</strong> - </p> + <template v-else> + <p> + <strong>{{ i18n.tokenTitle }}</strong> + </p> - <p> - <gl-sprintf :message="$options.i18n.tokenBody"> - <template #link="{ content }"> - <gl-link :href="basicInstallPath" target="_blank"> {{ content }}</gl-link> - </template> - </gl-sprintf> - </p> + <p> + <gl-sprintf :message="i18n.tokenBody"> + <template #link="{ content }"> + <gl-link :href="$options.basicInstallPath" target="_blank"> {{ content }}</gl-link> + </template> + </gl-sprintf> + </p> - <p> - <gl-alert - :title="$options.i18n.tokenSingleUseWarningTitle" - variant="warning" - :dismissible="false" - > - {{ $options.i18n.tokenSingleUseWarningBody }} - </gl-alert> - </p> + <p> + <gl-alert :title="i18n.tokenSingleUseWarningTitle" variant="warning" :dismissible="false"> + {{ i18n.tokenSingleUseWarningBody }} + </gl-alert> + </p> - <p> - <gl-form-input-group readonly :value="agentToken" :select-on-click="true"> - <template #append> - <clipboard-button :text="agentToken" :title="$options.i18n.copyToken" /> - </template> - </gl-form-input-group> - </p> + <p> + <gl-form-input-group readonly :value="agentToken" :select-on-click="true"> + <template #append> + <modal-copy-button + :text="agentToken" + :title="i18n.copyToken" + :modal-id="$options.modalId" + /> + </template> + </gl-form-input-group> + </p> - <p> - <strong>{{ $options.i18n.basicInstallTitle }}</strong> - </p> + <p> + <strong>{{ i18n.basicInstallTitle }}</strong> + </p> - <p> - {{ $options.i18n.basicInstallBody }} - </p> + <p> + {{ i18n.basicInstallBody }} + </p> - <p> - <code-block :code="agentRegistrationCommand" /> - </p> + <p> + <code-block :code="agentRegistrationCommand" /> + </p> + + <p> + <strong>{{ i18n.advancedInstallTitle }}</strong> + </p> + + <p> + <gl-sprintf :message="i18n.advancedInstallBody"> + <template #link="{ content }"> + <gl-link :href="$options.advancedInstallPath" target="_blank"> {{ content }}</gl-link> + </template> + </gl-sprintf> + </p> + </template> + </template> + + <template v-else> + <div class="gl-text-center gl-mb-5"> + <img :alt="i18n.altText" :src="emptyStateImage" height="100" /> + </div> <p> - <strong>{{ $options.i18n.advancedInstallTitle }}</strong> + <gl-sprintf :message="i18n.modalBody"> + <template #link="{ content }"> + <gl-link :href="$options.installAgentPath"> {{ content }}</gl-link> + </template> + </gl-sprintf> </p> - <p> - <gl-sprintf :message="$options.i18n.advancedInstallBody"> + <p v-if="kasDisabled"> + <gl-sprintf :message="i18n.enableKasText"> <template #link="{ content }"> - <gl-link :href="advancedInstallPath" target="_blank"> {{ content }}</gl-link> + <gl-link :href="$options.enableKasPath"> {{ content }}</gl-link> </template> </gl-sprintf> </p> </template> <template #modal-footer> - <gl-button v-if="canCancel" @click="closeModal">{{ $options.i18n.cancel }} </gl-button> - - <gl-button v-if="registered" variant="confirm" category="primary" @click="closeModal" - >{{ $options.i18n.close }} + <gl-button + v-if="registered" + variant="confirm" + category="primary" + :data-track-action="$options.EVENT_ACTIONS_CLICK" + :data-track-label="$options.EVENT_LABEL_MODAL" + data-track-property="close" + @click="closeModal" + >{{ i18n.close }} </gl-button> <gl-button - v-else + v-else-if="isAgentRegistrationModal" :disabled="!nextButtonDisabled" variant="confirm" category="primary" + :data-track-action="$options.EVENT_ACTIONS_CLICK" + :data-track-label="$options.EVENT_LABEL_MODAL" + data-track-property="register" @click="registerAgent" - >{{ $options.i18n.registerAgentButton }} + >{{ i18n.registerAgentButton }} + </gl-button> + + <gl-button + v-if="canCancel" + :data-track-action="$options.EVENT_ACTIONS_CLICK" + :data-track-label="$options.EVENT_LABEL_MODAL" + data-track-property="cancel" + @click="closeModal" + >{{ i18n.cancel }} + </gl-button> + + <gl-button + v-if="isEmptyStateModal" + :href="repositoryPath" + variant="confirm" + category="secondary" + data-testid="agent-secondary-button" + >{{ i18n.secondaryButton }} + </gl-button> + + <gl-button + v-if="isEmptyStateModal" + variant="confirm" + category="primary" + :data-track-action="$options.EVENT_ACTIONS_CLICK" + :data-track-label="$options.EVENT_LABEL_MODAL" + data-track-property="done" + @click="closeModal" + >{{ i18n.done }} </gl-button> </template> </gl-modal> |