Skip to content

Commit f6e2d07

Browse files
author
GitLab Bot
committed
Add latest changes from gitlab-org/gitlab@master
1 parent 687bfbe commit f6e2d07

File tree

26 files changed

+814
-474
lines changed

26 files changed

+814
-474
lines changed

.projections.json.example

+89-6
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
{
22
"ee/*": { "type": "ee" },
3+
"app/*": { "type": "ce" },
4+
"lib/*": { "type": "ce" },
35
"config/initializers/*.rb": {
46
"alternate": "spec/initializers/{}_spec.rb",
57
"type": "source"
@@ -57,37 +59,40 @@
5759
"type": "source"
5860
},
5961
"app/presenters/*.rb": {
62+
"alternate": "spec/app/presenters/{}_spec.rb",
6063
"related": "ee/app/presenters/ee/{}.rb",
6164
"type": "source"
6265
},
6366
"app/serializers/*.rb": {
67+
"alternate": "spec/app/serializers/{}_spec.rb",
6468
"related": "ee/app/serializers/ee/{}.rb",
6569
"type": "source"
6670
},
6771
"app/services/*.rb": {
72+
"alternate": "spec/app/services/{}_spec.rb",
6873
"related": "ee/app/services/ee/{}.rb",
6974
"type": "source"
7075
},
7176
"app/uploaders/*.rb": {
77+
"alternate": "spec/app/uploaders/{}_spec.rb",
7278
"related": "ee/app/uploaders/ee/{}.rb",
7379
"type": "source"
7480
},
7581
"app/validators/*.rb": {
82+
"alternate": "spec/app/validators/{}_spec.rb",
7683
"related": "ee/app/validators/ee/{}.rb",
7784
"type": "source"
7885
},
7986
"app/views/*.rb": {
87+
"alternate": "spec/app/views/{}_spec.rb",
8088
"related": "ee/app/views/ee/{}.rb",
8189
"type": "source"
8290
},
8391
"app/workers/*.rb": {
92+
"alternate": "spec/app/workers/{}_spec.rb",
8493
"related": "ee/app/workers/ee/{}.rb",
8594
"type": "source"
8695
},
87-
"app/*.rb": {
88-
"alternate": "spec/{}_spec.rb",
89-
"type": "source"
90-
},
9196
"spec/*_spec.rb": {
9297
"alternate": "app/{}.rb",
9398
"type": "test"
@@ -124,8 +129,79 @@
124129
"alternate": "ee/lib/api/{}.rb",
125130
"type": "test"
126131
},
132+
"ee/app/controllers/ee/*.rb": {
133+
"alternate": "ee/spec/{}_spec.rb",
134+
"related": "app/controllers/{}.rb",
135+
"type": "source"
136+
},
137+
"ee/app/finders/ee/*.rb": {
138+
"alternate": "ee/spec/{}_spec.rb",
139+
"related": "app/finders/{}.rb",
140+
"type": "source"
141+
},
142+
"ee/app/graphql/ee/*.rb": {
143+
"alternate": "ee/spec/{}_spec.rb",
144+
"related": "app/graphql/{}.rb",
145+
"type": "source"
146+
},
147+
"ee/app/helpers/ee/*.rb": {
148+
"alternate": "ee/spec/{}_spec.rb",
149+
"related": "app/helpers/{}.rb",
150+
"type": "source"
151+
},
152+
"ee/app/mailers/ee/*.rb": {
153+
"alternate": "ee/spec/{}_spec.rb",
154+
"related": "app/mailers/{}.rb",
155+
"type": "source"
156+
},
157+
"ee/app/models/ee/*.rb": {
158+
"alternate": "ee/spec/{}_spec.rb",
159+
"related": "app/models/{}.rb",
160+
"type": "source"
161+
},
162+
"ee/app/policies/ee/*.rb": {
163+
"alternate": "ee/spec/{}_spec.rb",
164+
"related": "app/policies/{}.rb",
165+
"type": "source"
166+
},
167+
"ee/app/presenters/ee/*.rb": {
168+
"alternate": "ee/spec/{}_spec.rb",
169+
"related": "app/presenters/{}.rb",
170+
"type": "source"
171+
},
172+
"ee/app/serializers/ee/*.rb": {
173+
"alternate": "spec/app/serializers/{}_spec.rb",
174+
"related": "app/serializers/{}.rb",
175+
"type": "source"
176+
},
177+
"ee/app/services/ee/*.rb": {
178+
"alternate": "spec/app/services/{}_spec.rb",
179+
"related": "app/services/{}.rb",
180+
"type": "source"
181+
},
182+
"ee/app/uploaders/ee/*.rb": {
183+
"alternate": "spec/app/uploaders/{}_spec.rb",
184+
"related": "app/uploaders/{}.rb",
185+
"type": "source"
186+
},
187+
"ee/app/validators/ee/*.rb": {
188+
"alternate": "spec/app/validators/{}_spec.rb",
189+
"related": "app/validators/{}.rb",
190+
"type": "source"
191+
},
192+
"ee/app/views/ee/*.rb": {
193+
"alternate": "spec/app/views/{}_spec.rb",
194+
"related": "app/views/{}.rb",
195+
"type": "source"
196+
},
197+
"ee/app/workers/ee/*.rb": {
198+
"alternate": "spec/app/workers/{}_spec.rb",
199+
"related": "app/workers/{}.rb",
200+
"type": "source"
201+
},
127202
"ee/app/*.rb": {
128203
"alternate": "ee/spec/{}_spec.rb",
204+
"related": "app/{}.rb",
129205
"type": "source"
130206
},
131207
"ee/spec/*_spec.rb": {
@@ -136,6 +212,11 @@
136212
"alternate": "ee/spec/lib/{}_spec.rb",
137213
"type": "source"
138214
},
215+
"ee/lib/ee/*.rb": {
216+
"alternate": "ee/spec/lib/{}_spec.rb",
217+
"related": "lib/{}.rb",
218+
"type": "source"
219+
},
139220
"ee/spec/lib/*_spec.rb": {
140221
"alternate": "ee/lib/{}.rb",
141222
"type": "test"
@@ -154,16 +235,18 @@
154235
},
155236
"ee/app/assets/javascripts/*.js": {
156237
"alternate": "ee/spec/frontend/{}_spec.js",
238+
"related": "app/assets/javascripts/{}.js",
157239
"type": "source"
158240
},
159241
"ee/app/assets/javascripts/*.vue": {
160242
"alternate": "ee/spec/frontend/{}_spec.js",
243+
"related": "app/assets/javascripts/{}.vue",
161244
"type": "source"
162245
},
163246
"ee/spec/frontend/*_spec.js": {
164247
"alternate": ["ee/app/assets/javascripts/{}.vue", "ee/app/assets/javascripts/{}.js"],
165248
"type": "test"
166249
},
167-
"*.rb": {"dispatch": "bundle exec rubocop {file}"},
168-
"*_spec.rb": {"dispatch": "bundle exec rspec {file}"}
250+
"*.rb": { "dispatch": "bundle exec rubocop {file}" },
251+
"*_spec.rb": { "dispatch": "bundle exec rspec {file}" }
169252
}

