summaryrefslogtreecommitdiff
path: root/app/assets/javascripts/ci_variable_list
diff options
context:
space:
mode:
Diffstat (limited to 'app/assets/javascripts/ci_variable_list')
-rw-r--r--app/assets/javascripts/ci_variable_list/ci_variable_list.js262
-rw-r--r--app/assets/javascripts/ci_variable_list/components/ci_admin_variables.vue36
-rw-r--r--app/assets/javascripts/ci_variable_list/components/ci_environments_dropdown.vue90
-rw-r--r--app/assets/javascripts/ci_variable_list/components/ci_group_variables.vue54
-rw-r--r--app/assets/javascripts/ci_variable_list/components/ci_project_variables.vue56
-rw-r--r--app/assets/javascripts/ci_variable_list/components/ci_variable_autocomplete_tokens.js15
-rw-r--r--app/assets/javascripts/ci_variable_list/components/ci_variable_modal.vue503
-rw-r--r--app/assets/javascripts/ci_variable_list/components/ci_variable_settings.vue108
-rw-r--r--app/assets/javascripts/ci_variable_list/components/ci_variable_shared.vue242
-rw-r--r--app/assets/javascripts/ci_variable_list/components/ci_variable_table.vue298
-rw-r--r--app/assets/javascripts/ci_variable_list/constants.js106
-rw-r--r--app/assets/javascripts/ci_variable_list/graphql/fragments/ci_variable.fragment.graphql7
-rw-r--r--app/assets/javascripts/ci_variable_list/graphql/mutations/admin_add_variable.mutation.graphql16
-rw-r--r--app/assets/javascripts/ci_variable_list/graphql/mutations/admin_delete_variable.mutation.graphql16
-rw-r--r--app/assets/javascripts/ci_variable_list/graphql/mutations/admin_update_variable.mutation.graphql16
-rw-r--r--app/assets/javascripts/ci_variable_list/graphql/mutations/client/add_project_environment.mutation.graphql3
-rw-r--r--app/assets/javascripts/ci_variable_list/graphql/mutations/group_add_variable.mutation.graphql26
-rw-r--r--app/assets/javascripts/ci_variable_list/graphql/mutations/group_delete_variable.mutation.graphql26
-rw-r--r--app/assets/javascripts/ci_variable_list/graphql/mutations/group_update_variable.mutation.graphql26
-rw-r--r--app/assets/javascripts/ci_variable_list/graphql/mutations/project_add_variable.mutation.graphql26
-rw-r--r--app/assets/javascripts/ci_variable_list/graphql/mutations/project_delete_variable.mutation.graphql31
-rw-r--r--app/assets/javascripts/ci_variable_list/graphql/mutations/project_update_variable.mutation.graphql31
-rw-r--r--app/assets/javascripts/ci_variable_list/graphql/queries/group_variables.query.graphql23
-rw-r--r--app/assets/javascripts/ci_variable_list/graphql/queries/project_environments.query.graphql11
-rw-r--r--app/assets/javascripts/ci_variable_list/graphql/queries/project_variables.query.graphql21
-rw-r--r--app/assets/javascripts/ci_variable_list/graphql/queries/variables.query.graphql18
-rw-r--r--app/assets/javascripts/ci_variable_list/graphql/settings.js242
-rw-r--r--app/assets/javascripts/ci_variable_list/index.js83
-rw-r--r--app/assets/javascripts/ci_variable_list/native_form_variable_list.js25
-rw-r--r--app/assets/javascripts/ci_variable_list/utils.js60
30 files changed, 0 insertions, 2477 deletions
diff --git a/app/assets/javascripts/ci_variable_list/ci_variable_list.js b/app/assets/javascripts/ci_variable_list/ci_variable_list.js
deleted file mode 100644
index 574a5e7fd99..00000000000
--- a/app/assets/javascripts/ci_variable_list/ci_variable_list.js
+++ /dev/null
@@ -1,262 +0,0 @@
-import $ from 'jquery';
-import SecretValues from '~/behaviors/secret_values';
-import CreateItemDropdown from '~/create_item_dropdown';
-import { parseBoolean } from '~/lib/utils/common_utils';
-import { s__ } from '~/locale';
-
-const ALL_ENVIRONMENTS_STRING = s__('CiVariable|All environments');
-
-function createEnvironmentItem(value) {
- return {
- title: value === '*' ? ALL_ENVIRONMENTS_STRING : value,
- id: value,
- text: value === '*' ? s__('CiVariable|* (All environments)') : value,
- };
-}
-
-export default class VariableList {
- constructor({ container, formField, maskableRegex }) {
- this.$container = $(container);
- this.formField = formField;
- this.maskableRegex = new RegExp(maskableRegex);
- this.environmentDropdownMap = new WeakMap();
-
- this.inputMap = {
- id: {
- selector: '.js-ci-variable-input-id',
- default: '',
- },
- variable_type: {
- selector: '.js-ci-variable-input-variable-type',
- default: 'env_var',
- },
- key: {
- selector: '.js-ci-variable-input-key',
- default: '',
- },
- secret_value: {
- selector: '.js-ci-variable-input-value',
- default: '',
- },
- protected: {
- selector: '.js-ci-variable-input-protected',
- // use `attr` instead of `data` as we don't want the value to be
- // converted. we need the value as a string.
- default: $('.js-ci-variable-input-protected').attr('data-default'),
- },
- masked: {
- selector: '.js-ci-variable-input-masked',
- // use `attr` instead of `data` as we don't want the value to be
- // converted. we need the value as a string.
- default: $('.js-ci-variable-input-masked').attr('data-default'),
- },
- environment_scope: {
- // We can't use a `.js-` class here because
- // deprecated_jquery_dropdown replaces the <input> and doesn't copy over the class
- // See https://gitlab.com/gitlab-org/gitlab-foss/issues/42458
- selector: `input[name="${this.formField}[variables_attributes][][environment_scope]"]`,
- default: '*',
- },
- _destroy: {
- selector: '.js-ci-variable-input-destroy',
- default: '',
- },
- };
-
- this.secretValues = new SecretValues({
- container: this.$container[0],
- valueSelector: '.js-row:not(:last-child) .js-secret-value',
- placeholderSelector: '.js-row:not(:last-child) .js-secret-value-placeholder',
- });
- }
-
- init() {
- this.bindEvents();
- this.secretValues.init();
- }
-
- bindEvents() {
- this.$container.find('.js-row').each((index, rowEl) => {
- this.initRow(rowEl);
- });
-
- this.$container.on('click', '.js-row-remove-button', (e) => {
- e.preventDefault();
- this.removeRow($(e.currentTarget).closest('.js-row'));
- });
-
- const inputSelector = Object.keys(this.inputMap)
- .map((name) => this.inputMap[name].selector)
- .join(',');
-
- // Remove any empty rows except the last row
- this.$container.on('blur', inputSelector, (e) => {
- const $row = $(e.currentTarget).closest('.js-row');
-
- if ($row.is(':not(:last-child)') && !this.checkIfRowTouched($row)) {
- this.removeRow($row);
- }
- });
-
- this.$container.on('input trigger-change', inputSelector, (e) => {
- // Always make sure there is an empty last row
- const $lastRow = this.$container.find('.js-row').last();
-
- if (this.checkIfRowTouched($lastRow)) {
- this.insertRow($lastRow);
- }
-
- // If masked, validate value against regex
- this.validateMaskability($(e.currentTarget).closest('.js-row'));
- });
- }
-
- initRow(rowEl) {
- const $row = $(rowEl);
-
- // Reset the resizable textarea
- $row.find(this.inputMap.secret_value.selector).css('height', '');
-
- const $environmentSelect = $row.find('.js-variable-environment-toggle');
- if ($environmentSelect.length) {
- const createItemDropdown = new CreateItemDropdown({
- $dropdown: $environmentSelect,
- defaultToggleLabel: ALL_ENVIRONMENTS_STRING,
- fieldName: `${this.formField}[variables_attributes][][environment_scope]`,
- getData: (term, callback) => callback(this.getEnvironmentValues()),
- createNewItemFromValue: createEnvironmentItem,
- onSelect: () => {
- // Refresh the other dropdowns in the variable list
- // so they have the new value we just picked
- this.refreshDropdownData();
-
- $row.find(this.inputMap.environment_scope.selector).trigger('trigger-change');
- },
- });
-
- // Clear out any data that might have been left-over from the row clone
- createItemDropdown.clearDropdown();
-
- this.environmentDropdownMap.set($row[0], createItemDropdown);
- }
- }
-
- insertRow($row) {
- const $rowClone = $row.clone();
- $rowClone.removeAttr('data-is-persisted');
-
- // Reset the inputs to their defaults
- Object.keys(this.inputMap).forEach((name) => {
- const entry = this.inputMap[name];
- $rowClone.find(entry.selector).val(entry.default);
- });
-
- // Close any dropdowns
- $rowClone.find('.dropdown-menu.show').each((index, $dropdown) => {
- $dropdown.classList.remove('show');
- });
-
- this.initRow($rowClone);
-
- $row.after($rowClone);
- }
-
- removeRow(row) {
- const $row = $(row);
- const isPersisted = parseBoolean($row.attr('data-is-persisted'));
-
- if (isPersisted) {
- $row.hide();
- $row
- // eslint-disable-next-line no-underscore-dangle
- .find(this.inputMap._destroy.selector)
- .val(true);
- } else {
- $row.remove();
- }
-
- // Refresh the other dropdowns in the variable list
- // so any value with the variable deleted is gone
- this.refreshDropdownData();
- }
-
- checkIfRowTouched($row) {
- return Object.keys(this.inputMap).some((name) => {
- // Row should not qualify as touched if only switches have been touched
- if (['protected', 'masked'].includes(name)) return false;
-
- const entry = this.inputMap[name];
- const $el = $row.find(entry.selector);
- return $el.length && $el.val() !== entry.default;
- });
- }
-
- validateMaskability($row) {
- const invalidInputClass = 'gl-field-error-outline';
-
- const variableValue = $row.find(this.inputMap.secret_value.selector).val();
- const isValueMaskable = this.maskableRegex.test(variableValue) || variableValue === '';
- const isMaskedChecked = $row.find(this.inputMap.masked.selector).val() === 'true';
-
- // Show a validation error if the user wants to mask an unmaskable variable value
- $row
- .find(this.inputMap.secret_value.selector)
- .toggleClass(invalidInputClass, isMaskedChecked && !isValueMaskable);
- $row
- .find('.js-secret-value-placeholder')
- .toggleClass(invalidInputClass, isMaskedChecked && !isValueMaskable);
- $row.find('.masking-validation-error').toggle(isMaskedChecked && !isValueMaskable);
- }
-
- toggleEnableRow(isEnabled = true) {
- this.$container.find(this.inputMap.key.selector).attr('disabled', !isEnabled);
- this.$container.find('.js-row-remove-button').attr('disabled', !isEnabled);
- }
-
- hideValues() {
- this.secretValues.updateDom(false);
- }
-
- getAllData() {
- // Ignore the last empty row because we don't want to try persist
- // a blank variable and run into validation problems.
- const validRows = this.$container.find('.js-row').toArray().slice(0, -1);
-
- return validRows.map((rowEl) => {
- const resultant = {};
- Object.keys(this.inputMap).forEach((name) => {
- const entry = this.inputMap[name];
- const $input = $(rowEl).find(entry.selector);
- if ($input.length) {
- resultant[name] = $input.val();
- }
- });
-
- return resultant;
- });
- }
-
- getEnvironmentValues() {
- const valueMap = this.$container
- .find(this.inputMap.environment_scope.selector)
- .toArray()
- .reduce(
- (prevValueMap, envInput) => ({
- ...prevValueMap,
- [envInput.value]: envInput.value,
- }),
- {},
- );
-
- return Object.keys(valueMap).map(createEnvironmentItem);
- }
-
- refreshDropdownData() {
- this.$container.find('.js-row').each((index, rowEl) => {
- const environmentDropdown = this.environmentDropdownMap.get(rowEl);
- if (environmentDropdown) {
- environmentDropdown.refreshData();
- }
- });
- }
-}
diff --git a/app/assets/javascripts/ci_variable_list/components/ci_admin_variables.vue b/app/assets/javascripts/ci_variable_list/components/ci_admin_variables.vue
deleted file mode 100644
index 719696f682e..00000000000
--- a/app/assets/javascripts/ci_variable_list/components/ci_admin_variables.vue
+++ /dev/null
@@ -1,36 +0,0 @@
-<script>
-import { ADD_MUTATION_ACTION, DELETE_MUTATION_ACTION, UPDATE_MUTATION_ACTION } from '../constants';
-import getAdminVariables from '../graphql/queries/variables.query.graphql';
-import addAdminVariable from '../graphql/mutations/admin_add_variable.mutation.graphql';
-import deleteAdminVariable from '../graphql/mutations/admin_delete_variable.mutation.graphql';
-import updateAdminVariable from '../graphql/mutations/admin_update_variable.mutation.graphql';
-import CiVariableShared from './ci_variable_shared.vue';
-
-export default {
- components: {
- CiVariableShared,
- },
- mutationData: {
- [ADD_MUTATION_ACTION]: addAdminVariable,
- [UPDATE_MUTATION_ACTION]: updateAdminVariable,
- [DELETE_MUTATION_ACTION]: deleteAdminVariable,
- },
- queryData: {
- ciVariables: {
- lookup: (data) => data?.ciVariables,
- query: getAdminVariables,
- },
- },
-};
-</script>
-
-<template>
- <ci-variable-shared
- :are-scoped-variables-available="false"
- component-name="InstanceVariables"
- :hide-environment-scope="true"
- :mutation-data="$options.mutationData"
- :refetch-after-mutation="true"
- :query-data="$options.queryData"
- />
-</template>
diff --git a/app/assets/javascripts/ci_variable_list/components/ci_environments_dropdown.vue b/app/assets/javascripts/ci_variable_list/components/ci_environments_dropdown.vue
deleted file mode 100644
index c9002edc1ab..00000000000
--- a/app/assets/javascripts/ci_variable_list/components/ci_environments_dropdown.vue
+++ /dev/null
@@ -1,90 +0,0 @@
-<script>
-import { GlDropdown, GlDropdownItem, GlDropdownDivider, GlSearchBoxByType } from '@gitlab/ui';
-import { __, sprintf } from '~/locale';
-import { convertEnvironmentScope } from '../utils';
-
-export default {
- name: 'CiEnvironmentsDropdown',
- components: {
- GlDropdown,
- GlDropdownItem,
- GlDropdownDivider,
- GlSearchBoxByType,
- },
- props: {
- environments: {
- type: Array,
- required: true,
- },
- selectedEnvironmentScope: {
- type: String,
- required: false,
- default: '',
- },
- },
- data() {
- return {
- searchTerm: '',
- };
- },
- computed: {
- composedCreateButtonLabel() {
- return sprintf(__('Create wildcard: %{searchTerm}'), { searchTerm: this.searchTerm });
- },
- filteredEnvironments() {
- const lowerCasedSearchTerm = this.searchTerm.toLowerCase();
- return this.environments.filter((environment) => {
- return environment.toLowerCase().includes(lowerCasedSearchTerm);
- });
- },
- shouldRenderCreateButton() {
- return this.searchTerm && !this.environments.includes(this.searchTerm);
- },
- environmentScopeLabel() {
- return convertEnvironmentScope(this.selectedEnvironmentScope);
- },
- },
- methods: {
- selectEnvironment(selected) {
- this.$emit('select-environment', selected);
- this.clearSearch();
- },
- convertEnvironmentScopeValue(scope) {
- return convertEnvironmentScope(scope);
- },
- createEnvironmentScope() {
- this.$emit('create-environment-scope', this.searchTerm);
- this.selectEnvironment(this.searchTerm);
- },
- isSelected(env) {
- return this.selectedEnvironmentScope === env;
- },
- clearSearch() {
- this.searchTerm = '';
- },
- },
-};
-</script>
-<template>
- <gl-dropdown :text="environmentScopeLabel" @show="clearSearch">
- <gl-search-box-by-type v-model.trim="searchTerm" data-testid="ci-environment-search" />
- <gl-dropdown-item
- v-for="environment in filteredEnvironments"
- :key="environment"
- :is-checked="isSelected(environment)"
- is-check-item
- @click="selectEnvironment(environment)"
- >
- {{ convertEnvironmentScopeValue(environment) }}
- </gl-dropdown-item>
- <gl-dropdown-item v-if="!filteredEnvironments.length" ref="noMatchingResults">{{
- __('No matching results')
- }}</gl-dropdown-item>
- <template v-if="shouldRenderCreateButton">
- <gl-dropdown-divider />
- <gl-dropdown-item data-testid="create-wildcard-button" @click="createEnvironmentScope">
- {{ composedCreateButtonLabel }}
- </gl-dropdown-item>
- </template>
- </gl-dropdown>
-</template>
diff --git a/app/assets/javascripts/ci_variable_list/components/ci_group_variables.vue b/app/assets/javascripts/ci_variable_list/components/ci_group_variables.vue
deleted file mode 100644
index 4466a6a8081..00000000000
--- a/app/assets/javascripts/ci_variable_list/components/ci_group_variables.vue
+++ /dev/null
@@ -1,54 +0,0 @@
-<script>
-import { convertToGraphQLId } from '~/graphql_shared/utils';
-import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
-import {
- ADD_MUTATION_ACTION,
- DELETE_MUTATION_ACTION,
- GRAPHQL_GROUP_TYPE,
- UPDATE_MUTATION_ACTION,
-} from '../constants';
-import getGroupVariables from '../graphql/queries/group_variables.query.graphql';
-import addGroupVariable from '../graphql/mutations/group_add_variable.mutation.graphql';
-import deleteGroupVariable from '../graphql/mutations/group_delete_variable.mutation.graphql';
-import updateGroupVariable from '../graphql/mutations/group_update_variable.mutation.graphql';
-import CiVariableShared from './ci_variable_shared.vue';
-
-export default {
- components: {
- CiVariableShared,
- },
- mixins: [glFeatureFlagsMixin()],
- inject: ['groupPath', 'groupId'],
- computed: {
- areScopedVariablesAvailable() {
- return this.glFeatures.groupScopedCiVariables;
- },
- graphqlId() {
- return convertToGraphQLId(GRAPHQL_GROUP_TYPE, this.groupId);
- },
- },
- mutationData: {
- [ADD_MUTATION_ACTION]: addGroupVariable,
- [UPDATE_MUTATION_ACTION]: updateGroupVariable,
- [DELETE_MUTATION_ACTION]: deleteGroupVariable,
- },
- queryData: {
- ciVariables: {
- lookup: (data) => data?.group?.ciVariables,
- query: getGroupVariables,
- },
- },
-};
-</script>
-
-<template>
- <ci-variable-shared
- :id="graphqlId"
- :are-scoped-variables-available="areScopedVariablesAvailable"
- component-name="GroupVariables"
- entity="group"
- :full-path="groupPath"
- :mutation-data="$options.mutationData"
- :query-data="$options.queryData"
- />
-</template>
diff --git a/app/assets/javascripts/ci_variable_list/components/ci_project_variables.vue b/app/assets/javascripts/ci_variable_list/components/ci_project_variables.vue
deleted file mode 100644
index 6326940148a..00000000000
--- a/app/assets/javascripts/ci_variable_list/components/ci_project_variables.vue
+++ /dev/null
@@ -1,56 +0,0 @@
-<script>
-import { convertToGraphQLId } from '~/graphql_shared/utils';
-import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
-import {
- ADD_MUTATION_ACTION,
- DELETE_MUTATION_ACTION,
- GRAPHQL_PROJECT_TYPE,
- UPDATE_MUTATION_ACTION,
-} from '../constants';
-import getProjectEnvironments from '../graphql/queries/project_environments.query.graphql';
-import getProjectVariables from '../graphql/queries/project_variables.query.graphql';
-import addProjectVariable from '../graphql/mutations/project_add_variable.mutation.graphql';
-import deleteProjectVariable from '../graphql/mutations/project_delete_variable.mutation.graphql';
-import updateProjectVariable from '../graphql/mutations/project_update_variable.mutation.graphql';
-import CiVariableShared from './ci_variable_shared.vue';
-
-export default {
- components: {
- CiVariableShared,
- },
- mixins: [glFeatureFlagsMixin()],
- inject: ['projectFullPath', 'projectId'],
- computed: {
- graphqlId() {
- return convertToGraphQLId(GRAPHQL_PROJECT_TYPE, this.projectId);
- },
- },
- mutationData: {
- [ADD_MUTATION_ACTION]: addProjectVariable,
- [UPDATE_MUTATION_ACTION]: updateProjectVariable,
- [DELETE_MUTATION_ACTION]: deleteProjectVariable,
- },
- queryData: {
- ciVariables: {
- lookup: (data) => data?.project?.ciVariables,
- query: getProjectVariables,
- },
- environments: {
- lookup: (data) => data?.project?.environments,
- query: getProjectEnvironments,
- },
- },
-};
-</script>
-
-<template>
- <ci-variable-shared
- :id="graphqlId"
- :are-scoped-variables-available="true"
- component-name="ProjectVariables"
- entity="project"
- :full-path="projectFullPath"
- :mutation-data="$options.mutationData"
- :query-data="$options.queryData"
- />
-</template>
diff --git a/app/assets/javascripts/ci_variable_list/components/ci_variable_autocomplete_tokens.js b/app/assets/javascripts/ci_variable_list/components/ci_variable_autocomplete_tokens.js
deleted file mode 100644
index 3f25e3df305..00000000000
--- a/app/assets/javascripts/ci_variable_list/components/ci_variable_autocomplete_tokens.js
+++ /dev/null
@@ -1,15 +0,0 @@
-import { AWS_ACCESS_KEY_ID, AWS_DEFAULT_REGION, AWS_SECRET_ACCESS_KEY } from '../constants';
-
-export const awsTokens = {
- [AWS_ACCESS_KEY_ID]: {
- name: AWS_ACCESS_KEY_ID,
- },
- [AWS_DEFAULT_REGION]: {
- name: AWS_DEFAULT_REGION,
- },
- [AWS_SECRET_ACCESS_KEY]: {
- name: AWS_SECRET_ACCESS_KEY,
- },
-};
-
-export const awsTokenList = Object.keys(awsTokens);
diff --git a/app/assets/javascripts/ci_variable_list/components/ci_variable_modal.vue b/app/assets/javascripts/ci_variable_list/components/ci_variable_modal.vue
deleted file mode 100644
index 00177539cdc..00000000000
--- a/app/assets/javascripts/ci_variable_list/components/ci_variable_modal.vue
+++ /dev/null
@@ -1,503 +0,0 @@
-<script>
-import {
- GlAlert,
- GlButton,
- GlCollapse,
- GlFormCheckbox,
- GlFormCombobox,
- GlFormGroup,
- GlFormSelect,
- GlFormInput,
- GlFormTextarea,
- GlIcon,
- GlLink,
- GlModal,
- GlSprintf,
-} from '@gitlab/ui';
-import { getCookie, setCookie } from '~/lib/utils/common_utils';
-import { __ } from '~/locale';
-import Tracking from '~/tracking';
-
-import {
- allEnvironments,
- AWS_TOKEN_CONSTANTS,
- ADD_CI_VARIABLE_MODAL_ID,
- AWS_TIP_DISMISSED_COOKIE_NAME,
- AWS_TIP_MESSAGE,
- CONTAINS_VARIABLE_REFERENCE_MESSAGE,
- defaultVariableState,
- ENVIRONMENT_SCOPE_LINK_TITLE,
- EVENT_LABEL,
- EVENT_ACTION,
- EXPANDED_VARIABLES_NOTE,
- EDIT_VARIABLE_ACTION,
- VARIABLE_ACTIONS,
- variableOptions,
-} from '../constants';
-import { createJoinedEnvironments } from '../utils';
-import CiEnvironmentsDropdown from './ci_environments_dropdown.vue';
-import { awsTokens, awsTokenList } from './ci_variable_autocomplete_tokens';
-
-const trackingMixin = Tracking.mixin({ label: EVENT_LABEL });
-
-export default {
- modalId: ADD_CI_VARIABLE_MODAL_ID,
- tokens: awsTokens,
- tokenList: awsTokenList,
- awsTipMessage: AWS_TIP_MESSAGE,
- containsVariableReferenceMessage: CONTAINS_VARIABLE_REFERENCE_MESSAGE,
- environmentScopeLinkTitle: ENVIRONMENT_SCOPE_LINK_TITLE,
- expandedVariablesNote: EXPANDED_VARIABLES_NOTE,
- components: {
- CiEnvironmentsDropdown,
- GlAlert,
- GlButton,
- GlCollapse,
- GlFormCheckbox,
- GlFormCombobox,
- GlFormGroup,
- GlFormSelect,
- GlFormInput,
- GlFormTextarea,
- GlIcon,
- GlLink,
- GlModal,
- GlSprintf,
- },
- mixins: [trackingMixin],
- inject: [
- 'awsLogoSvgPath',
- 'awsTipCommandsLink',
- 'awsTipDeployLink',
- 'awsTipLearnLink',
- 'containsVariableReferenceLink',
- 'environmentScopeLink',
- 'isProtectedByDefault',
- 'maskedEnvironmentVariablesLink',
- 'maskableRegex',
- 'protectedEnvironmentVariablesLink',
- ],
- props: {
- areScopedVariablesAvailable: {
- type: Boolean,
- required: false,
- default: false,
- },
- environments: {
- type: Array,
- required: false,
- default: () => [],
- },
- hideEnvironmentScope: {
- type: Boolean,
- required: false,
- default: false,
- },
- mode: {
- type: String,
- required: true,
- validator(val) {
- return VARIABLE_ACTIONS.includes(val);
- },
- },
- selectedVariable: {
- type: Object,
- required: false,
- default: () => {},
- },
- variables: {
- type: Array,
- required: false,
- default: () => [],
- },
- },
- data() {
- return {
- newEnvironments: [],
- isTipDismissed: getCookie(AWS_TIP_DISMISSED_COOKIE_NAME) === 'true',
- validationErrorEventProperty: '',
- variable: { ...defaultVariableState, ...this.selectedVariable },
- };
- },
- computed: {
- canMask() {
- const regex = RegExp(this.maskableRegex);
- return regex.test(this.variable.value);
- },
- canSubmit() {
- return this.variableValidationState && this.variable.key !== '' && this.variable.value !== '';
- },
- containsVariableReference() {
- const regex = /\$/;
- return regex.test(this.variable.value) && this.isExpanded;
- },
- displayMaskedError() {
- return !this.canMask && this.variable.masked;
- },
- isEditing() {
- return this.mode === EDIT_VARIABLE_ACTION;
- },
- isExpanded() {
- return !this.variable.raw;
- },
- isTipVisible() {
- return !this.isTipDismissed && AWS_TOKEN_CONSTANTS.includes(this.variable.key);
- },
- joinedEnvironments() {
- return createJoinedEnvironments(this.variables, this.environments, this.newEnvironments);
- },
- maskedFeedback() {
- return this.displayMaskedError ? __('This variable can not be masked.') : '';
- },
- maskedState() {
- if (this.displayMaskedError) {
- return false;
- }
- return true;
- },
- modalActionText() {
- return this.isEditing ? __('Update variable') : __('Add variable');
- },
- tokenValidationFeedback() {
- const tokenSpecificFeedback = this.$options.tokens?.[this.variable.key]?.invalidMessage;
- if (!this.tokenValidationState && tokenSpecificFeedback) {
- return tokenSpecificFeedback;
- }
- return '';
- },
- tokenValidationState() {
- const validator = this.$options.tokens?.[this.variable.key]?.validation;
-
- if (validator) {
- return validator(this.variable.value);
- }
-
- return true;
- },
- variableValidationFeedback() {
- return `${this.tokenValidationFeedback} ${this.maskedFeedback}`;
- },
- variableValidationState() {
- return this.variable.value === '' || (this.tokenValidationState && this.maskedState);
- },
- },
- watch: {
- variable: {
- handler() {
- this.trackVariableValidationErrors();
- },
- deep: true,
- },
- },
- methods: {
- addVariable() {
- this.$emit('add-variable', this.variable);
- },
- createEnvironmentScope(env) {
- this.newEnvironments.push(env);
- },
- deleteVariable() {
- this.$emit('delete-variable', this.variable);
- },
- updateVariable() {
- this.$emit('update-variable', this.variable);
- },
- dismissTip() {
- setCookie(AWS_TIP_DISMISSED_COOKIE_NAME, 'true', { expires: 90 });
- this.isTipDismissed = true;
- },
- deleteVarAndClose() {
- this.deleteVariable();
- this.hideModal();
- },
- hideModal() {
- this.$refs.modal.hide();
- },
- onShow() {
- this.setVariableProtectedByDefault();
- },
- resetModalHandler() {
- this.resetVariableData();
- this.resetValidationErrorEvents();
-
- this.$emit('hideModal');
- },
- resetVariableData() {
- this.variable = { ...defaultVariableState };
- },
- setEnvironmentScope(scope) {
- this.variable = { ...this.variable, environmentScope: scope };
- },
- setVariableRaw(expanded) {
- this.variable = { ...this.variable, raw: !expanded };
- },
- setVariableProtected() {
- this.variable = { ...this.variable, protected: true };
- },
- updateOrAddVariable() {
- if (this.isEditing) {
- this.updateVariable();
- } else {
- this.addVariable();
- }
- this.hideModal();
- },
- setVariableProtectedByDefault() {
- if (this.isProtectedByDefault && !this.isEditing) {
- this.setVariableProtected();
- }
- },
- trackVariableValidationErrors() {
- const property = this.getTrackingErrorProperty();
- if (!this.validationErrorEventProperty && property) {
- this.track(EVENT_ACTION, { property });
- this.validationErrorEventProperty = property;
- }
- },
- getTrackingErrorProperty() {
- let property;
- if (this.variable.value?.length && !property) {
- if (this.displayMaskedError && this.maskableRegex?.length) {
- const supportedChars = this.maskableRegex.replace('^', '').replace(/{(\d,)}\$/, '');
- const regex = new RegExp(supportedChars, 'g');
- property = this.variable.value.replace(regex, '');
- }
- if (this.containsVariableReference) {
- property = '$';
- }
- }
-
- return property;
- },
- resetValidationErrorEvents() {
- this.validationErrorEventProperty = '';
- },
- },
- defaultScope: allEnvironments.text,
- variableOptions,
-};
-</script>
-
-<template>
- <gl-modal
- ref="modal"
- :modal-id="$options.modalId"
- :title="modalActionText"
- static
- lazy
- @hidden="resetModalHandler"
- @shown="onShow"
- >
- <form>
- <gl-form-combobox
- v-model="variable.key"
- :token-list="$options.tokenList"
- :label-text="__('Key')"
- data-testid="pipeline-form-ci-variable-key"
- data-qa-selector="ci_variable_key_field"
- />
-
- <gl-form-group
- :label="__('Value')"
- label-for="ci-variable-value"
- :state="variableValidationState"
- :invalid-feedback="variableValidationFeedback"
- >
- <gl-form-textarea
- id="ci-variable-value"
- ref="valueField"
- v-model="variable.value"
- :state="variableValidationState"
- rows="3"
- max-rows="10"
- data-testid="pipeline-form-ci-variable-value"
- data-qa-selector="ci_variable_value_field"
- class="gl-font-monospace!"
- spellcheck="false"
- />
- <p
- v-if="variable.raw"
- class="gl-mt-2 gl-mb-0 text-secondary"
- data-testid="raw-variable-tip"
- >
- {{ __('Variable value will be evaluated as raw string.') }}
- </p>
- </gl-form-group>
-
- <div class="gl-display-flex">
- <gl-form-group :label="__('Type')" label-for="ci-variable-type" class="gl-w-half gl-mr-5">
- <gl-form-select
- id="ci-variable-type"
- v-model="variable.variableType"
- :options="$options.variableOptions"
- />
- </gl-form-group>
-
- <template v-if="!hideEnvironmentScope">
- <gl-form-group
- label-for="ci-variable-env"
- class="gl-w-half"
- data-testid="environment-scope"
- >
- <template #label>
- {{ __('Environment scope') }}
- <gl-link
- :title="$options.environmentScopeLinkTitle"
- :href="environmentScopeLink"
- target="_blank"
- data-testid="environment-scope-link"
- >
- <gl-icon name="question" :size="12" />
- </gl-link>
- </template>
- <ci-environments-dropdown
- v-if="areScopedVariablesAvailable"
- class="gl-w-full"
- :selected-environment-scope="variable.environmentScope"
- :environments="joinedEnvironments"
- @select-environment="setEnvironmentScope"
- @create-environment-scope="createEnvironmentScope"
- />
-
- <gl-form-input v-else :value="$options.defaultScope" class="gl-w-full" readonly />
- </gl-form-group>
- </template>
- </div>
-
- <gl-form-group :label="__('Flags')" label-for="ci-variable-flags">
- <gl-form-checkbox
- v-model="variable.protected"
- class="gl-mb-0"
- data-testid="ci-variable-protected-checkbox"
- :data-is-protected-checked="variable.protected"
- >
- {{ __('Protect variable') }}
- <gl-link target="_blank" :href="protectedEnvironmentVariablesLink">
- <gl-icon name="question" :size="12" />
- </gl-link>
- <p class="gl-mt-2 text-secondary">
- {{ __('Export variable to pipelines running on protected branches and tags only.') }}
- </p>
- </gl-form-checkbox>
- <gl-form-checkbox
- ref="masked-ci-variable"
- v-model="variable.masked"
- data-testid="ci-variable-masked-checkbox"
- >
- {{ __('Mask variable') }}
- <gl-link target="_blank" :href="maskedEnvironmentVariablesLink">
- <gl-icon name="question" :size="12" />
- </gl-link>
- <p class="gl-mt-2 text-secondary">
- {{ __('Variable will be masked in job logs.') }}
- <span
- :class="{
- 'bold text-plain': displayMaskedError,
- }"
- >
- {{ __('Requires values to meet regular expression requirements.') }}</span
- >
- <gl-link target="_blank" :href="maskedEnvironmentVariablesLink">{{
- __('More information')
- }}</gl-link>
- </p>
- </gl-form-checkbox>
- <gl-form-checkbox
- ref="expanded-ci-variable"
- :checked="isExpanded"
- data-testid="ci-variable-expanded-checkbox"
- @change="setVariableRaw"
- >
- {{ __('Expand variable reference') }}
- <gl-link target="_blank" :href="containsVariableReferenceLink">
- <gl-icon name="question" :size="12" />
- </gl-link>
- <p class="gl-mt-2 gl-mb-0 gl-text-secondary">
- <gl-sprintf :message="$options.expandedVariablesNote">
- <template #code="{ content }">
- <code>{{ content }}</code>
- </template>
- </gl-sprintf>
- </p>
- </gl-form-checkbox>
- </gl-form-group>
- </form>
- <gl-collapse :visible="isTipVisible">
- <gl-alert
- :title="__('Deploying to AWS is easy with GitLab')"
- variant="tip"
- data-testid="aws-guidance-tip"
- @dismiss="dismissTip"
- >
- <div class="gl-display-flex gl-flex-direction-row gl-flex-wrap-wrap gl-md-flex-wrap-nowrap">
- <div>
- <p>
- <gl-sprintf :message="$options.awsTipMessage">
- <template #deployLink="{ content }">
- <gl-link :href="awsTipDeployLink" target="_blank">{{ content }}</gl-link>
- </template>
- <template #commandsLink="{ content }">
- <gl-link :href="awsTipCommandsLink" target="_blank">{{ content }}</gl-link>
- </template>
- </gl-sprintf>
- </p>
- <p>
- <gl-button
- :href="awsTipLearnLink"
- target="_blank"
- category="secondary"
- variant="confirm"
- class="gl-overflow-wrap-break"
- >{{ __('Learn more about deploying to AWS') }}</gl-button
- >
- </p>
- </div>
- <img
- class="gl-mt-3"
- :alt="__('Amazon Web Services Logo')"
- :src="awsLogoSvgPath"
- height="32"
- />
- </div>
- </gl-alert>
- </gl-collapse>
- <gl-alert
- v-if="containsVariableReference"
- :title="__('Value might contain a variable reference')"
- :dismissible="false"
- variant="warning"
- data-testid="contains-variable-reference"
- >
- <gl-sprintf :message="$options.containsVariableReferenceMessage">
- <template #code="{ content }">
- <code>{{ content }}</code>
- </template>
- <template #docsLink="{ content }">
- <gl-link :href="containsVariableReferenceLink" target="_blank">{{ content }}</gl-link>
- </template>
- </gl-sprintf>
- </gl-alert>
- <template #modal-footer>
- <gl-button @click="hideModal">{{ __('Cancel') }}</gl-button>
- <gl-button
- v-if="isEditing"
- ref="deleteCiVariable"
- variant="danger"
- category="secondary"
- data-qa-selector="ci_variable_delete_button"
- @click="deleteVarAndClose"
- >{{ __('Delete variable') }}</gl-button
- >
- <gl-button
- ref="updateOrAddVariable"
- :disabled="!canSubmit"
- variant="confirm"
- category="primary"
- data-testid="ciUpdateOrAddVariableBtn"
- data-qa-selector="ci_variable_save_button"
- @click="updateOrAddVariable"
- >{{ modalActionText }}
- </gl-button>
- </template>
- </gl-modal>
-</template>
diff --git a/app/assets/javascripts/ci_variable_list/components/ci_variable_settings.vue b/app/assets/javascripts/ci_variable_list/components/ci_variable_settings.vue
deleted file mode 100644
index 3c6114b38ce..00000000000
--- a/app/assets/javascripts/ci_variable_list/components/ci_variable_settings.vue
+++ /dev/null
@@ -1,108 +0,0 @@
-<script>
-import { ADD_VARIABLE_ACTION, EDIT_VARIABLE_ACTION, VARIABLE_ACTIONS } from '../constants';
-import CiVariableTable from './ci_variable_table.vue';
-import CiVariableModal from './ci_variable_modal.vue';
-
-export default {
- components: {
- CiVariableTable,
- CiVariableModal,
- },
- props: {
- areScopedVariablesAvailable: {
- type: Boolean,
- required: false,
- default: false,
- },
- entity: {
- type: String,
- required: false,
- default: '',
- },
- environments: {
- type: Array,
- required: false,
- default: () => [],
- },
- hideEnvironmentScope: {
- type: Boolean,
- required: false,
- default: false,
- },
- isLoading: {
- type: Boolean,
- required: false,
- },
- maxVariableLimit: {
- type: Number,
- required: false,
- default: 0,
- },
- variables: {
- type: Array,
- required: true,
- },
- },
- data() {
- return {
- selectedVariable: {},
- mode: null,
- };
- },
- computed: {
- showModal() {
- return VARIABLE_ACTIONS.includes(this.mode);
- },
- },
- methods: {
- addVariable(variable) {
- this.$emit('add-variable', variable);
- },
- deleteVariable(variable) {
- this.$emit('delete-variable', variable);
- },
- updateVariable(variable) {
- this.$emit('update-variable', variable);
- },
- hideModal() {
- this.mode = null;
- },
- setSelectedVariable(variable = null) {
- if (!variable) {
- this.selectedVariable = {};
- this.mode = ADD_VARIABLE_ACTION;
- } else {
- this.selectedVariable = variable;
- this.mode = EDIT_VARIABLE_ACTION;
- }
- },
- },
-};
-</script>
-
-<template>
- <div class="row">
- <div class="col-lg-12">
- <ci-variable-table
- :entity="entity"
- :is-loading="isLoading"
- :max-variable-limit="maxVariableLimit"
- :variables="variables"
- @set-selected-variable="setSelectedVariable"
- />
- <ci-variable-modal
- v-if="showModal"
- :are-scoped-variables-available="areScopedVariablesAvailable"
- :environments="environments"
- :hide-environment-scope="hideEnvironmentScope"
- :variables="variables"
- :mode="mode"
- :selected-variable="selectedVariable"
- @add-variable="addVariable"
- @delete-variable="deleteVariable"
- @hideModal="hideModal"
- @update-variable="updateVariable"
- />
- </div>
- </div>
-</template>
diff --git a/app/assets/javascripts/ci_variable_list/components/ci_variable_shared.vue b/app/assets/javascripts/ci_variable_list/components/ci_variable_shared.vue
deleted file mode 100644
index 6e39bda0b07..00000000000
--- a/app/assets/javascripts/ci_variable_list/components/ci_variable_shared.vue
+++ /dev/null
@@ -1,242 +0,0 @@
-<script>
-import { createAlert } from '~/flash';
-import { __ } from '~/locale';
-import { mapEnvironmentNames, reportMessageToSentry } from '../utils';
-import {
- ADD_MUTATION_ACTION,
- DELETE_MUTATION_ACTION,
- UPDATE_MUTATION_ACTION,
- environmentFetchErrorText,
- genericMutationErrorText,
- variableFetchErrorText,
-} from '../constants';
-import CiVariableSettings from './ci_variable_settings.vue';
-
-export default {
- components: {
- CiVariableSettings,
- },
- inject: ['endpoint'],
- props: {
- areScopedVariablesAvailable: {
- required: true,
- type: Boolean,
- },
- componentName: {
- required: true,
- type: String,
- },
- entity: {
- required: false,
- type: String,
- default: '',
- },
- fullPath: {
- required: false,
- type: String,
- default: null,
- },
- hideEnvironmentScope: {
- type: Boolean,
- required: false,
- default: false,
- },
- id: {
- required: false,
- type: String,
- default: null,
- },
- mutationData: {
- required: true,
- type: Object,
- validator: (obj) => {
- const hasValidKeys = Object.keys(obj).includes(
- ADD_MUTATION_ACTION,
- UPDATE_MUTATION_ACTION,
- DELETE_MUTATION_ACTION,
- );
-
- const hasValidValues = Object.values(obj).reduce((acc, val) => {
- return acc && typeof val === 'object';
- }, true);
-
- return hasValidKeys && hasValidValues;
- },
- },
- refetchAfterMutation: {
- required: false,
- type: Boolean,
- default: false,
- },
- queryData: {
- required: true,
- type: Object,
- validator: (obj) => {
- const { ciVariables, environments } = obj;
- const hasCiVariablesKey = Boolean(ciVariables);
- let hasCorrectEnvData = true;
-
- const hasCorrectVariablesData =
- typeof ciVariables?.lookup === 'function' && typeof ciVariables.query === 'object';
-
- if (environments) {
- hasCorrectEnvData =
- typeof environments?.lookup === 'function' && typeof environments.query === 'object';
- }
-
- return hasCiVariablesKey && hasCorrectVariablesData && hasCorrectEnvData;
- },
- },
- },
- data() {
- return {
- ciVariables: [],
- hasNextPage: false,
- isInitialLoading: true,
- isLoadingMoreItems: false,
- loadingCounter: 0,
- maxVariableLimit: 0,
- pageInfo: {},
- };
- },
- apollo: {
- ciVariables: {
- query() {
- return this.queryData.ciVariables.query;
- },
- variables() {
- return {
- fullPath: this.fullPath || undefined,
- };
- },
- update(data) {
- return this.queryData.ciVariables.lookup(data)?.nodes || [];
- },
- result({ data }) {
- this.maxVariableLimit = this.queryData.ciVariables.lookup(data)?.limit || 0;
-
- this.pageInfo = this.queryData.ciVariables.lookup(data)?.pageInfo || this.pageInfo;
- this.hasNextPage = this.pageInfo?.hasNextPage || false;
-
- // Because graphQL has a limit of 100 items,
- // we batch load all the variables by making successive queries
- // to keep the same UX. As a safeguard, we make sure that we cannot go over
- // 20 consecutive API calls, which means 2000 variables loaded maximum.
- if (!this.hasNextPage) {
- this.isLoadingMoreItems = false;
- } else if (this.loadingCounter < 20) {
- this.hasNextPage = false;
- this.fetchMoreVariables();
- this.loadingCounter += 1;
- } else {
- createAlert({ message: this.$options.tooManyCallsError });
- reportMessageToSentry(this.componentName, this.$options.tooManyCallsError, {});
- }
- },
- error() {
- this.isLoadingMoreItems = false;
- this.hasNextPage = false;
- createAlert({ message: variableFetchErrorText });
- },
- watchLoading(flag) {
- if (!flag) {
- this.isInitialLoading = false;
- }
- },
- },
- environments: {
- query() {
- return this.queryData?.environments?.query || {};
- },
- skip() {
- return !this.queryData?.environments?.query;
- },
- variables() {
- return {
- fullPath: this.fullPath,
- };
- },
- update(data) {
- return mapEnvironmentNames(this.queryData.environments.lookup(data)?.nodes);
- },
- error() {
- createAlert({ message: environmentFetchErrorText });
- },
- },
- },
- computed: {
- isLoading() {
- return (
- (this.$apollo.queries.ciVariables.loading && this.isInitialLoading) ||
- this.$apollo.queries.environments.loading ||
- this.isLoadingMoreItems
- );
- },
- },
- methods: {
- addVariable(variable) {
- this.variableMutation(ADD_MUTATION_ACTION, variable);
- },
- deleteVariable(variable) {
- this.variableMutation(DELETE_MUTATION_ACTION, variable);
- },
- fetchMoreVariables() {
- this.isLoadingMoreItems = true;
-
- this.$apollo.queries.ciVariables.fetchMore({
- variables: {
- after: this.pageInfo.endCursor,
- },
- });
- },
- updateVariable(variable) {
- this.variableMutation(UPDATE_MUTATION_ACTION, variable);
- },
- async variableMutation(mutationAction, variable) {
- try {
- const currentMutation = this.mutationData[mutationAction];
-
- const { data } = await this.$apollo.mutate({
- mutation: currentMutation,
- variables: {
- endpoint: this.endpoint,
- fullPath: this.fullPath || undefined,
- id: this.id || undefined,
- variable,
- },
- });
-
- if (data.ciVariableMutation?.errors?.length) {
- const { errors } = data.ciVariableMutation;
- createAlert({ message: errors[0] });
- } else if (this.refetchAfterMutation) {
- // The writing to cache for admin variable is not working
- // because there is no ID in the cache at the top level.
- // We therefore need to manually refetch.
- this.$apollo.queries.ciVariables.refetch();
- }
- } catch (e) {
- createAlert({ message: genericMutationErrorText });
- }
- },
- },
- i18n: {
- tooManyCallsError: __('Maximum number of variables loaded (2000)'),
- },
-};
-</script>
-
-<template>
- <ci-variable-settings
- :are-scoped-variables-available="areScopedVariablesAvailable"
- :entity="entity"
- :hide-environment-scope="hideEnvironmentScope"
- :is-loading="isLoading"
- :variables="ciVariables"
- :max-variable-limit="maxVariableLimit"
- :environments="environments"
- @add-variable="addVariable"
- @delete-variable="deleteVariable"
- @update-variable="updateVariable"
- />
-</template>
diff --git a/app/assets/javascripts/ci_variable_list/components/ci_variable_table.vue b/app/assets/javascripts/ci_variable_list/components/ci_variable_table.vue
deleted file mode 100644
index 345a8def49d..00000000000
--- a/app/assets/javascripts/ci_variable_list/components/ci_variable_table.vue
+++ /dev/null
@@ -1,298 +0,0 @@
-<script>
-import {
- GlAlert,
- GlButton,
- GlLoadingIcon,
- GlModalDirective,
- GlTable,
- GlTooltipDirective,
-} from '@gitlab/ui';
-import { __, s__, sprintf } from '~/locale';
-import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
-import {
- ADD_CI_VARIABLE_MODAL_ID,
- DEFAULT_EXCEEDS_VARIABLE_LIMIT_TEXT,
- EXCEEDS_VARIABLE_LIMIT_TEXT,
- MAXIMUM_VARIABLE_LIMIT_REACHED,
- variableText,
-} from '../constants';
-import { convertEnvironmentScope } from '../utils';
-
-export default {
- modalId: ADD_CI_VARIABLE_MODAL_ID,
- fields: [
- {
- key: 'variableType',
- label: s__('CiVariables|Type'),
- thClass: 'gl-w-10p',
- },
- {
- key: 'key',
- label: s__('CiVariables|Key'),
- tdClass: 'text-plain',
- sortable: true,
- },
- {
- key: 'value',
- label: s__('CiVariables|Value'),
- thClass: 'gl-w-15p',
- },
- {
- key: 'options',
- label: s__('CiVariables|Options'),
- thClass: 'gl-w-10p',
- },
- {
- key: 'environmentScope',
- label: s__('CiVariables|Environments'),
- },
- {
- key: 'actions',
- label: '',
- tdClass: 'text-right',
- thClass: 'gl-w-5p',
- },
- ],
- components: {
- GlAlert,
- GlButton,
- GlLoadingIcon,
- GlTable,
- },
- directives: {
- GlModalDirective,
- GlTooltip: GlTooltipDirective,
- },
- mixins: [glFeatureFlagsMixin()],
- props: {
- entity: {
- type: String,
- required: false,
- default: '',
- },
- isLoading: {
- type: Boolean,
- required: true,
- },
- maxVariableLimit: {
- type: Number,
- required: true,
- },
- variables: {
- type: Array,
- required: true,
- },
- },
- data() {
- return {
- areValuesHidden: true,
- };
- },
- computed: {
- exceedsVariableLimit() {
- return this.maxVariableLimit > 0 && this.variables.length >= this.maxVariableLimit;
- },
- exceedsVariableLimitText() {
- if (this.exceedsVariableLimit && this.entity) {
- return sprintf(EXCEEDS_VARIABLE_LIMIT_TEXT, {
- entity: this.entity,
- currentVariableCount: this.variables.length,
- maxVariableLimit: this.maxVariableLimit,
- });
- }
-
- return DEFAULT_EXCEEDS_VARIABLE_LIMIT_TEXT;
- },
- showAlert() {
- return !this.isLoading && this.exceedsVariableLimit;
- },
- valuesButtonText() {
- return this.areValuesHidden ? __('Reveal values') : __('Hide values');
- },
- isTableEmpty() {
- return !this.variables || this.variables.length === 0;
- },
- fields() {
- return this.$options.fields;
- },
- variablesWithOptions() {
- return this.variables?.map((item, index) => ({
- ...item,
- options: this.getOptions(item),
- index,
- }));
- },
- },
- methods: {
- convertEnvironmentScopeValue(env) {
- return convertEnvironmentScope(env);
- },
- generateTypeText(item) {
- return variableText[item.variableType];
- },
- toggleHiddenState() {
- this.areValuesHidden = !this.areValuesHidden;
- },
- setSelectedVariable(index = -1) {
- this.$emit('set-selected-variable', this.variables[index] ?? null);
- },
- getOptions(item) {
- const options = [];
- if (item.protected) {
- options.push(s__('CiVariables|Protected'));
- }
- if (item.masked) {
- options.push(s__('CiVariables|Masked'));
- }
- if (!item.raw) {
- options.push(s__('CiVariables|Expanded'));
- }
- return options.join(', ');
- },
- },
- maximumVariableLimitReached: MAXIMUM_VARIABLE_LIMIT_REACHED,
-};
-</script>
-
-<template>
- <div class="ci-variable-table" data-testid="ci-variable-table">
- <gl-loading-icon v-if="isLoading" />
- <gl-alert
- v-if="showAlert"
- :dismissible="false"
- :title="$options.maximumVariableLimitReached"
- variant="info"
- >
- {{ exceedsVariableLimitText }}
- </gl-alert>
- <gl-table
- v-if="!isLoading"
- :fields="fields"
- :items="variablesWithOptions"
- tbody-tr-class="js-ci-variable-row"
- data-qa-selector="ci_variable_table_content"
- sort-by="key"
- sort-direction="asc"
- stacked="lg"
- table-class="text-secondary"
- fixed
- show-empty
- sort-icon-left
- no-sort-reset
- >
- <template #table-colgroup="scope">
- <col v-for="field in scope.fields" :key="field.key" :style="field.customStyle" />
- </template>
- <template #cell(variableType)="{ item }">
- {{ generateTypeText(item) }}
- </template>
- <template #cell(key)="{ item }">
- <div
- class="gl-display-flex gl-align-items-flex-start gl-justify-content-end gl-lg-justify-content-start gl-mr-n3"
- >
- <span
- :id="`ci-variable-key-${item.id}`"
- class="gl-display-inline-block gl-max-w-full gl-word-break-word"
- >{{ item.key }}</span
- >
- <gl-button
- v-gl-tooltip
- category="tertiary"
- icon="copy-to-clipboard"
- class="gl-my-n3 gl-ml-2"
- :title="__('Copy key')"
- :data-clipboard-text="item.key"
- :aria-label="__('Copy to clipboard')"
- />
- </div>
- </template>
- <template #cell(value)="{ item }">
- <div
- class="gl-display-flex gl-align-items-flex-start gl-justify-content-end gl-lg-justify-content-start gl-mr-n3"
- >
- <span v-if="areValuesHidden" data-testid="hiddenValue">*****</span>
- <span
- v-else
- :id="`ci-variable-value-${item.id}`"
- class="gl-display-inline-block gl-max-w-full gl-text-truncate"
- data-testid="revealedValue"
- >{{ item.value }}</span
- >
- <gl-button
- v-gl-tooltip
- category="tertiary"
- icon="copy-to-clipboard"
- class="gl-my-n3 gl-ml-2"
- :title="__('Copy value')"
- :data-clipboard-text="item.value"
- :aria-label="__('Copy to clipboard')"
- />
- </div>
- </template>
- <template #cell(options)="{ item }">
- <span data-testid="ci-variable-table-row-options">{{ item.options }}</span>
- </template>
- <template #cell(environmentScope)="{ item }">
- <div
- class="gl-display-flex gl-align-items-flex-start gl-justify-content-end gl-lg-justify-content-start gl-mr-n3"
- >
- <span
- :id="`ci-variable-env-${item.id}`"
- class="gl-display-inline-block gl-max-w-full gl-word-break-word"
- >{{ convertEnvironmentScopeValue(item.environmentScope) }}</span
- >
- <gl-button
- v-gl-tooltip
- category="tertiary"
- icon="copy-to-clipboard"
- class="gl-my-n3 gl-ml-2"
- :title="__('Copy environment')"
- :data-clipboard-text="convertEnvironmentScopeValue(item.environmentScope)"
- :aria-label="__('Copy to clipboard')"
- />
- </div>
- </template>
- <template #cell(actions)="{ item }">
- <gl-button
- v-gl-modal-directive="$options.modalId"
- icon="pencil"
- :aria-label="__('Edit')"
- data-qa-selector="edit_ci_variable_button"
- @click="setSelectedVariable(item.index)"
- />
- </template>
- <template #empty>
- <p class="gl-text-center gl-py-6 gl-text-black-normal gl-mb-0">
- {{ __('There are no variables yet.') }}
- </p>
- </template>
- </gl-table>
- <gl-alert
- v-if="showAlert"
- :dismissible="false"
- :title="$options.maximumVariableLimitReached"
- variant="info"
- >
- {{ exceedsVariableLimitText }}
- </gl-alert>
- <div class="ci-variable-actions gl-display-flex gl-mt-5">
- <gl-button
- v-gl-modal-directive="$options.modalId"
- class="gl-mr-3"
- data-qa-selector="add_ci_variable_button"
- variant="confirm"
- category="primary"
- :aria-label="__('Add')"
- :disabled="exceedsVariableLimit"
- @click="setSelectedVariable()"
- >{{ __('Add variable') }}</gl-button
- >
- <gl-button
- v-if="!isTableEmpty"
- data-qa-selector="reveal_ci_variable_value_button"
- @click="toggleHiddenState"
- >{{ valuesButtonText }}</gl-button
- >
- </div>
- </div>
-</template>
diff --git a/app/assets/javascripts/ci_variable_list/constants.js b/app/assets/javascripts/ci_variable_list/constants.js
deleted file mode 100644
index 828d0724d93..00000000000
--- a/app/assets/javascripts/ci_variable_list/constants.js
+++ /dev/null
@@ -1,106 +0,0 @@
-import { __, s__ } from '~/locale';
-
-export const ADD_CI_VARIABLE_MODAL_ID = 'add-ci-variable';
-
-// This const will be deprecated once we remove VueX from the section
-export const displayText = {
- variableText: __('Variable'),
- fileText: __('File'),
- allEnvironmentsText: __('All (default)'),
-};
-
-export const variableTypes = {
- envType: 'ENV_VAR',
- fileType: 'FILE',
-};
-
-// Once REST is removed, we won't need `types`
-export const types = {
- variableType: 'env_var',
- fileType: 'file',
-};
-
-export const allEnvironments = {
- type: '*',
- text: __('All (default)'),
-};
-
-// Once REST is removed, we won't need `types` key
-export const variableText = {
- [types.variableType]: __('Variable'),
- [types.fileType]: __('File'),
- [variableTypes.envType]: __('Variable'),
- [variableTypes.fileType]: __('File'),
-};
-
-export const variableOptions = [
- { value: variableTypes.envType, text: variableText[variableTypes.envType] },
- { value: variableTypes.fileType, text: variableText[variableTypes.fileType] },
-];
-
-export const defaultVariableState = {
- environmentScope: allEnvironments.type,
- key: '',
- masked: false,
- protected: false,
- raw: false,
- value: '',
- variableType: variableTypes.envType,
-};
-
-// eslint-disable-next-line @gitlab/require-i18n-strings
-export const groupString = 'Group';
-// eslint-disable-next-line @gitlab/require-i18n-strings
-export const instanceString = 'Instance';
-// eslint-disable-next-line @gitlab/require-i18n-strings
-export const projectString = 'Project';
-
-export const AWS_TIP_DISMISSED_COOKIE_NAME = 'ci_variable_list_constants_aws_tip_dismissed';
-export const AWS_TIP_MESSAGE = __(
- '%{deployLinkStart}Use a template to deploy to ECS%{deployLinkEnd}, or use a docker image to %{commandsLinkStart}run AWS commands in GitLab CI/CD%{commandsLinkEnd}.',
-);
-
-export const EVENT_LABEL = 'ci_variable_modal';
-export const EVENT_ACTION = 'validation_error';
-
-// AWS TOKEN CONSTANTS
-export const AWS_ACCESS_KEY_ID = 'AWS_ACCESS_KEY_ID';
-export const AWS_DEFAULT_REGION = 'AWS_DEFAULT_REGION';
-export const AWS_SECRET_ACCESS_KEY = 'AWS_SECRET_ACCESS_KEY';
-export const AWS_TOKEN_CONSTANTS = [AWS_ACCESS_KEY_ID, AWS_DEFAULT_REGION, AWS_SECRET_ACCESS_KEY];
-
-export const CONTAINS_VARIABLE_REFERENCE_MESSAGE = __(
- 'Unselect "Expand variable reference" if you want to use the variable value as a raw string.',
-);
-
-export const ENVIRONMENT_SCOPE_LINK_TITLE = __('Learn more');
-export const EXCEEDS_VARIABLE_LIMIT_TEXT = s__(
- 'CiVariables|This %{entity} has %{currentVariableCount} defined CI/CD variables. The maximum number of variables per %{entity} is %{maxVariableLimit}. To add new variables, you must reduce the number of defined variables.',
-);
-export const DEFAULT_EXCEEDS_VARIABLE_LIMIT_TEXT = s__(
- 'CiVariables|You have reached the maximum number of variables available. To add new variables, you must reduce the number of defined variables.',
-);
-export const MAXIMUM_VARIABLE_LIMIT_REACHED = s__(
- 'CiVariables|Maximum number of variables reached.',
-);
-
-export const ADD_VARIABLE_ACTION = 'ADD_VARIABLE';
-export const EDIT_VARIABLE_ACTION = 'EDIT_VARIABLE';
-export const VARIABLE_ACTIONS = [ADD_VARIABLE_ACTION, EDIT_VARIABLE_ACTION];
-
-export const GRAPHQL_PROJECT_TYPE = 'Project';
-export const GRAPHQL_GROUP_TYPE = 'Group';
-
-export const ADD_MUTATION_ACTION = 'add';
-export const UPDATE_MUTATION_ACTION = 'update';
-export const DELETE_MUTATION_ACTION = 'delete';
-
-export const EXPANDED_VARIABLES_NOTE = __(
- '%{codeStart}$%{codeEnd} will be treated as the start of a reference to another variable.',
-);
-
-export const environmentFetchErrorText = __(
- 'There was an error fetching the environments information.',
-);
-export const genericMutationErrorText = __('Something went wrong on our end. Please try again.');
-export const variableFetchErrorText = __('There was an error fetching the variables.');
diff --git a/app/assets/javascripts/ci_variable_list/graphql/fragments/ci_variable.fragment.graphql b/app/assets/javascripts/ci_variable_list/graphql/fragments/ci_variable.fragment.graphql
deleted file mode 100644
index a28ca4eebc9..00000000000
--- a/app/assets/javascripts/ci_variable_list/graphql/fragments/ci_variable.fragment.graphql
+++ /dev/null
@@ -1,7 +0,0 @@
-fragment BaseCiVariable on CiVariable {
- __typename
- id
- key
- value
- variableType
-}
diff --git a/app/assets/javascripts/ci_variable_list/graphql/mutations/admin_add_variable.mutation.graphql b/app/assets/javascripts/ci_variable_list/graphql/mutations/admin_add_variable.mutation.graphql
deleted file mode 100644
index 9208c34f154..00000000000
--- a/app/assets/javascripts/ci_variable_list/graphql/mutations/admin_add_variable.mutation.graphql
+++ /dev/null
@@ -1,16 +0,0 @@
-#import "~/ci_variable_list/graphql/fragments/ci_variable.fragment.graphql"
-
-mutation addAdminVariable($variable: CiVariable!, $endpoint: String!) {
- ciVariableMutation: addAdminVariable(variable: $variable, endpoint: $endpoint) @client {
- ciVariables {
- nodes {
- ...BaseCiVariable
- ... on CiInstanceVariable {
- protected
- masked
- }
- }
- }
- errors
- }
-}
diff --git a/app/assets/javascripts/ci_variable_list/graphql/mutations/admin_delete_variable.mutation.graphql b/app/assets/javascripts/ci_variable_list/graphql/mutations/admin_delete_variable.mutation.graphql
deleted file mode 100644
index a79b98f5e95..00000000000
--- a/app/assets/javascripts/ci_variable_list/graphql/mutations/admin_delete_variable.mutation.graphql
+++ /dev/null
@@ -1,16 +0,0 @@
-#import "~/ci_variable_list/graphql/fragments/ci_variable.fragment.graphql"
-
-mutation deleteAdminVariable($variable: CiVariable!, $endpoint: String!) {
- ciVariableMutation: deleteAdminVariable(variable: $variable, endpoint: $endpoint) @client {
- ciVariables {
- nodes {
- ...BaseCiVariable
- ... on CiInstanceVariable {
- protected
- masked
- }
- }
- }
- errors
- }
-}
diff --git a/app/assets/javascripts/ci_variable_list/graphql/mutations/admin_update_variable.mutation.graphql b/app/assets/javascripts/ci_variable_list/graphql/mutations/admin_update_variable.mutation.graphql
deleted file mode 100644
index ddea753bf90..00000000000
--- a/app/assets/javascripts/ci_variable_list/graphql/mutations/admin_update_variable.mutation.graphql
+++ /dev/null
@@ -1,16 +0,0 @@
-#import "~/ci_variable_list/graphql/fragments/ci_variable.fragment.graphql"
-
-mutation updateAdminVariable($variable: CiVariable!, $endpoint: String!) {
- ciVariableMutation: updateAdminVariable(variable: $variable, endpoint: $endpoint) @client {
- ciVariables {
- nodes {
- ...BaseCiVariable
- ... on CiInstanceVariable {
- protected
- masked
- }
- }
- }
- errors
- }
-}
diff --git a/app/assets/javascripts/ci_variable_list/graphql/mutations/client/add_project_environment.mutation.graphql b/app/assets/javascripts/ci_variable_list/graphql/mutations/client/add_project_environment.mutation.graphql
deleted file mode 100644
index 45109762e80..00000000000
--- a/app/assets/javascripts/ci_variable_list/graphql/mutations/client/add_project_environment.mutation.graphql
+++ /dev/null
@@ -1,3 +0,0 @@
-mutation addProjectEnvironment($environment: CiEnvironment, $fullPath: ID!) {
- addProjectEnvironment(environment: $environment, fullPath: $fullPath) @client
-}
diff --git a/app/assets/javascripts/ci_variable_list/graphql/mutations/group_add_variable.mutation.graphql b/app/assets/javascripts/ci_variable_list/graphql/mutations/group_add_variable.mutation.graphql
deleted file mode 100644
index 24388637672..00000000000
--- a/app/assets/javascripts/ci_variable_list/graphql/mutations/group_add_variable.mutation.graphql
+++ /dev/null
@@ -1,26 +0,0 @@
-#import "~/ci_variable_list/graphql/fragments/ci_variable.fragment.graphql"
-
-mutation addGroupVariable($variable: CiVariable!, $endpoint: String!, $fullPath: ID!, $id: ID!) {
- ciVariableMutation: addGroupVariable(
- variable: $variable
- endpoint: $endpoint
- fullPath: $fullPath
- id: $id
- ) @client {
- group {
- id
- ciVariables {
- nodes {
- ...BaseCiVariable
- ... on CiGroupVariable {
- environmentScope
- masked
- protected
- raw
- }
- }
- }
- }
- errors
- }
-}
diff --git a/app/assets/javascripts/ci_variable_list/graphql/mutations/group_delete_variable.mutation.graphql b/app/assets/javascripts/ci_variable_list/graphql/mutations/group_delete_variable.mutation.graphql
deleted file mode 100644
index f7c8e209ccd..00000000000
--- a/app/assets/javascripts/ci_variable_list/graphql/mutations/group_delete_variable.mutation.graphql
+++ /dev/null
@@ -1,26 +0,0 @@
-#import "~/ci_variable_list/graphql/fragments/ci_variable.fragment.graphql"
-
-mutation deleteGroupVariable($variable: CiVariable!, $endpoint: String!, $fullPath: ID!, $id: ID!) {
- ciVariableMutation: deleteGroupVariable(
- variable: $variable
- endpoint: $endpoint
- fullPath: $fullPath
- id: $id
- ) @client {
- group {
- id
- ciVariables {
- nodes {
- ...BaseCiVariable
- ... on CiGroupVariable {
- environmentScope
- masked
- protected
- raw
- }
- }
- }
- }
- errors
- }
-}
diff --git a/app/assets/javascripts/ci_variable_list/graphql/mutations/group_update_variable.mutation.graphql b/app/assets/javascripts/ci_variable_list/graphql/mutations/group_update_variable.mutation.graphql
deleted file mode 100644
index 757e61a5cd3..00000000000
--- a/app/assets/javascripts/ci_variable_list/graphql/mutations/group_update_variable.mutation.graphql
+++ /dev/null
@@ -1,26 +0,0 @@
-#import "~/ci_variable_list/graphql/fragments/ci_variable.fragment.graphql"
-
-mutation updateGroupVariable($variable: CiVariable!, $endpoint: String!, $fullPath: ID!, $id: ID!) {
- ciVariableMutation: updateGroupVariable(
- variable: $variable
- endpoint: $endpoint
- fullPath: $fullPath
- id: $id
- ) @client {
- group {
- id
- ciVariables {
- nodes {
- ...BaseCiVariable
- ... on CiGroupVariable {
- environmentScope
- masked
- protected
- raw
- }
- }
- }
- }
- errors
- }
-}
diff --git a/app/assets/javascripts/ci_variable_list/graphql/mutations/project_add_variable.mutation.graphql b/app/assets/javascripts/ci_variable_list/graphql/mutations/project_add_variable.mutation.graphql
deleted file mode 100644
index fa315084d86..00000000000
--- a/app/assets/javascripts/ci_variable_list/graphql/mutations/project_add_variable.mutation.graphql
+++ /dev/null
@@ -1,26 +0,0 @@
-#import "~/ci_variable_list/graphql/fragments/ci_variable.fragment.graphql"
-
-mutation addProjectVariable($variable: CiVariable!, $endpoint: String!, $fullPath: ID!, $id: ID!) {
- ciVariableMutation: addProjectVariable(
- variable: $variable
- endpoint: $endpoint
- fullPath: $fullPath
- id: $id
- ) @client {
- project {
- id
- ciVariables {
- nodes {
- ...BaseCiVariable
- ... on CiProjectVariable {
- environmentScope
- masked
- protected
- raw
- }
- }
- }
- }
- errors
- }
-}
diff --git a/app/assets/javascripts/ci_variable_list/graphql/mutations/project_delete_variable.mutation.graphql b/app/assets/javascripts/ci_variable_list/graphql/mutations/project_delete_variable.mutation.graphql
deleted file mode 100644
index c3358cc35b9..00000000000
--- a/app/assets/javascripts/ci_variable_list/graphql/mutations/project_delete_variable.mutation.graphql
+++ /dev/null
@@ -1,31 +0,0 @@
-#import "~/ci_variable_list/graphql/fragments/ci_variable.fragment.graphql"
-
-mutation deleteProjectVariable(
- $variable: CiVariable!
- $endpoint: String!
- $fullPath: ID!
- $id: ID!
-) {
- ciVariableMutation: deleteProjectVariable(
- variable: $variable
- endpoint: $endpoint
- fullPath: $fullPath
- id: $id
- ) @client {
- project {
- id
- ciVariables {
- nodes {
- ...BaseCiVariable
- ... on CiProjectVariable {
- environmentScope
- masked
- protected
- raw
- }
- }
- }
- }
- errors
- }
-}
diff --git a/app/assets/javascripts/ci_variable_list/graphql/mutations/project_update_variable.mutation.graphql b/app/assets/javascripts/ci_variable_list/graphql/mutations/project_update_variable.mutation.graphql
deleted file mode 100644
index fde92cef4cb..00000000000
--- a/app/assets/javascripts/ci_variable_list/graphql/mutations/project_update_variable.mutation.graphql
+++ /dev/null
@@ -1,31 +0,0 @@
-#import "~/ci_variable_list/graphql/fragments/ci_variable.fragment.graphql"
-
-mutation updateProjectVariable(
- $variable: CiVariable!
- $endpoint: String!
- $fullPath: ID!
- $id: ID!
-) {
- ciVariableMutation: updateProjectVariable(
- variable: $variable
- endpoint: $endpoint
- fullPath: $fullPath
- id: $id
- ) @client {
- project {
- id
- ciVariables {
- nodes {
- ...BaseCiVariable
- ... on CiProjectVariable {
- environmentScope
- masked
- protected
- raw
- }
- }
- }
- }
- errors
- }
-}
diff --git a/app/assets/javascripts/ci_variable_list/graphql/queries/group_variables.query.graphql b/app/assets/javascripts/ci_variable_list/graphql/queries/group_variables.query.graphql
deleted file mode 100644
index 900154cd24d..00000000000
--- a/app/assets/javascripts/ci_variable_list/graphql/queries/group_variables.query.graphql
+++ /dev/null
@@ -1,23 +0,0 @@
-#import "~/ci_variable_list/graphql/fragments/ci_variable.fragment.graphql"
-#import "~/graphql_shared/fragments/page_info.fragment.graphql"
-
-query getGroupVariables($after: String, $first: Int = 100, $fullPath: ID!) {
- group(fullPath: $fullPath) {
- id
- ciVariables(after: $after, first: $first) {
- limit
- pageInfo {
- ...PageInfo
- }
- nodes {
- ...BaseCiVariable
- ... on CiGroupVariable {
- environmentScope
- masked
- protected
- raw
- }
- }
- }
- }
-}
diff --git a/app/assets/javascripts/ci_variable_list/graphql/queries/project_environments.query.graphql b/app/assets/javascripts/ci_variable_list/graphql/queries/project_environments.query.graphql
deleted file mode 100644
index 921e0ca25b9..00000000000
--- a/app/assets/javascripts/ci_variable_list/graphql/queries/project_environments.query.graphql
+++ /dev/null
@@ -1,11 +0,0 @@
-query getProjectEnvironments($fullPath: ID!) {
- project(fullPath: $fullPath) {
- id
- environments {
- nodes {
- id
- name
- }
- }
- }
-}
diff --git a/app/assets/javascripts/ci_variable_list/graphql/queries/project_variables.query.graphql b/app/assets/javascripts/ci_variable_list/graphql/queries/project_variables.query.graphql
deleted file mode 100644
index ee75eba7547..00000000000
--- a/app/assets/javascripts/ci_variable_list/graphql/queries/project_variables.query.graphql
+++ /dev/null
@@ -1,21 +0,0 @@
-#import "~/ci_variable_list/graphql/fragments/ci_variable.fragment.graphql"
-#import "~/graphql_shared/fragments/page_info.fragment.graphql"
-
-query getProjectVariables($after: String, $first: Int = 100, $fullPath: ID!) {
- project(fullPath: $fullPath) {
- id
- ciVariables(after: $after, first: $first) {
- limit
- pageInfo {
- ...PageInfo
- }
- nodes {
- ...BaseCiVariable
- environmentScope
- masked
- protected
- raw
- }
- }
- }
-}
diff --git a/app/assets/javascripts/ci_variable_list/graphql/queries/variables.query.graphql b/app/assets/javascripts/ci_variable_list/graphql/queries/variables.query.graphql
deleted file mode 100644
index 9b255c3c182..00000000000
--- a/app/assets/javascripts/ci_variable_list/graphql/queries/variables.query.graphql
+++ /dev/null
@@ -1,18 +0,0 @@
-#import "~/ci_variable_list/graphql/fragments/ci_variable.fragment.graphql"
-#import "~/graphql_shared/fragments/page_info.fragment.graphql"
-
-query getVariables($after: String, $first: Int = 100) {
- ciVariables(after: $after, first: $first) {
- pageInfo {
- ...PageInfo
- }
- nodes {
- ...BaseCiVariable
- ... on CiInstanceVariable {
- masked
- protected
- raw
- }
- }
- }
-}
diff --git a/app/assets/javascripts/ci_variable_list/graphql/settings.js b/app/assets/javascripts/ci_variable_list/graphql/settings.js
deleted file mode 100644
index 02f6c226b0f..00000000000
--- a/app/assets/javascripts/ci_variable_list/graphql/settings.js
+++ /dev/null
@@ -1,242 +0,0 @@
-import axios from 'axios';
-import {
- convertObjectPropsToCamelCase,
- convertObjectPropsToSnakeCase,
-} from '../../lib/utils/common_utils';
-import { convertToGraphQLId, getIdFromGraphQLId } from '../../graphql_shared/utils';
-import {
- GRAPHQL_GROUP_TYPE,
- GRAPHQL_PROJECT_TYPE,
- groupString,
- instanceString,
- projectString,
-} from '../constants';
-import getProjectVariables from './queries/project_variables.query.graphql';
-import getGroupVariables from './queries/group_variables.query.graphql';
-import getAdminVariables from './queries/variables.query.graphql';
-
-const prepareVariableForApi = ({ variable, destroy = false }) => {
- return {
- ...convertObjectPropsToSnakeCase(variable),
- id: getIdFromGraphQLId(variable?.id),
- variable_type: variable.variableType.toLowerCase(),
- secret_value: variable.value,
- _destroy: destroy,
- };
-};
-
-const mapVariableTypes = (variables = [], kind) => {
- return variables.map((ciVar) => {
- return {
- __typename: `Ci${kind}Variable`,
- ...convertObjectPropsToCamelCase(ciVar),
- id: convertToGraphQLId('Ci::Variable', ciVar.id),
- variableType: ciVar.variable_type ? ciVar.variable_type.toUpperCase() : ciVar.variableType,
- };
- });
-};
-
-const prepareProjectGraphQLResponse = ({ data, id, errors = [] }) => {
- return {
- errors,
- project: {
- __typename: GRAPHQL_PROJECT_TYPE,
- id: convertToGraphQLId(GRAPHQL_PROJECT_TYPE, id),
- ciVariables: {
- __typename: `Ci${GRAPHQL_PROJECT_TYPE}VariableConnection`,
- pageInfo: {
- __typename: 'PageInfo',
- hasNextPage: false,
- hasPreviousPage: false,
- startCursor: '',
- endCursor: '',
- },
- nodes: mapVariableTypes(data.variables, projectString),
- },
- },
- };
-};
-
-const prepareGroupGraphQLResponse = ({ data, id, errors = [] }) => {
- return {
- errors,
- group: {
- __typename: GRAPHQL_GROUP_TYPE,
- id: convertToGraphQLId(GRAPHQL_GROUP_TYPE, id),
- ciVariables: {
- __typename: `Ci${GRAPHQL_GROUP_TYPE}VariableConnection`,
- pageInfo: {
- __typename: 'PageInfo',
- hasNextPage: false,
- hasPreviousPage: false,
- startCursor: '',
- endCursor: '',
- },
- nodes: mapVariableTypes(data.variables, groupString),
- },
- },
- };
-};
-
-const prepareAdminGraphQLResponse = ({ data, errors = [] }) => {
- return {
- errors,
- ciVariables: {
- __typename: `Ci${instanceString}VariableConnection`,
- pageInfo: {
- __typename: 'PageInfo',
- hasNextPage: false,
- hasPreviousPage: false,
- startCursor: '',
- endCursor: '',
- },
- nodes: mapVariableTypes(data.variables, instanceString),
- },
- };
-};
-
-async function callProjectEndpoint({ endpoint, fullPath, variable, id, cache, destroy = false }) {
- try {
- const { data } = await axios.patch(endpoint, {
- variables_attributes: [prepareVariableForApi({ variable, destroy })],
- });
-
- const graphqlData = prepareProjectGraphQLResponse({ data, id });
-
- cache.writeQuery({
- query: getProjectVariables,
- variables: {
- fullPath,
- after: null,
- },
- data: graphqlData,
- });
- return graphqlData;
- } catch (e) {
- return prepareProjectGraphQLResponse({
- data: cache.readQuery({ query: getProjectVariables, variables: { fullPath } }),
- id,
- errors: [...e.response.data],
- });
- }
-}
-
-const callGroupEndpoint = async ({ endpoint, fullPath, variable, id, cache, destroy = false }) => {
- try {
- const { data } = await axios.patch(endpoint, {
- variables_attributes: [prepareVariableForApi({ variable, destroy })],
- });
-
- const graphqlData = prepareGroupGraphQLResponse({ data, id });
-
- cache.writeQuery({
- query: getGroupVariables,
- data: graphqlData,
- });
-
- return graphqlData;
- } catch (e) {
- return prepareGroupGraphQLResponse({
- data: cache.readQuery({ query: getGroupVariables, variables: { fullPath } }),
- id,
- errors: [...e.response.data],
- });
- }
-};
-
-const callAdminEndpoint = async ({ endpoint, variable, cache, destroy = false }) => {
- try {
- const { data } = await axios.patch(endpoint, {
- variables_attributes: [prepareVariableForApi({ variable, destroy })],
- });
-
- const graphqlData = prepareAdminGraphQLResponse({ data });
-
- cache.writeQuery({
- query: getAdminVariables,
- data: graphqlData,
- });
-
- return graphqlData;
- } catch (e) {
- return prepareAdminGraphQLResponse({
- data: cache.readQuery({ query: getAdminVariables }),
- errors: [...e.response.data],
- });
- }
-};
-
-export const resolvers = {
- Mutation: {
- addProjectVariable: async (_, { endpoint, fullPath, variable, id }, { cache }) => {
- return callProjectEndpoint({ endpoint, fullPath, variable, id, cache });
- },
- updateProjectVariable: async (_, { endpoint, fullPath, variable, id }, { cache }) => {
- return callProjectEndpoint({ endpoint, fullPath, variable, id, cache });
- },
- deleteProjectVariable: async (_, { endpoint, fullPath, variable, id }, { cache }) => {
- return callProjectEndpoint({ endpoint, fullPath, variable, id, cache, destroy: true });
- },
- addGroupVariable: async (_, { endpoint, fullPath, variable, id }, { cache }) => {
- return callGroupEndpoint({ endpoint, fullPath, variable, id, cache });
- },
- updateGroupVariable: async (_, { endpoint, fullPath, variable, id }, { cache }) => {
- return callGroupEndpoint({ endpoint, fullPath, variable, id, cache });
- },
- deleteGroupVariable: async (_, { endpoint, fullPath, variable, id }, { cache }) => {
- return callGroupEndpoint({ endpoint, fullPath, variable, id, cache, destroy: true });
- },
- addAdminVariable: async (_, { endpoint, variable }, { cache }) => {
- return callAdminEndpoint({ endpoint, variable, cache });
- },
- updateAdminVariable: async (_, { endpoint, variable }, { cache }) => {
- return callAdminEndpoint({ endpoint, variable, cache });
- },
- deleteAdminVariable: async (_, { endpoint, variable }, { cache }) => {
- return callAdminEndpoint({ endpoint, variable, cache, destroy: true });
- },
- },
-};
-
-export const mergeVariables = (existing, incoming, { args }) => {
- if (!existing || !args?.after) {
- return incoming;
- }
-
- const { nodes, ...rest } = incoming;
- const result = rest;
- result.nodes = [...existing.nodes, ...nodes];
-
- return result;
-};
-
-export const cacheConfig = {
- cacheConfig: {
- typePolicies: {
- Query: {
- fields: {
- ciVariables: {
- keyArgs: false,
- merge: mergeVariables,
- },
- },
- },
- Project: {
- fields: {
- ciVariables: {
- keyArgs: ['fullPath', 'endpoint', 'id'],
- merge: mergeVariables,
- },
- },
- },
- Group: {
- fields: {
- ciVariables: {
- keyArgs: ['fullPath'],
- merge: mergeVariables,
- },
- },
- },
- },
- },
-};
diff --git a/app/assets/javascripts/ci_variable_list/index.js b/app/assets/javascripts/ci_variable_list/index.js
deleted file mode 100644
index 174a59aba42..00000000000
--- a/app/assets/javascripts/ci_variable_list/index.js
+++ /dev/null
@@ -1,83 +0,0 @@
-import Vue from 'vue';
-import VueApollo from 'vue-apollo';
-import createDefaultClient from '~/lib/graphql';
-import { parseBoolean } from '~/lib/utils/common_utils';
-import CiAdminVariables from './components/ci_admin_variables.vue';
-import CiGroupVariables from './components/ci_group_variables.vue';
-import CiProjectVariables from './components/ci_project_variables.vue';
-import { cacheConfig, resolvers } from './graphql/settings';
-
-const mountCiVariableListApp = (containerEl) => {
- const {
- awsLogoSvgPath,
- awsTipCommandsLink,
- awsTipDeployLink,
- awsTipLearnLink,
- containsVariableReferenceLink,
- endpoint,
- environmentScopeLink,
- groupId,
- groupPath,
- isGroup,
- isProject,
- maskedEnvironmentVariablesLink,
- maskableRegex,
- projectFullPath,
- projectId,
- protectedByDefault,
- protectedEnvironmentVariablesLink,
- } = containerEl.dataset;
-
- const parsedIsProject = parseBoolean(isProject);
- const parsedIsGroup = parseBoolean(isGroup);
- const isProtectedByDefault = parseBoolean(protectedByDefault);
-
- let component = CiAdminVariables;
-
- if (parsedIsGroup) {
- component = CiGroupVariables;
- } else if (parsedIsProject) {
- component = CiProjectVariables;
- }
-
- Vue.use(VueApollo);
-
- const apolloProvider = new VueApollo({
- defaultClient: createDefaultClient(resolvers, cacheConfig),
- });
-
- return new Vue({
- el: containerEl,
- apolloProvider,
- provide: {
- awsLogoSvgPath,
- awsTipCommandsLink,
- awsTipDeployLink,
- awsTipLearnLink,
- containsVariableReferenceLink,
- endpoint,
- environmentScopeLink,
- groupId,
- groupPath,
- isGroup: parsedIsGroup,
- isProject: parsedIsProject,
- isProtectedByDefault,
- maskedEnvironmentVariablesLink,
- maskableRegex,
- projectFullPath,
- projectId,
- protectedEnvironmentVariablesLink,
- },
- render(createElement) {
- return createElement(component);
- },
- });
-};
-
-export default (containerId = 'js-ci-variables') => {
- const el = document.getElementById(containerId);
-
- if (!el) return;
-
- mountCiVariableListApp(el);
-};
diff --git a/app/assets/javascripts/ci_variable_list/native_form_variable_list.js b/app/assets/javascripts/ci_variable_list/native_form_variable_list.js
deleted file mode 100644
index fdbefd8c313..00000000000
--- a/app/assets/javascripts/ci_variable_list/native_form_variable_list.js
+++ /dev/null
@@ -1,25 +0,0 @@
-import $ from 'jquery';
-import VariableList from './ci_variable_list';
-
-// Used for the variable list on scheduled pipeline edit page
-export default function setupNativeFormVariableList({ container, formField = 'variables' }) {
- const $container = $(container);
-
- const variableList = new VariableList({
- container: $container,
- formField,
- });
- variableList.init();
-
- // Clear out the names in the empty last row so it
- // doesn't get submitted and throw validation errors
- $container.closest('form').on('submit trigger-submit', () => {
- const $lastRow = $container.find('.js-row').last();
-
- const isTouched = variableList.checkIfRowTouched($lastRow);
- if (!isTouched) {
- $lastRow.find('input, textarea').attr('name', '');
- $lastRow.find('select').attr('name', '');
- }
- });
-}
diff --git a/app/assets/javascripts/ci_variable_list/utils.js b/app/assets/javascripts/ci_variable_list/utils.js
deleted file mode 100644
index eeca69274ce..00000000000
--- a/app/assets/javascripts/ci_variable_list/utils.js
+++ /dev/null
@@ -1,60 +0,0 @@
-import * as Sentry from '@sentry/browser';
-import { uniq } from 'lodash';
-import { allEnvironments } from './constants';
-
-/**
- * This function takes a list of variable, environments and
- * new environments added through the scope dropdown
- * and create a new Array that concatenate the environment list
- * with the environment scopes find in the variable list. This is
- * useful for variable settings so that we can render a list of all
- * environment scopes available based on the list of envs, the ones the user
- * added explictly and what is found under each variable.
- * @param {Array} variables
- * @param {Array} environments
- * @returns {Array} - Array of environments
- */
-
-export const createJoinedEnvironments = (
- variables = [],
- environments = [],
- newEnvironments = [],
-) => {
- const scopesFromVariables = variables.map((variable) => variable.environmentScope);
- return uniq([...environments, ...newEnvironments, ...scopesFromVariables]).sort();
-};
-
-/**
- * This function job is to convert the * wildcard to text when applicable
- * in the UI. It uses a constants to compare the incoming value to that
- * of the * and then apply the corresponding label if applicable. If there
- * is no scope, then we return the default value as well.
- * @param {String} scope
- * @returns {String} - Converted value if applicable
- */
-
-export const convertEnvironmentScope = (environmentScope = '') => {
- if (environmentScope === allEnvironments.type || !environmentScope) {
- return allEnvironments.text;
- }
-
- return environmentScope;
-};
-
-/**
- * Gives us an array of all the environments by name
- * @param {Array} nodes
- * @return {Array<String>} - Array of environments strings
- */
-export const mapEnvironmentNames = (nodes = []) => {
- return nodes.map((env) => env.name);
-};
-
-export const reportMessageToSentry = (component, message, context) => {
- Sentry.withScope((scope) => {
- // eslint-disable-next-line @gitlab/require-i18n-strings
- scope.setContext('Vue data', context);
- scope.setTag('component', component);
- Sentry.captureMessage(message);
- });
-};