2018-04-08 06:20:05 -04:00
|
|
|
<script>
|
2020-08-26 05:10:16 -04:00
|
|
|
/* eslint-disable vue/no-v-html */
|
2020-02-19 01:09:21 -05:00
|
|
|
import { escape, debounce } from 'lodash';
|
2018-04-08 06:20:05 -04:00
|
|
|
import { mapActions, mapState } from 'vuex';
|
2020-08-27 05:10:18 -04:00
|
|
|
import { GlLoadingIcon, GlFormInput, GlFormGroup, GlButton } from '@gitlab/ui';
|
2020-08-20 05:09:55 -04:00
|
|
|
import { deprecatedCreateFlash as createFlash } from '~/flash';
|
2018-04-08 06:20:05 -04:00
|
|
|
import { s__, sprintf } from '~/locale';
|
|
|
|
import createEmptyBadge from '../empty_badge';
|
|
|
|
import Badge from './badge.vue';
|
|
|
|
|
|
|
|
const badgePreviewDelayInMilliseconds = 1500;
|
|
|
|
|
|
|
|
export default {
|
|
|
|
name: 'BadgeForm',
|
|
|
|
components: {
|
|
|
|
Badge,
|
2020-08-27 05:10:18 -04:00
|
|
|
GlButton,
|
2018-11-07 05:06:15 -05:00
|
|
|
GlLoadingIcon,
|
2019-11-22 04:06:20 -05:00
|
|
|
GlFormInput,
|
|
|
|
GlFormGroup,
|
2018-04-08 06:20:05 -04:00
|
|
|
},
|
|
|
|
props: {
|
|
|
|
isEditing: {
|
|
|
|
type: Boolean,
|
|
|
|
required: true,
|
|
|
|
},
|
|
|
|
},
|
2018-09-03 09:16:23 -04:00
|
|
|
data() {
|
|
|
|
return {
|
|
|
|
wasValidated: false,
|
|
|
|
};
|
|
|
|
},
|
2018-04-08 06:20:05 -04:00
|
|
|
computed: {
|
|
|
|
...mapState([
|
|
|
|
'badgeInAddForm',
|
|
|
|
'badgeInEditForm',
|
|
|
|
'docsUrl',
|
|
|
|
'isRendering',
|
|
|
|
'isSaving',
|
|
|
|
'renderedBadge',
|
|
|
|
]),
|
|
|
|
badge() {
|
|
|
|
if (this.isEditing) {
|
|
|
|
return this.badgeInEditForm;
|
|
|
|
}
|
|
|
|
|
|
|
|
return this.badgeInAddForm;
|
|
|
|
},
|
|
|
|
helpText() {
|
|
|
|
const placeholders = ['project_path', 'project_id', 'default_branch', 'commit_sha']
|
2020-12-23 16:10:24 -05:00
|
|
|
.map((placeholder) => `<code>%{${placeholder}}</code>`)
|
2018-04-08 06:20:05 -04:00
|
|
|
.join(', ');
|
|
|
|
return sprintf(
|
2020-12-21 22:10:23 -05:00
|
|
|
s__('Badges|Supported %{docsLinkStart}variables%{docsLinkEnd}: %{placeholders}'),
|
2018-04-08 06:20:05 -04:00
|
|
|
{
|
|
|
|
docsLinkEnd: '</a>',
|
2020-02-19 01:09:21 -05:00
|
|
|
docsLinkStart: `<a href="${escape(this.docsUrl)}">`,
|
2018-04-08 06:20:05 -04:00
|
|
|
placeholders,
|
|
|
|
},
|
|
|
|
false,
|
|
|
|
);
|
|
|
|
},
|
|
|
|
renderedImageUrl() {
|
|
|
|
return this.renderedBadge ? this.renderedBadge.renderedImageUrl : '';
|
|
|
|
},
|
|
|
|
renderedLinkUrl() {
|
|
|
|
return this.renderedBadge ? this.renderedBadge.renderedLinkUrl : '';
|
|
|
|
},
|
2019-11-22 04:06:20 -05:00
|
|
|
name: {
|
|
|
|
get() {
|
|
|
|
return this.badge ? this.badge.name : '';
|
|
|
|
},
|
|
|
|
set(name) {
|
|
|
|
const badge = this.badge || createEmptyBadge();
|
|
|
|
this.updateBadgeInForm({
|
|
|
|
...badge,
|
|
|
|
name,
|
|
|
|
});
|
|
|
|
},
|
|
|
|
},
|
2018-04-08 06:20:05 -04:00
|
|
|
imageUrl: {
|
|
|
|
get() {
|
|
|
|
return this.badge ? this.badge.imageUrl : '';
|
|
|
|
},
|
|
|
|
set(imageUrl) {
|
|
|
|
const badge = this.badge || createEmptyBadge();
|
|
|
|
this.updateBadgeInForm({
|
|
|
|
...badge,
|
|
|
|
imageUrl,
|
|
|
|
});
|
|
|
|
},
|
|
|
|
},
|
|
|
|
linkUrl: {
|
|
|
|
get() {
|
|
|
|
return this.badge ? this.badge.linkUrl : '';
|
|
|
|
},
|
|
|
|
set(linkUrl) {
|
|
|
|
const badge = this.badge || createEmptyBadge();
|
|
|
|
this.updateBadgeInForm({
|
|
|
|
...badge,
|
|
|
|
linkUrl,
|
|
|
|
});
|
|
|
|
},
|
|
|
|
},
|
2018-09-03 09:16:23 -04:00
|
|
|
badgeImageUrlExample() {
|
|
|
|
const exampleUrl =
|
2019-02-20 09:26:13 -05:00
|
|
|
'https://example.gitlab.com/%{project_path}/badges/%{default_branch}/pipeline.svg';
|
2020-12-21 22:10:23 -05:00
|
|
|
return sprintf(s__('Badges|Example: %{exampleUrl}'), {
|
2018-09-03 09:16:23 -04:00
|
|
|
exampleUrl,
|
|
|
|
});
|
|
|
|
},
|
|
|
|
badgeLinkUrlExample() {
|
|
|
|
const exampleUrl = 'https://example.gitlab.com/%{project_path}';
|
2020-12-21 22:10:23 -05:00
|
|
|
return sprintf(s__('Badges|Example: %{exampleUrl}'), {
|
2018-09-03 09:16:23 -04:00
|
|
|
exampleUrl,
|
|
|
|
});
|
2018-04-08 06:20:05 -04:00
|
|
|
},
|
|
|
|
},
|
|
|
|
methods: {
|
|
|
|
...mapActions(['addBadge', 'renderBadge', 'saveBadge', 'stopEditing', 'updateBadgeInForm']),
|
2020-02-19 01:09:21 -05:00
|
|
|
debouncedPreview: debounce(function preview() {
|
2018-04-08 06:20:05 -04:00
|
|
|
this.renderBadge();
|
|
|
|
}, badgePreviewDelayInMilliseconds),
|
|
|
|
onCancel() {
|
|
|
|
this.stopEditing();
|
|
|
|
},
|
|
|
|
onSubmit() {
|
2018-09-03 09:16:23 -04:00
|
|
|
const form = this.$el;
|
|
|
|
if (!form.checkValidity()) {
|
|
|
|
this.wasValidated = true;
|
2018-04-08 06:20:05 -04:00
|
|
|
return Promise.resolve();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (this.isEditing) {
|
|
|
|
return this.saveBadge()
|
|
|
|
.then(() => {
|
2020-12-21 22:10:23 -05:00
|
|
|
createFlash(s__('Badges|Badge saved.'), 'notice');
|
2018-09-03 09:16:23 -04:00
|
|
|
this.wasValidated = false;
|
2018-04-08 06:20:05 -04:00
|
|
|
})
|
2020-12-23 16:10:24 -05:00
|
|
|
.catch((error) => {
|
2018-04-08 06:20:05 -04:00
|
|
|
createFlash(
|
|
|
|
s__('Badges|Saving the badge failed, please check the entered URLs and try again.'),
|
|
|
|
);
|
|
|
|
throw error;
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
return this.addBadge()
|
|
|
|
.then(() => {
|
2020-12-21 22:10:23 -05:00
|
|
|
createFlash(s__('Badges|New badge added.'), 'notice');
|
2018-09-03 09:16:23 -04:00
|
|
|
this.wasValidated = false;
|
2018-04-08 06:20:05 -04:00
|
|
|
})
|
2020-12-23 16:10:24 -05:00
|
|
|
.catch((error) => {
|
2018-04-08 06:20:05 -04:00
|
|
|
createFlash(
|
|
|
|
s__('Badges|Adding the badge failed, please check the entered URLs and try again.'),
|
|
|
|
);
|
|
|
|
throw error;
|
|
|
|
});
|
|
|
|
},
|
|
|
|
},
|
|
|
|
};
|
|
|
|
</script>
|
|
|
|
|
|
|
|
<template>
|
|
|
|
<form
|
2018-09-03 09:16:23 -04:00
|
|
|
:class="{ 'was-validated': wasValidated }"
|
2020-06-26 02:09:03 -04:00
|
|
|
class="gl-mt-3 gl-mb-3 needs-validation"
|
2018-09-03 09:16:23 -04:00
|
|
|
novalidate
|
2018-04-08 06:20:05 -04:00
|
|
|
@submit.prevent.stop="onSubmit"
|
|
|
|
>
|
2019-11-22 04:06:20 -05:00
|
|
|
<gl-form-group :label="s__('Badges|Name')" label-for="badge-name">
|
|
|
|
<gl-form-input id="badge-name" v-model="name" />
|
|
|
|
</gl-form-group>
|
|
|
|
|
2018-04-08 06:20:05 -04:00
|
|
|
<div class="form-group">
|
2018-11-16 15:07:38 -05:00
|
|
|
<label for="badge-link-url" class="label-bold">{{ s__('Badges|Link') }}</label>
|
2018-09-03 09:16:23 -04:00
|
|
|
<p v-html="helpText"></p>
|
2018-04-08 06:20:05 -04:00
|
|
|
<input
|
|
|
|
id="badge-link-url"
|
|
|
|
v-model="linkUrl"
|
2018-09-03 09:16:23 -04:00
|
|
|
type="URL"
|
2018-06-11 05:49:47 -04:00
|
|
|
class="form-control"
|
2018-09-03 09:16:23 -04:00
|
|
|
required
|
2018-04-08 06:20:05 -04:00
|
|
|
@input="debouncedPreview"
|
|
|
|
/>
|
2020-12-21 22:10:23 -05:00
|
|
|
<div class="invalid-feedback">{{ s__('Badges|Enter a valid URL') }}</div>
|
2020-08-11 17:10:09 -04:00
|
|
|
<span class="form-text text-muted">{{ badgeLinkUrlExample }}</span>
|
2018-04-08 06:20:05 -04:00
|
|
|
</div>
|
|
|
|
|
|
|
|
<div class="form-group">
|
2018-11-16 15:07:38 -05:00
|
|
|
<label for="badge-image-url" class="label-bold">{{ s__('Badges|Badge image URL') }}</label>
|
2018-09-03 09:16:23 -04:00
|
|
|
<p v-html="helpText"></p>
|
2018-04-08 06:20:05 -04:00
|
|
|
<input
|
|
|
|
id="badge-image-url"
|
|
|
|
v-model="imageUrl"
|
2018-09-03 09:16:23 -04:00
|
|
|
type="URL"
|
2018-06-11 05:49:47 -04:00
|
|
|
class="form-control"
|
2018-09-03 09:16:23 -04:00
|
|
|
required
|
2018-04-08 06:20:05 -04:00
|
|
|
@input="debouncedPreview"
|
|
|
|
/>
|
2020-12-21 22:10:23 -05:00
|
|
|
<div class="invalid-feedback">{{ s__('Badges|Enter a valid URL') }}</div>
|
2020-08-11 17:10:09 -04:00
|
|
|
<span class="form-text text-muted">{{ badgeImageUrlExample }}</span>
|
2018-04-08 06:20:05 -04:00
|
|
|
</div>
|
|
|
|
|
|
|
|
<div class="form-group">
|
|
|
|
<label for="badge-preview">{{ s__('Badges|Badge image preview') }}</label>
|
|
|
|
<badge
|
|
|
|
v-show="renderedBadge && !isRendering"
|
2018-06-11 05:49:47 -04:00
|
|
|
id="badge-preview"
|
2018-04-08 06:20:05 -04:00
|
|
|
:image-url="renderedImageUrl"
|
|
|
|
:link-url="renderedLinkUrl"
|
|
|
|
/>
|
2020-08-11 17:10:09 -04:00
|
|
|
<p v-show="isRendering">
|
|
|
|
<gl-loading-icon :inline="true" />
|
|
|
|
</p>
|
2018-11-16 15:07:38 -05:00
|
|
|
<p v-show="!renderedBadge && !isRendering" class="disabled-content">
|
|
|
|
{{ s__('Badges|No image to preview') }}
|
2018-04-08 06:20:05 -04:00
|
|
|
</p>
|
|
|
|
</div>
|
|
|
|
|
2020-09-23 17:09:28 -04:00
|
|
|
<div v-if="isEditing" class="row-content-block">
|
2020-08-27 05:10:18 -04:00
|
|
|
<gl-button class="btn-cancel gl-mr-4" data-testid="cancelEditing" @click="onCancel">
|
2020-08-11 17:10:09 -04:00
|
|
|
{{ __('Cancel') }}
|
2020-08-27 05:10:18 -04:00
|
|
|
</gl-button>
|
|
|
|
<gl-button
|
2018-04-08 06:20:05 -04:00
|
|
|
:loading="isSaving"
|
2018-06-11 05:49:47 -04:00
|
|
|
type="submit"
|
2020-08-27 05:10:18 -04:00
|
|
|
variant="success"
|
|
|
|
category="primary"
|
|
|
|
data-testid="saveEditing"
|
|
|
|
>
|
|
|
|
{{ s__('Badges|Save changes') }}
|
|
|
|
</gl-button>
|
2018-04-08 06:20:05 -04:00
|
|
|
</div>
|
2020-09-23 17:09:28 -04:00
|
|
|
<div v-else class="form-group">
|
2020-08-27 05:10:18 -04:00
|
|
|
<gl-button :loading="isSaving" type="submit" variant="success" category="primary">
|
|
|
|
{{ s__('Badges|Add badge') }}
|
|
|
|
</gl-button>
|
2018-09-03 09:16:23 -04:00
|
|
|
</div>
|
2018-04-08 06:20:05 -04:00
|
|
|
</form>
|
|
|
|
</template>
|