Move badge settings to general settings
This commit is contained in:
parent
c0625e5de1
commit
743add978a
24 changed files with 259 additions and 189 deletions
|
@ -23,6 +23,11 @@ export default {
|
||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
wasValidated: false,
|
||||||
|
};
|
||||||
|
},
|
||||||
computed: {
|
computed: {
|
||||||
...mapState([
|
...mapState([
|
||||||
'badgeInAddForm',
|
'badgeInAddForm',
|
||||||
|
@ -39,16 +44,6 @@ export default {
|
||||||
|
|
||||||
return this.badgeInAddForm;
|
return this.badgeInAddForm;
|
||||||
},
|
},
|
||||||
canSubmit() {
|
|
||||||
return (
|
|
||||||
this.badge !== null &&
|
|
||||||
this.badge.imageUrl &&
|
|
||||||
this.badge.imageUrl.trim() !== '' &&
|
|
||||||
this.badge.linkUrl &&
|
|
||||||
this.badge.linkUrl.trim() !== '' &&
|
|
||||||
!this.isSaving
|
|
||||||
);
|
|
||||||
},
|
|
||||||
helpText() {
|
helpText() {
|
||||||
const placeholders = ['project_path', 'project_id', 'default_branch', 'commit_sha']
|
const placeholders = ['project_path', 'project_id', 'default_branch', 'commit_sha']
|
||||||
.map(placeholder => `<code>%{${placeholder}}</code>`)
|
.map(placeholder => `<code>%{${placeholder}}</code>`)
|
||||||
|
@ -93,11 +88,18 @@ export default {
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
submitButtonLabel() {
|
badgeImageUrlExample() {
|
||||||
if (this.isEditing) {
|
const exampleUrl =
|
||||||
return s__('Badges|Save changes');
|
'https://example.gitlab.com/%{project_path}/badges/%{default_branch}/badge.svg';
|
||||||
}
|
return sprintf(s__('Badges|e.g. %{exampleUrl}'), {
|
||||||
return s__('Badges|Add badge');
|
exampleUrl,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
badgeLinkUrlExample() {
|
||||||
|
const exampleUrl = 'https://example.gitlab.com/%{project_path}';
|
||||||
|
return sprintf(s__('Badges|e.g. %{exampleUrl}'), {
|
||||||
|
exampleUrl,
|
||||||
|
});
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
@ -109,7 +111,9 @@ export default {
|
||||||
this.stopEditing();
|
this.stopEditing();
|
||||||
},
|
},
|
||||||
onSubmit() {
|
onSubmit() {
|
||||||
if (!this.canSubmit) {
|
const form = this.$el;
|
||||||
|
if (!form.checkValidity()) {
|
||||||
|
this.wasValidated = true;
|
||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -117,6 +121,7 @@ export default {
|
||||||
return this.saveBadge()
|
return this.saveBadge()
|
||||||
.then(() => {
|
.then(() => {
|
||||||
createFlash(s__('Badges|The badge was saved.'), 'notice');
|
createFlash(s__('Badges|The badge was saved.'), 'notice');
|
||||||
|
this.wasValidated = false;
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
createFlash(
|
createFlash(
|
||||||
|
@ -129,6 +134,7 @@ export default {
|
||||||
return this.addBadge()
|
return this.addBadge()
|
||||||
.then(() => {
|
.then(() => {
|
||||||
createFlash(s__('Badges|A new badge was added.'), 'notice');
|
createFlash(s__('Badges|A new badge was added.'), 'notice');
|
||||||
|
this.wasValidated = false;
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
createFlash(
|
createFlash(
|
||||||
|
@ -138,47 +144,58 @@ export default {
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
badgeImageUrlPlaceholder:
|
|
||||||
'https://example.gitlab.com/%{project_path}/badges/%{default_branch}/<badge>.svg',
|
|
||||||
badgeLinkUrlPlaceholder: 'https://example.gitlab.com/%{project_path}',
|
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<form
|
<form
|
||||||
class="prepend-top-default append-bottom-default"
|
:class="{ 'was-validated': wasValidated }"
|
||||||
|
class="prepend-top-default append-bottom-default needs-validation"
|
||||||
|
novalidate
|
||||||
@submit.prevent.stop="onSubmit"
|
@submit.prevent.stop="onSubmit"
|
||||||
>
|
>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="badge-link-url">{{ s__('Badges|Link') }}</label>
|
<label
|
||||||
|
for="badge-link-url"
|
||||||
|
class="label-bold"
|
||||||
|
>{{ s__('Badges|Link') }}</label>
|
||||||
|
<p v-html="helpText"></p>
|
||||||
<input
|
<input
|
||||||
id="badge-link-url"
|
id="badge-link-url"
|
||||||
v-model="linkUrl"
|
v-model="linkUrl"
|
||||||
:placeholder="$options.badgeLinkUrlPlaceholder"
|
type="URL"
|
||||||
type="text"
|
|
||||||
class="form-control"
|
class="form-control"
|
||||||
|
required
|
||||||
@input="debouncedPreview"
|
@input="debouncedPreview"
|
||||||
/>
|
/>
|
||||||
<span
|
<div class="invalid-feedback">
|
||||||
class="form-text text-muted"
|
{{ s__('Badges|Please fill in a valid URL') }}
|
||||||
v-html="helpText"
|
</div>
|
||||||
></span>
|
<span class="form-text text-muted">
|
||||||
|
{{ badgeLinkUrlExample }}
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="badge-image-url">{{ s__('Badges|Badge image URL') }}</label>
|
<label
|
||||||
|
for="badge-image-url"
|
||||||
|
class="label-bold"
|
||||||
|
>{{ s__('Badges|Badge image URL') }}</label>
|
||||||
|
<p v-html="helpText"></p>
|
||||||
<input
|
<input
|
||||||
id="badge-image-url"
|
id="badge-image-url"
|
||||||
v-model="imageUrl"
|
v-model="imageUrl"
|
||||||
:placeholder="$options.badgeImageUrlPlaceholder"
|
type="URL"
|
||||||
type="text"
|
|
||||||
class="form-control"
|
class="form-control"
|
||||||
|
required
|
||||||
@input="debouncedPreview"
|
@input="debouncedPreview"
|
||||||
/>
|
/>
|
||||||
<span
|
<div class="invalid-feedback">
|
||||||
class="form-text text-muted"
|
{{ s__('Badges|Please fill in a valid URL') }}
|
||||||
v-html="helpText"
|
</div>
|
||||||
></span>
|
<span class="form-text text-muted">
|
||||||
|
{{ badgeImageUrlExample }}
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
|
@ -200,20 +217,32 @@ export default {
|
||||||
>{{ s__('Badges|No image to preview') }}</p>
|
>{{ s__('Badges|No image to preview') }}</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="row-content-block">
|
<div
|
||||||
|
v-if="isEditing"
|
||||||
|
class="row-content-block"
|
||||||
|
>
|
||||||
<loading-button
|
<loading-button
|
||||||
:disabled="!canSubmit"
|
|
||||||
:loading="isSaving"
|
:loading="isSaving"
|
||||||
:label="submitButtonLabel"
|
:label="s__('Badges|Save changes')"
|
||||||
type="submit"
|
type="submit"
|
||||||
container-class="btn btn-success"
|
container-class="btn btn-success"
|
||||||
/>
|
/>
|
||||||
<button
|
<button
|
||||||
v-if="isEditing"
|
|
||||||
class="btn btn-cancel"
|
class="btn btn-cancel"
|
||||||
type="button"
|
type="button"
|
||||||
@click="onCancel"
|
@click="onCancel"
|
||||||
>{{ __('Cancel') }}</button>
|
>{{ __('Cancel') }}</button>
|
||||||
</div>
|
</div>
|
||||||
|
<div
|
||||||
|
v-else
|
||||||
|
class="form-group"
|
||||||
|
>
|
||||||
|
<loading-button
|
||||||
|
:loading="isSaving"
|
||||||
|
:label="s__('Badges|Add badge')"
|
||||||
|
type="submit"
|
||||||
|
container-class="btn btn-success"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -28,7 +28,7 @@ export default {
|
||||||
{{ s__('Badges|Your badges') }}
|
{{ s__('Badges|Your badges') }}
|
||||||
<span
|
<span
|
||||||
v-show="!isLoading"
|
v-show="!isLoading"
|
||||||
class="badge"
|
class="badge badge-pill"
|
||||||
>{{ badges.length }}</span>
|
>{{ badges.length }}</span>
|
||||||
</div>
|
</div>
|
||||||
<loading-icon
|
<loading-icon
|
||||||
|
|
|
@ -43,13 +43,13 @@ export default {
|
||||||
<badge
|
<badge
|
||||||
:image-url="badge.renderedImageUrl"
|
:image-url="badge.renderedImageUrl"
|
||||||
:link-url="badge.renderedLinkUrl"
|
:link-url="badge.renderedLinkUrl"
|
||||||
class="table-section section-30"
|
class="table-section section-40"
|
||||||
/>
|
/>
|
||||||
<span class="table-section section-50 str-truncated">{{ badge.linkUrl }}</span>
|
<span class="table-section section-30 str-truncated">{{ badge.linkUrl }}</span>
|
||||||
<div class="table-section section-10">
|
<div class="table-section section-15">
|
||||||
<span class="badge">{{ badgeKindText }}</span>
|
<span class="badge badge-pill">{{ badgeKindText }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="table-section section-10 table-button-footer">
|
<div class="table-section section-15 table-button-footer">
|
||||||
<div
|
<div
|
||||||
v-if="canEditBadge"
|
v-if="canEditBadge"
|
||||||
class="table-action-buttons">
|
class="table-action-buttons">
|
||||||
|
|
|
@ -2,14 +2,13 @@ import groupAvatar from '~/group_avatar';
|
||||||
import TransferDropdown from '~/groups/transfer_dropdown';
|
import TransferDropdown from '~/groups/transfer_dropdown';
|
||||||
import initConfirmDangerModal from '~/confirm_danger_modal';
|
import initConfirmDangerModal from '~/confirm_danger_modal';
|
||||||
import initSettingsPanels from '~/settings_panels';
|
import initSettingsPanels from '~/settings_panels';
|
||||||
|
import mountBadgeSettings from '~/pages/shared/mount_badge_settings';
|
||||||
|
import { GROUP_BADGE } from '~/badges/constants';
|
||||||
|
|
||||||
document.addEventListener('DOMContentLoaded', () => {
|
document.addEventListener('DOMContentLoaded', () => {
|
||||||
groupAvatar();
|
groupAvatar();
|
||||||
new TransferDropdown(); // eslint-disable-line no-new
|
new TransferDropdown(); // eslint-disable-line no-new
|
||||||
initConfirmDangerModal();
|
initConfirmDangerModal();
|
||||||
});
|
|
||||||
|
|
||||||
document.addEventListener('DOMContentLoaded', () => {
|
|
||||||
// Initialize expandable settings panels
|
|
||||||
initSettingsPanels();
|
initSettingsPanels();
|
||||||
|
mountBadgeSettings(GROUP_BADGE);
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
|
import { PROJECT_BADGE } from '~/badges/constants';
|
||||||
import initSettingsPanels from '~/settings_panels';
|
import initSettingsPanels from '~/settings_panels';
|
||||||
import setupProjectEdit from '~/project_edit';
|
import setupProjectEdit from '~/project_edit';
|
||||||
import initConfirmDangerModal from '~/confirm_danger_modal';
|
import initConfirmDangerModal from '~/confirm_danger_modal';
|
||||||
|
import mountBadgeSettings from '~/pages/shared/mount_badge_settings';
|
||||||
import initProjectLoadingSpinner from '../shared/save_project_loader';
|
import initProjectLoadingSpinner from '../shared/save_project_loader';
|
||||||
import projectAvatar from '../shared/project_avatar';
|
import projectAvatar from '../shared/project_avatar';
|
||||||
import initProjectPermissionsSettings from '../shared/permissions';
|
import initProjectPermissionsSettings from '../shared/permissions';
|
||||||
|
@ -13,4 +15,5 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||||
projectAvatar();
|
projectAvatar();
|
||||||
initProjectPermissionsSettings();
|
initProjectPermissionsSettings();
|
||||||
initConfirmDangerModal();
|
initConfirmDangerModal();
|
||||||
|
mountBadgeSettings(PROJECT_BADGE);
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,10 +0,0 @@
|
||||||
import Vue from 'vue';
|
|
||||||
import Translate from '~/vue_shared/translate';
|
|
||||||
import { PROJECT_BADGE } from '~/badges/constants';
|
|
||||||
import mountBadgeSettings from '~/pages/shared/mount_badge_settings';
|
|
||||||
|
|
||||||
Vue.use(Translate);
|
|
||||||
|
|
||||||
document.addEventListener('DOMContentLoaded', () => {
|
|
||||||
mountBadgeSettings(PROJECT_BADGE);
|
|
||||||
});
|
|
|
@ -1,13 +0,0 @@
|
||||||
module Groups
|
|
||||||
module Settings
|
|
||||||
class BadgesController < Groups::ApplicationController
|
|
||||||
include API::Helpers::RelatedResourcesHelpers
|
|
||||||
|
|
||||||
before_action :authorize_admin_group!
|
|
||||||
|
|
||||||
def index
|
|
||||||
@badge_api_endpoint = expose_url(api_v4_groups_badges_path(id: @group.id))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,4 +1,5 @@
|
||||||
class GroupsController < Groups::ApplicationController
|
class GroupsController < Groups::ApplicationController
|
||||||
|
include API::Helpers::RelatedResourcesHelpers
|
||||||
include IssuesAction
|
include IssuesAction
|
||||||
include MergeRequestsAction
|
include MergeRequestsAction
|
||||||
include ParamsBackwardCompatibility
|
include ParamsBackwardCompatibility
|
||||||
|
@ -77,6 +78,7 @@ class GroupsController < Groups::ApplicationController
|
||||||
end
|
end
|
||||||
|
|
||||||
def edit
|
def edit
|
||||||
|
@badge_api_endpoint = expose_url(api_v4_groups_badges_path(id: @group.id))
|
||||||
end
|
end
|
||||||
|
|
||||||
def projects
|
def projects
|
||||||
|
|
|
@ -1,13 +0,0 @@
|
||||||
module Projects
|
|
||||||
module Settings
|
|
||||||
class BadgesController < Projects::ApplicationController
|
|
||||||
include API::Helpers::RelatedResourcesHelpers
|
|
||||||
|
|
||||||
before_action :authorize_admin_project!
|
|
||||||
|
|
||||||
def index
|
|
||||||
@badge_api_endpoint = expose_url(api_v4_projects_badges_path(id: @project.id))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,4 +1,5 @@
|
||||||
class ProjectsController < Projects::ApplicationController
|
class ProjectsController < Projects::ApplicationController
|
||||||
|
include API::Helpers::RelatedResourcesHelpers
|
||||||
include IssuableCollections
|
include IssuableCollections
|
||||||
include ExtractsPath
|
include ExtractsPath
|
||||||
include PreviewMarkdown
|
include PreviewMarkdown
|
||||||
|
@ -32,6 +33,7 @@ class ProjectsController < Projects::ApplicationController
|
||||||
end
|
end
|
||||||
|
|
||||||
def edit
|
def edit
|
||||||
|
@badge_api_endpoint = expose_url(api_v4_projects_badges_path(id: @project.id))
|
||||||
render 'edit'
|
render 'edit'
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,18 @@
|
||||||
.settings-content
|
.settings-content
|
||||||
= render 'groups/settings/permissions'
|
= render 'groups/settings/permissions'
|
||||||
|
|
||||||
|
%section.settings.no-animate{ class: ('expanded' if expanded) }
|
||||||
|
.settings-header
|
||||||
|
%h4
|
||||||
|
= s_('GroupSettings|Badges')
|
||||||
|
%button.btn.js-settings-toggle{ type: 'button' }
|
||||||
|
= expanded ? 'Collapse' : 'Expand'
|
||||||
|
%p
|
||||||
|
= s_('GroupSettings|Customize your group badges.')
|
||||||
|
= link_to s_('GroupSettings|Learn more about badges.'), help_page_path('user/project/badges')
|
||||||
|
.settings-content
|
||||||
|
= render 'shared/badges/badge_settings'
|
||||||
|
|
||||||
%section.settings.gs-advanced.no-animate#js-advanced-settings{ class: ('expanded' if expanded) }
|
%section.settings.gs-advanced.no-animate#js-advanced-settings{ class: ('expanded' if expanded) }
|
||||||
.settings-header
|
.settings-header
|
||||||
%h4
|
%h4
|
||||||
|
|
|
@ -122,12 +122,6 @@
|
||||||
%span
|
%span
|
||||||
= _('General')
|
= _('General')
|
||||||
|
|
||||||
= nav_link(controller: :badges) do
|
|
||||||
= link_to group_settings_badges_path(@group), title: _('Project Badges') do
|
|
||||||
%span
|
|
||||||
= _('Project Badges')
|
|
||||||
|
|
||||||
|
|
||||||
= nav_link(path: 'groups#projects') do
|
= nav_link(path: 'groups#projects') do
|
||||||
= link_to projects_group_path(@group), title: _('Projects') do
|
= link_to projects_group_path(@group), title: _('Projects') do
|
||||||
%span
|
%span
|
||||||
|
|
|
@ -312,11 +312,6 @@
|
||||||
= link_to project_project_members_path(@project), title: _('Members') do
|
= link_to project_project_members_path(@project), title: _('Members') do
|
||||||
%span
|
%span
|
||||||
= _('Members')
|
= _('Members')
|
||||||
- if can_edit
|
|
||||||
= nav_link(controller: :badges) do
|
|
||||||
= link_to project_settings_badges_path(@project), title: _('Badges') do
|
|
||||||
%span
|
|
||||||
= _('Badges')
|
|
||||||
- if can_edit
|
- if can_edit
|
||||||
= nav_link(controller: [:integrations, :services, :hooks, :hook_logs]) do
|
= nav_link(controller: [:integrations, :services, :hooks, :hook_logs]) do
|
||||||
= link_to project_settings_integrations_path(@project), title: _('Integrations') do
|
= link_to project_settings_integrations_path(@project), title: _('Integrations') do
|
||||||
|
|
|
@ -102,6 +102,18 @@
|
||||||
|
|
||||||
= render_if_exists 'projects/service_desk_settings'
|
= render_if_exists 'projects/service_desk_settings'
|
||||||
|
|
||||||
|
%section.settings.no-animate{ class: ('expanded' if expanded) }
|
||||||
|
.settings-header
|
||||||
|
%h4
|
||||||
|
= s_('ProjectSettings|Badges')
|
||||||
|
%button.btn.js-settings-toggle{ type: 'button' }
|
||||||
|
= expanded ? 'Collapse' : 'Expand'
|
||||||
|
%p
|
||||||
|
= s_('ProjectSettings|Customize your project badges.')
|
||||||
|
= link_to s_('ProjectSettings|Learn more about badges.'), help_page_path('user/project/badges')
|
||||||
|
.settings-content
|
||||||
|
= render 'shared/badges/badge_settings'
|
||||||
|
|
||||||
= render 'export', project: @project
|
= render 'export', project: @project
|
||||||
|
|
||||||
%section.qa-advanced-settings.settings.advanced-settings.no-animate#js-project-advanced-settings{ class: ('expanded' if expanded) }
|
%section.qa-advanced-settings.settings.advanced-settings.no-animate#js-project-advanced-settings{ class: ('expanded' if expanded) }
|
||||||
|
|
5
changelogs/unreleased/winh-move-badge-settings.yml
Normal file
5
changelogs/unreleased/winh-move-badge-settings.yml
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
title: Move badge settings to general settings
|
||||||
|
merge_request: 21333
|
||||||
|
author:
|
||||||
|
type: changed
|
|
@ -25,7 +25,6 @@ constraints(::Constraints::GroupUrlConstrainer.new) do
|
||||||
constraints: { group_id: Gitlab::PathRegex.full_namespace_route_regex }) do
|
constraints: { group_id: Gitlab::PathRegex.full_namespace_route_regex }) do
|
||||||
namespace :settings do
|
namespace :settings do
|
||||||
resource :ci_cd, only: [:show], controller: 'ci_cd'
|
resource :ci_cd, only: [:show], controller: 'ci_cd'
|
||||||
resources :badges, only: [:index]
|
|
||||||
end
|
end
|
||||||
|
|
||||||
resource :variables, only: [:show, :update]
|
resource :variables, only: [:show, :update]
|
||||||
|
|
|
@ -442,7 +442,6 @@ constraints(::Constraints::ProjectUrlConstrainer.new) do
|
||||||
resource :repository, only: [:show], controller: :repository do
|
resource :repository, only: [:show], controller: :repository do
|
||||||
post :create_deploy_token, path: 'deploy_token/create'
|
post :create_deploy_token, path: 'deploy_token/create'
|
||||||
end
|
end
|
||||||
resources :badges, only: [:index]
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# Since both wiki and repository routing contains wildcard characters
|
# Since both wiki and repository routing contains wildcard characters
|
||||||
|
|
|
@ -17,7 +17,7 @@ If you find that you have to add the same badges to several projects, you may wa
|
||||||
|
|
||||||
To add a new badge to a project:
|
To add a new badge to a project:
|
||||||
|
|
||||||
1. Navigate to your project's **Settings > Badges**.
|
1. Navigate to your project's **Settings > General > Badges**.
|
||||||
1. Under "Link", enter the URL that the badges should point to and under
|
1. Under "Link", enter the URL that the badges should point to and under
|
||||||
"Badge image URL" the URL of the image that should be displayed.
|
"Badge image URL" the URL of the image that should be displayed.
|
||||||
1. Submit the badge by clicking the **Add badge** button.
|
1. Submit the badge by clicking the **Add badge** button.
|
||||||
|
@ -39,7 +39,7 @@ project, consider adding them on the [project level](#project-badges) or use
|
||||||
|
|
||||||
To add a new badge to a group:
|
To add a new badge to a group:
|
||||||
|
|
||||||
1. Navigate to your group's **Settings > Project Badges**.
|
1. Navigate to your group's **Settings > General > Badges**.
|
||||||
1. Under "Link", enter the URL that the badges should point to and under
|
1. Under "Link", enter the URL that the badges should point to and under
|
||||||
"Badge image URL" the URL of the image that should be displayed.
|
"Badge image URL" the URL of the image that should be displayed.
|
||||||
1. Submit the badge by clicking the **Add badge** button.
|
1. Submit the badge by clicking the **Add badge** button.
|
||||||
|
|
|
@ -805,6 +805,9 @@ msgstr ""
|
||||||
msgid "Badges|No image to preview"
|
msgid "Badges|No image to preview"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Badges|Please fill in a valid URL"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Badges|Project Badge"
|
msgid "Badges|Project Badge"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -838,6 +841,9 @@ msgstr ""
|
||||||
msgid "Badges|Your badges"
|
msgid "Badges|Your badges"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Badges|e.g. %{exampleUrl}"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Begin with the selected commit"
|
msgid "Begin with the selected commit"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -2897,6 +2903,15 @@ msgstr ""
|
||||||
msgid "Group: %{group_name}"
|
msgid "Group: %{group_name}"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "GroupSettings|Badges"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "GroupSettings|Customize your group badges."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "GroupSettings|Learn more about badges."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
|
msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -4536,6 +4551,15 @@ msgstr ""
|
||||||
msgid "ProjectPage|Project ID: %{project_id}"
|
msgid "ProjectPage|Project ID: %{project_id}"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "ProjectSettings|Badges"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "ProjectSettings|Customize your project badges."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "ProjectSettings|Learn more about badges."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Projects"
|
msgid "Projects"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
|
|
@ -57,6 +57,16 @@ describe GroupsController do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe 'GET edit' do
|
||||||
|
it 'sets the badge API endpoint' do
|
||||||
|
sign_in(owner)
|
||||||
|
|
||||||
|
get :edit, id: group.to_param
|
||||||
|
|
||||||
|
expect(assigns(:badge_api_endpoint)).not_to be_nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
describe 'GET #new' do
|
describe 'GET #new' do
|
||||||
context 'when creating subgroups', :nested_groups do
|
context 'when creating subgroups', :nested_groups do
|
||||||
[true, false].each do |can_create_group_status|
|
[true, false].each do |can_create_group_status|
|
||||||
|
|
|
@ -284,6 +284,19 @@ describe ProjectsController do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe 'GET edit' do
|
||||||
|
it 'sets the badge API endpoint' do
|
||||||
|
sign_in(user)
|
||||||
|
project.add_maintainer(user)
|
||||||
|
|
||||||
|
get :edit,
|
||||||
|
namespace_id: project.namespace.path,
|
||||||
|
id: project.path
|
||||||
|
|
||||||
|
expect(assigns(:badge_api_endpoint)).not_to be_nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
describe "#update" do
|
describe "#update" do
|
||||||
render_views
|
render_views
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,7 @@ describe 'Group Badges' do
|
||||||
group.add_owner(user)
|
group.add_owner(user)
|
||||||
sign_in(user)
|
sign_in(user)
|
||||||
|
|
||||||
visit(group_settings_badges_path(group))
|
visit(edit_group_path(group))
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'shows a list of badges', :js do
|
it 'shows a list of badges', :js do
|
||||||
|
|
|
@ -15,7 +15,7 @@ describe 'Project Badges' do
|
||||||
group.add_maintainer(user)
|
group.add_maintainer(user)
|
||||||
sign_in(user)
|
sign_in(user)
|
||||||
|
|
||||||
visit(project_settings_badges_path(project))
|
visit(edit_project_path(project))
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'shows a list of badges', :js do
|
it 'shows a list of badges', :js do
|
||||||
|
|
|
@ -1,21 +1,31 @@
|
||||||
import Vue from 'vue';
|
import Vue from 'vue';
|
||||||
|
import MockAdapter from 'axios-mock-adapter';
|
||||||
|
import axios from '~/lib/utils/axios_utils';
|
||||||
import store from '~/badges/store';
|
import store from '~/badges/store';
|
||||||
|
import createEmptyBadge from '~/badges/empty_badge';
|
||||||
import BadgeForm from '~/badges/components/badge_form.vue';
|
import BadgeForm from '~/badges/components/badge_form.vue';
|
||||||
import { mountComponentWithStore } from 'spec/helpers/vue_mount_component_helper';
|
import { mountComponentWithStore } from 'spec/helpers/vue_mount_component_helper';
|
||||||
import { createDummyBadge } from '../dummy_badge';
|
import { DUMMY_IMAGE_URL, TEST_HOST } from '../../test_constants';
|
||||||
|
|
||||||
|
// avoid preview background process
|
||||||
|
BadgeForm.methods.debouncedPreview = () => {};
|
||||||
|
|
||||||
describe('BadgeForm component', () => {
|
describe('BadgeForm component', () => {
|
||||||
const Component = Vue.extend(BadgeForm);
|
const Component = Vue.extend(BadgeForm);
|
||||||
|
let axiosMock;
|
||||||
let vm;
|
let vm;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
setFixtures(`
|
setFixtures(`
|
||||||
<div id="dummy-element"></div>
|
<div id="dummy-element"></div>
|
||||||
`);
|
`);
|
||||||
|
|
||||||
|
axiosMock = new MockAdapter(axios);
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
vm.$destroy();
|
vm.$destroy();
|
||||||
|
axiosMock.restore();
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('methods', () => {
|
describe('methods', () => {
|
||||||
|
@ -38,93 +48,86 @@ describe('BadgeForm component', () => {
|
||||||
expect(vm.stopEditing).toHaveBeenCalled();
|
expect(vm.stopEditing).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
const sharedSubmitTests = submitAction => {
|
||||||
|
const imageUrlSelector = '#badge-image-url';
|
||||||
|
const findImageUrlElement = () => vm.$el.querySelector(imageUrlSelector);
|
||||||
|
const linkUrlSelector = '#badge-link-url';
|
||||||
|
const findLinkUrlElement = () => vm.$el.querySelector(linkUrlSelector);
|
||||||
|
const setValue = (inputElementSelector, url) => {
|
||||||
|
const inputElement = vm.$el.querySelector(inputElementSelector);
|
||||||
|
inputElement.value = url;
|
||||||
|
inputElement.dispatchEvent(new Event('input'));
|
||||||
|
};
|
||||||
|
const submitForm = () => {
|
||||||
|
const submitButton = vm.$el.querySelector('button[type="submit"]');
|
||||||
|
submitButton.click();
|
||||||
|
};
|
||||||
|
const expectInvalidInput = inputElementSelector => {
|
||||||
|
const inputElement = vm.$el.querySelector(inputElementSelector);
|
||||||
|
expect(inputElement).toBeMatchedBy(':invalid');
|
||||||
|
const feedbackElement = vm.$el.querySelector(`${inputElementSelector} + .invalid-feedback`);
|
||||||
|
expect(feedbackElement).toBeVisible();
|
||||||
|
};
|
||||||
|
|
||||||
describe('onSubmit', () => {
|
|
||||||
describe('if isEditing is true', () => {
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
spyOn(vm, 'saveBadge').and.returnValue(Promise.resolve());
|
spyOn(vm, submitAction).and.returnValue(Promise.resolve());
|
||||||
store.replaceState({
|
store.replaceState({
|
||||||
...store.state,
|
...store.state,
|
||||||
|
badgeInAddForm: createEmptyBadge(),
|
||||||
|
badgeInEditForm: createEmptyBadge(),
|
||||||
isSaving: false,
|
isSaving: false,
|
||||||
badgeInEditForm: createDummyBadge(),
|
|
||||||
});
|
});
|
||||||
vm.isEditing = true;
|
|
||||||
|
setValue(linkUrlSelector, `${TEST_HOST}/link/url`);
|
||||||
|
setValue(imageUrlSelector, `${window.location.origin}${DUMMY_IMAGE_URL}`);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('returns immediately if imageUrl is empty', () => {
|
it('returns immediately if imageUrl is empty', () => {
|
||||||
store.state.badgeInEditForm.imageUrl = '';
|
setValue(imageUrlSelector, '');
|
||||||
|
|
||||||
vm.onSubmit();
|
submitForm();
|
||||||
|
|
||||||
expect(vm.saveBadge).not.toHaveBeenCalled();
|
expectInvalidInput(imageUrlSelector);
|
||||||
|
expect(vm[submitAction]).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns immediately if imageUrl is malformed', () => {
|
||||||
|
setValue(imageUrlSelector, 'not-a-url');
|
||||||
|
|
||||||
|
submitForm();
|
||||||
|
|
||||||
|
expectInvalidInput(imageUrlSelector);
|
||||||
|
expect(vm[submitAction]).not.toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('returns immediately if linkUrl is empty', () => {
|
it('returns immediately if linkUrl is empty', () => {
|
||||||
store.state.badgeInEditForm.linkUrl = '';
|
setValue(linkUrlSelector, '');
|
||||||
|
|
||||||
vm.onSubmit();
|
submitForm();
|
||||||
|
|
||||||
expect(vm.saveBadge).not.toHaveBeenCalled();
|
expectInvalidInput(linkUrlSelector);
|
||||||
|
expect(vm[submitAction]).not.toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('returns immediately if isSaving is true', () => {
|
it('returns immediately if linkUrl is malformed', () => {
|
||||||
store.state.isSaving = true;
|
setValue(linkUrlSelector, 'not-a-url');
|
||||||
|
|
||||||
vm.onSubmit();
|
submitForm();
|
||||||
|
|
||||||
expect(vm.saveBadge).not.toHaveBeenCalled();
|
expectInvalidInput(linkUrlSelector);
|
||||||
|
expect(vm[submitAction]).not.toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('calls saveBadge', () => {
|
it(`calls ${submitAction}`, () => {
|
||||||
vm.onSubmit();
|
submitForm();
|
||||||
|
|
||||||
expect(vm.saveBadge).toHaveBeenCalled();
|
expect(findImageUrlElement()).toBeMatchedBy(':valid');
|
||||||
});
|
expect(findLinkUrlElement()).toBeMatchedBy(':valid');
|
||||||
});
|
expect(vm[submitAction]).toHaveBeenCalled();
|
||||||
|
|
||||||
describe('if isEditing is false', () => {
|
|
||||||
beforeEach(() => {
|
|
||||||
spyOn(vm, 'addBadge').and.returnValue(Promise.resolve());
|
|
||||||
store.replaceState({
|
|
||||||
...store.state,
|
|
||||||
isSaving: false,
|
|
||||||
badgeInAddForm: createDummyBadge(),
|
|
||||||
});
|
|
||||||
vm.isEditing = false;
|
|
||||||
});
|
|
||||||
|
|
||||||
it('returns immediately if imageUrl is empty', () => {
|
|
||||||
store.state.badgeInAddForm.imageUrl = '';
|
|
||||||
|
|
||||||
vm.onSubmit();
|
|
||||||
|
|
||||||
expect(vm.addBadge).not.toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('returns immediately if linkUrl is empty', () => {
|
|
||||||
store.state.badgeInAddForm.linkUrl = '';
|
|
||||||
|
|
||||||
vm.onSubmit();
|
|
||||||
|
|
||||||
expect(vm.addBadge).not.toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('returns immediately if isSaving is true', () => {
|
|
||||||
store.state.isSaving = true;
|
|
||||||
|
|
||||||
vm.onSubmit();
|
|
||||||
|
|
||||||
expect(vm.addBadge).not.toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('calls addBadge', () => {
|
|
||||||
vm.onSubmit();
|
|
||||||
|
|
||||||
expect(vm.addBadge).toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
};
|
||||||
|
|
||||||
describe('if isEditing is false', () => {
|
describe('if isEditing is false', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
|
@ -138,12 +141,15 @@ describe('BadgeForm component', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('renders one button', () => {
|
it('renders one button', () => {
|
||||||
const buttons = vm.$el.querySelectorAll('.row-content-block button');
|
expect(vm.$el.querySelector('.row-content-block')).toBeNull();
|
||||||
|
const buttons = vm.$el.querySelectorAll('.form-group:last-of-type button');
|
||||||
expect(buttons.length).toBe(1);
|
expect(buttons.length).toBe(1);
|
||||||
const buttonAddElement = buttons[0];
|
const buttonAddElement = buttons[0];
|
||||||
expect(buttonAddElement).toBeVisible();
|
expect(buttonAddElement).toBeVisible();
|
||||||
expect(buttonAddElement).toHaveText('Add badge');
|
expect(buttonAddElement).toHaveText('Add badge');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
sharedSubmitTests('addBadge');
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('if isEditing is true', () => {
|
describe('if isEditing is true', () => {
|
||||||
|
@ -167,5 +173,7 @@ describe('BadgeForm component', () => {
|
||||||
expect(buttonCancelElement).toBeVisible();
|
expect(buttonCancelElement).toBeVisible();
|
||||||
expect(buttonCancelElement).toHaveText('Cancel');
|
expect(buttonCancelElement).toHaveText('Cancel');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
sharedSubmitTests('saveBadge');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in a new issue