app/assets/javascripts/content_editor/components/suggestions_dropdown.vue

+28-9
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ export default {
4242
4343
computed: {
4444
isReference() {
45-
return this.nodeType === 'reference';
45+
return this.nodeType.startsWith('reference');
4646
},
4747
4848
isCommand() {
@@ -96,7 +96,7 @@ export default {
9696
getText(item) {
9797
if (this.isEmoji) return item.e;
9898
99-
switch (this.nodeType === 'reference' && this.nodeProps.referenceType) {
99+
switch (this.isReference && this.nodeProps.referenceType) {
100100
case 'user':
101101
return `${this.char}${item.username}`;
102102
case 'issue':
@@ -105,12 +105,13 @@ export default {
105105
case 'snippet':
106106
return `${this.char}${item.id}`;
107107
case 'milestone':
108-
case 'label':
109108
return `${this.char}${item.title}`;
109+
case 'label':
110+
return item.title;
110111
case 'command':
111-
return `${this.char}${item.name} `;
112+
return `${this.char}${item.name}`;
112113
case 'epic':
113-
return `${item.reference}`;
114+
return item.reference;
114115
case 'vulnerability':
115116
return `[vulnerability:${item.id}]`;
116117
default:
@@ -119,17 +120,35 @@ export default {
119120
},
120121
121122
getProps(item) {
123+
const props = {};
124+
122125
if (this.isEmoji) {
123-
return {
126+
Object.assign(props, {
124127
name: item.name,
125128
unicodeVersion: item.u,
126129
title: item.d,
127130
moji: item.e,
128-
...this.nodeProps,
129-
};
131+
});
130132
}
131133
132-
return this.nodeProps;
134+
if (this.isLabel || this.isMilestone) {
135+
Object.assign(props, {
136+
originalText: `${this.char}${
137+
/\W/.test(item.title) ? JSON.stringify(item.title) : item.title
138+
}`,
139+
});
140+
}
141+
142+
if (this.isLabel) {
143+
Object.assign(props, {
144+
text: item.title,
145+
color: item.color,
146+
});
147+
}
148+
149+
Object.assign(props, this.nodeProps);
150+
151+
return props;
133152
},
134153
135154
onKeyDown({ event }) {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
<script>
2+
import { NodeViewWrapper } from '@tiptap/vue-2';
3+
import { GlLabel } from '@gitlab/ui';
4+
import { isScopedLabel } from '~/lib/utils/common_utils';
5+
6+
export default {
7+
name: 'DetailsWrapper',
8+
components: {
9+
NodeViewWrapper,
10+
GlLabel,
11+
},
12+
props: {
13+
node: {
14+
type: Object,
15+
required: true,
16+
},
17+
},
18+
computed: {
19+
isScopedLabel() {
20+
return isScopedLabel({ title: this.node.attrs.originalText });
21+
},
22+
},
23+
};
24+
</script>
25+
<template>
26+
<node-view-wrapper class="gl-display-inline-block">
27+
<gl-label
28+
size="sm"
29+
:scoped="isScopedLabel"
30+
:background-color="node.attrs.color"
31+
:title="node.attrs.text"
32+
/>
33+
</node-view-wrapper>
34+
</template>

app/assets/javascripts/content_editor/extensions/reference.js

+1-13
Original file line numberDiff line numberDiff line change
@@ -46,22 +46,10 @@ export default Node.create({
4646
tag: 'a.gfm:not([data-link=true])',
4747
priority: PARSE_HTML_PRIORITY_HIGHEST,
4848
},
49-
{
50-
tag: 'span.gl-label',
51-
},
5249
];
5350
},
5451

5552
renderHTML({ node }) {
56-
return [
57-
'a',
58-
{
59-
class: node.attrs.className,
60-
href: '#',
61-
'data-reference-type': node.attrs.referenceType,
62-
'data-original': node.attrs.originalText,
63-
},
64-
node.attrs.text,
65-
];
53+
return ['a', { href: '#' }, node.attrs.text];
6654
},
6755
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import { VueNodeViewRenderer } from '@tiptap/vue-2';
2+
import { SCOPED_LABEL_DELIMITER } from '~/vue_shared/components/sidebar/labels_select_widget/constants';
3+
import LabelWrapper from '../components/wrappers/label.vue';
4+
import Reference from './reference';
5+
6+
export default Reference.extend({
7+
name: 'reference_label',
8+
9+
addAttributes() {
10+
return {
11+
...this.parent(),
12+
text: {
13+
default: null,
14+
parseHTML: (element) => {
15+
const text = element.querySelector('.gl-label-text').textContent;
16+
const scopedText = element.querySelector('.gl-label-text-scoped')?.textContent;
17+
if (!scopedText) return text;
18+
return `${text}${SCOPED_LABEL_DELIMITER}${scopedText}`;
19+
},
20+
},
21+
color: {
22+
default: null,
23+
parseHTML: (element) => element.querySelector('.gl-label-text').style.backgroundColor,
24+
},
25+
};
26+
},
27+
28+
parseHTML() {
29+
return [{ tag: 'span.gl-label' }];
30+
},
31+
32+
addNodeView() {
33+
return new VueNodeViewRenderer(LabelWrapper);
34+
},
35+
});

app/assets/javascripts/content_editor/extensions/suggestions.js

+8-5
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,10 @@ function createSuggestionPlugin({
3434
tiptapEditor
3535
.chain()
3636
.focus()
37-
.insertContentAt(range, [{ type: nodeType, attrs: props }])
37+
.insertContentAt(range, [
38+
{ type: nodeType, attrs: props },
39+
{ type: 'text', text: ' ' },
40+
])
3841
.run();
3942
},
4043

@@ -82,7 +85,7 @@ function createSuggestionPlugin({
8285
},
8386

8487
onUpdate(props) {
85-
component.updateProps(props);
88+
component?.updateProps(props);
8689

8790
if (!props.clientRect) {
8891
return;
@@ -100,12 +103,12 @@ function createSuggestionPlugin({
100103
return true;
101104
}
102105

103-
return component.ref?.onKeyDown(props);
106+
return component?.ref?.onKeyDown(props);
104107
},
105108

106109
onExit() {
107110
popup?.[0].destroy();
108-
component.destroy();
111+
component?.destroy();
109112
},
110113
};
111114
},
@@ -151,7 +154,7 @@ export default Node.create({
151154
editor: this.editor,
152155
char: '~',
153156
dataSource: gl.GfmAutoComplete?.dataSources.labels,
154-
nodeType: 'reference',
157+
nodeType: 'reference_label',
155158
nodeProps: {
156159
referenceType: 'label',
157160
},

app/assets/javascripts/content_editor/services/create_content_editor.js

+2
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ import OrderedList from '../extensions/ordered_list';
4343
import Paragraph from '../extensions/paragraph';
4444
import PasteMarkdown from '../extensions/paste_markdown';
4545
import Reference from '../extensions/reference';
46+
import ReferenceLabel from '../extensions/reference_label';
4647
import ReferenceDefinition from '../extensions/reference_definition';
4748
import Sourcemap from '../extensions/sourcemap';
4849
import Strike from '../extensions/strike';
@@ -132,6 +133,7 @@ export const createContentEditor = ({
132133
Paragraph,
133134
PasteMarkdown.configure({ eventHub, renderMarkdown }),
134135
Reference,
136+
ReferenceLabel,
135137
ReferenceDefinition,
136138
Sourcemap,
137139
Strike,

0 commit comments

Comments
 (0)