gitlab-org--gitlab-foss/app/assets/javascripts/jobs/components/manual_variables_form.vue

194 lines
5.3 KiB
Vue

<script>
import {
GlFormInputGroup,
GlInputGroupText,
GlFormInput,
GlButton,
GlLink,
GlSprintf,
} from '@gitlab/ui';
import { uniqueId } from 'lodash';
import { mapActions } from 'vuex';
import { helpPagePath } from '~/helpers/help_page_helper';
import { s__ } from '~/locale';
export default {
name: 'ManualVariablesForm',
components: {
GlFormInputGroup,
GlInputGroupText,
GlFormInput,
GlButton,
GlLink,
GlSprintf,
},
props: {
action: {
type: Object,
required: false,
default: null,
validator(value) {
return (
value === null ||
(Object.prototype.hasOwnProperty.call(value, 'path') &&
Object.prototype.hasOwnProperty.call(value, 'method') &&
Object.prototype.hasOwnProperty.call(value, 'button_title'))
);
},
},
},
inputTypes: {
key: 'key',
value: 'value',
},
i18n: {
header: s__('CiVariables|Variables'),
keyLabel: s__('CiVariables|Key'),
valueLabel: s__('CiVariables|Value'),
keyPlaceholder: s__('CiVariables|Input variable key'),
valuePlaceholder: s__('CiVariables|Input variable value'),
formHelpText: s__(
'CiVariables|Specify variable values to be used in this run. The values specified in %{linkStart}CI/CD settings%{linkEnd} will be used as default',
),
},
data() {
return {
variables: [
{
key: '',
secretValue: '',
id: uniqueId(),
},
],
triggerBtnDisabled: false,
};
},
computed: {
variableSettings() {
return helpPagePath('ci/variables/index', { anchor: 'add-a-cicd-variable-to-a-project' });
},
preparedVariables() {
// we need to ensure no empty variables are passed to the API
// and secretValue should be snake_case when passed to the API
return this.variables
.filter((variable) => variable.key !== '')
.map(({ key, secretValue }) => ({ key, secret_value: secretValue }));
},
},
methods: {
...mapActions(['triggerManualJob']),
canRemove(index) {
return index < this.variables.length - 1;
},
addEmptyVariable() {
const lastVar = this.variables[this.variables.length - 1];
if (lastVar.key === '') {
return;
}
this.variables.push({
key: '',
secret_value: '',
id: uniqueId(),
});
},
deleteVariable(id) {
this.variables.splice(
this.variables.findIndex((el) => el.id === id),
1,
);
},
trigger() {
this.triggerBtnDisabled = true;
this.triggerManualJob(this.preparedVariables);
},
},
};
</script>
<template>
<div class="row gl-justify-content-center">
<div class="col-10" data-testid="manual-vars-form">
<label>{{ $options.i18n.header }}</label>
<div
v-for="(variable, index) in variables"
:key="variable.id"
class="gl-display-flex gl-align-items-center gl-mb-4"
data-testid="ci-variable-row"
>
<gl-form-input-group class="gl-mr-4 gl-flex-grow-1">
<template #prepend>
<gl-input-group-text>
{{ $options.i18n.keyLabel }}
</gl-input-group-text>
</template>
<gl-form-input
:ref="`${$options.inputTypes.key}-${variable.id}`"
v-model="variable.key"
:placeholder="$options.i18n.keyPlaceholder"
data-testid="ci-variable-key"
@change="addEmptyVariable"
/>
</gl-form-input-group>
<gl-form-input-group class="gl-flex-grow-2">
<template #prepend>
<gl-input-group-text>
{{ $options.i18n.valueLabel }}
</gl-input-group-text>
</template>
<gl-form-input
:ref="`${$options.inputTypes.value}-${variable.id}`"
v-model="variable.secretValue"
:placeholder="$options.i18n.valuePlaceholder"
data-testid="ci-variable-value"
/>
</gl-form-input-group>
<!-- delete variable button placeholder to not break flex layout -->
<div
v-if="!canRemove(index)"
class="gl-w-7 gl-mr-3"
data-testid="delete-variable-btn-placeholder"
></div>
<gl-button
v-if="canRemove(index)"
class="gl-flex-grow-0 gl-flex-basis-0"
category="tertiary"
variant="danger"
icon="clear"
:aria-label="__('Delete variable')"
data-testid="delete-variable-btn"
@click="deleteVariable(variable.id)"
/>
</div>
<div class="gl-text-center gl-mt-5">
<gl-sprintf :message="$options.i18n.formHelpText">
<template #link="{ content }">
<gl-link :href="variableSettings" target="_blank">
{{ content }}
</gl-link>
</template>
</gl-sprintf>
</div>
<div class="gl-display-flex gl-justify-content-center gl-mt-5">
<gl-button
class="gl-mt-5"
variant="info"
category="primary"
:aria-label="__('Trigger manual job')"
:disabled="triggerBtnDisabled"
data-testid="trigger-manual-job-btn"
@click="trigger"
>
{{ action.button_title }}
</gl-button>
</div>
</div>
</div>
</template>