Skip to content

Commit 215313e

Browse files
author
GitLab Bot
committed
Add latest changes from gitlab-org/gitlab@master
1 parent 285aff2 commit 215313e

File tree

60 files changed

+874
-528
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

60 files changed

+874
-528
lines changed

app/assets/javascripts/boards/components/board_card.vue

+93-14
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,16 @@ export default {
4040
required: false,
4141
default: true,
4242
},
43+
columnIndex: {
44+
type: Number,
45+
required: false,
46+
default: 0,
47+
},
48+
rowIndex: {
49+
type: Number,
50+
required: false,
51+
default: 0,
52+
},
4353
},
4454
apollo: {
4555
// eslint-disable-next-line @gitlab/vue-no-undef-apollo-properties
@@ -85,6 +95,9 @@ export default {
8595
labels: this.item.labels?.nodes || [],
8696
};
8797
},
98+
showFocusBackground() {
99+
return !this.isActive && !this.multiSelectVisible;
100+
},
88101
},
89102
methods: {
90103
toggleIssue(e) {
@@ -100,6 +113,7 @@ export default {
100113
if (isMultiSelect && gon?.features?.boardMultiSelect) {
101114
this.toggleBoardItemMultiSelection(this.item);
102115
} else {
116+
e.currentTarget.focus();
103117
this.toggleItem();
104118
this.track('click_card', { label: 'right_sidebar' });
105119
}
@@ -137,6 +151,54 @@ export default {
137151
},
138152
});
139153
},
154+
changeFocusInColumn(currentCard, i) {
155+
// Building a list using data-col-index instead of just traversing the ul is necessary for swimlanes
156+
const columnCards = [
157+
...document.querySelectorAll(
158+
`button.board-card-button[data-col-index="${this.columnIndex}"]`,
159+
),
160+
];
161+
const currentIndex = columnCards.indexOf(currentCard);
162+
if (currentIndex + i < 0 || currentIndex + i > columnCards.length - 1) {
163+
return;
164+
}
165+
columnCards[currentIndex + i].focus();
166+
},
167+
focusNext(e) {
168+
this.changeFocusInColumn(e.target, 1);
169+
},
170+
focusPrev(e) {
171+
this.changeFocusInColumn(e.target, -1);
172+
},
173+
changeFocusInRow(currentCard, i) {
174+
const currentList = currentCard.closest('ul');
175+
// Find next in line list/cell with cards. If none, don't move.
176+
let listSelector = 'board-list';
177+
// Account for swimlanes using different structure. Swimlanes traverse within their lane.
178+
if (currentList.classList.contains('board-cell')) {
179+
listSelector = `board-cell[data-row-index="${this.rowIndex}"]`;
180+
}
181+
const lists = [
182+
...document.querySelectorAll(`ul.${listSelector}:not(.list-empty):not(.list-collapsed)`),
183+
];
184+
const currentIndex = lists.indexOf(currentList);
185+
if (currentIndex + i < 0 || currentIndex + i > lists.length - 1) {
186+
return;
187+
}
188+
// Focus the same index if possible, or last card
189+
const targetCards = lists[currentIndex + i].querySelectorAll('button.board-card-button');
190+
if (targetCards.length <= this.index) {
191+
targetCards[targetCards.length - 1].focus();
192+
} else {
193+
targetCards[this.index].focus();
194+
}
195+
},
196+
focusLeft(e) {
197+
this.changeFocusInRow(e.target, -1);
198+
},
199+
focusRight(e) {
200+
this.changeFocusInRow(e.target, 1);
201+
},
140202
},
141203
};
142204
</script>
@@ -147,30 +209,47 @@ export default {
147209
{
148210
'multi-select gl-border-blue-200 gl-bg-blue-50': multiSelectVisible,
149211
'gl-cursor-grab': isDraggable,
212+
'is-active !gl-bg-blue-50 hover:!gl-bg-blue-50': isActive,
150213
'is-disabled': isDisabled,
151-
'is-active gl-bg-blue-50 hover:!gl-bg-blue-50': isActive,
152214
'gl-cursor-not-allowed gl-bg-gray-10': item.isLoading,
153-
'gl-border-l-4 gl-pl-4 gl-border-l-solid': itemColor,
154215
},
155216
]"
156217
:index="index"
157218
:data-item-id="item.id"
158219
:data-item-iid="item.iid"
159220
:data-item-path="item.referencePath"
160-
:style="cardStyle"
161221
data-testid="board-card"
162-
class="board-card gl-border gl-relative gl-mb-3 gl-rounded-base gl-p-4 gl-leading-normal hover:gl-bg-gray-10"
163-
@click="toggleIssue($event)"
222+
class="board-card gl-border gl-relative gl-mb-3 gl-rounded-base gl-leading-normal hover:gl-bg-gray-10"
164223
>
165-
<board-card-inner
166-
:list="list"
167-
:item="formattedItem"
168-
:update-filters="true"
169-
:index="index"
170-
:show-work-item-type-icon="showWorkItemTypeIcon"
171-
@setFilters="$emit('setFilters', $event)"
224+
<button
225+
:class="[
226+
{
227+
'focus:gl-bg-gray-10': showFocusBackground,
228+
'gl-border-l-4 gl-pl-4 gl-border-l-solid': itemColor,
229+
},
230+
]"
231+
:aria-label="item.title"
232+
:data-col-index="columnIndex"
233+
:data-row-index="rowIndex"
234+
:style="cardStyle"
235+
data-testid="board-card-button"
236+
class="board-card-button btn-transparent gl-block gl-h-full gl-w-full gl-rounded-base gl-p-4 gl-text-left gl-outline-none focus:gl-focus"
237+
@click="toggleIssue"
238+
@keydown.left.exact.prevent="focusLeft"
239+
@keydown.right.exact.prevent="focusRight"
240+
@keydown.down.exact.prevent="focusNext"
241+
@keydown.up.exact.prevent="focusPrev"
172242
>
173-
<slot></slot>
174-
</board-card-inner>
243+
<board-card-inner
244+
:list="list"
245+
:item="formattedItem"
246+
:update-filters="true"
247+
:index="index"
248+
:show-work-item-type-icon="showWorkItemTypeIcon"
249+
@setFilters="$emit('setFilters', $event)"
250+
>
251+
<slot></slot>
252+
</board-card-inner>
253+
</button>
175254
</li>
176255
</template>

app/assets/javascripts/boards/components/board_column.vue

+5
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,10 @@ export default {
5151
required: false,
5252
default: false,
5353
},
54+
columnIndex: {
55+
type: Number,
56+
required: true,
57+
},
5458
},
5559
data() {
5660
return {
@@ -126,6 +130,7 @@ export default {
126130
:list="list"
127131
:filter-params="filters"
128132
:show-new-form="showNewForm"
133+
:column-index="columnIndex"
129134
@toggleNewForm="toggleNewForm"
130135
@setFilters="$emit('setFilters', $event)"
131136
/>

app/assets/javascripts/boards/components/board_content.vue

+1
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,7 @@ export default {
266266
v-for="(list, index) in boardListsToUse"
267267
:key="index"
268268
ref="board"
269+
:column-index="index"
269270
:board-id="boardId"
270271
:list="list"
271272
:filters="filterParams"

app/assets/javascripts/boards/components/board_list.vue

+11-2
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,10 @@ export default {
7575
required: false,
7676
default: false,
7777
},
78+
columnIndex: {
79+
type: Number,
80+
required: true,
81+
},
7882
},
7983
data() {
8084
return {
@@ -652,9 +656,11 @@ export default {
652656
'gl-rounded-bl-base gl-rounded-br-base gl-bg-red-50': boardItemsSizeExceedsMax,
653657
'gl-overflow-hidden': disableScrollingWhenMutationInProgress,
654658
'gl-overflow-y-auto': !disableScrollingWhenMutationInProgress,
659+
'list-empty': !listItemsCount,
660+
'list-collapsed': list.collapsed,
655661
}"
656662
:draggable="canMoveIssue ? '.board-card' : false"
657-
class="board-list gl-mb-0 gl-h-full gl-w-full gl-list-none gl-overflow-x-hidden gl-p-3 gl-pt-0"
663+
class="board-list gl-mb-0 gl-h-full gl-w-full gl-list-none gl-overflow-x-hidden gl-p-3 gl-pt-2"
658664
data-testid="tree-root-wrapper"
659665
@start="handleDragOnStart"
660666
@end="handleDragOnEnd"
@@ -666,6 +672,7 @@ export default {
666672
:index="index"
667673
:list="list"
668674
:item="item"
675+
:column-index="columnIndex"
669676
:data-draggable-item-type="$options.draggableItemTypes.card"
670677
:show-work-item-type-icon="!isEpicBoard"
671678
@setFilters="$emit('setFilters', $event)"
@@ -689,11 +696,13 @@ export default {
689696
v-for="(item, index) in afterCutLine"
690697
ref="issue"
691698
:key="item.id"
692-
:index="index"
699+
:index="index + list.maxIssueCount"
693700
:list="list"
694701
:item="item"
702+
:column-index="columnIndex"
695703
:data-draggable-item-type="$options.draggableItemTypes.card"
696704
:show-work-item-type-icon="!isEpicBoard"
705+
:list-items-length="boardListItems.length"
697706
@setFilters="$emit('setFilters', $event)"
698707
>
699708
<board-card-move-to-position

app/assets/javascripts/environments/components/empty_state.vue

+6-4
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,15 @@
22
import emptyEnvironmentsSvgPath from '@gitlab/svgs/dist/illustrations/empty-state/empty-environment-md.svg';
33
import { GlButton, GlEmptyState, GlLink, GlSprintf } from '@gitlab/ui';
44
import { s__ } from '~/locale';
5+
import EmptyResult from '~/vue_shared/components/empty_result.vue';
56
67
export default {
78
components: {
89
GlButton,
910
GlEmptyState,
1011
GlLink,
1112
GlSprintf,
13+
EmptyResult,
1214
},
1315
inject: ['newEnvironmentPath'],
1416
props: {
@@ -31,9 +33,7 @@ export default {
3133
},
3234
},
3335
i18n: {
34-
searchingTitle: s__('Environments|No results found'),
3536
title: s__('Environments|Get started with environments'),
36-
searchingContent: s__('Environments|Edit your search and try again'),
3737
content: s__(
3838
'Environments|Environments are places where code gets deployed, such as staging or production. You can create an environment in the UI or in your .gitlab-ci.yml file. You can also enable review apps, which assist with providing an environment to showcase product changes. %{linkStart}Learn more%{linkEnd} about environments.',
3939
),
@@ -44,13 +44,15 @@ export default {
4444
};
4545
</script>
4646
<template>
47+
<empty-result v-if="hasTerm" type="search" />
4748
<gl-empty-state
49+
v-else
4850
class="gl-mx-auto gl-max-w-limited"
49-
:title="title"
51+
:title="$options.i18n.title"
5052
:svg-path="$options.emptyEnvironmentsSvgPath"
5153
>
5254
<template #description>
53-
<gl-sprintf :message="content">
55+
<gl-sprintf :message="$options.i18n.content">
5456
<template #link="{ content: contentToDisplay }">
5557
<gl-link :href="helpPath">{{ contentToDisplay }}</gl-link>
5658
</template>

app/assets/javascripts/environments/environment_details/components/kubernetes/kubernetes_logs.vue

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<script>
22
import { GlLoadingIcon, GlAlert, GlEmptyState, GlSprintf, GlIcon } from '@gitlab/ui';
3-
import EmptyStateSvg from '@gitlab/svgs/dist/illustrations/Dependency-list-empty-state.svg?url';
3+
import EmptyStateSvg from '@gitlab/svgs/dist/illustrations/status/status-nothing-md.svg';
44
import k8sLogsQuery from '~/environments/graphql/queries/k8s_logs.query.graphql';
55
import environmentClusterAgentQuery from '~/environments/graphql/queries/environment_cluster_agent.query.graphql';
66
import { createK8sAccessConfiguration } from '~/environments/helpers/k8s_integration_helper';

app/assets/javascripts/environments/environment_details/components/kubernetes/kubernetes_overview.vue

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import {
88
GlDisclosureDropdownItem,
99
GlModalDirective,
1010
} from '@gitlab/ui';
11-
import CLUSTER_EMPTY_SVG from '@gitlab/svgs/dist/illustrations/empty-state/empty-state-clusters.svg?url';
11+
import CLUSTER_EMPTY_SVG from '@gitlab/svgs/dist/illustrations/empty-state/empty-environment-md.svg';
1212
import { isEmpty } from 'lodash';
1313
import { s__, __ } from '~/locale';
1414
import { createAlert } from '~/alert';

app/assets/javascripts/environments/environment_details/empty_state.vue

+3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
<script>
22
import { GlEmptyState, GlLink, GlSprintf } from '@gitlab/ui';
3+
import EMPTY_SVG from '@gitlab/svgs/dist/illustrations/status/status-nothing-md.svg';
34
import { translations, environmentsLearnMorePath, environmentsHelpPagePath } from './constants';
45
56
export default {
@@ -11,10 +12,12 @@ export default {
1112
translations,
1213
actionButtonUrl: environmentsHelpPagePath,
1314
learnMoreHelpPath: environmentsLearnMorePath,
15+
EMPTY_SVG,
1416
};
1517
</script>
1618
<template>
1719
<gl-empty-state
20+
:svg-path="$options.EMPTY_SVG"
1821
:title="$options.translations.emptyStateTitle"
1922
:primary-button-text="$options.translations.emptyStatePrimaryButton"
2023
:primary-button-link="$options.actionButtonUrl"

app/assets/javascripts/members/components/table/members_table.vue

+4-2
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import { GlTable, GlBadge, GlButton } from '@gitlab/ui';
33
// eslint-disable-next-line no-restricted-imports
44
import { mapState } from 'vuex';
5+
import EmptyResult from '~/vue_shared/components/empty_result.vue';
56
import MembersTableCell from 'ee_else_ce/members/components/table/members_table_cell.vue';
67
import {
78
canDisableTwoFactor,
@@ -40,6 +41,7 @@ export default {
4041
GlTable,
4142
GlBadge,
4243
GlButton,
44+
EmptyResult,
4345
MemberAvatar,
4446
CreatedAt,
4547
MembersTableCell,
@@ -238,15 +240,14 @@ export default {
238240
<div>
239241
<user-limit-reached-alert v-if="onAccessRequestTab" />
240242
<gl-table
243+
v-if="members.length > 0"
241244
v-bind="tableAttrs.table"
242245
class="members-table"
243246
data-testid="members-table"
244247
stacked="lg"
245248
:fields="filteredAndModifiedFields"
246249
:items="members"
247250
primary-key="id"
248-
:empty-text="__('No members found')"
249-
show-empty
250251
:tbody-tr-attr="tbodyTrAttr"
251252
>
252253
<template #cell(account)="{ item: member }">
@@ -324,6 +325,7 @@ export default {
324325
<span data-testid="col-actions" class="gl-sr-only">{{ label }}</span>
325326
</template>
326327
</gl-table>
328+
<empty-result v-else />
327329
<members-pagination :pagination="pagination" :tab-query-param-value="tabQueryParamValue" />
328330
<disable-two-factor-modal />
329331
<remove-group-link-modal />

app/assets/javascripts/work_items/components/work_item_detail.vue

+6-4
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,10 @@ import WorkItemAbuseModal from './work_item_abuse_modal.vue';
6868
import DesignWidget from './design_management/design_management_widget.vue';
6969
import DesignUploadButton from './design_management/upload_button.vue';
7070
71+
const defaultWorkspacePermissions = {
72+
createDesign: false,
73+
};
74+
7175
export default {
7276
name: 'WorkItemDetail',
7377
i18n,
@@ -157,9 +161,7 @@ export default {
157161
filesToBeSaved: [],
158162
allowedChildTypes: [],
159163
designUploadError: null,
160-
workspacePermissions: {
161-
createDesign: false,
162-
},
164+
workspacePermissions: defaultWorkspacePermissions,
163165
};
164166
},
165167
apollo: {
@@ -247,7 +249,7 @@ export default {
247249
return this.isGroupWorkItem;
248250
},
249251
update(data) {
250-
return data.workspace.userPermissions;
252+
return data.workspace?.userPermissions ?? defaultWorkspacePermissions;
251253
},
252254
},
253255
},

app/assets/stylesheets/framework/buttons.scss

-8
Original file line numberDiff line numberDiff line change
@@ -174,14 +174,6 @@
174174
}
175175
}
176176

177-
.clone-dropdown-btn a {
178-
color: $gray-700;
179-
180-
&:hover {
181-
text-decoration: none;
182-
}
183-
}
184-
185177
.btn-inverted {
186178
&-secondary {
187179
@include btn-outline($white, $blue-500, $blue-500, $blue-100, $blue-700, $blue-500, $blue-200, $blue-600, $blue-800);

0 commit comments

Comments
 (0)