Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
gitlab-ce
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
1
Merge Requests
1
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
gitlab-ce
Commits
8e554b7b
Commit
8e554b7b
authored
Apr 03, 2019
by
GitLab Bot
Browse files
Options
Browse Files
Download
Plain Diff
Automatic merge of gitlab-org/gitlab-ce master
parents
43030472
07cc1885
Changes
8
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
268 additions
and
30 deletions
+268
-30
app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/timezone_dropdown.js
...pipeline_schedules/shared/components/timezone_dropdown.js
+26
-25
app/assets/javascripts/pages/projects/pipeline_schedules/shared/init_form.js
...pts/pages/projects/pipeline_schedules/shared/init_form.js
+7
-1
app/services/quick_actions/interpret_service.rb
app/services/quick_actions/interpret_service.rb
+16
-3
changelogs/unreleased/53459-quick-action-adds-multiple-labels-to-issue-if-middle-words-overlap-with-existing-label.yml
...-to-issue-if-middle-words-overlap-with-existing-label.yml
+5
-0
changelogs/unreleased/ekigbo-extend-timezone-dropdown.yml
changelogs/unreleased/ekigbo-extend-timezone-dropdown.yml
+5
-0
doc/user/project/quick_actions.md
doc/user/project/quick_actions.md
+1
-1
spec/javascripts/pages/projects/pipeline_schedules/shared/components/timezone_dropdown_spec.js
...ine_schedules/shared/components/timezone_dropdown_spec.js
+167
-0
spec/services/quick_actions/interpret_service_spec.rb
spec/services/quick_actions/interpret_service_spec.rb
+41
-0
No files found.
app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/timezone_dropdown.js
View file @
8e554b7b
/* eslint-disable class-methods-use-this */
const
defaultTimezone
=
'
UTC
'
;
export
const
formatUtcOffset
=
offset
=>
{
const
parsed
=
parseInt
(
offset
,
10
);
if
(
Number
.
isNaN
(
parsed
)
||
parsed
===
0
)
{
return
`0`
;
}
const
prefix
=
offset
>
0
?
'
+
'
:
'
-
'
;
return
`
${
prefix
}
${
Math
.
abs
(
offset
/
3600
)}
`
;
};
import
$
from
'
jquery
'
;
export
const
formatTimezone
=
item
=>
`[UTC
${
formatUtcOffset
(
item
.
offset
)}
]
${
item
.
name
}
`
;
const
defaultTimezone
=
'
UTC
'
;
const
defaults
=
{
$inputEl
:
null
,
$dropdownEl
:
null
,
onSelectTimezone
:
null
,
};
export
default
class
TimezoneDropdown
{
constructor
()
{
this
.
$dropdown
=
$
(
'
.js-timezone-dropdown
'
)
;
constructor
(
{
$dropdownEl
,
$inputEl
,
onSelectTimezone
}
=
defaults
)
{
this
.
$dropdown
=
$
dropdownEl
;
this
.
$dropdownToggle
=
this
.
$dropdown
.
find
(
'
.dropdown-toggle-text
'
);
this
.
$input
=
$
(
'
#schedule_cron_timezone
'
)
;
this
.
$input
=
$
inputEl
;
this
.
timezoneData
=
this
.
$dropdown
.
data
(
'
data
'
);
this
.
initDefaultTimezone
();
this
.
initDropdown
();
this
.
onSelectTimezone
=
onSelectTimezone
;
}
initDropdown
()
{
...
...
@@ -24,28 +40,12 @@ export default class TimezoneDropdown {
fields
:
[
'
name
'
],
},
clicked
:
cfg
=>
this
.
updateInputValue
(
cfg
),
text
:
item
=>
this
.
formatTimezone
(
item
),
text
:
item
=>
formatTimezone
(
item
),
});
this
.
setDropdownToggle
();
}
formatUtcOffset
(
offset
)
{
let
prefix
=
''
;
if
(
offset
>
0
)
{
prefix
=
'
+
'
;
}
else
if
(
offset
<
0
)
{
prefix
=
'
-
'
;
}
return
`
${
prefix
}
${
Math
.
abs
(
offset
/
3600
)}
`
;
}
formatTimezone
(
item
)
{
return
`[UTC
${
this
.
formatUtcOffset
(
item
.
offset
)}
]
${
item
.
name
}
`
;
}
initDefaultTimezone
()
{
const
initialValue
=
this
.
$input
.
val
();
...
...
@@ -56,13 +56,14 @@ export default class TimezoneDropdown {
setDropdownToggle
()
{
const
initialValue
=
this
.
$input
.
val
();
this
.
$dropdownToggle
.
text
(
initialValue
);
}
updateInputValue
({
selectedObj
,
e
})
{
e
.
preventDefault
();
this
.
$input
.
val
(
selectedObj
.
identifier
);
gl
.
pipelineScheduleFieldErrors
.
updateFormValidityState
();
if
(
this
.
onSelectTimezone
)
{
this
.
onSelectTimezone
({
selectedObj
,
e
});
}
}
}
app/assets/javascripts/pages/projects/pipeline_schedules/shared/init_form.js
View file @
8e554b7b
...
...
@@ -41,7 +41,13 @@ export default () => {
const
formElement
=
document
.
getElementById
(
'
new-pipeline-schedule-form
'
);
gl
.
timezoneDropdown
=
new
TimezoneDropdown
();
gl
.
timezoneDropdown
=
new
TimezoneDropdown
({
$dropdownEl
:
$
(
'
.js-timezone-dropdown
'
),
$inputEl
:
$
(
'
#schedule_cron_timezone
'
),
onSelectTimezone
:
()
=>
{
gl
.
pipelineScheduleFieldErrors
.
updateFormValidityState
();
},
});
gl
.
targetBranchDropdown
=
new
TargetBranchDropdown
();
gl
.
pipelineScheduleFieldErrors
=
new
GlFieldErrors
(
formElement
);
...
...
app/services/quick_actions/interpret_service.rb
View file @
8e554b7b
...
...
@@ -96,14 +96,27 @@ module QuickActions
end
def
find_labels
(
labels_params
=
nil
)
extract_references
(
labels_params
,
:label
)
|
find_labels_by_name_no_tilde
(
labels_params
)
end
def
find_labels_by_name_no_tilde
(
labels_params
)
return
Label
.
none
if
label_with_tilde?
(
labels_params
)
finder_params
=
{
include_ancestor_groups:
true
}
finder_params
[
:project_id
]
=
project
.
id
if
project
finder_params
[
:group_id
]
=
group
.
id
if
group
finder_params
[
:name
]
=
labels_params
.
split
if
labels_params
finder_params
[
:name
]
=
extract_label_names
(
labels_params
)
if
labels_params
result
=
LabelsFinder
.
new
(
current_user
,
finder_params
).
execute
LabelsFinder
.
new
(
current_user
,
finder_params
).
execute
end
def
label_with_tilde?
(
labels_params
)
labels_params
&
.
include?
(
'~'
)
end
extract_references
(
labels_params
,
:label
)
|
result
def
extract_label_names
(
labels_params
)
# '"A" "A B C" A B' => ["A", "A B C", "A", "B"]
labels_params
.
scan
(
/"([^"]+)"|([^ ]+)/
).
flatten
.
compact
end
def
find_label_references
(
labels_param
)
...
...
changelogs/unreleased/53459-quick-action-adds-multiple-labels-to-issue-if-middle-words-overlap-with-existing-label.yml
0 → 100644
View file @
8e554b7b
---
title
:
Fix quick actions add label name middle word overlaps
merge_request
:
26602
author
:
Jacopo Beschi @jacopo-beschi
type
:
fixed
changelogs/unreleased/ekigbo-extend-timezone-dropdown.yml
0 → 100644
View file @
8e554b7b
---
title
:
Extend timezone dropdown
merge_request
:
26311
author
:
type
:
changed
doc/user/project/quick_actions.md
View file @
8e554b7b
...
...
@@ -31,7 +31,7 @@ discussions, and descriptions:
|
`/reassign @user1 @user2`
| Change assignee | ✓ | ✓ |
|
`/milestone %milestone`
| Set milestone | ✓ | ✓ |
|
`/remove_milestone`
| Remove milestone | ✓ | ✓ |
|
`/label ~label1 ~label2`
| Add label(s) | ✓ | ✓ |
|
`/label ~label1 ~label2`
| Add label(s)
. Label names can also start without ~ but mixed syntax is not supported.
| ✓ | ✓ |
|
`/unlabel ~label1 ~label2`
| Remove all or specific label(s)| ✓ | ✓ |
|
`/relabel ~label1 ~label2`
| Replace label | ✓ | ✓ |
|
<code>
/copy_metadata #issue
|
!merge_request
</code>
| Copy labels and milestone from other issue or merge request | ✓ | ✓ |
...
...
spec/javascripts/pages/projects/pipeline_schedules/shared/components/timezone_dropdown_spec.js
0 → 100644
View file @
8e554b7b
import
$
from
'
jquery
'
;
import
GLDropdown
from
'
~/gl_dropdown
'
;
// eslint-disable-line no-unused-vars
import
TimezoneDropdown
,
{
formatUtcOffset
,
formatTimezone
,
}
from
'
~/pages/projects/pipeline_schedules/shared/components/timezone_dropdown
'
;
describe
(
'
Timezone Dropdown
'
,
function
()
{
preloadFixtures
(
'
pipeline_schedules/edit.html
'
);
let
$inputEl
=
null
;
let
$dropdownEl
=
null
;
let
$wrapper
=
null
;
const
tzListSel
=
'
.dropdown-content ul li a.is-active
'
;
describe
(
'
Initialize
'
,
()
=>
{
describe
(
'
with dropdown already loaded
'
,
()
=>
{
beforeEach
(()
=>
{
loadFixtures
(
'
pipeline_schedules/edit.html
'
);
$wrapper
=
$
(
'
.dropdown
'
);
$inputEl
=
$
(
'
#schedule_cron_timezone
'
);
$dropdownEl
=
$
(
'
.js-timezone-dropdown
'
);
// eslint-disable-next-line no-new
new
TimezoneDropdown
({
$inputEl
,
$dropdownEl
,
});
});
it
(
'
can take an $inputEl in the constructor
'
,
()
=>
{
const
tzStr
=
'
[UTC + 5.5] Sri Jayawardenepura
'
;
const
tzValue
=
'
Asia/Colombo
'
;
expect
(
$inputEl
.
val
()).
toBe
(
'
UTC
'
);
$
(
`
${
tzListSel
}
:contains('
${
tzStr
}
')`
,
$wrapper
).
trigger
(
'
click
'
);
const
val
=
$inputEl
.
val
();
expect
(
val
).
toBe
(
tzValue
);
expect
(
val
).
not
.
toBe
(
'
UTC
'
);
});
it
(
'
will format data array of timezones into a list of offsets
'
,
()
=>
{
const
data
=
$dropdownEl
.
data
(
'
data
'
);
const
formatted
=
$wrapper
.
find
(
tzListSel
).
text
();
data
.
forEach
(
item
=>
{
expect
(
formatted
).
toContain
(
formatTimezone
(
item
));
});
});
it
(
'
will default the timezone to UTC
'
,
()
=>
{
const
tz
=
$inputEl
.
val
();
expect
(
tz
).
toBe
(
'
UTC
'
);
});
});
describe
(
'
without dropdown loaded
'
,
()
=>
{
beforeEach
(()
=>
{
loadFixtures
(
'
pipeline_schedules/edit.html
'
);
$wrapper
=
$
(
'
.dropdown
'
);
$inputEl
=
$
(
'
#schedule_cron_timezone
'
);
$dropdownEl
=
$
(
'
.js-timezone-dropdown
'
);
});
it
(
'
will populate the list of UTC offsets after the dropdown is loaded
'
,
()
=>
{
expect
(
$wrapper
.
find
(
tzListSel
).
length
).
toEqual
(
0
);
// eslint-disable-next-line no-new
new
TimezoneDropdown
({
$inputEl
,
$dropdownEl
,
});
expect
(
$wrapper
.
find
(
tzListSel
).
length
).
toEqual
(
$
(
$dropdownEl
).
data
(
'
data
'
).
length
);
});
it
(
'
will call a provided handler when a new timezone is selected
'
,
()
=>
{
const
onSelectTimezone
=
jasmine
.
createSpy
(
'
onSelectTimezoneMock
'
);
// eslint-disable-next-line no-new
new
TimezoneDropdown
({
$inputEl
,
$dropdownEl
,
onSelectTimezone
,
});
$wrapper
.
find
(
tzListSel
)
.
first
()
.
trigger
(
'
click
'
);
expect
(
onSelectTimezone
).
toHaveBeenCalled
();
});
});
});
describe
(
'
formatUtcOffset
'
,
()
=>
{
it
(
'
will convert negative utc offsets in seconds to hours and minutes
'
,
()
=>
{
expect
(
formatUtcOffset
(
-
21600
)).
toEqual
(
'
- 6
'
);
});
it
(
'
will convert positive utc offsets in seconds to hours and minutes
'
,
()
=>
{
expect
(
formatUtcOffset
(
25200
)).
toEqual
(
'
+ 7
'
);
expect
(
formatUtcOffset
(
49500
)).
toEqual
(
'
+ 13.75
'
);
});
it
(
'
will return 0 when given a string
'
,
()
=>
{
expect
(
formatUtcOffset
(
'
BLAH
'
)).
toEqual
(
'
0
'
);
expect
(
formatUtcOffset
(
'
$%$%
'
)).
toEqual
(
'
0
'
);
});
it
(
'
will return 0 when given an array
'
,
()
=>
{
expect
(
formatUtcOffset
([
'
an
'
,
'
array
'
])).
toEqual
(
'
0
'
);
});
it
(
'
will return 0 when given an object
'
,
()
=>
{
expect
(
formatUtcOffset
({
some
:
''
,
object
:
''
})).
toEqual
(
'
0
'
);
});
it
(
'
will return 0 when given null
'
,
()
=>
{
expect
(
formatUtcOffset
(
null
)).
toEqual
(
'
0
'
);
});
it
(
'
will return 0 when given undefined
'
,
()
=>
{
expect
(
formatUtcOffset
(
undefined
)).
toEqual
(
'
0
'
);
});
it
(
'
will return 0 when given empty input
'
,
()
=>
{
expect
(
formatUtcOffset
(
''
)).
toEqual
(
'
0
'
);
});
});
describe
(
'
formatTimezone
'
,
()
=>
{
it
(
'
given name: "Chatham Is.", offset: "49500", will format for display as "[UTC + 13.75] Chatham Is."
'
,
()
=>
{
expect
(
formatTimezone
({
name
:
'
Chatham Is.
'
,
offset
:
49500
,
identifier
:
'
Pacific/Chatham
'
,
}),
).
toEqual
(
'
[UTC + 13.75] Chatham Is.
'
);
});
it
(
'
given name: "Saskatchewan", offset: "-21600", will format for display as "[UTC - 6] Saskatchewan"
'
,
()
=>
{
expect
(
formatTimezone
({
name
:
'
Saskatchewan
'
,
offset
:
-
21600
,
identifier
:
'
America/Regina
'
,
}),
).
toEqual
(
'
[UTC - 6] Saskatchewan
'
);
});
it
(
'
given name: "Accra", offset: "0", will format for display as "[UTC 0] Accra"
'
,
()
=>
{
expect
(
formatTimezone
({
name
:
'
Accra
'
,
offset
:
0
,
identifier
:
'
Africa/Accra
'
,
}),
).
toEqual
(
'
[UTC 0] Accra
'
);
});
});
});
spec/services/quick_actions/interpret_service_spec.rb
View file @
8e554b7b
...
...
@@ -10,6 +10,7 @@ describe QuickActions::InterpretService do
let
(
:milestone
)
{
create
(
:milestone
,
project:
project
,
title:
'9.10'
)
}
let
(
:commit
)
{
create
(
:commit
,
project:
project
)
}
let
(
:inprogress
)
{
create
(
:label
,
project:
project
,
title:
'In Progress'
)
}
let
(
:helmchart
)
{
create
(
:label
,
project:
project
,
title:
'Helm Chart Registry'
)
}
let
(
:bug
)
{
create
(
:label
,
project:
project
,
title:
'Bug'
)
}
let
(
:note
)
{
build
(
:note
,
commit_id:
merge_request
.
diff_head_sha
)
}
let
(
:service
)
{
described_class
.
new
(
project
,
developer
)
}
...
...
@@ -94,6 +95,26 @@ describe QuickActions::InterpretService do
end
end
shared_examples
'multiword label name starting without ~'
do
it
'fetches label ids and populates add_label_ids if content contains /label'
do
helmchart
# populate the label
_
,
updates
=
service
.
execute
(
content
,
issuable
)
expect
(
updates
).
to
eq
(
add_label_ids:
[
helmchart
.
id
])
end
end
shared_examples
'label name is included in the middle of another label name'
do
it
'ignores the sublabel when the content contains the includer label name'
do
helmchart
# populate the label
create
(
:label
,
project:
project
,
title:
'Chart'
)
_
,
updates
=
service
.
execute
(
content
,
issuable
)
expect
(
updates
).
to
eq
(
add_label_ids:
[
helmchart
.
id
])
end
end
shared_examples
'unlabel command'
do
it
'fetches label ids and populates remove_label_ids if content contains /unlabel'
do
issuable
.
update!
(
label_ids:
[
inprogress
.
id
])
# populate the label
...
...
@@ -664,6 +685,26 @@ describe QuickActions::InterpretService do
let
(
:issuable
)
{
issue
}
end
it_behaves_like
'multiword label name starting without ~'
do
let
(
:content
)
{
%(/label "#{helmchart.title}")
}
let
(
:issuable
)
{
issue
}
end
it_behaves_like
'multiword label name starting without ~'
do
let
(
:content
)
{
%(/label "#{helmchart.title}")
}
let
(
:issuable
)
{
merge_request
}
end
it_behaves_like
'label name is included in the middle of another label name'
do
let
(
:content
)
{
%(/label ~"#{helmchart.title}")
}
let
(
:issuable
)
{
issue
}
end
it_behaves_like
'label name is included in the middle of another label name'
do
let
(
:content
)
{
%(/label ~"#{helmchart.title}")
}
let
(
:issuable
)
{
merge_request
}
end
it_behaves_like
'unlabel command'
do
let
(
:content
)
{
%(/unlabel ~"#{inprogress.title}")
}
let
(
:issuable
)
{
issue
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment