Commit 80d359ed authored by GitLab Bot's avatar GitLab Bot

Automatic merge of gitlab-org/gitlab master

parents dfb5eb92 5984177a
<script>
import { __ } from '~/locale';
import { GlModal } from '@gitlab/ui';
import { __, s__ } from '~/locale';
import { deprecatedCreateFlash as Flash } from '~/flash';
import DeprecatedModal from '~/vue_shared/components/deprecated_modal.vue';
import { visitUrl } from '~/lib/utils/url_utility';
import boardsStore from '~/boards/stores/boards_store';
......@@ -19,10 +19,28 @@ const boardDefaults = {
hide_closed_list: false,
};
const formType = {
new: 'new',
delete: 'delete',
edit: 'edit',
};
export default {
i18n: {
[formType.new]: { title: s__('Board|Create new board'), btnText: s__('Board|Create board') },
[formType.delete]: { title: s__('Board|Delete board'), btnText: __('Delete') },
[formType.edit]: { title: s__('Board|Edit board'), btnText: __('Save changes') },
scopeModalTitle: s__('Board|Board scope'),
cancelButtonText: __('Cancel'),
deleteErrorMessage: s__('Board|Failed to delete board. Please try again.'),
saveErrorMessage: __('Unable to save your changes. Please try again.'),
deleteConfirmationMessage: s__('Board|Are you sure you want to delete this board?'),
titleFieldLabel: __('Title'),
titleFieldPlaceholder: s__('Board|Enter board name'),
},
components: {
BoardScope: () => import('ee_component/boards/components/board_scope.vue'),
DeprecatedModal,
GlModal,
BoardConfigurationOptions,
},
props: {
......@@ -74,25 +92,16 @@ export default {
},
computed: {
isNewForm() {
return this.currentPage === 'new';
return this.currentPage === formType.new;
},
isDeleteForm() {
return this.currentPage === 'delete';
return this.currentPage === formType.delete;
},
isEditForm() {
return this.currentPage === 'edit';
},
isVisible() {
return this.currentPage !== '';
return this.currentPage === formType.edit;
},
buttonText() {
if (this.isNewForm) {
return __('Create board');
}
if (this.isDeleteForm) {
return __('Delete');
}
return __('Save changes');
return this.$options.i18n[this.currentPage].btnText;
},
buttonKind() {
if (this.isNewForm) {
......@@ -104,16 +113,11 @@ export default {
return 'info';
},
title() {
if (this.isNewForm) {
return __('Create new board');
}
if (this.isDeleteForm) {
return __('Delete board');
}
if (this.readonly) {
return __('Board scope');
return this.$options.i18n.scopeModalTitle;
}
return __('Edit board');
return this.$options.i18n[this.currentPage].title;
},
readonly() {
return !this.canAdminBoard;
......@@ -121,6 +125,24 @@ export default {
submitDisabled() {
return this.isLoading || this.board.name.length === 0;
},
primaryProps() {
return {
text: this.buttonText,
attributes: [
{
variant: this.buttonKind,
disabled: this.submitDisabled,
loading: this.isLoading,
'data-qa-selector': 'save_changes_button',
},
],
};
},
cancelProps() {
return {
text: this.$options.i18n.cancelButtonText,
};
},
},
mounted() {
this.resetFormState();
......@@ -136,10 +158,11 @@ export default {
boardsStore
.deleteBoard(this.currentBoard)
.then(() => {
this.isLoading = false;
visitUrl(boardsStore.rootPath);
})
.catch(() => {
Flash(__('Failed to delete board. Please try again.'));
Flash(this.$options.i18n.deleteErrorMessage);
this.isLoading = false;
});
} else {
......@@ -157,10 +180,11 @@ export default {
return resp.data ? resp.data : resp;
})
.then(data => {
this.isLoading = false;
visitUrl(data.board_path);
})
.catch(() => {
Flash(__('Unable to save your changes. Please try again.'));
Flash(this.$options.i18n.saveErrorMessage);
this.isLoading = false;
});
}
......@@ -181,53 +205,56 @@ export default {
</script>
<template>
<deprecated-modal
v-show="isVisible"
<gl-modal
modal-id="board-config-modal"
modal-class="board-config-modal"
content-class="gl-absolute gl-top-7"
visible
:hide-footer="readonly"
:title="title"
:primary-button-label="buttonText"
:kind="buttonKind"
:submit-disabled="submitDisabled"
modal-dialog-class="board-config-modal"
:action-primary="primaryProps"
:action-cancel="cancelProps"
@primary="submit"
@cancel="cancel"
@submit="submit"
@close="cancel"
@hide.prevent
>
<template #body>
<p v-if="isDeleteForm">{{ __('Are you sure you want to delete this board?') }}</p>
<form v-else class="js-board-config-modal" @submit.prevent>
<div v-if="!readonly" class="gl-mb-5">
<label class="label-bold gl-font-lg" for="board-new-name">{{ __('Title') }}</label>
<input
id="board-new-name"
ref="name"
v-model="board.name"
class="form-control"
data-qa-selector="board_name_field"
type="text"
:placeholder="__('Enter board name')"
@keyup.enter="submit"
/>
</div>
<board-configuration-options
:is-new-form="isNewForm"
:board="board"
:current-board="currentBoard"
<p v-if="isDeleteForm">{{ $options.i18n.deleteConfirmationMessage }}</p>
<form v-else class="js-board-config-modal" @submit.prevent>
<div v-if="!readonly" class="gl-mb-5">
<label class="gl-font-weight-bold gl-font-lg" for="board-new-name">
{{ $options.i18n.titleFieldLabel }}
</label>
<input
id="board-new-name"
ref="name"
v-model="board.name"
class="form-control"
data-qa-selector="board_name_field"
type="text"
:placeholder="$options.i18n.titleFieldPlaceholder"
@keyup.enter="submit"
/>
</div>
<board-scope
v-if="scopedIssueBoardFeatureEnabled"
:collapse-scope="isNewForm"
:board="board"
:can-admin-board="canAdminBoard"
:labels-path="labelsPath"
:labels-web-url="labelsWebUrl"
:enable-scoped-labels="enableScopedLabels"
:project-id="projectId"
:group-id="groupId"
:weights="weights"
/>
</form>
</template>
</deprecated-modal>
<board-configuration-options
:is-new-form="isNewForm"
:board="board"
:current-board="currentBoard"
/>
<board-scope
v-if="scopedIssueBoardFeatureEnabled"
:collapse-scope="isNewForm"
:board="board"
:can-admin-board="canAdminBoard"
:labels-path="labelsPath"
:labels-web-url="labelsWebUrl"
:enable-scoped-labels="enableScopedLabels"
:project-id="projectId"
:group-id="groupId"
:weights="weights"
/>
</form>
</gl-modal>
</template>
......@@ -7,6 +7,7 @@ import {
GlDropdownDivider,
GlDropdownSectionHeader,
GlDropdownItem,
GlModalDirective,
} from '@gitlab/ui';
import httpStatusCodes from '~/lib/utils/http_status';
......@@ -31,6 +32,9 @@ export default {
GlDropdownSectionHeader,
GlDropdownItem,
},
directives: {
GlModalDirective,
},
props: {
currentBoard: {
type: Object,
......@@ -313,6 +317,7 @@ export default {
<gl-dropdown-item
v-if="multipleIssueBoardsAvailable"
v-gl-modal-directive="'board-config-modal'"
data-qa-selector="create_new_board_button"
@click.prevent="showPage('new')"
>
......@@ -321,6 +326,7 @@ export default {
<gl-dropdown-item
v-if="showDelete"
v-gl-modal-directive="'board-config-modal'"
class="text-danger js-delete-board"
@click.prevent="showPage('delete')"
>
......
......@@ -82,7 +82,7 @@ export default {
mergeInfo2() {
return this.isFork
? `git fetch origin\ngit checkout "${this.targetBranch}"\ngit merge --no-ff "${this.sourceProjectPath}-${this.sourceBranch}"`
: `git fetch origin\ngit checkout "${this.targetBranch}"\ngit merge --no-ff " ${this.sourceBranch}"`;
: `git fetch origin\ngit checkout "${this.targetBranch}"\ngit merge --no-ff "${this.sourceBranch}"`;
},
mergeInfo3() {
return this.canMerge
......
......@@ -91,6 +91,7 @@
body.modal-open {
overflow: hidden;
padding-right: 0 !important;
}
.modal-no-backdrop {
......
......@@ -36,6 +36,7 @@ module Projects
def log_response(response)
log_data = LOG_DATA_BASE.merge(
container_repository_id: @container_repository.id,
project_id: @container_repository.project_id,
message: 'deleted tags',
deleted_tags_count: response[:deleted]&.size
).compact
......
......@@ -5,7 +5,7 @@
.dropdown
%button.dropdown.dropdown-new.btn.gl-button.btn-default.has-tooltip{ type: 'button', 'data-toggle' => 'dropdown', title: s_('Environments|Deploy to...') }
= sprite_icon('play')
= icon('caret-down')
= sprite_icon('chevron-down')
%ul.dropdown-menu.dropdown-menu-right
- actions.each do |action|
- next unless can?(current_user, :update_build, action)
......
......@@ -4,7 +4,7 @@
Showing
%button.diff-stats-summary-toggler.js-diff-stats-dropdown{ type: "button", data: { toggle: "dropdown", display: "static" } }<
= pluralize(diff_files.size, "changed file")
= icon("caret-down", class: "gl-ml-2")
= sprite_icon("chevron-down", css_class: "gl-ml-2")
%span.diff-stats-additions-deletions-expanded#diff-stats
with
%strong.cgreen= pluralize(sum_added_lines, 'addition')
......
......@@ -8,7 +8,7 @@
%a#clone-dropdown.input-group-text.btn.clone-dropdown-btn.qa-clone-dropdown{ href: '#', data: { toggle: 'dropdown' } }
%span.js-clone-dropdown-label
= default_clone_protocol.upcase
= icon('caret-down')
= sprite_icon('chevron-down')
%ul.dropdown-menu.dropdown-menu-selectable.clone-options-dropdown
%li
= ssh_clone_button(container)
......
---
title: Fix typo on merge locally step
merge_request: 49330
author:
type: fixed
---
title: Convert fa-caret-down icons to chevron-down SVG
merge_request: 49332
author:
type: changed
......@@ -261,6 +261,18 @@ The union of A, B, and C is (1, 4) and (6, 7). Therefore, the total running time
(4 - 1) + (7 - 6) => 4
```
#### How pipeline quota usage is calculated
Pipeline quota usage is calculated as the sum of the duration of each individual job. This is slightly different to how pipeline _duration_ is [calculated](#how-pipeline-duration-is-calculated). Pipeline quota usage doesn't consider any overlap of jobs running in parallel.
For example, a pipeline consists of the following jobs:
- Job A takes 3 minutes.
- Job B takes 3 minutes.
- Job C takes 2 minutes.
The pipeline quota usage is the sum of each job's duration. In this example, 8 runner minutes would be used, calculated as: 3 + 3 + 2.
### Pipeline security on protected branches
A strict security model is enforced when pipelines are executed on
......
......@@ -276,8 +276,13 @@ In its current state, the Rake task:
This uses some features from `graphql-docs` gem like its schema parser and helper methods.
The docs generator code comes from our side giving us more flexibility, like using Haml templates and generating Markdown files.
To edit the template used, please take a look at `lib/gitlab/graphql/docs/templates/default.md.haml`.
The actual renderer is at `Gitlab::Graphql::Docs::Renderer`.
To edit the content, you may need to edit the following:
- The template. You can edit the template at `lib/gitlab/graphql/docs/templates/default.md.haml`.
The actual renderer is at `Gitlab::Graphql::Docs::Renderer`.
- The applicable `description` field in the code, which
[Updates machine-readable schema files](#update-machine-readable-schema-files),
which is then used by the `rake` task described earlier.
`@parsed_schema` is an instance variable that the `graphql-docs` gem expects to have available.
`Gitlab::Graphql::Docs::Helper` defines the `object` method we currently use. This is also where you
......
import Vue from 'vue';
import { GlTooltipDirective } from '@gitlab/ui';
import { GlButton, GlModalDirective, GlTooltipDirective } from '@gitlab/ui';
import { s__, __ } from '~/locale';
export default boardsStore => {
......@@ -8,8 +8,12 @@ export default boardsStore => {
if (configEl) {
gl.boardConfigToggle = new Vue({
el: configEl,
components: {
GlButton,
},
directives: {
GlTooltip: GlTooltipDirective,
GlModalDirective,
},
data() {
return {
......@@ -31,17 +35,16 @@ export default boardsStore => {
},
template: `
<div class="gl-ml-3">
<button
<gl-button
v-gl-modal-directive="'board-config-modal'"
v-gl-tooltip
:title="tooltipTitle"
class="btn btn-inverted"
:class="{ 'dot-highlight': hasScope }"
type="button"
data-qa-selector="boards_config_button"
@click.prevent="showPage('edit')"
>
{{ buttonText }}
</button>
</gl-button>
</div>
`,
});
......
<script>
import { GlLink, GlEmptyState } from '@gitlab/ui';
import { __ } from '~/locale';
export default {
components: {
GlLink,
GlEmptyState,
},
props: {
imagePath: {
type: String,
......@@ -9,27 +14,24 @@ export default {
},
},
strings: {
heading: __(
"Merge requests are a place to propose changes you've made to a project and discuss those changes with others",
heading: __("A merge request hasn't yet been merged"),
subheading: __(
"The Compliance Dashboard gives you the ability to see a group's merge request activity by providing a high-level view for all projects in the group.",
),
subheading: __('Interested parties can even contribute by pushing commits if they want to.'),
alt: __('Merge Requests'),
documentation: __('View documentation'),
},
documentationPath: 'https://docs.gitlab.com/ee/user/compliance/compliance_dashboard/index.html',
};
</script>
<template>
<div class="row empty-state merge-requests">
<div class="col-12">
<div class="svg-content">
<img :src="imagePath" :alt="$options.strings.alt" />
</div>
</div>
<div class="col-12">
<div class="text-content">
<h4>{{ $options.strings.heading }}</h4>
<p>{{ $options.strings.subheading }}</p>
</div>
</div>
</div>
<gl-empty-state
:title="$options.strings.heading"
:description="$options.strings.subheading"
:svg-path="imagePath"
>
<template #actions>
<gl-link :href="$options.documentationPath">{{ $options.strings.documentation }}</gl-link>
</template>
</gl-empty-state>
</template>
......@@ -76,7 +76,7 @@
}
}
.board-config-modal {
.board-config-modal .modal-dialog {
width: 440px;
.block {
......
---
title: Improve compliance dashboard empty state message
merge_request: 45273
author:
type: changed
......@@ -21,7 +21,7 @@ RSpec.describe 'Group Boards', :js do
wait_for_requests
find(:css, '.js-delete-board button').click
find(:css, '.board-config-modal .js-primary-button').click
find(:css, '.board-config-modal .js-modal-action-primary').click
click_boards_dropdown
......
......@@ -297,6 +297,9 @@ RSpec.describe 'Scoped issue boards', :js do
visit project_boards_path(project)
update_board_label(label_title)
wait_for_all_requests
update_board_label(label_2_title)
expect(page).to have_css('.js-visual-token')
......@@ -455,7 +458,7 @@ RSpec.describe 'Scoped issue boards', :js do
it "doesn't show the input when creating a board" do
click_on_create_new_board
page.within '.js-boards-selector' do
page.within '.js-board-config-modal' do
# To make sure the form is shown
expect(page).to have_field('board-new-name')
......@@ -469,14 +472,14 @@ RSpec.describe 'Scoped issue boards', :js do
end
def expect_dot_highlight(button_title)
button = first('.filter-dropdown-container .btn.btn-inverted')
button = first('.filter-dropdown-container .btn.gl-button')
expect(button.text).to include(button_title)
expect(button[:class]).to include('dot-highlight')
expect(button['title']).to include('This board\'s scope is reduced')
end
def expect_no_dot_highlight(button_title)
button = first('.filter-dropdown-container .btn.btn-inverted')
button = first('.filter-dropdown-container .btn.gl-button')
expect(button.text).to include(button_title)
expect(button[:class]).not_to include('dot-highlight')
expect(button['title']).not_to include('This board\'s scope is reduced')
......@@ -540,7 +543,7 @@ RSpec.describe 'Scoped issue boards', :js do
click_on_board_modal
click_button 'Create'
click_button 'Create board'
wait_for_requests
......@@ -569,7 +572,7 @@ RSpec.describe 'Scoped issue boards', :js do
click_on_board_modal
click_button 'Save'
click_button 'Save changes'
wait_for_requests
......@@ -579,6 +582,6 @@ RSpec.describe 'Scoped issue boards', :js do
# Click on modal to make sure the dropdown is closed (e.g. label scenario)
#
def click_on_board_modal
find('.board-config-modal').click
find('.board-config-modal .modal-content').click
end
end
import { shallowMount } from '@vue/test-utils';
import { GlEmptyState } from '@gitlab/ui';
import EmptyState from 'ee/compliance_dashboard/components/empty_state.vue';
......@@ -7,8 +8,7 @@ const IMAGE_PATH = 'empty.svg';
describe('EmptyState component', () => {
let wrapper;
const findImage = () => wrapper.find('img');
const findText = () => wrapper.find('.text-content');
const emptyStateProp = prop => wrapper.find(GlEmptyState).props(prop);
const createComponent = (props = {}) => {
return shallowMount(EmptyState, {
......@@ -29,12 +29,12 @@ describe('EmptyState component', () => {
describe('behaviour', () => {
it('sets the empty SVG path', () => {
expect(findImage().element.getAttribute('src')).toEqual(IMAGE_PATH);
expect(emptyStateProp('svgPath')).toBe(IMAGE_PATH);
});
it('renders a message', () => {
expect(findText().text()).toEqual(
"Merge requests are a place to propose changes you've made to a project and discuss those changes with others Interested parties can even contribute by pushing commits if they want to.",
it('sets the description', () => {
expect(emptyStateProp('description')).toBe(
"The Compliance Dashboard gives you the ability to see a group's merge request activity by providing a high-level view for all projects in the group.",
);
});
});
......
......@@ -1253,6 +1253,9 @@ msgstr ""
msgid "A merge request approval is required when the license compliance report contains a denied license."
msgstr ""
msgid "A merge request hasn't yet been merged"
msgstr ""
msgid "A new Auto DevOps pipeline has been created, go to %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details"
msgstr ""
......@@ -3683,9 +3686,6 @@ msgstr ""
msgid "Are you sure you want to delete this SSH key?"
msgstr ""
msgid "Are you sure you want to delete this board?"
msgstr ""
msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr ""
......@@ -4486,9 +4486,6 @@ msgstr ""
msgid "Blog"
msgstr ""
msgid "Board scope"
msgstr ""
msgid "Board scope affects which issues are displayed for anyone who visits this board"
msgstr ""
......@@ -4543,6 +4540,30 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
msgid "Board|Are you sure you want to delete this board?"
msgstr ""
msgid "Board|Board scope"
msgstr ""
msgid "Board|Create board"
msgstr ""
msgid "Board|Create new board"
msgstr ""
msgid "Board|Delete board"
msgstr ""
msgid "Board|Edit board"
msgstr ""
msgid "Board|Enter board name"
msgstr ""
msgid "Board|Failed to delete board. Please try again."
msgstr ""
msgid "Board|Load more issues"
msgstr ""
......@@ -7943,9 +7964,6 @@ msgstr ""
msgid "Create and provide your GitHub %{link_start}Personal Access Token%{link_end}. You will need to select the %{code_open}repo%{code_close} scope, so we can display a list of your public and private repositories which are available to import."
msgstr ""
msgid "Create board"
msgstr ""
msgid "Create branch"
msgstr ""
......@@ -8003,9 +8021,6 @@ msgstr ""
msgid "Create new Value Stream"
msgstr ""
msgid "Create new board"
msgstr ""
msgid "Create new branch"
msgstr ""
......@@ -8926,9 +8941,6 @@ msgstr ""
msgid "Delete badge"
msgstr ""
msgid "Delete board"
msgstr ""
msgid "Delete comment"
msgstr ""
......@@ -10062,9 +10074,6 @@ msgstr ""
msgid "Edit application"
msgstr ""
msgid "Edit board"
msgstr ""
msgid "Edit comment"
msgstr ""
......@@ -10479,9 +10488,6 @@ msgstr ""
msgid "Enter at least three characters to search"
msgstr ""
msgid "Enter board name"
msgstr ""
msgid "Enter domain"
msgstr ""
......@@ -11490,9 +11496,6 @@ msgstr ""
msgid "Failed to create wiki"
msgstr ""
msgid "Failed to delete board. Please try again."
msgstr ""
msgid "Failed to deploy to"
msgstr ""
......@@ -27121,6 +27124,9 @@ msgstr ""
msgid "The CSV export will be created in the background. Once finished, it will be sent to %{strong_open}%{email}%{strong_close} in an attachment."
msgstr ""
msgid "The Compliance Dashboard gives you the ability to see a group's merge request activity by providing a high-level view for all projects in the group."
msgstr ""
msgid "The GitLab user to which the Jira user %{jiraDisplayName} will be mapped"
msgstr ""
......
import { mount } from '@vue/test-utils';
import { TEST_HOST } from 'jest/helpers/test_constants';
import { GlModal } from '@gitlab/ui';
import boardsStore from '~/boards/stores/boards_store';
import boardForm from '~/boards/components/board_form.vue';
import DeprecatedModal from '~/vue_shared/components/deprecated_modal.vue';
describe('board_form.vue', () => {
let wrapper;
......@@ -14,7 +14,7 @@ describe('board_form.vue', () => {
labelsWebUrl: `${TEST_HOST}/-/labels`,
};
const findModal = () => wrapper.find(DeprecatedModal);
const findModal = () => wrapper.find(GlModal);
beforeEach(() => {
boardsStore.state.currentPage = 'edit';
......
......@@ -20,6 +20,7 @@ RSpec.describe Projects::ContainerRepository::DeleteTagsService do
service_class: 'Projects::ContainerRepository::DeleteTagsService',
message: 'deleted tags',
container_repository_id: repository.id,
project_id: repository.project_id,
deleted_tags_count: tags.size
)
......@@ -32,7 +33,8 @@ RSpec.describe Projects::ContainerRepository::DeleteTagsService do
log_data = {
service_class: 'Projects::ContainerRepository::DeleteTagsService',
message: message,
container_repository_id: repository.id
container_repository_id: repository.id,
project_id: repository.project_id
}
log_data.merge!(extra_log) if extra_log.any?
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment