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
c559bcca
Commit
c559bcca
authored
Oct 10, 2018
by
Mike Greiling
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Prettify additional modules (I through Z)
parent
aeaf6686
Changes
50
Hide whitespace changes
Inline
Side-by-side
Showing
50 changed files
with
1330 additions
and
1051 deletions
+1330
-1051
app/assets/javascripts/issuable_index.js
app/assets/javascripts/issuable_index.js
+6
-3
app/assets/javascripts/issue.js
app/assets/javascripts/issue.js
+44
-29
app/assets/javascripts/job.js
app/assets/javascripts/job.js
+13
-15
app/assets/javascripts/label_manager.js
app/assets/javascripts/label_manager.js
+7
-7
app/assets/javascripts/labels.js
app/assets/javascripts/labels.js
+1
-1
app/assets/javascripts/layout_nav.js
app/assets/javascripts/layout_nav.js
+33
-27
app/assets/javascripts/line_highlighter.js
app/assets/javascripts/line_highlighter.js
+17
-11
app/assets/javascripts/locale/sprintf.js
app/assets/javascripts/locale/sprintf.js
+1
-1
app/assets/javascripts/member_expiration_date.js
app/assets/javascripts/member_expiration_date.js
+6
-2
app/assets/javascripts/merge_request.js
app/assets/javascripts/merge_request.js
+13
-10
app/assets/javascripts/milestone.js
app/assets/javascripts/milestone.js
+20
-14
app/assets/javascripts/mini_pipeline_graph_dropdown.js
app/assets/javascripts/mini_pipeline_graph_dropdown.js
+11
-6
app/assets/javascripts/namespace_select.js
app/assets/javascripts/namespace_select.js
+4
-4
app/assets/javascripts/network/branch_graph.js
app/assets/javascripts/network/branch_graph.js
+89
-73
app/assets/javascripts/network/raphael.js
app/assets/javascripts/network/raphael.js
+1
-1
app/assets/javascripts/new_branch_form.js
app/assets/javascripts/new_branch_form.js
+7
-7
app/assets/javascripts/new_commit_form.js
app/assets/javascripts/new_commit_form.js
+1
-3
app/assets/javascripts/notifications_dropdown.js
app/assets/javascripts/notifications_dropdown.js
+3
-1
app/assets/javascripts/notifications_form.js
app/assets/javascripts/notifications_form.js
+7
-3
app/assets/javascripts/pager.js
app/assets/javascripts/pager.js
+18
-15
app/assets/javascripts/pdf/index.vue
app/assets/javascripts/pdf/index.vue
+52
-51
app/assets/javascripts/pdf/page/index.vue
app/assets/javascripts/pdf/page/index.vue
+53
-50
app/assets/javascripts/pipelines/components/pipelines_table_row.vue
.../javascripts/pipelines/components/pipelines_table_row.vue
+1
-4
app/assets/javascripts/project_find_file.js
app/assets/javascripts/project_find_file.js
+56
-39
app/assets/javascripts/project_import.js
app/assets/javascripts/project_import.js
+0
-1
app/assets/javascripts/project_label_subscription.js
app/assets/javascripts/project_label_subscription.js
+23
-20
app/assets/javascripts/project_select.js
app/assets/javascripts/project_select.js
+29
-20
app/assets/javascripts/project_select_combo_button.js
app/assets/javascripts/project_select_combo_button.js
+20
-7
app/assets/javascripts/project_visibility.js
app/assets/javascripts/project_visibility.js
+2
-3
app/assets/javascripts/prometheus_metrics/prometheus_metrics.js
...sets/javascripts/prometheus_metrics/prometheus_metrics.js
+25
-11
app/assets/javascripts/raven/raven_config.js
app/assets/javascripts/raven/raven_config.js
+1
-1
app/assets/javascripts/ref_select_dropdown.js
app/assets/javascripts/ref_select_dropdown.js
+3
-2
app/assets/javascripts/settings_panels.js
app/assets/javascripts/settings_panels.js
+8
-3
app/assets/javascripts/single_file_diff.js
app/assets/javascripts/single_file_diff.js
+25
-9
app/assets/javascripts/smart_interval.js
app/assets/javascripts/smart_interval.js
+12
-8
app/assets/javascripts/star.js
app/assets/javascripts/star.js
+6
-2
app/assets/javascripts/task_list.js
app/assets/javascripts/task_list.js
+7
-2
app/assets/javascripts/templates/issuable_template_selector.js
...ssets/javascripts/templates/issuable_template_selector.js
+12
-6
app/assets/javascripts/terminal/terminal.js
app/assets/javascripts/terminal/terminal.js
+8
-4
app/assets/javascripts/test_utils/simulate_drag.js
app/assets/javascripts/test_utils/simulate_drag.js
+43
-13
app/assets/javascripts/test_utils/simulate_input.js
app/assets/javascripts/test_utils/simulate_input.js
+1
-1
app/assets/javascripts/toggle_buttons.js
app/assets/javascripts/toggle_buttons.js
+1
-1
app/assets/javascripts/tree.js
app/assets/javascripts/tree.js
+9
-9
app/assets/javascripts/u2f/authenticate.js
app/assets/javascripts/u2f/authenticate.js
+9
-5
app/assets/javascripts/u2f/register.js
app/assets/javascripts/u2f/register.js
+9
-4
app/assets/javascripts/u2f/util.js
app/assets/javascripts/u2f/util.js
+2
-3
app/assets/javascripts/ui_development_kit.js
app/assets/javascripts/ui_development_kit.js
+11
-7
app/assets/javascripts/usage_ping_consent.js
app/assets/javascripts/usage_ping_consent.js
+3
-2
app/assets/javascripts/users_select.js
app/assets/javascripts/users_select.js
+576
-519
app/assets/javascripts/zen_mode.js
app/assets/javascripts/zen_mode.js
+21
-11
No files found.
app/assets/javascripts/issuable_index.js
View file @
c559bcca
...
@@ -26,14 +26,17 @@ export default class IssuableIndex {
...
@@ -26,14 +26,17 @@ export default class IssuableIndex {
static
resetIncomingEmailToken
()
{
static
resetIncomingEmailToken
()
{
const
$resetToken
=
$
(
'
.incoming-email-token-reset
'
);
const
$resetToken
=
$
(
'
.incoming-email-token-reset
'
);
$resetToken
.
on
(
'
click
'
,
(
e
)
=>
{
$resetToken
.
on
(
'
click
'
,
e
=>
{
e
.
preventDefault
();
e
.
preventDefault
();
$resetToken
.
text
(
'
resetting...
'
);
$resetToken
.
text
(
'
resetting...
'
);
axios
.
put
(
$resetToken
.
attr
(
'
href
'
))
axios
.
put
(
$resetToken
.
attr
(
'
href
'
))
.
then
(({
data
})
=>
{
.
then
(({
data
})
=>
{
$
(
'
#issuable_email
'
).
val
(
data
.
new_address
).
focus
();
$
(
'
#issuable_email
'
)
.
val
(
data
.
new_address
)
.
focus
();
$resetToken
.
text
(
'
reset it
'
);
$resetToken
.
text
(
'
reset it
'
);
})
})
...
...
app/assets/javascripts/issue.js
View file @
c559bcca
...
@@ -28,7 +28,7 @@ export default class Issue {
...
@@ -28,7 +28,7 @@ export default class Issue {
}
}
// Listen to state changes in the Vue app
// Listen to state changes in the Vue app
document
.
addEventListener
(
'
issuable_vue_app:change
'
,
(
event
)
=>
{
document
.
addEventListener
(
'
issuable_vue_app:change
'
,
event
=>
{
this
.
updateTopState
(
event
.
detail
.
isClosed
,
event
.
detail
.
data
);
this
.
updateTopState
(
event
.
detail
.
isClosed
,
event
.
detail
.
data
);
});
});
}
}
...
@@ -55,7 +55,13 @@ export default class Issue {
...
@@ -55,7 +55,13 @@ export default class Issue {
$
(
document
).
trigger
(
'
issuable:change
'
,
isClosed
);
$
(
document
).
trigger
(
'
issuable:change
'
,
isClosed
);
this
.
toggleCloseReopenButton
(
isClosed
);
this
.
toggleCloseReopenButton
(
isClosed
);
let
numProjectIssues
=
Number
(
projectIssuesCounter
.
first
().
text
().
trim
().
replace
(
/
[^\d]
/
,
''
));
let
numProjectIssues
=
Number
(
projectIssuesCounter
.
first
()
.
text
()
.
trim
()
.
replace
(
/
[^\d]
/
,
''
),
);
numProjectIssues
=
isClosed
?
numProjectIssues
-
1
:
numProjectIssues
+
1
;
numProjectIssues
=
isClosed
?
numProjectIssues
-
1
:
numProjectIssues
+
1
;
projectIssuesCounter
.
text
(
addDelimiter
(
numProjectIssues
));
projectIssuesCounter
.
text
(
addDelimiter
(
numProjectIssues
));
...
@@ -76,29 +82,34 @@ export default class Issue {
...
@@ -76,29 +82,34 @@ export default class Issue {
initIssueBtnEventListeners
()
{
initIssueBtnEventListeners
()
{
const
issueFailMessage
=
'
Unable to update this issue at this time.
'
;
const
issueFailMessage
=
'
Unable to update this issue at this time.
'
;
return
$
(
document
).
on
(
'
click
'
,
'
.js-issuable-actions a.btn-close, .js-issuable-actions a.btn-reopen
'
,
(
e
)
=>
{
return
$
(
document
).
on
(
var
$button
,
shouldSubmit
,
url
;
'
click
'
,
e
.
preventDefault
();
'
.js-issuable-actions a.btn-close, .js-issuable-actions a.btn-reopen
'
,
e
.
stopImmediatePropagation
();
e
=>
{
$button
=
$
(
e
.
currentTarget
);
var
$button
,
shouldSubmit
,
url
;
shouldSubmit
=
$button
.
hasClass
(
'
btn-comment
'
);
e
.
preventDefault
();
if
(
shouldSubmit
)
{
e
.
stopImmediatePropagation
();
Issue
.
submitNoteForm
(
$button
.
closest
(
'
form
'
));
$button
=
$
(
e
.
currentTarget
);
}
shouldSubmit
=
$button
.
hasClass
(
'
btn-comment
'
);
if
(
shouldSubmit
)
{
this
.
disableCloseReopenButton
(
$button
);
Issue
.
submitNoteForm
(
$button
.
closest
(
'
form
'
));
}
url
=
$button
.
attr
(
'
href
'
);
this
.
disableCloseReopenButton
(
$button
);
return
axios
.
put
(
url
)
.
then
(({
data
})
=>
{
url
=
$button
.
attr
(
'
href
'
);
const
isClosed
=
$button
.
hasClass
(
'
btn-close
'
);
return
axios
this
.
updateTopState
(
isClosed
,
data
);
.
put
(
url
)
})
.
then
(({
data
})
=>
{
.
catch
(()
=>
flash
(
issueFailMessage
))
const
isClosed
=
$button
.
hasClass
(
'
btn-close
'
);
.
then
(()
=>
{
this
.
updateTopState
(
isClosed
,
data
);
this
.
disableCloseReopenButton
(
$button
,
false
);
})
});
.
catch
(()
=>
flash
(
issueFailMessage
))
});
.
then
(()
=>
{
this
.
disableCloseReopenButton
(
$button
,
false
);
});
},
);
}
}
initCloseReopenReport
()
{
initCloseReopenReport
()
{
...
@@ -124,7 +135,7 @@ export default class Issue {
...
@@ -124,7 +135,7 @@ export default class Issue {
static
submitNoteForm
(
form
)
{
static
submitNoteForm
(
form
)
{
var
noteText
;
var
noteText
;
noteText
=
form
.
find
(
"
textarea.js-note-text
"
).
val
();
noteText
=
form
.
find
(
'
textarea.js-note-text
'
).
val
();
if
(
noteText
&&
noteText
.
trim
().
length
>
0
)
{
if
(
noteText
&&
noteText
.
trim
().
length
>
0
)
{
return
form
.
submit
();
return
form
.
submit
();
}
}
...
@@ -133,22 +144,26 @@ export default class Issue {
...
@@ -133,22 +144,26 @@ export default class Issue {
static
initMergeRequests
()
{
static
initMergeRequests
()
{
var
$container
;
var
$container
;
$container
=
$
(
'
#merge-requests
'
);
$container
=
$
(
'
#merge-requests
'
);
return
axios
.
get
(
$container
.
data
(
'
url
'
))
return
axios
.
get
(
$container
.
data
(
'
url
'
))
.
then
(({
data
})
=>
{
.
then
(({
data
})
=>
{
if
(
'
html
'
in
data
)
{
if
(
'
html
'
in
data
)
{
$container
.
html
(
data
.
html
);
$container
.
html
(
data
.
html
);
}
}
}).
catch
(()
=>
flash
(
'
Failed to load referenced merge requests
'
));
})
.
catch
(()
=>
flash
(
'
Failed to load referenced merge requests
'
));
}
}
static
initRelatedBranches
()
{
static
initRelatedBranches
()
{
var
$container
;
var
$container
;
$container
=
$
(
'
#related-branches
'
);
$container
=
$
(
'
#related-branches
'
);
return
axios
.
get
(
$container
.
data
(
'
url
'
))
return
axios
.
get
(
$container
.
data
(
'
url
'
))
.
then
(({
data
})
=>
{
.
then
(({
data
})
=>
{
if
(
'
html
'
in
data
)
{
if
(
'
html
'
in
data
)
{
$container
.
html
(
data
.
html
);
$container
.
html
(
data
.
html
);
}
}
}).
catch
(()
=>
flash
(
'
Failed to load related branches
'
));
})
.
catch
(()
=>
flash
(
'
Failed to load related branches
'
));
}
}
}
}
app/assets/javascripts/job.js
View file @
c559bcca
...
@@ -42,16 +42,14 @@ export default class Job extends LogOutputBehaviours {
...
@@ -42,16 +42,14 @@ export default class Job extends LogOutputBehaviours {
this
.
scrollThrottled
=
_
.
throttle
(
this
.
toggleScroll
.
bind
(
this
),
100
);
this
.
scrollThrottled
=
_
.
throttle
(
this
.
toggleScroll
.
bind
(
this
),
100
);
this
.
$window
this
.
$window
.
off
(
'
scroll
'
).
on
(
'
scroll
'
,
()
=>
{
.
off
(
'
scroll
'
)
if
(
!
isScrolledToBottom
())
{
.
on
(
'
scroll
'
,
()
=>
{
this
.
toggleScrollAnimation
(
false
);
if
(
!
isScrolledToBottom
())
{
}
else
if
(
isScrolledToBottom
()
&&
!
this
.
isLogComplete
)
{
this
.
toggleScrollAnimation
(
false
);
this
.
toggleScrollAnimation
(
true
);
}
else
if
(
isScrolledToBottom
()
&&
!
this
.
isLogComplete
)
{
}
this
.
toggleScrollAnimation
(
true
);
this
.
scrollThrottled
();
}
});
this
.
scrollThrottled
();
});
this
.
$window
this
.
$window
.
off
(
'
resize.build
'
)
.
off
(
'
resize.build
'
)
...
@@ -87,10 +85,11 @@ export default class Job extends LogOutputBehaviours {
...
@@ -87,10 +85,11 @@ export default class Job extends LogOutputBehaviours {
}
}
getBuildTrace
()
{
getBuildTrace
()
{
return
axios
.
get
(
`
${
this
.
pagePath
}
/trace.json`
,
{
return
axios
params
:
{
state
:
this
.
state
},
.
get
(
`
${
this
.
pagePath
}
/trace.json`
,
{
})
params
:
{
state
:
this
.
state
},
.
then
((
res
)
=>
{
})
.
then
(
res
=>
{
const
log
=
res
.
data
;
const
log
=
res
.
data
;
if
(
!
this
.
fetchingStatusFavicon
)
{
if
(
!
this
.
fetchingStatusFavicon
)
{
...
@@ -186,5 +185,4 @@ export default class Job extends LogOutputBehaviours {
...
@@ -186,5 +185,4 @@ export default class Job extends LogOutputBehaviours {
sidebarOnClick
()
{
sidebarOnClick
()
{
if
(
this
.
shouldHideSidebarForViewport
())
this
.
toggleSidebar
();
if
(
this
.
shouldHideSidebarForViewport
())
this
.
toggleSidebar
();
}
}
}
}
app/assets/javascripts/label_manager.js
View file @
c559bcca
...
@@ -47,7 +47,10 @@ export default class LabelManager {
...
@@ -47,7 +47,10 @@ export default class LabelManager {
}
}
toggleEmptyState
(
$label
,
$btn
,
action
)
{
toggleEmptyState
(
$label
,
$btn
,
action
)
{
this
.
emptyState
.
classList
.
toggle
(
'
hidden
'
,
!!
this
.
prioritizedLabels
[
0
].
querySelector
(
'
:scope > li
'
));
this
.
emptyState
.
classList
.
toggle
(
'
hidden
'
,
!!
this
.
prioritizedLabels
[
0
].
querySelector
(
'
:scope > li
'
),
);
}
}
toggleLabelPriority
(
$label
,
action
,
persistState
)
{
toggleLabelPriority
(
$label
,
action
,
persistState
)
{
...
@@ -80,16 +83,14 @@ export default class LabelManager {
...
@@ -80,16 +83,14 @@ export default class LabelManager {
return
;
return
;
}
}
if
(
action
===
'
remove
'
)
{
if
(
action
===
'
remove
'
)
{
axios
.
delete
(
url
)
axios
.
delete
(
url
).
catch
(
rollbackLabelPosition
);
.
catch
(
rollbackLabelPosition
);
// Restore empty message
// Restore empty message
if
(
!
$from
.
find
(
'
li
'
).
length
)
{
if
(
!
$from
.
find
(
'
li
'
).
length
)
{
$from
.
find
(
'
.empty-message
'
).
removeClass
(
'
hidden
'
);
$from
.
find
(
'
.empty-message
'
).
removeClass
(
'
hidden
'
);
}
}
}
else
{
}
else
{
this
.
savePrioritySort
(
$label
,
action
)
this
.
savePrioritySort
(
$label
,
action
).
catch
(
rollbackLabelPosition
);
.
catch
(
rollbackLabelPosition
);
}
}
}
}
...
@@ -102,8 +103,7 @@ export default class LabelManager {
...
@@ -102,8 +103,7 @@ export default class LabelManager {
}
}
onPrioritySortUpdate
()
{
onPrioritySortUpdate
()
{
this
.
savePrioritySort
()
this
.
savePrioritySort
().
catch
(()
=>
flash
(
this
.
errorMessage
));
.
catch
(()
=>
flash
(
this
.
errorMessage
));
}
}
savePrioritySort
()
{
savePrioritySort
()
{
...
...
app/assets/javascripts/labels.js
View file @
c559bcca
...
@@ -22,7 +22,7 @@ export default class Labels {
...
@@ -22,7 +22,7 @@ export default class Labels {
updateColorPreview
()
{
updateColorPreview
()
{
const
previewColor
=
$
(
'
input#label_color
'
).
val
();
const
previewColor
=
$
(
'
input#label_color
'
).
val
();
return
$
(
'
div.label-color-preview
'
).
css
(
'
background-color
'
,
previewColor
);
return
$
(
'
div.label-color-preview
'
).
css
(
'
background-color
'
,
previewColor
);
// Updates the the preview color with the hex-color input
// Updates the the preview color with the hex-color input
}
}
// Updates the preview color with a click on a suggested color
// Updates the preview color with a click on a suggested color
...
...
app/assets/javascripts/layout_nav.js
View file @
c559bcca
...
@@ -5,7 +5,9 @@ import initFlyOutNav from './fly_out_nav';
...
@@ -5,7 +5,9 @@ import initFlyOutNav from './fly_out_nav';
function
hideEndFade
(
$scrollingTabs
)
{
function
hideEndFade
(
$scrollingTabs
)
{
$scrollingTabs
.
each
(
function
scrollTabsLoop
()
{
$scrollingTabs
.
each
(
function
scrollTabsLoop
()
{
const
$this
=
$
(
this
);
const
$this
=
$
(
this
);
$this
.
siblings
(
'
.fade-right
'
).
toggleClass
(
'
scrolling
'
,
Math
.
round
(
$this
.
width
())
<
$this
.
prop
(
'
scrollWidth
'
));
$this
.
siblings
(
'
.fade-right
'
)
.
toggleClass
(
'
scrolling
'
,
Math
.
round
(
$this
.
width
())
<
$this
.
prop
(
'
scrollWidth
'
));
});
});
}
}
...
@@ -15,38 +17,42 @@ export default function initLayoutNav() {
...
@@ -15,38 +17,42 @@ export default function initLayoutNav() {
initFlyOutNav
();
initFlyOutNav
();
$
(
document
).
on
(
'
init.scrolling-tabs
'
,
()
=>
{
$
(
document
)
const
$scrollingTabs
=
$
(
'
.scrolling-tabs
'
).
not
(
'
.is-initialized
'
);
.
on
(
'
init.scrolling-tabs
'
,
()
=>
{
$scrollingTabs
.
addClass
(
'
is-initialized
'
);
const
$scrollingTabs
=
$
(
'
.scrolling-tabs
'
).
not
(
'
.is-initialized
'
);
$scrollingTabs
.
addClass
(
'
is-initialized
'
);
$
(
window
).
on
(
'
resize.nav
'
,
()
=>
{
$
(
window
)
hideEndFade
(
$scrollingTabs
);
.
on
(
'
resize.nav
'
,
()
=>
{
}).
trigger
(
'
resize.nav
'
);
hideEndFade
(
$scrollingTabs
);
})
.
trigger
(
'
resize.nav
'
);
$scrollingTabs
.
on
(
'
scroll
'
,
function
tabsScrollEvent
()
{
$scrollingTabs
.
on
(
'
scroll
'
,
function
tabsScrollEvent
()
{
const
$this
=
$
(
this
);
const
$this
=
$
(
this
);
const
currentPosition
=
$this
.
scrollLeft
();
const
currentPosition
=
$this
.
scrollLeft
();
const
maxPosition
=
$this
.
prop
(
'
scrollWidth
'
)
-
$this
.
outerWidth
();
const
maxPosition
=
$this
.
prop
(
'
scrollWidth
'
)
-
$this
.
outerWidth
();
$this
.
siblings
(
'
.fade-left
'
).
toggleClass
(
'
scrolling
'
,
currentPosition
>
0
);
$this
.
siblings
(
'
.fade-left
'
).
toggleClass
(
'
scrolling
'
,
currentPosition
>
0
);
$this
.
siblings
(
'
.fade-right
'
).
toggleClass
(
'
scrolling
'
,
currentPosition
<
maxPosition
-
1
);
$this
.
siblings
(
'
.fade-right
'
).
toggleClass
(
'
scrolling
'
,
currentPosition
<
maxPosition
-
1
);
});
});
$scrollingTabs
.
each
(
function
scrollTabsEachLoop
()
{
$scrollingTabs
.
each
(
function
scrollTabsEachLoop
()
{
const
$this
=
$
(
this
);
const
$this
=
$
(
this
);
const
scrollingTabWidth
=
$this
.
width
();
const
scrollingTabWidth
=
$this
.
width
();
const
$active
=
$this
.
find
(
'
.active
'
);
const
$active
=
$this
.
find
(
'
.active
'
);
const
activeWidth
=
$active
.
width
();
const
activeWidth
=
$active
.
width
();
if
(
$active
.
length
)
{
if
(
$active
.
length
)
{
const
offset
=
$active
.
offset
().
left
+
activeWidth
;
const
offset
=
$active
.
offset
().
left
+
activeWidth
;
if
(
offset
>
scrollingTabWidth
-
30
)
{
if
(
offset
>
scrollingTabWidth
-
30
)
{
const
scrollLeft
=
(
offset
-
(
scrollingTabWidth
/
2
))
-
(
activeWidth
/
2
)
;
const
scrollLeft
=
offset
-
scrollingTabWidth
/
2
-
activeWidth
/
2
;
$this
.
scrollLeft
(
scrollLeft
);
$this
.
scrollLeft
(
scrollLeft
);
}
}
}
}
}
);
})
;
})
})
.
trigger
(
'
init.scrolling-tabs
'
);
.
trigger
(
'
init.scrolling-tabs
'
);
}
}
app/assets/javascripts/line_highlighter.js
View file @
c559bcca
...
@@ -70,7 +70,7 @@ LineHighlighter.prototype.highlightHash = function(newHash) {
...
@@ -70,7 +70,7 @@ LineHighlighter.prototype.highlightHash = function(newHash) {
const
scrollOptions
=
{
const
scrollOptions
=
{
// Scroll to the first highlighted line on initial load
// Scroll to the first highlighted line on initial load
// Offset -50 for the sticky top bar, and another -100 for some context
// Offset -50 for the sticky top bar, and another -100 for some context
offset
:
-
150
offset
:
-
150
,
};
};
if
(
this
.
options
.
scrollFileHolder
)
{
if
(
this
.
options
.
scrollFileHolder
)
{
$
(
this
.
options
.
fileHolderSelector
).
scrollTo
(
lineSelector
,
scrollOptions
);
$
(
this
.
options
.
fileHolderSelector
).
scrollTo
(
lineSelector
,
scrollOptions
);
...
@@ -85,7 +85,9 @@ LineHighlighter.prototype.clickHandler = function(event) {
...
@@ -85,7 +85,9 @@ LineHighlighter.prototype.clickHandler = function(event) {
var
current
,
lineNumber
,
range
;
var
current
,
lineNumber
,
range
;
event
.
preventDefault
();
event
.
preventDefault
();
this
.
clearHighlight
();
this
.
clearHighlight
();
lineNumber
=
$
(
event
.
target
).
closest
(
'
a
'
).
data
(
'
lineNumber
'
);
lineNumber
=
$
(
event
.
target
)
.
closest
(
'
a
'
)
.
data
(
'
lineNumber
'
);
current
=
this
.
hashToRange
(
this
.
_hash
);
current
=
this
.
hashToRange
(
this
.
_hash
);
if
(
!
(
current
[
0
]
&&
event
.
shiftKey
))
{
if
(
!
(
current
[
0
]
&&
event
.
shiftKey
))
{
// If there's no current selection, or there is but Shift wasn't held,
// If there's no current selection, or there is but Shift wasn't held,
...
@@ -104,7 +106,7 @@ LineHighlighter.prototype.clickHandler = function(event) {
...
@@ -104,7 +106,7 @@ LineHighlighter.prototype.clickHandler = function(event) {
};
};
LineHighlighter
.
prototype
.
clearHighlight
=
function
()
{
LineHighlighter
.
prototype
.
clearHighlight
=
function
()
{
return
$
(
"
.
"
+
this
.
highlightLineClass
).
removeClass
(
this
.
highlightLineClass
);
return
$
(
'
.
'
+
this
.
highlightLineClass
).
removeClass
(
this
.
highlightLineClass
);
};
};
// Convert a URL hash String into line numbers
// Convert a URL hash String into line numbers
...
@@ -135,7 +137,7 @@ LineHighlighter.prototype.hashToRange = function(hash) {
...
@@ -135,7 +137,7 @@ LineHighlighter.prototype.hashToRange = function(hash) {
//
//
// lineNumber - Line number to highlight
// lineNumber - Line number to highlight
LineHighlighter
.
prototype
.
highlightLine
=
function
(
lineNumber
)
{
LineHighlighter
.
prototype
.
highlightLine
=
function
(
lineNumber
)
{
return
$
(
"
#LC
"
+
lineNumber
).
addClass
(
this
.
highlightLineClass
);
return
$
(
'
#LC
'
+
lineNumber
).
addClass
(
this
.
highlightLineClass
);
};
};
// Highlight all lines within a range
// Highlight all lines within a range
...
@@ -160,9 +162,9 @@ LineHighlighter.prototype.highlightRange = function(range) {
...
@@ -160,9 +162,9 @@ LineHighlighter.prototype.highlightRange = function(range) {
LineHighlighter
.
prototype
.
setHash
=
function
(
firstLineNumber
,
lastLineNumber
)
{
LineHighlighter
.
prototype
.
setHash
=
function
(
firstLineNumber
,
lastLineNumber
)
{
var
hash
;
var
hash
;
if
(
lastLineNumber
)
{
if
(
lastLineNumber
)
{
hash
=
"
#L
"
+
firstLineNumber
+
"
-
"
+
lastLineNumber
;
hash
=
'
#L
'
+
firstLineNumber
+
'
-
'
+
lastLineNumber
;
}
else
{
}
else
{
hash
=
"
#L
"
+
firstLineNumber
;
hash
=
'
#L
'
+
firstLineNumber
;
}
}
this
.
_hash
=
hash
;
this
.
_hash
=
hash
;
return
this
.
__setLocationHash__
(
hash
);
return
this
.
__setLocationHash__
(
hash
);
...
@@ -172,11 +174,15 @@ LineHighlighter.prototype.setHash = function(firstLineNumber, lastLineNumber) {
...
@@ -172,11 +174,15 @@ LineHighlighter.prototype.setHash = function(firstLineNumber, lastLineNumber) {
//
//
// This method is stubbed in tests.
// This method is stubbed in tests.
LineHighlighter
.
prototype
.
__setLocationHash__
=
function
(
value
)
{
LineHighlighter
.
prototype
.
__setLocationHash__
=
function
(
value
)
{
return
window
.
history
.
pushState
({
return
window
.
history
.
pushState
(
url
:
value
{
// We're using pushState instead of assigning location.hash directly to
url
:
value
,
// prevent the page from scrolling on the hashchange event
// We're using pushState instead of assigning location.hash directly to
},
document
.
title
,
value
);
// prevent the page from scrolling on the hashchange event
},
document
.
title
,
value
,
);
};
};
export
default
LineHighlighter
;
export
default
LineHighlighter
;
app/assets/javascripts/locale/sprintf.js
View file @
c559bcca
...
@@ -15,7 +15,7 @@ export default (input, parameters, escapeParameters = true) => {
...
@@ -15,7 +15,7 @@ export default (input, parameters, escapeParameters = true) => {
let
output
=
input
;
let
output
=
input
;
if
(
parameters
)
{
if
(
parameters
)
{
Object
.
keys
(
parameters
).
forEach
(
(
parameterName
)
=>
{
Object
.
keys
(
parameters
).
forEach
(
parameterName
=>
{
const
parameterValue
=
parameters
[
parameterName
];
const
parameterValue
=
parameters
[
parameterName
];
const
escapedParameterValue
=
escapeParameters
?
_
.
escape
(
parameterValue
)
:
parameterValue
;
const
escapedParameterValue
=
escapeParameters
?
_
.
escape
(
parameterValue
)
:
parameterValue
;
output
=
output
.
replace
(
new
RegExp
(
`%{
${
parameterName
}
}`
,
'
g
'
),
escapedParameterValue
);
output
=
output
.
replace
(
new
RegExp
(
`%{
${
parameterName
}
}`
,
'
g
'
),
escapedParameterValue
);
...
...
app/assets/javascripts/member_expiration_date.js
View file @
c559bcca
...
@@ -9,7 +9,9 @@ import { parsePikadayDate, pikadayToString } from './lib/utils/datefix';
...
@@ -9,7 +9,9 @@ import { parsePikadayDate, pikadayToString } from './lib/utils/datefix';
//
//
export
default
function
memberExpirationDate
(
selector
=
'
.js-access-expiration-date
'
)
{
export
default
function
memberExpirationDate
(
selector
=
'
.js-access-expiration-date
'
)
{
function
toggleClearInput
()
{
function
toggleClearInput
()
{
$
(
this
).
closest
(
'
.clearable-input
'
).
toggleClass
(
'
has-value
'
,
$
(
this
).
val
()
!==
''
);
$
(
this
)
.
closest
(
'
.clearable-input
'
)
.
toggleClass
(
'
has-value
'
,
$
(
this
).
val
()
!==
''
);
}
}
const
inputs
=
$
(
selector
);
const
inputs
=
$
(
selector
);
...
@@ -40,7 +42,9 @@ export default function memberExpirationDate(selector = '.js-access-expiration-d
...
@@ -40,7 +42,9 @@ export default function memberExpirationDate(selector = '.js-access-expiration-d
inputs
.
next
(
'
.js-clear-input
'
).
on
(
'
click
'
,
function
clicked
(
event
)
{
inputs
.
next
(
'
.js-clear-input
'
).
on
(
'
click
'
,
function
clicked
(
event
)
{
event
.
preventDefault
();
event
.
preventDefault
();
const
input
=
$
(
this
).
closest
(
'
.clearable-input
'
).
find
(
selector
);
const
input
=
$
(
this
)
.
closest
(
'
.clearable-input
'
)
.
find
(
selector
);
const
calendar
=
input
.
data
(
'
pikaday
'
);
const
calendar
=
input
.
data
(
'
pikaday
'
);
calendar
.
setDate
(
null
);
calendar
.
setDate
(
null
);
...
...
app/assets/javascripts/merge_request.js
View file @
c559bcca
...
@@ -16,26 +16,29 @@ function MergeRequest(opts) {
...
@@ -16,26 +16,29 @@ function MergeRequest(opts) {
this
.
opts
=
opts
!=
null
?
opts
:
{};
this
.
opts
=
opts
!=
null
?
opts
:
{};
this
.
submitNoteForm
=
this
.
submitNoteForm
.
bind
(
this
);
this
.
submitNoteForm
=
this
.
submitNoteForm
.
bind
(
this
);
this
.
$el
=
$
(
'
.merge-request
'
);
this
.
$el
=
$
(
'
.merge-request
'
);
this
.
$
(
'
.show-all-commits
'
).
on
(
'
click
'
,
(
function
(
_this
)
{
this
.
$
(
'
.show-all-commits
'
).
on
(
return
function
()
{
'
click
'
,
return
_this
.
showAllCommits
();
(
function
(
_this
)
{
};
return
function
()
{
})(
this
));
return
_this
.
showAllCommits
();
};
})(
this
),
);
this
.
initTabs
();
this
.
initTabs
();
this
.
initMRBtnListeners
();
this
.
initMRBtnListeners
();
this
.
initCommitMessageListeners
();
this
.
initCommitMessageListeners
();
this
.
closeReopenReportToggle
=
IssuablesHelper
.
initCloseReopenReport
();
this
.
closeReopenReportToggle
=
IssuablesHelper
.
initCloseReopenReport
();
if
(
$
(
"
a.btn-close
"
).
length
)
{
if
(
$
(
'
a.btn-close
'
).
length
)
{
this
.
taskList
=
new
TaskList
({
this
.
taskList
=
new
TaskList
({
dataType
:
'
merge_request
'
,
dataType
:
'
merge_request
'
,
fieldName
:
'
description
'
,
fieldName
:
'
description
'
,
selector
:
'
.detail-page-description
'
,
selector
:
'
.detail-page-description
'
,
onSuccess
:
(
result
)
=>
{
onSuccess
:
result
=>
{
document
.
querySelector
(
'
#task_status
'
).
innerText
=
result
.
task_status
;
document
.
querySelector
(
'
#task_status
'
).
innerText
=
result
.
task_status
;
document
.
querySelector
(
'
#task_status_short
'
).
innerText
=
result
.
task_status_short
;
document
.
querySelector
(
'
#task_status_short
'
).
innerText
=
result
.
task_status_short
;
}
}
,
});
});
}
}
}
}
...
@@ -84,7 +87,7 @@ MergeRequest.prototype.initMRBtnListeners = function() {
...
@@ -84,7 +87,7 @@ MergeRequest.prototype.initMRBtnListeners = function() {
MergeRequest
.
prototype
.
submitNoteForm
=
function
(
form
,
$button
)
{
MergeRequest
.
prototype
.
submitNoteForm
=
function
(
form
,
$button
)
{
var
noteText
;
var
noteText
;
noteText
=
form
.
find
(
"
textarea.js-note-text
"
).
val
();
noteText
=
form
.
find
(
'
textarea.js-note-text
'
).
val
();
if
(
noteText
.
trim
().
length
>
0
)
{
if
(
noteText
.
trim
().
length
>
0
)
{
form
.
submit
();
form
.
submit
();
$button
.
data
(
'
submitted
'
,
true
);
$button
.
data
(
'
submitted
'
,
true
);
...
@@ -122,7 +125,7 @@ MergeRequest.setStatusBoxToMerged = function() {
...
@@ -122,7 +125,7 @@ MergeRequest.setStatusBoxToMerged = function() {
MergeRequest
.
decreaseCounter
=
function
(
by
=
1
)
{
MergeRequest
.
decreaseCounter
=
function
(
by
=
1
)
{
const
$el
=
$
(
'
.js-merge-counter
'
);
const
$el
=
$
(
'
.js-merge-counter
'
);
const
count
=
Math
.
max
(
(
parseInt
(
$el
.
text
().
replace
(
/
[^\d]
/
,
''
),
10
)
-
by
)
,
0
);
const
count
=
Math
.
max
(
parseInt
(
$el
.
text
().
replace
(
/
[^\d]
/
,
''
),
10
)
-
by
,
0
);
$el
.
text
(
addDelimiter
(
count
));
$el
.
text
(
addDelimiter
(
count
));
};
};
...
...
app/assets/javascripts/milestone.js
View file @
c559bcca
...
@@ -15,7 +15,7 @@ export default class Milestone {
...
@@ -15,7 +15,7 @@ export default class Milestone {
}
}
bindTabsSwitching
()
{
bindTabsSwitching
()
{
return
$
(
'
a[data-toggle="tab"]
'
).
on
(
'
show.bs.tab
'
,
(
e
)
=>
{
return
$
(
'
a[data-toggle="tab"]
'
).
on
(
'
show.bs.tab
'
,
e
=>
{
const
$target
=
$
(
e
.
target
);
const
$target
=
$
(
e
.
target
);
window
.
location
.
hash
=
$target
.
attr
(
'
href
'
);
window
.
location
.
hash
=
$target
.
attr
(
'
href
'
);
...
@@ -36,7 +36,8 @@ export default class Milestone {
...
@@ -36,7 +36,8 @@ export default class Milestone {
const
tabElId
=
$target
.
attr
(
'
href
'
);
const
tabElId
=
$target
.
attr
(
'
href
'
);
if
(
endpoint
&&
!
$target
.
hasClass
(
'
is-loaded
'
))
{
if
(
endpoint
&&
!
$target
.
hasClass
(
'
is-loaded
'
))
{
axios
.
get
(
endpoint
)
axios
.
get
(
endpoint
)
.
then
(({
data
})
=>
{
.
then
(({
data
})
=>
{
$
(
tabElId
).
html
(
data
.
html
);
$
(
tabElId
).
html
(
data
.
html
);
$target
.
addClass
(
'
is-loaded
'
);
$target
.
addClass
(
'
is-loaded
'
);
...
@@ -46,23 +47,28 @@ export default class Milestone {
...
@@ -46,23 +47,28 @@ export default class Milestone {
}
}
static
initDeprecationMessage
()
{
static
initDeprecationMessage
()
{
const
deprecationMesssageContainer
=
document
.
querySelector
(
'
.js-milestone-deprecation-message
'
);
const
deprecationMesssageContainer
=
document
.
querySelector
(
'
.js-milestone-deprecation-message
'
,
);
if
(
!
deprecationMesssageContainer
)
return
;
if
(
!
deprecationMesssageContainer
)
return
;
const
deprecationMessage
=
deprecationMesssageContainer
.
querySelector
(
'
.js-milestone-deprecation-message-template
'
).
innerHTML
;
const
deprecationMessage
=
deprecationMesssageContainer
.
querySelector
(
'
.js-milestone-deprecation-message-template
'
,
).
innerHTML
;
const
$popover
=
$
(
'
.js-popover-link
'
,
deprecationMesssageContainer
);
const
$popover
=
$
(
'
.js-popover-link
'
,
deprecationMesssageContainer
);
const
hideOnScroll
=
togglePopover
.
bind
(
$popover
,
false
);
const
hideOnScroll
=
togglePopover
.
bind
(
$popover
,
false
);
$popover
.
popover
({
$popover
content
:
deprecationMessage
,
.
popover
({
html
:
true
,
content
:
deprecationMessage
,
placement
:
'
bottom
'
,
html
:
true
,
})
placement
:
'
bottom
'
,
.
on
(
'
mouseenter
'
,
mouseenter
)
})
.
on
(
'
mouseleave
'
,
debouncedMouseleave
())
.
on
(
'
mouseenter
'
,
mouseenter
)
.
on
(
'
show.bs.popover
'
,
()
=>
{
.
on
(
'
mouseleave
'
,
debouncedMouseleave
())
window
.
addEventListener
(
'
scroll
'
,
hideOnScroll
,
{
once
:
true
});
.
on
(
'
show.bs.popover
'
,
()
=>
{
});
window
.
addEventListener
(
'
scroll
'
,
hideOnScroll
,
{
once
:
true
});
});
}
}
}
}
app/assets/javascripts/mini_pipeline_graph_dropdown.js
View file @
c559bcca
...
@@ -46,7 +46,7 @@ export default class MiniPipelineGraph {
...
@@ -46,7 +46,7 @@ export default class MiniPipelineGraph {
$
(
document
).
on
(
$
(
document
).
on
(
'
click
'
,
'
click
'
,
`
${
this
.
container
}
.js-builds-dropdown-list a.mini-pipeline-graph-dropdown-item`
,
`
${
this
.
container
}
.js-builds-dropdown-list a.mini-pipeline-graph-dropdown-item`
,
(
e
)
=>
{
e
=>
{
e
.
stopPropagation
();
e
.
stopPropagation
();
},
},
);
);
...
@@ -82,7 +82,8 @@ export default class MiniPipelineGraph {
...
@@ -82,7 +82,8 @@ export default class MiniPipelineGraph {
this
.
renderBuildsList
(
button
,
''
);
this
.
renderBuildsList
(
button
,
''
);
this
.
toggleLoading
(
button
);
this
.
toggleLoading
(
button
);
axios
.
get
(
endpoint
)
axios
.
get
(
endpoint
)
.
then
(({
data
})
=>
{
.
then
(({
data
})
=>
{
this
.
toggleLoading
(
button
);
this
.
toggleLoading
(
button
);
this
.
renderBuildsList
(
button
,
data
.
html
);
this
.
renderBuildsList
(
button
,
data
.
html
);
...
@@ -90,7 +91,11 @@ export default class MiniPipelineGraph {
...
@@ -90,7 +91,11 @@ export default class MiniPipelineGraph {
})
})
.
catch
(()
=>
{
.
catch
(()
=>
{
this
.
toggleLoading
(
button
);
this
.
toggleLoading
(
button
);
if
(
$
(
button
).
parent
().
hasClass
(
'
open
'
))
{
if
(
$
(
button
)
.
parent
()
.
hasClass
(
'
open
'
)
)
{
$
(
button
).
dropdown
(
'
toggle
'
);
$
(
button
).
dropdown
(
'
toggle
'
);
}
}
flash
(
'
An error occurred while fetching the builds.
'
,
'
alert
'
);
flash
(
'
An error occurred while fetching the builds.
'
,
'
alert
'
);
...
@@ -104,8 +109,8 @@ export default class MiniPipelineGraph {
...
@@ -104,8 +109,8 @@ export default class MiniPipelineGraph {
* @return {type}
* @return {type}
*/
*/
toggleLoading
(
stageContainer
)
{
toggleLoading
(
stageContainer
)
{
stageContainer
.
parentElement
.
querySelector
(
stageContainer
.
parentElement
`
${
this
.
dropdownListSelector
}
.js-builds-dropdown-loading`
,
.
querySelector
(
`
${
this
.
dropdownListSelector
}
.js-builds-dropdown-loading`
)
)
.
classList
.
toggle
(
'
hidden
'
);
.
classList
.
toggle
(
'
hidden
'
);
}
}
}
}
app/assets/javascripts/namespace_select.js
View file @
c559bcca
...
@@ -14,14 +14,14 @@ export default class NamespaceSelect {
...
@@ -14,14 +14,14 @@ export default class NamespaceSelect {
selectable
:
true
,
selectable
:
true
,
filterRemote
:
true
,
filterRemote
:
true
,
search
:
{
search
:
{
fields
:
[
'
path
'
]
fields
:
[
'
path
'
]
,
},
},
fieldName
:
fieldName
,
fieldName
:
fieldName
,
toggleLabel
:
function
(
selected
)
{
toggleLabel
:
function
(
selected
)
{
if
(
selected
.
id
==
null
)
{
if
(
selected
.
id
==
null
)
{
return
selected
.
text
;
return
selected
.
text
;
}
else
{
}
else
{
return
selected
.
kind
+
"
:
"
+
selected
.
full_path
;
return
selected
.
kind
+
'
:
'
+
selected
.
full_path
;
}
}
},
},
data
:
function
(
term
,
dataCallback
)
{
data
:
function
(
term
,
dataCallback
)
{
...
@@ -29,7 +29,7 @@ export default class NamespaceSelect {
...
@@ -29,7 +29,7 @@ export default class NamespaceSelect {
if
(
isFilter
)
{
if
(
isFilter
)
{
const
anyNamespace
=
{
const
anyNamespace
=
{
text
:
'
Any namespace
'
,
text
:
'
Any namespace
'
,
id
:
null
id
:
null
,
};
};
namespaces
.
unshift
(
anyNamespace
);
namespaces
.
unshift
(
anyNamespace
);
namespaces
.
splice
(
1
,
0
,
'
divider
'
);
namespaces
.
splice
(
1
,
0
,
'
divider
'
);
...
@@ -41,7 +41,7 @@ export default class NamespaceSelect {
...
@@ -41,7 +41,7 @@ export default class NamespaceSelect {
if
(
namespace
.
id
==
null
)
{
if
(
namespace
.
id
==
null
)
{
return
namespace
.
text
;
return
namespace
.
text
;
}
else
{
}
else
{
return
namespace
.
kind
+
"
:
"
+
namespace
.
full_path
;
return
namespace
.
kind
+
'
:
'
+
namespace
.
full_path
;
}
}
},
},
renderRow
:
this
.
renderRow
,
renderRow
:
this
.
renderRow
,
...
...
app/assets/javascripts/network/branch_graph.js
View file @
c559bcca
...
@@ -20,7 +20,7 @@ export default (function() {
...
@@ -20,7 +20,7 @@ export default (function() {
this
.
mtime
=
0
;
this
.
mtime
=
0
;
this
.
mspace
=
0
;
this
.
mspace
=
0
;
this
.
parents
=
{};
this
.
parents
=
{};
this
.
colors
=
[
"
#000
"
];
this
.
colors
=
[
'
#000
'
];
this
.
offsetX
=
150
;
this
.
offsetX
=
150
;
this
.
offsetY
=
20
;
this
.
offsetY
=
20
;
this
.
unitTime
=
30
;
this
.
unitTime
=
30
;
...
@@ -30,9 +30,10 @@ export default (function() {
...
@@ -30,9 +30,10 @@ export default (function() {
}
}
BranchGraph
.
prototype
.
load
=
function
()
{
BranchGraph
.
prototype
.
load
=
function
()
{
axios
.
get
(
this
.
options
.
url
)
axios
.
get
(
this
.
options
.
url
)
.
then
(({
data
})
=>
{
.
then
(({
data
})
=>
{
$
(
"
.loading
"
,
this
.
element
).
hide
();
$
(
'
.loading
'
,
this
.
element
).
hide
();
this
.
prepareData
(
data
.
days
,
data
.
commits
);
this
.
prepareData
(
data
.
days
,
data
.
commits
);
this
.
buildGraph
();
this
.
buildGraph
();
})
})
...
@@ -71,17 +72,19 @@ export default (function() {
...
@@ -71,17 +72,19 @@ export default (function() {
c
=
ref
[
j
];
c
=
ref
[
j
];
this
.
mtime
=
Math
.
max
(
this
.
mtime
,
c
.
time
);
this
.
mtime
=
Math
.
max
(
this
.
mtime
,
c
.
time
);
this
.
mspace
=
Math
.
max
(
this
.
mspace
,
c
.
space
);
this
.
mspace
=
Math
.
max
(
this
.
mspace
,
c
.
space
);
results
.
push
((
function
()
{
results
.
push
(
var
l
,
len1
,
ref1
,
results1
;
function
()
{
ref1
=
c
.
parents
;
var
l
,
len1
,
ref1
,
results1
;
results1
=
[];
ref1
=
c
.
parents
;
for
(
l
=
0
,
len1
=
ref1
.
length
;
l
<
len1
;
l
+=
1
)
{
results1
=
[];
p
=
ref1
[
l
];
for
(
l
=
0
,
len1
=
ref1
.
length
;
l
<
len1
;
l
+=
1
)
{
this
.
parents
[
p
[
0
]]
=
true
;
p
=
ref1
[
l
];
results1
.
push
(
this
.
mspace
=
Math
.
max
(
this
.
mspace
,
p
[
1
]));
this
.
parents
[
p
[
0
]]
=
true
;
}
results1
.
push
((
this
.
mspace
=
Math
.
max
(
this
.
mspace
,
p
[
1
])));
return
results1
;
}
}).
call
(
this
));
return
results1
;
}.
call
(
this
),
);
}
}
return
results
;
return
results
;
};
};
...
@@ -91,11 +94,11 @@ export default (function() {
...
@@ -91,11 +94,11 @@ export default (function() {
k
=
0
;
k
=
0
;
results
=
[];
results
=
[];
while
(
k
<
this
.
mspace
)
{
while
(
k
<
this
.
mspace
)
{
this
.
colors
.
push
(
Raphael
.
getColor
(.
8
));
this
.
colors
.
push
(
Raphael
.
getColor
(
0
.8
));
// Skipping a few colors in the spectrum to get more contrast between colors
// Skipping a few colors in the spectrum to get more contrast between colors
Raphael
.
getColor
();
Raphael
.
getColor
();
Raphael
.
getColor
();
Raphael
.
getColor
();
results
.
push
(
k
+=
1
);
results
.
push
(
(
k
+=
1
)
);
}
}
return
results
;
return
results
;
};
};
...
@@ -104,12 +107,12 @@ export default (function() {
...
@@ -104,12 +107,12 @@ export default (function() {
var
cuday
,
cumonth
,
day
,
j
,
len
,
mm
,
ref
;
var
cuday
,
cumonth
,
day
,
j
,
len
,
mm
,
ref
;
const
{
r
}
=
this
;
const
{
r
}
=
this
;
cuday
=
0
;
cuday
=
0
;
cumonth
=
""
;
cumonth
=
''
;
r
.
rect
(
0
,
0
,
40
,
this
.
barHeight
).
attr
({
r
.
rect
(
0
,
0
,
40
,
this
.
barHeight
).
attr
({
fill
:
"
#222
"
fill
:
'
#222
'
,
});
});
r
.
rect
(
40
,
0
,
30
,
this
.
barHeight
).
attr
({
r
.
rect
(
40
,
0
,
30
,
this
.
barHeight
).
attr
({
fill
:
"
#444
"
fill
:
'
#444
'
,
});
});
ref
=
this
.
days
;
ref
=
this
.
days
;
...
@@ -118,16 +121,16 @@ export default (function() {
...
@@ -118,16 +121,16 @@ export default (function() {
if
(
cuday
!==
day
[
0
]
||
cumonth
!==
day
[
1
])
{
if
(
cuday
!==
day
[
0
]
||
cumonth
!==
day
[
1
])
{
// Dates
// Dates
r
.
text
(
55
,
this
.
offsetY
+
this
.
unitTime
*
mm
,
day
[
0
]).
attr
({
r
.
text
(
55
,
this
.
offsetY
+
this
.
unitTime
*
mm
,
day
[
0
]).
attr
({
font
:
"
12px Monaco, monospace
"
,
font
:
'
12px Monaco, monospace
'
,
fill
:
"
#BBB
"
fill
:
'
#BBB
'
,
});
});
[
cuday
]
=
day
;
[
cuday
]
=
day
;
}
}
if
(
cumonth
!==
day
[
1
])
{
if
(
cumonth
!==
day
[
1
])
{
// Months
// Months
r
.
text
(
20
,
this
.
offsetY
+
this
.
unitTime
*
mm
,
day
[
1
]).
attr
({
r
.
text
(
20
,
this
.
offsetY
+
this
.
unitTime
*
mm
,
day
[
1
]).
attr
({
font
:
"
12px Monaco, monospace
"
,
font
:
'
12px Monaco, monospace
'
,
fill
:
"
#EEE
"
fill
:
'
#EEE
'
,
});
});
// eslint-disable-next-line prefer-destructuring
// eslint-disable-next-line prefer-destructuring
...
@@ -173,11 +176,13 @@ export default (function() {
...
@@ -173,11 +176,13 @@ export default (function() {
BranchGraph
.
prototype
.
bindEvents
=
function
()
{
BranchGraph
.
prototype
.
bindEvents
=
function
()
{
const
{
element
}
=
this
;
const
{
element
}
=
this
;
return
$
(
element
).
scroll
((
function
(
_this
)
{
return
$
(
element
).
scroll
(
return
function
(
event
)
{
(
function
(
_this
)
{
return
_this
.
renderPartialGraph
();
return
function
(
event
)
{
};
return
_this
.
renderPartialGraph
();
})(
this
));
};
})(
this
),
);
};
};
BranchGraph
.
prototype
.
scrollDown
=
function
()
{
BranchGraph
.
prototype
.
scrollDown
=
function
()
{
...
@@ -219,46 +224,53 @@ export default (function() {
...
@@ -219,46 +224,53 @@ export default (function() {
shortrefs
=
commit
.
refs
;
shortrefs
=
commit
.
refs
;
// Truncate if longer than 15 chars
// Truncate if longer than 15 chars
if
(
shortrefs
.
length
>
17
)
{
if
(
shortrefs
.
length
>
17
)
{
shortrefs
=
shortrefs
.
substr
(
0
,
15
)
+
"
…
"
;
shortrefs
=
shortrefs
.
substr
(
0
,
15
)
+
'
…
'
;
}
}
text
=
r
.
text
(
x
+
4
,
y
,
shortrefs
).
attr
({
text
=
r
.
text
(
x
+
4
,
y
,
shortrefs
).
attr
({
"
text-anchor
"
:
"
start
"
,
'
text-anchor
'
:
'
start
'
,
font
:
"
10px Monaco, monospace
"
,
font
:
'
10px Monaco, monospace
'
,
fill
:
"
#FFF
"
,
fill
:
'
#FFF
'
,
title
:
commit
.
refs
title
:
commit
.
refs
,
});
});
textbox
=
text
.
getBBox
();
textbox
=
text
.
getBBox
();
// Create rectangle based on the size of the textbox
// Create rectangle based on the size of the textbox
rect
=
r
.
rect
(
x
,
y
-
7
,
textbox
.
width
+
5
,
textbox
.
height
+
5
,
4
).
attr
({
rect
=
r
.
rect
(
x
,
y
-
7
,
textbox
.
width
+
5
,
textbox
.
height
+
5
,
4
).
attr
({
fill
:
"
#000
"
,
fill
:
'
#000
'
,
"
fill-opacity
"
:
.
5
,
'
fill-opacity
'
:
0
.5
,
stroke
:
"
none
"
stroke
:
'
none
'
,
});
});
triangle
=
r
.
path
([
"
M
"
,
x
-
5
,
y
,
"
L
"
,
x
-
15
,
y
-
4
,
"
L
"
,
x
-
15
,
y
+
4
,
"
Z
"
]).
attr
({
triangle
=
r
.
path
([
'
M
'
,
x
-
5
,
y
,
'
L
'
,
x
-
15
,
y
-
4
,
'
L
'
,
x
-
15
,
y
+
4
,
'
Z
'
]).
attr
({
fill
:
"
#000
"
,
fill
:
'
#000
'
,
"
fill-opacity
"
:
.
5
,
'
fill-opacity
'
:
0
.5
,
stroke
:
"
none
"
stroke
:
'
none
'
,
});
});
label
=
r
.
set
(
rect
,
text
);
label
=
r
.
set
(
rect
,
text
);
label
.
transform
([
"
t
"
,
-
rect
.
getBBox
().
width
-
15
,
0
]);
label
.
transform
([
'
t
'
,
-
rect
.
getBBox
().
width
-
15
,
0
]);
// Set text to front
// Set text to front
return
text
.
toFront
();
return
text
.
toFront
();
};
};
BranchGraph
.
prototype
.
appendAnchor
=
function
(
x
,
y
,
commit
)
{
BranchGraph
.
prototype
.
appendAnchor
=
function
(
x
,
y
,
commit
)
{
const
{
r
,
top
,
options
}
=
this
;
const
{
r
,
top
,
options
}
=
this
;
const
anchor
=
r
.
circle
(
x
,
y
,
10
).
attr
({
const
anchor
=
r
fill
:
"
#000
"
,
.
circle
(
x
,
y
,
10
)
opacity
:
0
,
.
attr
({
cursor
:
"
pointer
"
fill
:
'
#000
'
,
}).
click
(
function
()
{
opacity
:
0
,
return
window
.
open
(
options
.
commit_url
.
replace
(
"
%s
"
,
commit
.
id
),
"
_blank
"
);
cursor
:
'
pointer
'
,
}).
hover
(
function
()
{
})
this
.
tooltip
=
r
.
commitTooltip
(
x
+
5
,
y
,
commit
);
.
click
(
function
()
{
return
top
.
push
(
this
.
tooltip
.
insertBefore
(
this
));
return
window
.
open
(
options
.
commit_url
.
replace
(
'
%s
'
,
commit
.
id
),
'
_blank
'
);
},
function
()
{
})
return
this
.
tooltip
&&
this
.
tooltip
.
remove
()
&&
delete
this
.
tooltip
;
.
hover
(
});
function
()
{
this
.
tooltip
=
r
.
commitTooltip
(
x
+
5
,
y
,
commit
);
return
top
.
push
(
this
.
tooltip
.
insertBefore
(
this
));
},
function
()
{
return
this
.
tooltip
&&
this
.
tooltip
.
remove
()
&&
delete
this
.
tooltip
;
},
);
return
top
.
push
(
anchor
);
return
top
.
push
(
anchor
);
};
};
...
@@ -266,7 +278,7 @@ export default (function() {
...
@@ -266,7 +278,7 @@ export default (function() {
const
{
r
}
=
this
;
const
{
r
}
=
this
;
r
.
circle
(
x
,
y
,
3
).
attr
({
r
.
circle
(
x
,
y
,
3
).
attr
({
fill
:
this
.
colors
[
commit
.
space
],
fill
:
this
.
colors
[
commit
.
space
],
stroke
:
"
none
"
stroke
:
'
none
'
,
});
});
const
avatar_box_x
=
this
.
offsetX
+
this
.
unitSpace
*
this
.
mspace
+
10
;
const
avatar_box_x
=
this
.
offsetX
+
this
.
unitSpace
*
this
.
mspace
+
10
;
...
@@ -274,13 +286,15 @@ export default (function() {
...
@@ -274,13 +286,15 @@ export default (function() {
r
.
rect
(
avatar_box_x
,
avatar_box_y
,
20
,
20
).
attr
({
r
.
rect
(
avatar_box_x
,
avatar_box_y
,
20
,
20
).
attr
({
stroke
:
this
.
colors
[
commit
.
space
],
stroke
:
this
.
colors
[
commit
.
space
],
"
stroke-width
"
:
2
'
stroke-width
'
:
2
,
});
});
r
.
image
(
commit
.
author
.
icon
,
avatar_box_x
,
avatar_box_y
,
20
,
20
);
r
.
image
(
commit
.
author
.
icon
,
avatar_box_x
,
avatar_box_y
,
20
,
20
);
return
r
.
text
(
this
.
offsetX
+
this
.
unitSpace
*
this
.
mspace
+
35
,
y
,
commit
.
message
.
split
(
"
\n
"
)[
0
]).
attr
({
return
r
"
text-anchor
"
:
"
start
"
,
.
text
(
this
.
offsetX
+
this
.
unitSpace
*
this
.
mspace
+
35
,
y
,
commit
.
message
.
split
(
'
\n
'
)[
0
])
font
:
"
14px Monaco, monospace
"
.
attr
({
});
'
text-anchor
'
:
'
start
'
,
font
:
'
14px Monaco, monospace
'
,
});
};
};
BranchGraph
.
prototype
.
drawLines
=
function
(
x
,
y
,
commit
)
{
BranchGraph
.
prototype
.
drawLines
=
function
(
x
,
y
,
commit
)
{
...
@@ -304,30 +318,32 @@ export default (function() {
...
@@ -304,30 +318,32 @@ export default (function() {
// Build line shape
// Build line shape
if
(
parent
[
1
]
===
commit
.
space
)
{
if
(
parent
[
1
]
===
commit
.
space
)
{
offset
=
[
0
,
5
];
offset
=
[
0
,
5
];
arrow
=
"
l-2,5,4,0,-2,-5,0,5
"
;
arrow
=
'
l-2,5,4,0,-2,-5,0,5
'
;
}
else
if
(
parent
[
1
]
<
commit
.
space
)
{
}
else
if
(
parent
[
1
]
<
commit
.
space
)
{
offset
=
[
3
,
3
];
offset
=
[
3
,
3
];
arrow
=
"
l5,0,-2,4,-3,-4,4,2
"
;
arrow
=
'
l5,0,-2,4,-3,-4,4,2
'
;
}
else
{
}
else
{
offset
=
[
-
3
,
3
];
offset
=
[
-
3
,
3
];
arrow
=
"
l-5,0,2,4,3,-4,-4,2
"
;
arrow
=
'
l-5,0,2,4,3,-4,-4,2
'
;
}
}
// Start point
// Start point
route
=
[
"
M
"
,
x
+
offset
[
0
],
y
+
offset
[
1
]];
route
=
[
'
M
'
,
x
+
offset
[
0
],
y
+
offset
[
1
]];
// Add arrow if not first parent
// Add arrow if not first parent
if
(
i
>
0
)
{
if
(
i
>
0
)
{
route
.
push
(
arrow
);
route
.
push
(
arrow
);
}
}
// Circumvent if overlap
// Circumvent if overlap
if
(
commit
.
space
!==
parentCommit
.
space
||
commit
.
space
!==
parent
[
1
])
{
if
(
commit
.
space
!==
parentCommit
.
space
||
commit
.
space
!==
parent
[
1
])
{
route
.
push
(
"
L
"
,
parentX2
,
y
+
10
,
"
L
"
,
parentX2
,
parentY
-
5
);
route
.
push
(
'
L
'
,
parentX2
,
y
+
10
,
'
L
'
,
parentX2
,
parentY
-
5
);
}
}
// End point
// End point
route
.
push
(
"
L
"
,
parentX1
,
parentY
);
route
.
push
(
'
L
'
,
parentX1
,
parentY
);
results
.
push
(
r
.
path
(
route
).
attr
({
results
.
push
(
stroke
:
color
,
r
.
path
(
route
).
attr
({
"
stroke-width
"
:
2
stroke
:
color
,
}));
'
stroke-width
'
:
2
,
}),
);
}
}
return
results
;
return
results
;
};
};
...
@@ -337,10 +353,10 @@ export default (function() {
...
@@ -337,10 +353,10 @@ export default (function() {
const
{
r
}
=
this
;
const
{
r
}
=
this
;
const
x
=
this
.
offsetX
+
this
.
unitSpace
*
(
this
.
mspace
-
commit
.
space
);
const
x
=
this
.
offsetX
+
this
.
unitSpace
*
(
this
.
mspace
-
commit
.
space
);
const
y
=
this
.
offsetY
+
this
.
unitTime
*
commit
.
time
;
const
y
=
this
.
offsetY
+
this
.
unitTime
*
commit
.
time
;
r
.
path
([
"
M
"
,
x
+
5
,
y
,
"
L
"
,
x
+
15
,
y
+
4
,
"
L
"
,
x
+
15
,
y
-
4
,
"
Z
"
]).
attr
({
r
.
path
([
'
M
'
,
x
+
5
,
y
,
'
L
'
,
x
+
15
,
y
+
4
,
'
L
'
,
x
+
15
,
y
-
4
,
'
Z
'
]).
attr
({
fill
:
"
#000
"
,
fill
:
'
#000
'
,
"
fill-opacity
"
:
.
5
,
'
fill-opacity
'
:
0
.5
,
stroke
:
"
none
"
stroke
:
'
none
'
,
});
});
// Displayed in the center
// Displayed in the center
return
this
.
element
.
scrollTop
(
y
-
this
.
graphHeight
/
2
);
return
this
.
element
.
scrollTop
(
y
-
this
.
graphHeight
/
2
);
...
...
app/assets/javascripts/network/raphael.js
View file @
c559bcca
...
@@ -49,7 +49,7 @@ Raphael.prototype.textWrap = function testWrap(t, width) {
...
@@ -49,7 +49,7 @@ Raphael.prototype.textWrap = function testWrap(t, width) {
const
s
=
[];
const
s
=
[];
for
(
let
j
=
0
,
len
=
words
.
length
;
j
<
len
;
j
+=
1
)
{
for
(
let
j
=
0
,
len
=
words
.
length
;
j
<
len
;
j
+=
1
)
{
const
word
=
words
[
j
];
const
word
=
words
[
j
];
if
(
x
+
(
word
.
length
*
letterWidth
)
>
width
)
{
if
(
x
+
word
.
length
*
letterWidth
>
width
)
{
s
.
push
(
'
\n
'
);
s
.
push
(
'
\n
'
);
x
=
0
;
x
=
0
;
}
}
...
...
app/assets/javascripts/new_branch_form.js
View file @
c559bcca
...
@@ -30,24 +30,24 @@ export default class NewBranchForm {
...
@@ -30,24 +30,24 @@ export default class NewBranchForm {
startsWith
=
{
startsWith
=
{
pattern
:
/^
(\/
|
\.)
/g
,
pattern
:
/^
(\/
|
\.)
/g
,
prefix
:
"
can't start with
"
,
prefix
:
"
can't start with
"
,
conjunction
:
"
or
"
conjunction
:
'
or
'
,
};
};
endsWith
=
{
endsWith
=
{
pattern
:
/
(\/
|
\.
|
\.
lock
)
$/g
,
pattern
:
/
(\/
|
\.
|
\.
lock
)
$/g
,
prefix
:
"
can't end in
"
,
prefix
:
"
can't end in
"
,
conjunction
:
"
or
"
conjunction
:
'
or
'
,
};
};
invalid
=
{
invalid
=
{
pattern
:
/
(\s
|~|
\^
|:|
\?
|
\*
|
\[
|
\\
|
\.\.
|@
\{
|
\/{2,}){1}
/g
,
pattern
:
/
(\s
|~|
\^
|:|
\?
|
\*
|
\[
|
\\
|
\.\.
|@
\{
|
\/{2,}){1}
/g
,
prefix
:
"
can't contain
"
,
prefix
:
"
can't contain
"
,
conjunction
:
"
,
"
conjunction
:
'
,
'
,
};
};
single
=
{
single
=
{
pattern
:
/^@+$/g
,
pattern
:
/^@+$/g
,
prefix
:
"
can't be
"
,
prefix
:
"
can't be
"
,
conjunction
:
"
or
"
conjunction
:
'
or
'
,
};
};
return
this
.
restrictions
=
[
startsWith
,
invalid
,
endsWith
,
single
]
;
return
(
this
.
restrictions
=
[
startsWith
,
invalid
,
endsWith
,
single
])
;
}
}
validate
()
{
validate
()
{
...
@@ -73,7 +73,7 @@ export default class NewBranchForm {
...
@@ -73,7 +73,7 @@ export default class NewBranchForm {
return
"
'
"
+
value
+
"
'
"
;
return
"
'
"
+
value
+
"
'
"
;
}
}
});
});
return
restriction
.
prefix
+
"
"
+
(
formatted
.
join
(
restriction
.
conjunction
)
);
return
restriction
.
prefix
+
'
'
+
formatted
.
join
(
restriction
.
conjunction
);
};
};
validator
=
(
function
(
_this
)
{
validator
=
(
function
(
_this
)
{
return
function
(
errors
,
restriction
)
{
return
function
(
errors
,
restriction
)
{
...
@@ -88,7 +88,7 @@ export default class NewBranchForm {
...
@@ -88,7 +88,7 @@ export default class NewBranchForm {
})(
this
);
})(
this
);
errors
=
this
.
restrictions
.
reduce
(
validator
,
[]);
errors
=
this
.
restrictions
.
reduce
(
validator
,
[]);
if
(
errors
.
length
>
0
)
{
if
(
errors
.
length
>
0
)
{
errorMessage
=
$
(
"
<span/>
"
).
text
(
errors
.
join
(
'
,
'
));
errorMessage
=
$
(
'
<span/>
'
).
text
(
errors
.
join
(
'
,
'
));
return
this
.
branchNameError
.
append
(
errorMessage
);
return
this
.
branchNameError
.
append
(
errorMessage
);
}
}
}
}
...
...
app/assets/javascripts/new_commit_form.js
View file @
c559bcca
...
@@ -6,9 +6,7 @@ export default class NewCommitForm {
...
@@ -6,9 +6,7 @@ export default class NewCommitForm {
this
.
branchName
=
form
.
find
(
'
.js-branch-name
'
);
this
.
branchName
=
form
.
find
(
'
.js-branch-name
'
);
this
.
originalBranch
=
form
.
find
(
'
.js-original-branch
'
);
this
.
originalBranch
=
form
.
find
(
'
.js-original-branch
'
);
this
.
createMergeRequest
=
form
.
find
(
'
.js-create-merge-request
'
);
this
.
createMergeRequest
=
form
.
find
(
'
.js-create-merge-request
'
);
this
.
createMergeRequestContainer
=
form
.
find
(
this
.
createMergeRequestContainer
=
form
.
find
(
'
.js-create-merge-request-container
'
);
'
.js-create-merge-request-container
'
,
);
this
.
branchName
.
keyup
(
this
.
renderDestination
);
this
.
branchName
.
keyup
(
this
.
renderDestination
);
this
.
renderDestination
();
this
.
renderDestination
();
}
}
...
...
app/assets/javascripts/notifications_dropdown.js
View file @
c559bcca
...
@@ -18,7 +18,9 @@ export default function notificationsDropdown() {
...
@@ -18,7 +18,9 @@ export default function notificationsDropdown() {
$
(
document
).
on
(
'
ajax:success
'
,
'
.notification-form
'
,
(
e
,
data
)
=>
{
$
(
document
).
on
(
'
ajax:success
'
,
'
.notification-form
'
,
(
e
,
data
)
=>
{
if
(
data
.
saved
)
{
if
(
data
.
saved
)
{
$
(
e
.
currentTarget
).
closest
(
'
.js-notification-dropdown
'
).
replaceWith
(
data
.
html
);
$
(
e
.
currentTarget
)
.
closest
(
'
.js-notification-dropdown
'
)
.
replaceWith
(
data
.
html
);
}
else
{
}
else
{
Flash
(
'
Failed to save new settings
'
,
'
alert
'
);
Flash
(
'
Failed to save new settings
'
,
'
alert
'
);
}
}
...
...
app/assets/javascripts/notifications_form.js
View file @
c559bcca
...
@@ -22,7 +22,8 @@ export default class NotificationsForm {
...
@@ -22,7 +22,8 @@ export default class NotificationsForm {
// eslint-disable-next-line class-methods-use-this
// eslint-disable-next-line class-methods-use-this
showCheckboxLoadingSpinner
(
$parent
)
{
showCheckboxLoadingSpinner
(
$parent
)
{
$parent
.
addClass
(
'
is-loading
'
)
$parent
.
addClass
(
'
is-loading
'
)
.
find
(
'
.custom-notification-event-loading
'
)
.
find
(
'
.custom-notification-event-loading
'
)
.
removeClass
(
'
fa-check
'
)
.
removeClass
(
'
fa-check
'
)
.
addClass
(
'
fa-spin fa-spinner
'
)
.
addClass
(
'
fa-spin fa-spinner
'
)
...
@@ -38,9 +39,12 @@ export default class NotificationsForm {
...
@@ -38,9 +39,12 @@ export default class NotificationsForm {
.
then
(({
data
})
=>
{
.
then
(({
data
})
=>
{
$checkbox
.
enable
();
$checkbox
.
enable
();
if
(
data
.
saved
)
{
if
(
data
.
saved
)
{
$parent
.
find
(
'
.custom-notification-event-loading
'
).
toggleClass
(
'
fa-spin fa-spinner fa-check is-done
'
);
$parent
.
find
(
'
.custom-notification-event-loading
'
)
.
toggleClass
(
'
fa-spin fa-spinner fa-check is-done
'
);
setTimeout
(()
=>
{
setTimeout
(()
=>
{
$parent
.
removeClass
(
'
is-loading
'
)
$parent
.
removeClass
(
'
is-loading
'
)
.
find
(
'
.custom-notification-event-loading
'
)
.
find
(
'
.custom-notification-event-loading
'
)
.
toggleClass
(
'
fa-spin fa-spinner fa-check is-done
'
);
.
toggleClass
(
'
fa-spin fa-spinner fa-check is-done
'
);
},
2000
);
},
2000
);
...
...
app/assets/javascripts/pager.js
View file @
c559bcca
...
@@ -24,22 +24,25 @@ export default {
...
@@ -24,22 +24,25 @@ export default {
getOld
()
{
getOld
()
{
this
.
loading
.
show
();
this
.
loading
.
show
();
axios
.
get
(
this
.
url
,
{
axios
params
:
{
.
get
(
this
.
url
,
{
limit
:
this
.
limit
,
params
:
{
offset
:
this
.
offset
,
limit
:
this
.
limit
,
},
offset
:
this
.
offset
,
}).
then
(({
data
})
=>
{
},
this
.
append
(
data
.
count
,
this
.
prepareData
(
data
.
html
));
})
this
.
callback
();
.
then
(({
data
})
=>
{
this
.
append
(
data
.
count
,
this
.
prepareData
(
data
.
html
));
this
.
callback
();
// keep loading until we've filled the viewport height
// keep loading until we've filled the viewport height
if
(
!
this
.
disable
&&
!
this
.
isScrollable
())
{
if
(
!
this
.
disable
&&
!
this
.
isScrollable
())
{
this
.
getOld
();
this
.
getOld
();
}
else
{
}
else
{
this
.
loading
.
hide
();
this
.
loading
.
hide
();
}
}
}).
catch
(()
=>
this
.
loading
.
hide
());
})
.
catch
(()
=>
this
.
loading
.
hide
());
},
},
append
(
count
,
html
)
{
append
(
count
,
html
)
{
...
...
app/assets/javascripts/pdf/index.vue
View file @
c559bcca
<
script
>
<
script
>
import
pdfjsLib
from
'
vendor/pdf
'
;
import
pdfjsLib
from
'
vendor/pdf
'
;
import
workerSrc
from
'
vendor/pdf.worker.min
'
;
import
workerSrc
from
'
vendor/pdf.worker.min
'
;
import
page
from
'
./page/index.vue
'
;
import
page
from
'
./page/index.vue
'
;
export
default
{
export
default
{
components
:
{
page
},
components
:
{
page
},
props
:
{
props
:
{
pdf
:
{
pdf
:
{
type
:
[
String
,
Uint8Array
],
type
:
[
String
,
Uint8Array
],
required
:
true
,
required
:
true
,
},
},
},
data
()
{
},
return
{
data
()
{
loading
:
false
,
return
{
pages
:
[],
loading
:
false
,
};
pages
:
[],
};
},
computed
:
{
document
()
{
return
typeof
this
.
pdf
===
'
string
'
?
this
.
pdf
:
{
data
:
this
.
pdf
};
},
},
computed
:
{
hasPDF
()
{
document
()
{
return
this
.
pdf
&&
this
.
pdf
.
length
>
0
;
return
typeof
this
.
pdf
===
'
string
'
?
this
.
pdf
:
{
data
:
this
.
pdf
};
},
hasPDF
()
{
return
this
.
pdf
&&
this
.
pdf
.
length
>
0
;
},
},
},
watch
:
{
pdf
:
'
load
'
},
},
mounted
()
{
watch
:
{
pdf
:
'
load
'
},
pdfjsLib
.
PDFJS
.
workerSrc
=
workerSrc
;
mounted
()
{
if
(
this
.
hasPDF
)
this
.
load
();
pdfjsLib
.
PDFJS
.
workerSrc
=
workerSrc
;
if
(
this
.
hasPDF
)
this
.
load
();
},
methods
:
{
load
()
{
this
.
pages
=
[];
return
pdfjsLib
.
getDocument
(
this
.
document
)
.
then
(
this
.
renderPages
)
.
then
(()
=>
this
.
$emit
(
'
pdflabload
'
))
.
catch
(
error
=>
this
.
$emit
(
'
pdflaberror
'
,
error
))
.
then
(()
=>
{
this
.
loading
=
false
;
});
},
},
methods
:
{
renderPages
(
pdf
)
{
load
()
{
const
pagePromises
=
[];
this
.
pages
=
[];
this
.
loading
=
true
;
return
pdfjsLib
.
getDocument
(
this
.
document
)
for
(
let
num
=
1
;
num
<=
pdf
.
numPages
;
num
+=
1
)
{
.
then
(
this
.
renderPages
)
pagePromises
.
push
(
pdf
.
getPage
(
num
).
then
(
p
=>
this
.
pages
.
push
(
p
)));
.
then
(()
=>
this
.
$emit
(
'
pdflabload
'
))
}
.
catch
(
error
=>
this
.
$emit
(
'
pdflaberror
'
,
error
))
return
Promise
.
all
(
pagePromises
);
.
then
(()
=>
{
this
.
loading
=
false
;
});
},
renderPages
(
pdf
)
{
const
pagePromises
=
[];
this
.
loading
=
true
;
for
(
let
num
=
1
;
num
<=
pdf
.
numPages
;
num
+=
1
)
{
pagePromises
.
push
(
pdf
.
getPage
(
num
).
then
(
p
=>
this
.
pages
.
push
(
p
)),
);
}
return
Promise
.
all
(
pagePromises
);
},
},
},
};
},
};
</
script
>
</
script
>
<
template
>
<
template
>
...
@@ -69,9 +70,9 @@
...
@@ -69,9 +70,9 @@
</
template
>
</
template
>
<
style
>
<
style
>
.pdf-viewer
{
.pdf-viewer
{
background
:
url('./assets/img/bg.gif')
;
background
:
url('./assets/img/bg.gif')
;
display
:
flex
;
display
:
flex
;
flex-flow
:
column
nowrap
;
flex-flow
:
column
nowrap
;
}
}
</
style
>
</
style
>
app/assets/javascripts/pdf/page/index.vue
View file @
c559bcca
<
script
>
<
script
>
export
default
{
export
default
{
props
:
{
props
:
{
page
:
{
page
:
{
type
:
Object
,
type
:
Object
,
required
:
true
,
required
:
true
,
},
number
:
{
type
:
Number
,
required
:
true
,
},
},
},
data
()
{
number
:
{
return
{
type
:
Number
,
scale
:
4
,
required
:
true
,
rendering
:
false
,
},
};
},
data
()
{
return
{
scale
:
4
,
rendering
:
false
,
};
},
computed
:
{
viewport
()
{
return
this
.
page
.
getViewport
(
this
.
scale
);
},
},
computed
:
{
context
()
{
viewport
()
{
return
this
.
$refs
.
canvas
.
getContext
(
'
2d
'
);
return
this
.
page
.
getViewport
(
this
.
scale
);
},
context
()
{
return
this
.
$refs
.
canvas
.
getContext
(
'
2d
'
);
},
renderContext
()
{
return
{
canvasContext
:
this
.
context
,
viewport
:
this
.
viewport
,
};
},
},
},
mounted
()
{
renderContext
()
{
this
.
$refs
.
canvas
.
height
=
this
.
viewport
.
height
;
return
{
this
.
$refs
.
canvas
.
width
=
this
.
viewport
.
width
;
canvasContext
:
this
.
context
,
this
.
rendering
=
true
;
viewport
:
this
.
viewport
,
this
.
page
.
render
(
this
.
renderContext
)
};
.
then
(()
=>
{
this
.
rendering
=
false
;
})
.
catch
(
error
=>
this
.
$emit
(
'
pdflaberror
'
,
error
));
},
},
};
},
mounted
()
{
this
.
$refs
.
canvas
.
height
=
this
.
viewport
.
height
;
this
.
$refs
.
canvas
.
width
=
this
.
viewport
.
width
;
this
.
rendering
=
true
;
this
.
page
.
render
(
this
.
renderContext
)
.
then
(()
=>
{
this
.
rendering
=
false
;
})
.
catch
(
error
=>
this
.
$emit
(
'
pdflaberror
'
,
error
));
},
};
</
script
>
</
script
>
<
template
>
<
template
>
...
@@ -51,20 +54,20 @@
...
@@ -51,20 +54,20 @@
</
template
>
</
template
>
<
style
>
<
style
>
.pdf-page
{
.pdf-page
{
margin
:
8px
auto
0
auto
;
margin
:
8px
auto
0
auto
;
border-top
:
1px
#ddd
solid
;
border-top
:
1px
#ddd
solid
;
border-bottom
:
1px
#ddd
solid
;
border-bottom
:
1px
#ddd
solid
;
width
:
100%
;
width
:
100%
;
}
}
.pdf-page
:first-child
{
.pdf-page
:first-child
{
margin-top
:
0px
;
margin-top
:
0px
;
border-top
:
0px
;
border-top
:
0px
;
}
}
.pdf-page
:last-child
{
.pdf-page
:last-child
{
margin-bottom
:
0px
;
margin-bottom
:
0px
;
border-bottom
:
0px
;
border-bottom
:
0px
;
}
}
</
style
>
</
style
>
app/assets/javascripts/pipelines/components/pipelines_table_row.vue
View file @
c559bcca
...
@@ -64,10 +64,7 @@ export default {
...
@@ -64,10 +64,7 @@ export default {
return
[];
return
[];
}
}
const
{
details
}
=
this
.
pipeline
;
const
{
details
}
=
this
.
pipeline
;
return
[
return
[...(
details
.
manual_actions
||
[]),
...(
details
.
scheduled_actions
||
[])];
...(
details
.
manual_actions
||
[]),
...(
details
.
scheduled_actions
||
[]),
];
},
},
/**
/**
* If provided, returns the commit tag.
* If provided, returns the commit tag.
...
...
app/assets/javascripts/project_find_file.js
View file @
c559bcca
...
@@ -10,14 +10,14 @@ import { __ } from '~/locale';
...
@@ -10,14 +10,14 @@ import { __ } from '~/locale';
const
highlighter
=
function
(
element
,
text
,
matches
)
{
const
highlighter
=
function
(
element
,
text
,
matches
)
{
var
highlightText
,
j
,
lastIndex
,
len
,
matchIndex
,
matchedChars
,
unmatched
;
var
highlightText
,
j
,
lastIndex
,
len
,
matchIndex
,
matchedChars
,
unmatched
;
lastIndex
=
0
;
lastIndex
=
0
;
highlightText
=
""
;
highlightText
=
''
;
matchedChars
=
[];
matchedChars
=
[];
for
(
j
=
0
,
len
=
matches
.
length
;
j
<
len
;
j
+=
1
)
{
for
(
j
=
0
,
len
=
matches
.
length
;
j
<
len
;
j
+=
1
)
{
matchIndex
=
matches
[
j
];
matchIndex
=
matches
[
j
];
unmatched
=
text
.
substring
(
lastIndex
,
matchIndex
);
unmatched
=
text
.
substring
(
lastIndex
,
matchIndex
);
if
(
unmatched
)
{
if
(
unmatched
)
{
if
(
matchedChars
.
length
)
{
if
(
matchedChars
.
length
)
{
element
.
append
(
matchedChars
.
join
(
""
).
bold
());
element
.
append
(
matchedChars
.
join
(
''
).
bold
());
}
}
matchedChars
=
[];
matchedChars
=
[];
element
.
append
(
document
.
createTextNode
(
unmatched
));
element
.
append
(
document
.
createTextNode
(
unmatched
));
...
@@ -26,7 +26,7 @@ const highlighter = function(element, text, matches) {
...
@@ -26,7 +26,7 @@ const highlighter = function(element, text, matches) {
lastIndex
=
matchIndex
+
1
;
lastIndex
=
matchIndex
+
1
;
}
}
if
(
matchedChars
.
length
)
{
if
(
matchedChars
.
length
)
{
element
.
append
(
matchedChars
.
join
(
""
).
bold
());
element
.
append
(
matchedChars
.
join
(
''
).
bold
());
}
}
return
element
.
append
(
document
.
createTextNode
(
text
.
substring
(
lastIndex
)));
return
element
.
append
(
document
.
createTextNode
(
text
.
substring
(
lastIndex
)));
};
};
...
@@ -40,7 +40,7 @@ export default class ProjectFindFile {
...
@@ -40,7 +40,7 @@ export default class ProjectFindFile {
this
.
selectRowDown
=
this
.
selectRowDown
.
bind
(
this
);
this
.
selectRowDown
=
this
.
selectRowDown
.
bind
(
this
);
this
.
selectRowUp
=
this
.
selectRowUp
.
bind
(
this
);
this
.
selectRowUp
=
this
.
selectRowUp
.
bind
(
this
);
this
.
filePaths
=
{};
this
.
filePaths
=
{};
this
.
inputElement
=
this
.
element
.
find
(
"
.file-finder-input
"
);
this
.
inputElement
=
this
.
element
.
find
(
'
.file-finder-input
'
);
// init event
// init event
this
.
initEvent
();
this
.
initEvent
();
// focus text input box
// focus text input box
...
@@ -50,38 +50,51 @@ export default class ProjectFindFile {
...
@@ -50,38 +50,51 @@ export default class ProjectFindFile {
}
}
initEvent
()
{
initEvent
()
{
this
.
inputElement
.
off
(
"
keyup
"
);
this
.
inputElement
.
off
(
'
keyup
'
);
this
.
inputElement
.
on
(
"
keyup
"
,
(
function
(
_this
)
{
this
.
inputElement
.
on
(
return
function
(
event
)
{
'
keyup
'
,
var
oldValue
,
ref
,
target
,
value
;
(
function
(
_this
)
{
target
=
$
(
event
.
target
);
return
function
(
event
)
{
value
=
target
.
val
();
var
oldValue
,
ref
,
target
,
value
;
oldValue
=
(
ref
=
target
.
data
(
"
oldValue
"
))
!=
null
?
ref
:
""
;
target
=
$
(
event
.
target
);
if
(
value
!==
oldValue
)
{
value
=
target
.
val
();
target
.
data
(
"
oldValue
"
,
value
);
oldValue
=
(
ref
=
target
.
data
(
'
oldValue
'
))
!=
null
?
ref
:
''
;
_this
.
findFile
();
if
(
value
!==
oldValue
)
{
return
_this
.
element
.
find
(
"
tr.tree-item
"
).
eq
(
0
).
addClass
(
"
selected
"
).
focus
();
target
.
data
(
'
oldValue
'
,
value
);
}
_this
.
findFile
();
};
return
_this
.
element
})(
this
));
.
find
(
'
tr.tree-item
'
)
.
eq
(
0
)
.
addClass
(
'
selected
'
)
.
focus
();
}
};
})(
this
),
);
}
}
findFile
()
{
findFile
()
{
var
result
,
searchText
;
var
result
,
searchText
;
searchText
=
this
.
inputElement
.
val
();
searchText
=
this
.
inputElement
.
val
();
result
=
searchText
.
length
>
0
?
fuzzaldrinPlus
.
filter
(
this
.
filePaths
,
searchText
)
:
this
.
filePaths
;
result
=
searchText
.
length
>
0
?
fuzzaldrinPlus
.
filter
(
this
.
filePaths
,
searchText
)
:
this
.
filePaths
;
return
this
.
renderList
(
result
,
searchText
);
return
this
.
renderList
(
result
,
searchText
);
// find file
// find file
}
}
// files pathes load
// files pathes load
load
(
url
)
{
load
(
url
)
{
axios
.
get
(
url
)
axios
.
get
(
url
)
.
then
(({
data
})
=>
{
.
then
(({
data
})
=>
{
this
.
element
.
find
(
'
.loading
'
).
hide
();
this
.
element
.
find
(
'
.loading
'
).
hide
();
this
.
filePaths
=
data
;
this
.
filePaths
=
data
;
this
.
findFile
();
this
.
findFile
();
this
.
element
.
find
(
'
.files-slider tr.tree-item
'
).
eq
(
0
).
addClass
(
'
selected
'
).
focus
();
this
.
element
.
find
(
'
.files-slider tr.tree-item
'
)
.
eq
(
0
)
.
addClass
(
'
selected
'
)
.
focus
();
})
})
.
catch
(()
=>
flash
(
__
(
'
An error occurred while loading filenames
'
)));
.
catch
(()
=>
flash
(
__
(
'
An error occurred while loading filenames
'
)));
}
}
...
@@ -89,7 +102,7 @@ export default class ProjectFindFile {
...
@@ -89,7 +102,7 @@ export default class ProjectFindFile {
// render result
// render result
renderList
(
filePaths
,
searchText
)
{
renderList
(
filePaths
,
searchText
)
{
var
blobItemUrl
,
filePath
,
html
,
i
,
len
,
matches
,
results
;
var
blobItemUrl
,
filePath
,
html
,
i
,
len
,
matches
,
results
;
this
.
element
.
find
(
"
.tree-table > tbody
"
).
empty
();
this
.
element
.
find
(
'
.tree-table > tbody
'
).
empty
();
results
=
[];
results
=
[];
for
(
i
=
0
,
len
=
filePaths
.
length
;
i
<
len
;
i
+=
1
)
{
for
(
i
=
0
,
len
=
filePaths
.
length
;
i
<
len
;
i
+=
1
)
{
...
@@ -100,9 +113,9 @@ export default class ProjectFindFile {
...
@@ -100,9 +113,9 @@ export default class ProjectFindFile {
if
(
searchText
)
{
if
(
searchText
)
{
matches
=
fuzzaldrinPlus
.
match
(
filePath
,
searchText
);
matches
=
fuzzaldrinPlus
.
match
(
filePath
,
searchText
);
}
}
blobItemUrl
=
this
.
options
.
blobUrlTemplate
+
"
/
"
+
filePath
;
blobItemUrl
=
this
.
options
.
blobUrlTemplate
+
'
/
'
+
filePath
;
html
=
ProjectFindFile
.
makeHtml
(
filePath
,
matches
,
blobItemUrl
);
html
=
ProjectFindFile
.
makeHtml
(
filePath
,
matches
,
blobItemUrl
);
results
.
push
(
this
.
element
.
find
(
"
.tree-table > tbody
"
).
append
(
html
));
results
.
push
(
this
.
element
.
find
(
'
.tree-table > tbody
'
).
append
(
html
));
}
}
return
results
;
return
results
;
}
}
...
@@ -110,52 +123,56 @@ export default class ProjectFindFile {
...
@@ -110,52 +123,56 @@ export default class ProjectFindFile {
// make tbody row html
// make tbody row html
static
makeHtml
(
filePath
,
matches
,
blobItemUrl
)
{
static
makeHtml
(
filePath
,
matches
,
blobItemUrl
)
{
var
$tr
;
var
$tr
;
$tr
=
$
(
"
<tr class='tree-item'><td class='tree-item-file-name link-container'><a><i class='fa fa-file-text-o fa-fw'></i><span class='str-truncated'></span></a></td></tr>
"
);
$tr
=
$
(
"
<tr class='tree-item'><td class='tree-item-file-name link-container'><a><i class='fa fa-file-text-o fa-fw'></i><span class='str-truncated'></span></a></td></tr>
"
,
);
if
(
matches
)
{
if
(
matches
)
{
$tr
.
find
(
"
a
"
).
replaceWith
(
highlighter
(
$tr
.
find
(
"
a
"
),
filePath
,
matches
).
attr
(
"
href
"
,
blobItemUrl
));
$tr
.
find
(
'
a
'
)
.
replaceWith
(
highlighter
(
$tr
.
find
(
'
a
'
),
filePath
,
matches
).
attr
(
'
href
'
,
blobItemUrl
));
}
else
{
}
else
{
$tr
.
find
(
"
a
"
).
attr
(
"
href
"
,
blobItemUrl
);
$tr
.
find
(
'
a
'
).
attr
(
'
href
'
,
blobItemUrl
);
$tr
.
find
(
"
.str-truncated
"
).
text
(
filePath
);
$tr
.
find
(
'
.str-truncated
'
).
text
(
filePath
);
}
}
return
$tr
;
return
$tr
;
}
}
selectRow
(
type
)
{
selectRow
(
type
)
{
var
next
,
rows
,
selectedRow
;
var
next
,
rows
,
selectedRow
;
rows
=
this
.
element
.
find
(
"
.files-slider tr.tree-item
"
);
rows
=
this
.
element
.
find
(
'
.files-slider tr.tree-item
'
);
selectedRow
=
this
.
element
.
find
(
"
.files-slider tr.tree-item.selected
"
);
selectedRow
=
this
.
element
.
find
(
'
.files-slider tr.tree-item.selected
'
);
if
(
rows
&&
rows
.
length
>
0
)
{
if
(
rows
&&
rows
.
length
>
0
)
{
if
(
selectedRow
&&
selectedRow
.
length
>
0
)
{
if
(
selectedRow
&&
selectedRow
.
length
>
0
)
{
if
(
type
===
"
UP
"
)
{
if
(
type
===
'
UP
'
)
{
next
=
selectedRow
.
prev
();
next
=
selectedRow
.
prev
();
}
else
if
(
type
===
"
DOWN
"
)
{
}
else
if
(
type
===
'
DOWN
'
)
{
next
=
selectedRow
.
next
();
next
=
selectedRow
.
next
();
}
}
if
(
next
.
length
>
0
)
{
if
(
next
.
length
>
0
)
{
selectedRow
.
removeClass
(
"
selected
"
);
selectedRow
.
removeClass
(
'
selected
'
);
selectedRow
=
next
;
selectedRow
=
next
;
}
}
}
else
{
}
else
{
selectedRow
=
rows
.
eq
(
0
);
selectedRow
=
rows
.
eq
(
0
);
}
}
return
selectedRow
.
addClass
(
"
selected
"
).
focus
();
return
selectedRow
.
addClass
(
'
selected
'
).
focus
();
}
}
}
}
selectRowUp
()
{
selectRowUp
()
{
return
this
.
selectRow
(
"
UP
"
);
return
this
.
selectRow
(
'
UP
'
);
}
}
selectRowDown
()
{
selectRowDown
()
{
return
this
.
selectRow
(
"
DOWN
"
);
return
this
.
selectRow
(
'
DOWN
'
);
}
}
goToTree
()
{
goToTree
()
{
return
window
.
location
.
href
=
this
.
options
.
treeUrl
;
return
(
window
.
location
.
href
=
this
.
options
.
treeUrl
)
;
}
}
goToBlob
()
{
goToBlob
()
{
var
$link
=
this
.
element
.
find
(
"
.tree-item.selected .tree-item-file-name a
"
);
var
$link
=
this
.
element
.
find
(
'
.tree-item.selected .tree-item-file-name a
'
);
if
(
$link
.
length
)
{
if
(
$link
.
length
)
{
$link
.
get
(
0
).
click
();
$link
.
get
(
0
).
click
();
...
...
app/assets/javascripts/project_import.js
View file @
c559bcca
...
@@ -5,4 +5,3 @@ export default function projectImport() {
...
@@ -5,4 +5,3 @@ export default function projectImport() {
visitUrl
(
window
.
location
.
href
);
visitUrl
(
window
.
location
.
href
);
},
5000
);
},
5000
);
}
}
app/assets/javascripts/project_label_subscription.js
View file @
c559bcca
...
@@ -31,32 +31,35 @@ export default class ProjectLabelSubscription {
...
@@ -31,32 +31,35 @@ export default class ProjectLabelSubscription {
$btn
.
addClass
(
'
disabled
'
);
$btn
.
addClass
(
'
disabled
'
);
axios
.
post
(
url
).
then
(()
=>
{
axios
let
newStatus
;
.
post
(
url
)
let
newAction
;
.
then
(()
=>
{
let
newStatus
;
let
newAction
;
if
(
oldStatus
===
'
unsubscribed
'
)
{
if
(
oldStatus
===
'
unsubscribed
'
)
{
[
newStatus
,
newAction
]
=
[
'
subscribed
'
,
'
Unsubscribe
'
];
[
newStatus
,
newAction
]
=
[
'
subscribed
'
,
'
Unsubscribe
'
];
}
else
{
}
else
{
[
newStatus
,
newAction
]
=
[
'
unsubscribed
'
,
'
Subscribe
'
];
[
newStatus
,
newAction
]
=
[
'
unsubscribed
'
,
'
Subscribe
'
];
}
}
$btn
.
removeClass
(
'
disabled
'
);
$btn
.
removeClass
(
'
disabled
'
);
this
.
$buttons
.
attr
(
'
data-status
'
,
newStatus
);
this
.
$buttons
.
attr
(
'
data-status
'
,
newStatus
);
this
.
$buttons
.
find
(
'
> span
'
).
text
(
newAction
);
this
.
$buttons
.
find
(
'
> span
'
).
text
(
newAction
);
this
.
$buttons
.
map
((
i
,
button
)
=>
{
this
.
$buttons
.
map
((
i
,
button
)
=>
{
const
$button
=
$
(
button
);
const
$button
=
$
(
button
);
const
originalTitle
=
$button
.
attr
(
'
data-original-title
'
);
const
originalTitle
=
$button
.
attr
(
'
data-original-title
'
);
if
(
originalTitle
)
{
if
(
originalTitle
)
{
ProjectLabelSubscription
.
setNewTitle
(
$button
,
originalTitle
,
newStatus
,
newAction
);
ProjectLabelSubscription
.
setNewTitle
(
$button
,
originalTitle
,
newStatus
,
newAction
);
}
}
return
button
;
return
button
;
});
});
}).
catch
(()
=>
flash
(
__
(
'
There was an error subscribing to this label.
'
)));
})
.
catch
(()
=>
flash
(
__
(
'
There was an error subscribing to this label.
'
)));
}
}
static
setNewTitle
(
$button
,
originalTitle
,
newStatus
)
{
static
setNewTitle
(
$button
,
originalTitle
,
newStatus
)
{
...
...
app/assets/javascripts/project_select.js
View file @
c559bcca
...
@@ -16,28 +16,28 @@ export default function projectSelect() {
...
@@ -16,28 +16,28 @@ export default function projectSelect() {
this
.
withMergeRequestsEnabled
=
$
(
select
).
data
(
'
withMergeRequestsEnabled
'
);
this
.
withMergeRequestsEnabled
=
$
(
select
).
data
(
'
withMergeRequestsEnabled
'
);
this
.
allowClear
=
$
(
select
).
data
(
'
allowClear
'
)
||
false
;
this
.
allowClear
=
$
(
select
).
data
(
'
allowClear
'
)
||
false
;
placeholder
=
"
Search for project
"
;
placeholder
=
'
Search for project
'
;
if
(
this
.
includeGroups
)
{
if
(
this
.
includeGroups
)
{
placeholder
+=
"
or group
"
;
placeholder
+=
'
or group
'
;
}
}
$
(
select
).
select2
({
$
(
select
).
select2
({
placeholder
:
placeholder
,
placeholder
:
placeholder
,
minimumInputLength
:
0
,
minimumInputLength
:
0
,
query
:
(
function
(
_this
)
{
query
:
(
function
(
_this
)
{
return
function
(
query
)
{
return
function
(
query
)
{
var
finalCallback
,
projectsCallback
;
var
finalCallback
,
projectsCallback
;
finalCallback
=
function
(
projects
)
{
finalCallback
=
function
(
projects
)
{
var
data
;
var
data
;
data
=
{
data
=
{
results
:
projects
results
:
projects
,
};
};
return
query
.
callback
(
data
);
return
query
.
callback
(
data
);
};
};
if
(
_this
.
includeGroups
)
{
if
(
_this
.
includeGroups
)
{
projectsCallback
=
function
(
projects
)
{
projectsCallback
=
function
(
projects
)
{
var
groupsCallback
;
var
groupsCallback
;
groupsCallback
=
function
(
groups
)
{
groupsCallback
=
function
(
groups
)
{
var
data
;
var
data
;
data
=
groups
.
concat
(
projects
);
data
=
groups
.
concat
(
projects
);
return
finalCallback
(
data
);
return
finalCallback
(
data
);
...
@@ -48,17 +48,26 @@ export default function projectSelect() {
...
@@ -48,17 +48,26 @@ export default function projectSelect() {
projectsCallback
=
finalCallback
;
projectsCallback
=
finalCallback
;
}
}
if
(
_this
.
groupId
)
{
if
(
_this
.
groupId
)
{
return
Api
.
groupProjects
(
_this
.
groupId
,
query
.
term
,
{
return
Api
.
groupProjects
(
with_issues_enabled
:
_this
.
withIssuesEnabled
,
_this
.
groupId
,
with_merge_requests_enabled
:
_this
.
withMergeRequestsEnabled
,
query
.
term
,
},
projectsCallback
);
{
with_issues_enabled
:
_this
.
withIssuesEnabled
,
with_merge_requests_enabled
:
_this
.
withMergeRequestsEnabled
,
},
projectsCallback
,
);
}
else
{
}
else
{
return
Api
.
projects
(
query
.
term
,
{
return
Api
.
projects
(
order_by
:
_this
.
orderBy
,
query
.
term
,
with_issues_enabled
:
_this
.
withIssuesEnabled
,
{
with_merge_requests_enabled
:
_this
.
withMergeRequestsEnabled
,
order_by
:
_this
.
orderBy
,
membership
:
!
_this
.
allProjects
,
with_issues_enabled
:
_this
.
withIssuesEnabled
,
},
projectsCallback
);
with_merge_requests_enabled
:
_this
.
withMergeRequestsEnabled
,
membership
:
!
_this
.
allProjects
,
},
projectsCallback
,
);
}
}
};
};
})(
this
),
})(
this
),
...
@@ -69,7 +78,7 @@ export default function projectSelect() {
...
@@ -69,7 +78,7 @@ export default function projectSelect() {
url
:
project
.
web_url
,
url
:
project
.
web_url
,
});
});
},
},
text
:
function
(
project
)
{
text
:
function
(
project
)
{
return
project
.
name_with_namespace
||
project
.
name
;
return
project
.
name_with_namespace
||
project
.
name
;
},
},
...
@@ -79,7 +88,7 @@ export default function projectSelect() {
...
@@ -79,7 +88,7 @@ export default function projectSelect() {
allowClear
:
this
.
allowClear
,
allowClear
:
this
.
allowClear
,
dropdownCssClass
:
"
ajax-project-dropdown
"
dropdownCssClass
:
'
ajax-project-dropdown
'
,
});
});
if
(
simpleFilter
)
return
select
;
if
(
simpleFilter
)
return
select
;
return
new
ProjectSelectComboButton
(
select
);
return
new
ProjectSelectComboButton
(
select
);
...
...
app/assets/javascripts/project_select_combo_button.js
View file @
c559bcca
...
@@ -14,10 +14,11 @@ export default class ProjectSelectComboButton {
...
@@ -14,10 +14,11 @@ export default class ProjectSelectComboButton {
}
}
bindEvents
()
{
bindEvents
()
{
this
.
projectSelectInput
.
siblings
(
'
.new-project-item-select-button
'
)
this
.
projectSelectInput
.
siblings
(
'
.new-project-item-select-button
'
)
.
on
(
'
click
'
,
e
=>
this
.
openDropdown
(
e
));
.
on
(
'
click
'
,
e
=>
this
.
openDropdown
(
e
));
this
.
newItemBtn
.
on
(
'
click
'
,
(
e
)
=>
{
this
.
newItemBtn
.
on
(
'
click
'
,
e
=>
{
if
(
!
this
.
getProjectFromLocalStorage
())
{
if
(
!
this
.
getProjectFromLocalStorage
())
{
e
.
preventDefault
();
e
.
preventDefault
();
this
.
openDropdown
(
e
);
this
.
openDropdown
(
e
);
...
@@ -31,14 +32,21 @@ export default class ProjectSelectComboButton {
...
@@ -31,14 +32,21 @@ export default class ProjectSelectComboButton {
const
localStorageIsSafe
=
AccessorUtilities
.
isLocalStorageAccessSafe
();
const
localStorageIsSafe
=
AccessorUtilities
.
isLocalStorageAccessSafe
();
if
(
localStorageIsSafe
)
{
if
(
localStorageIsSafe
)
{
this
.
localStorageKey
=
[
'
group
'
,
this
.
groupId
,
this
.
formattedText
.
localStorageItemType
,
'
recent-project
'
].
join
(
'
-
'
);
this
.
localStorageKey
=
[
'
group
'
,
this
.
groupId
,
this
.
formattedText
.
localStorageItemType
,
'
recent-project
'
,
].
join
(
'
-
'
);
this
.
setBtnTextFromLocalStorage
();
this
.
setBtnTextFromLocalStorage
();
}
}
}
}
// eslint-disable-next-line class-methods-use-this
// eslint-disable-next-line class-methods-use-this
openDropdown
(
event
)
{
openDropdown
(
event
)
{
$
(
event
.
currentTarget
).
siblings
(
'
.project-item-select
'
).
select2
(
'
open
'
);
$
(
event
.
currentTarget
)
.
siblings
(
'
.project-item-select
'
)
.
select2
(
'
open
'
);
}
}
selectProject
()
{
selectProject
()
{
...
@@ -86,8 +94,14 @@ export default class ProjectSelectComboButton {
...
@@ -86,8 +94,14 @@ export default class ProjectSelectComboButton {
const
defaultTextPrefix
=
this
.
resourceLabel
;
const
defaultTextPrefix
=
this
.
resourceLabel
;
// the trailing slice call depluralizes each of these strings (e.g. new-issues -> new-issue)
// the trailing slice call depluralizes each of these strings (e.g. new-issues -> new-issue)
const
localStorageItemType
=
`new-
${
this
.
resourceType
.
split
(
'
_
'
).
join
(
'
-
'
).
slice
(
0
,
-
1
)}
`
;
const
localStorageItemType
=
`new-
${
this
.
resourceType
const
presetTextSuffix
=
this
.
resourceType
.
split
(
'
_
'
).
join
(
'
'
).
slice
(
0
,
-
1
);
.
split
(
'
_
'
)
.
join
(
'
-
'
)
.
slice
(
0
,
-
1
)}
`
;
const
presetTextSuffix
=
this
.
resourceType
.
split
(
'
_
'
)
.
join
(
'
'
)
.
slice
(
0
,
-
1
);
return
{
return
{
localStorageItemType
,
// new-issue / new-merge-request
localStorageItemType
,
// new-issue / new-merge-request
...
@@ -96,4 +110,3 @@ export default class ProjectSelectComboButton {
...
@@ -96,4 +110,3 @@ export default class ProjectSelectComboButton {
};
};
}
}
}
}
app/assets/javascripts/project_visibility.js
View file @
c559bcca
...
@@ -7,7 +7,7 @@ function setVisibilityOptions(namespaceSelector) {
...
@@ -7,7 +7,7 @@ function setVisibilityOptions(namespaceSelector) {
const
selectedNamespace
=
namespaceSelector
.
options
[
namespaceSelector
.
selectedIndex
];
const
selectedNamespace
=
namespaceSelector
.
options
[
namespaceSelector
.
selectedIndex
];
const
{
name
,
visibility
,
visibilityLevel
,
showPath
,
editPath
}
=
selectedNamespace
.
dataset
;
const
{
name
,
visibility
,
visibilityLevel
,
showPath
,
editPath
}
=
selectedNamespace
.
dataset
;
document
.
querySelectorAll
(
'
.visibility-level-setting .form-check
'
).
forEach
(
(
option
)
=>
{
document
.
querySelectorAll
(
'
.visibility-level-setting .form-check
'
).
forEach
(
option
=>
{
const
optionInput
=
option
.
querySelector
(
'
input[type=radio]
'
);
const
optionInput
=
option
.
querySelector
(
'
input[type=radio]
'
);
const
optionValue
=
optionInput
?
optionInput
.
value
:
0
;
const
optionValue
=
optionInput
?
optionInput
.
value
:
0
;
const
optionTitle
=
option
.
querySelector
(
'
.option-title
'
);
const
optionTitle
=
option
.
querySelector
(
'
.option-title
'
);
...
@@ -20,8 +20,7 @@ function setVisibilityOptions(namespaceSelector) {
...
@@ -20,8 +20,7 @@ function setVisibilityOptions(namespaceSelector) {
optionInput
.
disabled
=
true
;
optionInput
.
disabled
=
true
;
const
reason
=
option
.
querySelector
(
'
.option-disabled-reason
'
);
const
reason
=
option
.
querySelector
(
'
.option-disabled-reason
'
);
if
(
reason
)
{
if
(
reason
)
{
reason
.
innerHTML
=
reason
.
innerHTML
=
`This project cannot be
${
optionName
}
because the visibility of
`This project cannot be
${
optionName
}
because the visibility of
<a href="
${
showPath
}
">
${
name
}
</a> is
${
visibility
}
. To make this project
<a href="
${
showPath
}
">
${
name
}
</a> is
${
visibility
}
. To make this project
${
optionName
}
, you must first <a href="
${
editPath
}
">change the visibility</a>
${
optionName
}
, you must first <a href="
${
editPath
}
">change the visibility</a>
of the parent group.`
;
of the parent group.`
;
...
...
app/assets/javascripts/prometheus_metrics/prometheus_metrics.js
View file @
c559bcca
...
@@ -65,10 +65,14 @@ export default class PrometheusMetrics {
...
@@ -65,10 +65,14 @@ export default class PrometheusMetrics {
let
totalMissingEnvVarMetrics
=
0
;
let
totalMissingEnvVarMetrics
=
0
;
let
totalExporters
=
0
;
let
totalExporters
=
0
;
metrics
.
forEach
(
(
metric
)
=>
{
metrics
.
forEach
(
metric
=>
{
if
(
metric
.
active_metrics
>
0
)
{
if
(
metric
.
active_metrics
>
0
)
{
totalExporters
+=
1
;
totalExporters
+=
1
;
this
.
$monitoredMetricsList
.
append
(
`<li>
${
_
.
escape
(
metric
.
group
)}
<span class="badge">
${
_
.
escape
(
metric
.
active_metrics
)}
</span></li>`
);
this
.
$monitoredMetricsList
.
append
(
`<li>
${
_
.
escape
(
metric
.
group
)}
<span class="badge">
${
_
.
escape
(
metric
.
active_metrics
,
)}
</span></li>`
,
);
totalMonitoredMetrics
+=
metric
.
active_metrics
;
totalMonitoredMetrics
+=
metric
.
active_metrics
;
if
(
metric
.
metrics_missing_requirements
>
0
)
{
if
(
metric
.
metrics_missing_requirements
>
0
)
{
this
.
$missingEnvVarMetricsList
.
append
(
`<li>
${
_
.
escape
(
metric
.
group
)}
</li>`
);
this
.
$missingEnvVarMetricsList
.
append
(
`<li>
${
_
.
escape
(
metric
.
group
)}
</li>`
);
...
@@ -78,17 +82,26 @@ export default class PrometheusMetrics {
...
@@ -78,17 +82,26 @@ export default class PrometheusMetrics {
});
});
if
(
totalMonitoredMetrics
===
0
)
{
if
(
totalMonitoredMetrics
===
0
)
{
const
emptyCommonMetricsText
=
sprintf
(
s__
(
'
PrometheusService|<p class="text-tertiary">No <a href="%{docsUrl}">common metrics</a> were found</p>
'
),
{
const
emptyCommonMetricsText
=
sprintf
(
docsUrl
:
this
.
helpMetricsPath
,
s__
(
},
false
);
'
PrometheusService|<p class="text-tertiary">No <a href="%{docsUrl}">common metrics</a> were found</p>
'
,
),
{
docsUrl
:
this
.
helpMetricsPath
,
},
false
,
);
this
.
$monitoredMetricsEmpty
.
empty
();
this
.
$monitoredMetricsEmpty
.
empty
();
this
.
$monitoredMetricsEmpty
.
append
(
emptyCommonMetricsText
);
this
.
$monitoredMetricsEmpty
.
append
(
emptyCommonMetricsText
);
this
.
showMonitoringMetricsPanelState
(
PANEL_STATE
.
EMPTY
);
this
.
showMonitoringMetricsPanelState
(
PANEL_STATE
.
EMPTY
);
}
else
{
}
else
{
const
metricsCountText
=
sprintf
(
s__
(
'
PrometheusService|%{exporters} with %{metrics} were found
'
),
{
const
metricsCountText
=
sprintf
(
exporters
:
n__
(
'
%d exporter
'
,
'
%d exporters
'
,
totalExporters
),
s__
(
'
PrometheusService|%{exporters} with %{metrics} were found
'
),
metrics
:
n__
(
'
%d metric
'
,
'
%d metrics
'
,
totalMonitoredMetrics
),
{
});
exporters
:
n__
(
'
%d exporter
'
,
'
%d exporters
'
,
totalExporters
),
metrics
:
n__
(
'
%d metric
'
,
'
%d metrics
'
,
totalMonitoredMetrics
),
},
);
this
.
$monitoredMetricsCount
.
text
(
metricsCountText
);
this
.
$monitoredMetricsCount
.
text
(
metricsCountText
);
this
.
showMonitoringMetricsPanelState
(
PANEL_STATE
.
LIST
);
this
.
showMonitoringMetricsPanelState
(
PANEL_STATE
.
LIST
);
...
@@ -102,7 +115,8 @@ export default class PrometheusMetrics {
...
@@ -102,7 +115,8 @@ export default class PrometheusMetrics {
loadActiveMetrics
()
{
loadActiveMetrics
()
{
this
.
showMonitoringMetricsPanelState
(
PANEL_STATE
.
LOADING
);
this
.
showMonitoringMetricsPanelState
(
PANEL_STATE
.
LOADING
);
backOff
((
next
,
stop
)
=>
{
backOff
((
next
,
stop
)
=>
{
axios
.
get
(
this
.
activeMetricsEndpoint
)
axios
.
get
(
this
.
activeMetricsEndpoint
)
.
then
(({
data
})
=>
{
.
then
(({
data
})
=>
{
if
(
data
&&
data
.
success
)
{
if
(
data
&&
data
.
success
)
{
stop
(
data
);
stop
(
data
);
...
@@ -117,7 +131,7 @@ export default class PrometheusMetrics {
...
@@ -117,7 +131,7 @@ export default class PrometheusMetrics {
})
})
.
catch
(
stop
);
.
catch
(
stop
);
})
})
.
then
(
(
res
)
=>
{
.
then
(
res
=>
{
if
(
res
&&
res
.
data
&&
res
.
data
.
length
)
{
if
(
res
&&
res
.
data
&&
res
.
data
.
length
)
{
this
.
populateActiveMetrics
(
res
.
data
);
this
.
populateActiveMetrics
(
res
.
data
);
}
else
{
}
else
{
...
...
app/assets/javascripts/raven/raven_config.js
View file @
c559bcca
...
@@ -9,7 +9,7 @@ const IGNORE_ERRORS = [
...
@@ -9,7 +9,7 @@ const IGNORE_ERRORS = [
'
canvas.contentDocument
'
,
'
canvas.contentDocument
'
,
'
MyApp_RemoveAllHighlights
'
,
'
MyApp_RemoveAllHighlights
'
,
'
http://tt.epicplay.com
'
,
'
http://tt.epicplay.com
'
,
'
Can
\'
t find variable: ZiteReader
'
,
"
Can't find variable: ZiteReader
"
,
'
jigsaw is not defined
'
,
'
jigsaw is not defined
'
,
'
ComboSearch is not defined
'
,
'
ComboSearch is not defined
'
,
'
http://loading.retry.widdit.com/
'
,
'
http://loading.retry.widdit.com/
'
,
...
...
app/assets/javascripts/ref_select_dropdown.js
View file @
c559bcca
...
@@ -2,7 +2,8 @@ import $ from 'jquery';
...
@@ -2,7 +2,8 @@ import $ from 'jquery';
class
RefSelectDropdown
{
class
RefSelectDropdown
{
constructor
(
$dropdownButton
,
availableRefs
)
{
constructor
(
$dropdownButton
,
availableRefs
)
{
const
availableRefsValue
=
availableRefs
||
JSON
.
parse
(
document
.
getElementById
(
'
availableRefs
'
).
innerHTML
);
const
availableRefsValue
=
availableRefs
||
JSON
.
parse
(
document
.
getElementById
(
'
availableRefs
'
).
innerHTML
);
$dropdownButton
.
glDropdown
({
$dropdownButton
.
glDropdown
({
data
:
availableRefsValue
,
data
:
availableRefsValue
,
filterable
:
true
,
filterable
:
true
,
...
@@ -29,7 +30,7 @@ class RefSelectDropdown {
...
@@ -29,7 +30,7 @@ class RefSelectDropdown {
const
$fieldInput
=
$
(
`input[name="
${
$dropdownButton
.
data
(
'
fieldName
'
)}
"]`
,
$dropdownContainer
);
const
$fieldInput
=
$
(
`input[name="
${
$dropdownButton
.
data
(
'
fieldName
'
)}
"]`
,
$dropdownContainer
);
const
$filterInput
=
$
(
'
input[type="search"]
'
,
$dropdownContainer
);
const
$filterInput
=
$
(
'
input[type="search"]
'
,
$dropdownContainer
);
$filterInput
.
on
(
'
keyup
'
,
(
e
)
=>
{
$filterInput
.
on
(
'
keyup
'
,
e
=>
{
const
keyCode
=
e
.
keyCode
||
e
.
which
;
const
keyCode
=
e
.
keyCode
||
e
.
which
;
if
(
keyCode
!==
13
)
return
;
if
(
keyCode
!==
13
)
return
;
...
...
app/assets/javascripts/settings_panels.js
View file @
c559bcca
...
@@ -3,10 +3,14 @@ import { __ } from './locale';
...
@@ -3,10 +3,14 @@ import { __ } from './locale';
function
expandSection
(
$section
)
{
function
expandSection
(
$section
)
{
$section
.
find
(
'
.js-settings-toggle:not(.js-settings-toggle-trigger-only)
'
).
text
(
__
(
'
Collapse
'
));
$section
.
find
(
'
.js-settings-toggle:not(.js-settings-toggle-trigger-only)
'
).
text
(
__
(
'
Collapse
'
));
$section
.
find
(
'
.settings-content
'
).
off
(
'
scroll.expandSection
'
).
scrollTop
(
0
);
$section
.
find
(
'
.settings-content
'
)
.
off
(
'
scroll.expandSection
'
)
.
scrollTop
(
0
);
$section
.
addClass
(
'
expanded
'
);
$section
.
addClass
(
'
expanded
'
);
if
(
!
$section
.
hasClass
(
'
no-animate
'
))
{
if
(
!
$section
.
hasClass
(
'
no-animate
'
))
{
$section
.
addClass
(
'
animating
'
)
$section
.
addClass
(
'
animating
'
)
.
one
(
'
animationend.animateSection
'
,
()
=>
$section
.
removeClass
(
'
animating
'
));
.
one
(
'
animationend.animateSection
'
,
()
=>
$section
.
removeClass
(
'
animating
'
));
}
}
}
}
...
@@ -16,7 +20,8 @@ function closeSection($section) {
...
@@ -16,7 +20,8 @@ function closeSection($section) {
$section
.
find
(
'
.settings-content
'
).
on
(
'
scroll.expandSection
'
,
()
=>
expandSection
(
$section
));
$section
.
find
(
'
.settings-content
'
).
on
(
'
scroll.expandSection
'
,
()
=>
expandSection
(
$section
));
$section
.
removeClass
(
'
expanded
'
);
$section
.
removeClass
(
'
expanded
'
);
if
(
!
$section
.
hasClass
(
'
no-animate
'
))
{
if
(
!
$section
.
hasClass
(
'
no-animate
'
))
{
$section
.
addClass
(
'
animating
'
)
$section
.
addClass
(
'
animating
'
)
.
one
(
'
animationend.animateSection
'
,
()
=>
$section
.
removeClass
(
'
animating
'
));
.
one
(
'
animationend.animateSection
'
,
()
=>
$section
.
removeClass
(
'
animating
'
));
}
}
}
}
...
...
app/assets/javascripts/single_file_diff.js
View file @
c559bcca
...
@@ -10,8 +10,10 @@ import syntaxHighlight from './syntax_highlight';
...
@@ -10,8 +10,10 @@ import syntaxHighlight from './syntax_highlight';
const
WRAPPER
=
'
<div class="diff-content"></div>
'
;
const
WRAPPER
=
'
<div class="diff-content"></div>
'
;
const
LOADING_HTML
=
'
<i class="fa fa-spinner fa-spin"></i>
'
;
const
LOADING_HTML
=
'
<i class="fa fa-spinner fa-spin"></i>
'
;
const
ERROR_HTML
=
'
<div class="nothing-here-block"><i class="fa fa-warning"></i> Could not load diff</div>
'
;
const
ERROR_HTML
=
const
COLLAPSED_HTML
=
'
<div class="nothing-here-block diff-collapsed">This diff is collapsed. <button class="click-to-expand btn btn-link">Click to expand it.</button></div>
'
;
'
<div class="nothing-here-block"><i class="fa fa-warning"></i> Could not load diff</div>
'
;
const
COLLAPSED_HTML
=
'
<div class="nothing-here-block diff-collapsed">This diff is collapsed. <button class="click-to-expand btn btn-link">Click to expand it.</button></div>
'
;
export
default
class
SingleFileDiff
{
export
default
class
SingleFileDiff
{
constructor
(
file
)
{
constructor
(
file
)
{
...
@@ -23,23 +25,36 @@ export default class SingleFileDiff {
...
@@ -23,23 +25,36 @@ export default class SingleFileDiff {
this
.
isOpen
=
!
this
.
diffForPath
;
this
.
isOpen
=
!
this
.
diffForPath
;
if
(
this
.
diffForPath
)
{
if
(
this
.
diffForPath
)
{
this
.
collapsedContent
=
this
.
content
;
this
.
collapsedContent
=
this
.
content
;
this
.
loadingContent
=
$
(
WRAPPER
).
addClass
(
'
loading
'
).
html
(
LOADING_HTML
).
hide
();
this
.
loadingContent
=
$
(
WRAPPER
)
.
addClass
(
'
loading
'
)
.
html
(
LOADING_HTML
)
.
hide
();
this
.
content
=
null
;
this
.
content
=
null
;
this
.
collapsedContent
.
after
(
this
.
loadingContent
);
this
.
collapsedContent
.
after
(
this
.
loadingContent
);
this
.
$toggleIcon
.
addClass
(
'
fa-caret-right
'
);
this
.
$toggleIcon
.
addClass
(
'
fa-caret-right
'
);
}
else
{
}
else
{
this
.
collapsedContent
=
$
(
WRAPPER
).
html
(
COLLAPSED_HTML
).
hide
();
this
.
collapsedContent
=
$
(
WRAPPER
)
.
html
(
COLLAPSED_HTML
)
.
hide
();
this
.
content
.
after
(
this
.
collapsedContent
);
this
.
content
.
after
(
this
.
collapsedContent
);
this
.
$toggleIcon
.
addClass
(
'
fa-caret-down
'
);
this
.
$toggleIcon
.
addClass
(
'
fa-caret-down
'
);
}
}
$
(
'
.js-file-title, .click-to-expand
'
,
this
.
file
).
on
(
'
click
'
,
(
function
(
e
)
{
$
(
'
.js-file-title, .click-to-expand
'
,
this
.
file
).
on
(
this
.
toggleDiff
(
$
(
e
.
target
));
'
click
'
,
}).
bind
(
this
));
function
(
e
)
{
this
.
toggleDiff
(
$
(
e
.
target
));
}.
bind
(
this
),
);
}
}
toggleDiff
(
$target
,
cb
)
{
toggleDiff
(
$target
,
cb
)
{
if
(
!
$target
.
hasClass
(
'
js-file-title
'
)
&&
!
$target
.
hasClass
(
'
click-to-expand
'
)
&&
!
$target
.
hasClass
(
'
diff-toggle-caret
'
))
return
;
if
(
!
$target
.
hasClass
(
'
js-file-title
'
)
&&
!
$target
.
hasClass
(
'
click-to-expand
'
)
&&
!
$target
.
hasClass
(
'
diff-toggle-caret
'
)
)
return
;
this
.
isOpen
=
!
this
.
isOpen
;
this
.
isOpen
=
!
this
.
isOpen
;
if
(
!
this
.
isOpen
&&
!
this
.
hasError
)
{
if
(
!
this
.
isOpen
&&
!
this
.
hasError
)
{
this
.
content
.
hide
();
this
.
content
.
hide
();
...
@@ -65,7 +80,8 @@ export default class SingleFileDiff {
...
@@ -65,7 +80,8 @@ export default class SingleFileDiff {
this
.
collapsedContent
.
hide
();
this
.
collapsedContent
.
hide
();
this
.
loadingContent
.
show
();
this
.
loadingContent
.
show
();
axios
.
get
(
this
.
diffForPath
)
axios
.
get
(
this
.
diffForPath
)
.
then
(({
data
})
=>
{
.
then
(({
data
})
=>
{
this
.
loadingContent
.
hide
();
this
.
loadingContent
.
hide
();
if
(
data
.
html
)
{
if
(
data
.
html
)
{
...
...
app/assets/javascripts/smart_interval.js
View file @
c559bcca
...
@@ -93,7 +93,9 @@ export default class SmartInterval {
...
@@ -93,7 +93,9 @@ export default class SmartInterval {
destroy
()
{
destroy
()
{
this
.
cancel
();
this
.
cancel
();
document
.
removeEventListener
(
'
visibilitychange
'
,
this
.
handleVisibilityChange
);
document
.
removeEventListener
(
'
visibilitychange
'
,
this
.
handleVisibilityChange
);
$
(
document
).
off
(
'
visibilitychange
'
).
off
(
'
beforeunload
'
);
$
(
document
)
.
off
(
'
visibilitychange
'
)
.
off
(
'
beforeunload
'
);
}
}
/* private */
/* private */
...
@@ -111,11 +113,12 @@ export default class SmartInterval {
...
@@ -111,11 +113,12 @@ export default class SmartInterval {
triggerCallback
()
{
triggerCallback
()
{
this
.
isLoading
=
true
;
this
.
isLoading
=
true
;
this
.
cfg
.
callback
()
this
.
cfg
.
callback
()
.
then
(()
=>
{
.
then
(()
=>
{
this
.
isLoading
=
false
;
this
.
isLoading
=
false
;
})
})
.
catch
(
(
err
)
=>
{
.
catch
(
err
=>
{
this
.
isLoading
=
false
;
this
.
isLoading
=
false
;
throw
err
;
throw
err
;
});
});
...
@@ -134,9 +137,9 @@ export default class SmartInterval {
...
@@ -134,9 +137,9 @@ export default class SmartInterval {
handleVisibilityChange
(
e
)
{
handleVisibilityChange
(
e
)
{
this
.
state
.
pageVisibility
=
e
.
target
.
visibilityState
;
this
.
state
.
pageVisibility
=
e
.
target
.
visibilityState
;
const
intervalAction
=
this
.
isPageVisible
()
?
const
intervalAction
=
this
.
isPageVisible
()
this
.
onVisibilityVisible
:
?
this
.
onVisibilityVisible
this
.
onVisibilityHidden
;
:
this
.
onVisibilityHidden
;
intervalAction
.
apply
(
this
);
intervalAction
.
apply
(
this
);
}
}
...
@@ -162,7 +165,9 @@ export default class SmartInterval {
...
@@ -162,7 +165,9 @@ export default class SmartInterval {
this
.
setCurrentInterval
(
nextInterval
);
this
.
setCurrentInterval
(
nextInterval
);
}
}
isPageVisible
()
{
return
this
.
state
.
pageVisibility
===
'
visible
'
;
}
isPageVisible
()
{
return
this
.
state
.
pageVisibility
===
'
visible
'
;
}
stopTimer
()
{
stopTimer
()
{
const
{
state
}
=
this
;
const
{
state
}
=
this
;
...
@@ -170,4 +175,3 @@ export default class SmartInterval {
...
@@ -170,4 +175,3 @@ export default class SmartInterval {
state
.
intervalId
=
window
.
clearInterval
(
state
.
intervalId
);
state
.
intervalId
=
window
.
clearInterval
(
state
.
intervalId
);
}
}
}
}
app/assets/javascripts/star.js
View file @
c559bcca
...
@@ -11,10 +11,14 @@ export default class Star {
...
@@ -11,10 +11,14 @@ export default class Star {
const
$starSpan
=
$this
.
find
(
'
span
'
);
const
$starSpan
=
$this
.
find
(
'
span
'
);
const
$startIcon
=
$this
.
find
(
'
svg
'
);
const
$startIcon
=
$this
.
find
(
'
svg
'
);
axios
.
post
(
$this
.
data
(
'
endpoint
'
))
axios
.
post
(
$this
.
data
(
'
endpoint
'
))
.
then
(({
data
})
=>
{
.
then
(({
data
})
=>
{
const
isStarred
=
$starSpan
.
hasClass
(
'
starred
'
);
const
isStarred
=
$starSpan
.
hasClass
(
'
starred
'
);
$this
.
parent
().
find
(
'
.star-count
'
).
text
(
data
.
star_count
);
$this
.
parent
()
.
find
(
'
.star-count
'
)
.
text
(
data
.
star_count
);
if
(
isStarred
)
{
if
(
isStarred
)
{
$starSpan
.
removeClass
(
'
starred
'
).
text
(
s__
(
'
StarProject|Star
'
));
$starSpan
.
removeClass
(
'
starred
'
).
text
(
s__
(
'
StarProject|Star
'
));
...
...
app/assets/javascripts/task_list.js
View file @
c559bcca
...
@@ -26,7 +26,11 @@ export default class TaskList {
...
@@ -26,7 +26,11 @@ export default class TaskList {
// Prevent duplicate event bindings
// Prevent duplicate event bindings
this
.
disable
();
this
.
disable
();
$
(
`
${
this
.
selector
}
.js-task-list-container`
).
taskList
(
'
enable
'
);
$
(
`
${
this
.
selector
}
.js-task-list-container`
).
taskList
(
'
enable
'
);
$
(
document
).
on
(
'
tasklist:changed
'
,
`
${
this
.
selector
}
.js-task-list-container`
,
this
.
update
.
bind
(
this
));
$
(
document
).
on
(
'
tasklist:changed
'
,
`
${
this
.
selector
}
.js-task-list-container`
,
this
.
update
.
bind
(
this
),
);
}
}
disable
()
{
disable
()
{
...
@@ -41,7 +45,8 @@ export default class TaskList {
...
@@ -41,7 +45,8 @@ export default class TaskList {
[
this
.
fieldName
]:
$target
.
val
(),
[
this
.
fieldName
]:
$target
.
val
(),
};
};
return
axios
.
patch
(
$target
.
data
(
'
updateUrl
'
)
||
$
(
'
form.js-issuable-update
'
).
attr
(
'
action
'
),
patchData
)
return
axios
.
patch
(
$target
.
data
(
'
updateUrl
'
)
||
$
(
'
form.js-issuable-update
'
).
attr
(
'
action
'
),
patchData
)
.
then
(({
data
})
=>
this
.
onSuccess
(
data
))
.
then
(({
data
})
=>
this
.
onSuccess
(
data
))
.
catch
(
err
=>
this
.
onError
(
err
));
.
catch
(
err
=>
this
.
onError
(
err
));
}
}
...
...
app/assets/javascripts/templates/issuable_template_selector.js
View file @
c559bcca
...
@@ -31,12 +31,18 @@ export default class IssuableTemplateSelector extends TemplateSelector {
...
@@ -31,12 +31,18 @@ export default class IssuableTemplateSelector extends TemplateSelector {
requestFile
(
query
)
{
requestFile
(
query
)
{
this
.
startLoadingSpinner
();
this
.
startLoadingSpinner
();
Api
.
issueTemplate
(
this
.
namespacePath
,
this
.
projectPath
,
query
.
name
,
this
.
issuableType
,
(
err
,
currentTemplate
)
=>
{
Api
.
issueTemplate
(
this
.
currentTemplate
=
currentTemplate
;
this
.
namespacePath
,
this
.
stopLoadingSpinner
();
this
.
projectPath
,
if
(
err
)
return
;
// Error handled by global AJAX error handler
query
.
name
,
this
.
setInputValueToTemplateContent
();
this
.
issuableType
,
});
(
err
,
currentTemplate
)
=>
{
this
.
currentTemplate
=
currentTemplate
;
this
.
stopLoadingSpinner
();
if
(
err
)
return
;
// Error handled by global AJAX error handler
this
.
setInputValueToTemplateContent
();
},
);
return
;
return
;
}
}
...
...
app/assets/javascripts/terminal/terminal.js
View file @
c559bcca
...
@@ -4,10 +4,14 @@ import * as fit from 'xterm/lib/addons/fit/fit';
...
@@ -4,10 +4,14 @@ import * as fit from 'xterm/lib/addons/fit/fit';
export
default
class
GLTerminal
{
export
default
class
GLTerminal
{
constructor
(
options
=
{})
{
constructor
(
options
=
{})
{
this
.
options
=
Object
.
assign
({},
{
this
.
options
=
Object
.
assign
(
cursorBlink
:
true
,
{},
screenKeys
:
true
,
{
},
options
);
cursorBlink
:
true
,
screenKeys
:
true
,
},
options
,
);
this
.
container
=
document
.
querySelector
(
options
.
selector
);
this
.
container
=
document
.
querySelector
(
options
.
selector
);
...
...
app/assets/javascripts/test_utils/simulate_drag.js
View file @
c559bcca
...
@@ -4,15 +4,43 @@ function simulateEvent(el, type, options = {}) {
...
@@ -4,15 +4,43 @@ function simulateEvent(el, type, options = {}) {
if
(
/^mouse/
.
test
(
type
))
{
if
(
/^mouse/
.
test
(
type
))
{
event
=
el
.
ownerDocument
.
createEvent
(
'
MouseEvents
'
);
event
=
el
.
ownerDocument
.
createEvent
(
'
MouseEvents
'
);
event
.
initMouseEvent
(
type
,
true
,
true
,
el
.
ownerDocument
.
defaultView
,
event
.
initMouseEvent
(
options
.
button
,
options
.
screenX
,
options
.
screenY
,
options
.
clientX
,
options
.
clientY
,
type
,
options
.
ctrlKey
,
options
.
altKey
,
options
.
shiftKey
,
options
.
metaKey
,
options
.
button
,
el
);
true
,
true
,
el
.
ownerDocument
.
defaultView
,
options
.
button
,
options
.
screenX
,
options
.
screenY
,
options
.
clientX
,
options
.
clientY
,
options
.
ctrlKey
,
options
.
altKey
,
options
.
shiftKey
,
options
.
metaKey
,
options
.
button
,
el
,
);
}
else
{
}
else
{
event
=
el
.
ownerDocument
.
createEvent
(
'
CustomEvent
'
);
event
=
el
.
ownerDocument
.
createEvent
(
'
CustomEvent
'
);
event
.
initCustomEvent
(
type
,
true
,
true
,
el
.
ownerDocument
.
defaultView
,
event
.
initCustomEvent
(
options
.
button
,
options
.
screenX
,
options
.
screenY
,
options
.
clientX
,
options
.
clientY
,
type
,
options
.
ctrlKey
,
options
.
altKey
,
options
.
shiftKey
,
options
.
metaKey
,
options
.
button
,
el
);
true
,
true
,
el
.
ownerDocument
.
defaultView
,
options
.
button
,
options
.
screenX
,
options
.
screenY
,
options
.
clientX
,
options
.
clientY
,
options
.
ctrlKey
,
options
.
altKey
,
options
.
shiftKey
,
options
.
metaKey
,
options
.
button
,
el
,
);
event
.
dataTransfer
=
{
event
.
dataTransfer
=
{
data
:
{},
data
:
{},
...
@@ -37,14 +65,16 @@ function simulateEvent(el, type, options = {}) {
...
@@ -37,14 +65,16 @@ function simulateEvent(el, type, options = {}) {
}
}
function
isLast
(
target
)
{
function
isLast
(
target
)
{
const
el
=
typeof
target
.
el
===
'
string
'
?
document
.
getElementById
(
target
.
el
.
substr
(
1
))
:
target
.
el
;
const
el
=
typeof
target
.
el
===
'
string
'
?
document
.
getElementById
(
target
.
el
.
substr
(
1
))
:
target
.
el
;
const
{
children
}
=
el
;
const
{
children
}
=
el
;
return
children
.
length
-
1
===
target
.
index
;
return
children
.
length
-
1
===
target
.
index
;
}
}
function
getTarget
(
target
)
{
function
getTarget
(
target
)
{
const
el
=
typeof
target
.
el
===
'
string
'
?
document
.
getElementById
(
target
.
el
.
substr
(
1
))
:
target
.
el
;
const
el
=
typeof
target
.
el
===
'
string
'
?
document
.
getElementById
(
target
.
el
.
substr
(
1
))
:
target
.
el
;
const
{
children
}
=
el
;
const
{
children
}
=
el
;
return
(
return
(
...
@@ -58,13 +88,13 @@ function getTarget(target) {
...
@@ -58,13 +88,13 @@ function getTarget(target) {
function
getRect
(
el
)
{
function
getRect
(
el
)
{
const
rect
=
el
.
getBoundingClientRect
();
const
rect
=
el
.
getBoundingClientRect
();
const
width
=
rect
.
right
-
rect
.
left
;
const
width
=
rect
.
right
-
rect
.
left
;
const
height
=
(
rect
.
bottom
-
rect
.
top
)
+
10
;
const
height
=
rect
.
bottom
-
rect
.
top
+
10
;
return
{
return
{
x
:
rect
.
left
,
x
:
rect
.
left
,
y
:
rect
.
top
,
y
:
rect
.
top
,
cx
:
rect
.
left
+
(
width
/
2
)
,
cx
:
rect
.
left
+
width
/
2
,
cy
:
rect
.
top
+
(
height
/
2
)
,
cy
:
rect
.
top
+
height
/
2
,
w
:
width
,
w
:
width
,
h
:
height
,
h
:
height
,
hw
:
width
/
2
,
hw
:
width
/
2
,
...
@@ -112,8 +142,8 @@ export default function simulateDrag(options) {
...
@@ -112,8 +142,8 @@ export default function simulateDrag(options) {
const
dragInterval
=
setInterval
(()
=>
{
const
dragInterval
=
setInterval
(()
=>
{
const
progress
=
(
new
Date
().
getTime
()
-
startTime
)
/
duration
;
const
progress
=
(
new
Date
().
getTime
()
-
startTime
)
/
duration
;
const
x
=
(
fromRect
.
cx
+
((
toRect
.
cx
-
fromRect
.
cx
)
*
progress
))
;
const
x
=
fromRect
.
cx
+
(
toRect
.
cx
-
fromRect
.
cx
)
*
progress
;
const
y
=
(
fromRect
.
cy
+
((
toRect
.
cy
-
fromRect
.
cy
)
*
progress
))
;
const
y
=
fromRect
.
cy
+
(
toRect
.
cy
-
fromRect
.
cy
)
*
progress
;
const
overEl
=
fromEl
.
ownerDocument
.
elementFromPoint
(
x
,
y
);
const
overEl
=
fromEl
.
ownerDocument
.
elementFromPoint
(
x
,
y
);
simulateEvent
(
overEl
,
'
mousemove
'
,
{
simulateEvent
(
overEl
,
'
mousemove
'
,
{
...
...
app/assets/javascripts/test_utils/simulate_input.js
View file @
c559bcca
...
@@ -12,7 +12,7 @@ export default function simulateInput(target, text) {
...
@@ -12,7 +12,7 @@ export default function simulateInput(target, text) {
}
}
if
(
text
.
length
>
0
)
{
if
(
text
.
length
>
0
)
{
Array
.
prototype
.
forEach
.
call
(
text
,
(
char
)
=>
{
Array
.
prototype
.
forEach
.
call
(
text
,
char
=>
{
input
.
value
+=
char
;
input
.
value
+=
char
;
triggerEvents
(
input
);
triggerEvents
(
input
);
});
});
...
...
app/assets/javascripts/toggle_buttons.js
View file @
c559bcca
...
@@ -49,7 +49,7 @@ function onToggleClicked(toggle, input, clickCallback) {
...
@@ -49,7 +49,7 @@ function onToggleClicked(toggle, input, clickCallback) {
export
default
function
setupToggleButtons
(
container
,
clickCallback
=
()
=>
{})
{
export
default
function
setupToggleButtons
(
container
,
clickCallback
=
()
=>
{})
{
const
toggles
=
container
.
querySelectorAll
(
'
.js-project-feature-toggle
'
);
const
toggles
=
container
.
querySelectorAll
(
'
.js-project-feature-toggle
'
);
toggles
.
forEach
(
(
toggle
)
=>
{
toggles
.
forEach
(
toggle
=>
{
const
input
=
toggle
.
querySelector
(
'
.js-project-feature-toggle-input
'
);
const
input
=
toggle
.
querySelector
(
'
.js-project-feature-toggle-input
'
);
const
isOn
=
convertPermissionToBoolean
(
input
.
value
);
const
isOn
=
convertPermissionToBoolean
(
input
.
value
);
...
...
app/assets/javascripts/tree.js
View file @
c559bcca
...
@@ -8,7 +8,7 @@ export default class TreeView {
...
@@ -8,7 +8,7 @@ export default class TreeView {
this
.
initKeyNav
();
this
.
initKeyNav
();
// Code browser tree slider
// Code browser tree slider
// Make the entire tree-item row clickable, but not if clicking another link (like a commit message)
// Make the entire tree-item row clickable, but not if clicking another link (like a commit message)
$
(
"
.tree-content-holder .tree-item
"
).
on
(
'
click
'
,
function
(
e
)
{
$
(
'
.tree-content-holder .tree-item
'
).
on
(
'
click
'
,
function
(
e
)
{
var
$clickedEl
,
path
;
var
$clickedEl
,
path
;
$clickedEl
=
$
(
e
.
target
);
$clickedEl
=
$
(
e
.
target
);
path
=
$
(
'
.tree-item-file-name a
'
,
this
).
attr
(
'
href
'
);
path
=
$
(
'
.tree-item-file-name a
'
,
this
).
attr
(
'
href
'
);
...
@@ -27,33 +27,33 @@ export default class TreeView {
...
@@ -27,33 +27,33 @@ export default class TreeView {
initKeyNav
()
{
initKeyNav
()
{
var
li
,
liSelected
;
var
li
,
liSelected
;
li
=
$
(
"
tr.tree-item
"
);
li
=
$
(
'
tr.tree-item
'
);
liSelected
=
null
;
liSelected
=
null
;
return
$
(
'
body
'
).
keydown
(
function
(
e
)
{
return
$
(
'
body
'
).
keydown
(
function
(
e
)
{
var
next
,
path
;
var
next
,
path
;
if
(
$
(
"
input:focus
"
).
length
>
0
&&
(
e
.
which
===
38
||
e
.
which
===
40
))
{
if
(
$
(
'
input:focus
'
).
length
>
0
&&
(
e
.
which
===
38
||
e
.
which
===
40
))
{
return
false
;
return
false
;
}
}
if
(
e
.
which
===
40
)
{
if
(
e
.
which
===
40
)
{
if
(
liSelected
)
{
if
(
liSelected
)
{
next
=
liSelected
.
next
();
next
=
liSelected
.
next
();
if
(
next
.
length
>
0
)
{
if
(
next
.
length
>
0
)
{
liSelected
.
removeClass
(
"
selected
"
);
liSelected
.
removeClass
(
'
selected
'
);
liSelected
=
next
.
addClass
(
"
selected
"
);
liSelected
=
next
.
addClass
(
'
selected
'
);
}
}
}
else
{
}
else
{
liSelected
=
li
.
eq
(
0
).
addClass
(
"
selected
"
);
liSelected
=
li
.
eq
(
0
).
addClass
(
'
selected
'
);
}
}
return
$
(
liSelected
).
focus
();
return
$
(
liSelected
).
focus
();
}
else
if
(
e
.
which
===
38
)
{
}
else
if
(
e
.
which
===
38
)
{
if
(
liSelected
)
{
if
(
liSelected
)
{
next
=
liSelected
.
prev
();
next
=
liSelected
.
prev
();
if
(
next
.
length
>
0
)
{
if
(
next
.
length
>
0
)
{
liSelected
.
removeClass
(
"
selected
"
);
liSelected
.
removeClass
(
'
selected
'
);
liSelected
=
next
.
addClass
(
"
selected
"
);
liSelected
=
next
.
addClass
(
'
selected
'
);
}
}
}
else
{
}
else
{
liSelected
=
li
.
last
().
addClass
(
"
selected
"
);
liSelected
=
li
.
last
().
addClass
(
'
selected
'
);
}
}
return
$
(
liSelected
).
focus
();
return
$
(
liSelected
).
focus
();
}
else
if
(
e
.
which
===
13
)
{
}
else
if
(
e
.
which
===
13
)
{
...
...
app/assets/javascripts/u2f/authenticate.js
View file @
c559bcca
...
@@ -49,7 +49,7 @@ export default class U2FAuthenticate {
...
@@ -49,7 +49,7 @@ export default class U2FAuthenticate {
start
()
{
start
()
{
return
importU2FLibrary
()
return
importU2FLibrary
()
.
then
(
(
utils
)
=>
{
.
then
(
utils
=>
{
this
.
u2fUtils
=
utils
;
this
.
u2fUtils
=
utils
;
this
.
renderInProgress
();
this
.
renderInProgress
();
})
})
...
@@ -57,14 +57,19 @@ export default class U2FAuthenticate {
...
@@ -57,14 +57,19 @@ export default class U2FAuthenticate {
}
}
authenticate
()
{
authenticate
()
{
return
this
.
u2fUtils
.
sign
(
this
.
appId
,
this
.
challenge
,
this
.
signRequests
,
return
this
.
u2fUtils
.
sign
(
(
response
)
=>
{
this
.
appId
,
this
.
challenge
,
this
.
signRequests
,
response
=>
{
if
(
response
.
errorCode
)
{
if
(
response
.
errorCode
)
{
const
error
=
new
U2FError
(
response
.
errorCode
,
'
authenticate
'
);
const
error
=
new
U2FError
(
response
.
errorCode
,
'
authenticate
'
);
return
this
.
renderError
(
error
);
return
this
.
renderError
(
error
);
}
}
return
this
.
renderAuthenticated
(
JSON
.
stringify
(
response
));
return
this
.
renderAuthenticated
(
JSON
.
stringify
(
response
));
},
10
);
},
10
,
);
}
}
renderTemplate
(
name
,
params
)
{
renderTemplate
(
name
,
params
)
{
...
@@ -99,5 +104,4 @@ export default class U2FAuthenticate {
...
@@ -99,5 +104,4 @@ export default class U2FAuthenticate {
this
.
container
[
0
].
classList
.
add
(
'
hidden
'
);
this
.
container
[
0
].
classList
.
add
(
'
hidden
'
);
this
.
fallbackUI
.
classList
.
remove
(
'
hidden
'
);
this
.
fallbackUI
.
classList
.
remove
(
'
hidden
'
);
}
}
}
}
app/assets/javascripts/u2f/register.js
View file @
c559bcca
...
@@ -34,7 +34,7 @@ export default class U2FRegister {
...
@@ -34,7 +34,7 @@ export default class U2FRegister {
start
()
{
start
()
{
return
importU2FLibrary
()
return
importU2FLibrary
()
.
then
(
(
utils
)
=>
{
.
then
(
utils
=>
{
this
.
u2fUtils
=
utils
;
this
.
u2fUtils
=
utils
;
this
.
renderSetup
();
this
.
renderSetup
();
})
})
...
@@ -42,14 +42,19 @@ export default class U2FRegister {
...
@@ -42,14 +42,19 @@ export default class U2FRegister {
}
}
register
()
{
register
()
{
return
this
.
u2fUtils
.
register
(
this
.
appId
,
this
.
registerRequests
,
this
.
signRequests
,
return
this
.
u2fUtils
.
register
(
(
response
)
=>
{
this
.
appId
,
this
.
registerRequests
,
this
.
signRequests
,
response
=>
{
if
(
response
.
errorCode
)
{
if
(
response
.
errorCode
)
{
const
error
=
new
U2FError
(
response
.
errorCode
,
'
register
'
);
const
error
=
new
U2FError
(
response
.
errorCode
,
'
register
'
);
return
this
.
renderError
(
error
);
return
this
.
renderError
(
error
);
}
}
return
this
.
renderRegistered
(
JSON
.
stringify
(
response
));
return
this
.
renderRegistered
(
JSON
.
stringify
(
response
));
},
10
);
},
10
,
);
}
}
renderTemplate
(
name
,
params
)
{
renderTemplate
(
name
,
params
)
{
...
...
app/assets/javascripts/u2f/util.js
View file @
c559bcca
...
@@ -19,11 +19,10 @@ function getChromeVersion(userAgent) {
...
@@ -19,11 +19,10 @@ function getChromeVersion(userAgent) {
export
function
canInjectU2fApi
(
userAgent
)
{
export
function
canInjectU2fApi
(
userAgent
)
{
const
isSupportedChrome
=
isChrome
(
userAgent
)
&&
getChromeVersion
(
userAgent
)
>=
41
;
const
isSupportedChrome
=
isChrome
(
userAgent
)
&&
getChromeVersion
(
userAgent
)
>=
41
;
const
isSupportedOpera
=
isOpera
(
userAgent
)
&&
getOperaVersion
(
userAgent
)
>=
40
;
const
isSupportedOpera
=
isOpera
(
userAgent
)
&&
getOperaVersion
(
userAgent
)
>=
40
;
const
isMobile
=
(
const
isMobile
=
userAgent
.
indexOf
(
'
droid
'
)
>=
0
||
userAgent
.
indexOf
(
'
droid
'
)
>=
0
||
userAgent
.
indexOf
(
'
CriOS
'
)
>=
0
||
userAgent
.
indexOf
(
'
CriOS
'
)
>=
0
||
/
\b(
iPad|iPhone|iPod
)(?=
;
)
/
.
test
(
userAgent
)
/
\b(
iPad|iPhone|iPod
)(?=
;
)
/
.
test
(
userAgent
);
);
return
(
isSupportedChrome
||
isSupportedOpera
)
&&
!
isMobile
;
return
(
isSupportedChrome
||
isSupportedOpera
)
&&
!
isMobile
;
}
}
...
...
app/assets/javascripts/ui_development_kit.js
View file @
c559bcca
...
@@ -4,13 +4,17 @@ import Api from './api';
...
@@ -4,13 +4,17 @@ import Api from './api';
export
default
()
=>
{
export
default
()
=>
{
$
(
'
#js-project-dropdown
'
).
glDropdown
({
$
(
'
#js-project-dropdown
'
).
glDropdown
({
data
:
(
term
,
callback
)
=>
{
data
:
(
term
,
callback
)
=>
{
Api
.
projects
(
term
,
{
Api
.
projects
(
order_by
:
'
last_activity_at
'
,
term
,
},
(
data
)
=>
{
{
callback
(
data
);
order_by
:
'
last_activity_at
'
,
});
},
data
=>
{
callback
(
data
);
},
);
},
},
text
:
project
=>
(
project
.
name_with_namespace
||
project
.
name
)
,
text
:
project
=>
project
.
name_with_namespace
||
project
.
name
,
selectable
:
true
,
selectable
:
true
,
fieldName
:
'
author_id
'
,
fieldName
:
'
author_id
'
,
filterable
:
true
,
filterable
:
true
,
...
@@ -18,6 +22,6 @@ export default () => {
...
@@ -18,6 +22,6 @@ export default () => {
fields
:
[
'
name_with_namespace
'
],
fields
:
[
'
name_with_namespace
'
],
},
},
id
:
data
=>
data
.
id
,
id
:
data
=>
data
.
id
,
isSelected
:
data
=>
(
data
.
id
===
2
)
,
isSelected
:
data
=>
data
.
id
===
2
,
});
});
};
};
app/assets/javascripts/usage_ping_consent.js
View file @
c559bcca
...
@@ -4,7 +4,7 @@ import Flash, { hideFlash } from './flash';
...
@@ -4,7 +4,7 @@ import Flash, { hideFlash } from './flash';
import
{
convertPermissionToBoolean
}
from
'
./lib/utils/common_utils
'
;
import
{
convertPermissionToBoolean
}
from
'
./lib/utils/common_utils
'
;
export
default
()
=>
{
export
default
()
=>
{
$
(
'
body
'
).
on
(
'
click
'
,
'
.js-usage-consent-action
'
,
(
e
)
=>
{
$
(
'
body
'
).
on
(
'
click
'
,
'
.js-usage-consent-action
'
,
e
=>
{
e
.
preventDefault
();
e
.
preventDefault
();
e
.
stopImmediatePropagation
();
// overwrite rails listener
e
.
stopImmediatePropagation
();
// overwrite rails listener
...
@@ -18,7 +18,8 @@ export default () => {
...
@@ -18,7 +18,8 @@ export default () => {
const
hideConsentMessage
=
()
=>
hideFlash
(
document
.
querySelector
(
'
.ping-consent-message
'
));
const
hideConsentMessage
=
()
=>
hideFlash
(
document
.
querySelector
(
'
.ping-consent-message
'
));
axios
.
put
(
url
,
data
)
axios
.
put
(
url
,
data
)
.
then
(()
=>
{
.
then
(()
=>
{
hideConsentMessage
();
hideConsentMessage
();
})
})
...
...
app/assets/javascripts/users_select.js
View file @
c559bcca
...
@@ -15,8 +15,8 @@ function UsersSelect(currentUser, els, options = {}) {
...
@@ -15,8 +15,8 @@ function UsersSelect(currentUser, els, options = {}) {
var
$els
;
var
$els
;
this
.
users
=
this
.
users
.
bind
(
this
);
this
.
users
=
this
.
users
.
bind
(
this
);
this
.
user
=
this
.
user
.
bind
(
this
);
this
.
user
=
this
.
user
.
bind
(
this
);
this
.
usersPath
=
"
/autocomplete/users.json
"
;
this
.
usersPath
=
'
/autocomplete/users.json
'
;
this
.
userPath
=
"
/autocomplete/users/:id.json
"
;
this
.
userPath
=
'
/autocomplete/users/:id.json
'
;
if
(
currentUser
!=
null
)
{
if
(
currentUser
!=
null
)
{
if
(
typeof
currentUser
===
'
object
'
)
{
if
(
typeof
currentUser
===
'
object
'
)
{
this
.
currentUser
=
currentUser
;
this
.
currentUser
=
currentUser
;
...
@@ -33,156 +33,180 @@ function UsersSelect(currentUser, els, options = {}) {
...
@@ -33,156 +33,180 @@ function UsersSelect(currentUser, els, options = {}) {
$els
=
$
(
'
.js-user-search
'
);
$els
=
$
(
'
.js-user-search
'
);
}
}
$els
.
each
((
function
(
_this
)
{
$els
.
each
(
return
function
(
i
,
dropdown
)
{
(
function
(
_this
)
{
var
options
=
{};
return
function
(
i
,
dropdown
)
{
var
$block
,
$collapsedSidebar
,
$dropdown
,
$loading
,
$selectbox
,
$value
,
abilityName
,
assignTo
,
assigneeTemplate
,
collapsedAssigneeTemplate
,
defaultLabel
,
defaultNullUser
,
firstUser
,
issueURL
,
selectedId
,
selectedIdDefault
,
showAnyUser
,
showNullUser
,
showMenuAbove
;
var
options
=
{};
$dropdown
=
$
(
dropdown
);
var
$block
,
options
.
projectId
=
$dropdown
.
data
(
'
projectId
'
);
$collapsedSidebar
,
options
.
groupId
=
$dropdown
.
data
(
'
groupId
'
);
$dropdown
,
options
.
showCurrentUser
=
$dropdown
.
data
(
'
currentUser
'
);
$loading
,
options
.
todoFilter
=
$dropdown
.
data
(
'
todoFilter
'
);
$selectbox
,
options
.
todoStateFilter
=
$dropdown
.
data
(
'
todoStateFilter
'
);
$value
,
showNullUser
=
$dropdown
.
data
(
'
nullUser
'
);
abilityName
,
defaultNullUser
=
$dropdown
.
data
(
'
nullUserDefault
'
);
assignTo
,
showMenuAbove
=
$dropdown
.
data
(
'
showMenuAbove
'
);
assigneeTemplate
,
showAnyUser
=
$dropdown
.
data
(
'
anyUser
'
);
collapsedAssigneeTemplate
,
firstUser
=
$dropdown
.
data
(
'
firstUser
'
);
defaultLabel
,
options
.
authorId
=
$dropdown
.
data
(
'
authorId
'
);
defaultNullUser
,
defaultLabel
=
$dropdown
.
data
(
'
defaultLabel
'
);
firstUser
,
issueURL
=
$dropdown
.
data
(
'
issueUpdate
'
);
issueURL
,
$selectbox
=
$dropdown
.
closest
(
'
.selectbox
'
);
selectedId
,
$block
=
$selectbox
.
closest
(
'
.block
'
);
selectedIdDefault
,
abilityName
=
$dropdown
.
data
(
'
abilityName
'
);
showAnyUser
,
$value
=
$block
.
find
(
'
.value
'
);
showNullUser
,
$collapsedSidebar
=
$block
.
find
(
'
.sidebar-collapsed-user
'
);
showMenuAbove
;
$loading
=
$block
.
find
(
'
.block-loading
'
).
fadeOut
();
$dropdown
=
$
(
dropdown
);
selectedIdDefault
=
(
defaultNullUser
&&
showNullUser
)
?
0
:
null
;
options
.
projectId
=
$dropdown
.
data
(
'
projectId
'
);
selectedId
=
$dropdown
.
data
(
'
selected
'
);
options
.
groupId
=
$dropdown
.
data
(
'
groupId
'
);
options
.
showCurrentUser
=
$dropdown
.
data
(
'
currentUser
'
);
if
(
selectedId
===
undefined
)
{
options
.
todoFilter
=
$dropdown
.
data
(
'
todoFilter
'
);
selectedId
=
selectedIdDefault
;
options
.
todoStateFilter
=
$dropdown
.
data
(
'
todoStateFilter
'
);
}
showNullUser
=
$dropdown
.
data
(
'
nullUser
'
);
defaultNullUser
=
$dropdown
.
data
(
'
nullUserDefault
'
);
const
assignYourself
=
function
()
{
showMenuAbove
=
$dropdown
.
data
(
'
showMenuAbove
'
);
const
unassignedSelected
=
$dropdown
.
closest
(
'
.selectbox
'
)
showAnyUser
=
$dropdown
.
data
(
'
anyUser
'
);
.
find
(
`input[name='
${
$dropdown
.
data
(
'
fieldName
'
)}
'][value=0]`
);
firstUser
=
$dropdown
.
data
(
'
firstUser
'
);
options
.
authorId
=
$dropdown
.
data
(
'
authorId
'
);
if
(
unassignedSelected
)
{
defaultLabel
=
$dropdown
.
data
(
'
defaultLabel
'
);
unassignedSelected
.
remove
();
issueURL
=
$dropdown
.
data
(
'
issueUpdate
'
);
$selectbox
=
$dropdown
.
closest
(
'
.selectbox
'
);
$block
=
$selectbox
.
closest
(
'
.block
'
);
abilityName
=
$dropdown
.
data
(
'
abilityName
'
);
$value
=
$block
.
find
(
'
.value
'
);
$collapsedSidebar
=
$block
.
find
(
'
.sidebar-collapsed-user
'
);
$loading
=
$block
.
find
(
'
.block-loading
'
).
fadeOut
();
selectedIdDefault
=
defaultNullUser
&&
showNullUser
?
0
:
null
;
selectedId
=
$dropdown
.
data
(
'
selected
'
);
if
(
selectedId
===
undefined
)
{
selectedId
=
selectedIdDefault
;
}
}
// Save current selected user to the DOM
const
assignYourself
=
function
()
{
const
input
=
document
.
createElement
(
'
input
'
);
const
unassignedSelected
=
$dropdown
input
.
type
=
'
hidden
'
;
.
closest
(
'
.selectbox
'
)
input
.
name
=
$dropdown
.
data
(
'
fieldName
'
);
.
find
(
`input[name='
${
$dropdown
.
data
(
'
fieldName
'
)}
'][value=0]`
);
const
currentUserInfo
=
$dropdown
.
data
(
'
currentUserInfo
'
);
if
(
unassignedSelected
)
{
unassignedSelected
.
remove
();
if
(
currentUserInfo
)
{
}
input
.
value
=
currentUserInfo
.
id
;
input
.
dataset
.
meta
=
_
.
escape
(
currentUserInfo
.
name
);
}
else
if
(
_this
.
currentUser
)
{
input
.
value
=
_this
.
currentUser
.
id
;
}
if
(
$selectbox
)
{
$dropdown
.
parent
().
before
(
input
);
}
else
{
$dropdown
.
after
(
input
);
}
};
if
(
$block
[
0
])
{
$block
[
0
].
addEventListener
(
'
assignYourself
'
,
assignYourself
);
}
const
getSelectedUserInputs
=
function
()
{
return
$selectbox
.
find
(
`input[name="
${
$dropdown
.
data
(
'
fieldName
'
)}
"]`
);
};
const
getSelected
=
function
()
{
// Save current selected user to the DOM
return
getSelectedUserInputs
()
const
input
=
document
.
createElement
(
'
input
'
);
.
map
((
index
,
input
)
=>
parseInt
(
input
.
value
,
10
))
input
.
type
=
'
hidden
'
;
.
get
();
input
.
name
=
$dropdown
.
data
(
'
fieldName
'
);
};
const
checkMaxSelect
=
function
()
{
const
currentUserInfo
=
$dropdown
.
data
(
'
currentUserInfo
'
);
const
maxSelect
=
$dropdown
.
data
(
'
maxSelect
'
);
if
(
maxSelect
)
{
const
selected
=
getSelected
();
if
(
selected
.
length
>
maxSelect
)
{
if
(
currentUserInfo
)
{
const
firstSelectedId
=
selected
[
0
];
input
.
value
=
currentUserInfo
.
id
;
const
firstSelected
=
$dropdown
.
closest
(
'
.selectbox
'
)
input
.
dataset
.
meta
=
_
.
escape
(
currentUserInfo
.
name
);
.
find
(
`input[name='
${
$dropdown
.
data
(
'
fieldName
'
)}
'][value=
${
firstSelectedId
}
]`
);
}
else
if
(
_this
.
currentUser
)
{
input
.
value
=
_this
.
currentUser
.
id
;
}
firstSelected
.
remove
();
if
(
$selectbox
)
{
emitSidebarEvent
(
'
sidebar.removeAssignee
'
,
{
$dropdown
.
parent
().
before
(
input
);
id
:
firstSelectedId
,
}
else
{
}
);
$dropdown
.
after
(
input
);
}
}
}
};
};
const
getMultiSelectDropdownTitle
=
function
(
selectedUser
,
isSelected
)
{
if
(
$block
[
0
])
{
const
selectedUsers
=
getSelected
()
$block
[
0
].
addEventListener
(
'
assignYourself
'
,
assignYourself
);
.
filter
(
u
=>
u
!==
0
);
const
firstUser
=
getSelectedUserInputs
()
.
map
((
index
,
input
)
=>
({
name
:
input
.
dataset
.
meta
,
value
:
parseInt
(
input
.
value
,
10
),
}))
.
filter
(
u
=>
u
.
id
!==
0
)
.
get
(
0
);
if
(
selectedUsers
.
length
===
0
)
{
return
'
Unassigned
'
;
}
else
if
(
selectedUsers
.
length
===
1
)
{
return
firstUser
.
name
;
}
else
if
(
isSelected
)
{
const
otherSelected
=
selectedUsers
.
filter
(
s
=>
s
!==
selectedUser
.
id
);
return
`
${
selectedUser
.
name
}
+
${
otherSelected
.
length
}
more`
;
}
else
{
return
`
${
firstUser
.
name
}
+
${
selectedUsers
.
length
-
1
}
more`
;
}
}
};
$
(
'
.assign-to-me-link
'
).
on
(
'
click
'
,
(
e
)
=>
{
const
getSelectedUserInputs
=
function
()
{
e
.
preventDefault
();
return
$selectbox
.
find
(
`input[name="
${
$dropdown
.
data
(
'
fieldName
'
)}
"]`
);
$
(
e
.
currentTarget
).
hide
();
};
const
getSelected
=
function
()
{
return
getSelectedUserInputs
()
.
map
((
index
,
input
)
=>
parseInt
(
input
.
value
,
10
))
.
get
();
};
const
checkMaxSelect
=
function
()
{
const
maxSelect
=
$dropdown
.
data
(
'
maxSelect
'
);
if
(
maxSelect
)
{
const
selected
=
getSelected
();
if
(
selected
.
length
>
maxSelect
)
{
const
firstSelectedId
=
selected
[
0
];
const
firstSelected
=
$dropdown
.
closest
(
'
.selectbox
'
)
.
find
(
`input[name='
${
$dropdown
.
data
(
'
fieldName
'
)}
'][value=
${
firstSelectedId
}
]`
);
firstSelected
.
remove
();
emitSidebarEvent
(
'
sidebar.removeAssignee
'
,
{
id
:
firstSelectedId
,
});
}
}
};
const
getMultiSelectDropdownTitle
=
function
(
selectedUser
,
isSelected
)
{
const
selectedUsers
=
getSelected
().
filter
(
u
=>
u
!==
0
);
const
firstUser
=
getSelectedUserInputs
()
.
map
((
index
,
input
)
=>
({
name
:
input
.
dataset
.
meta
,
value
:
parseInt
(
input
.
value
,
10
),
}))
.
filter
(
u
=>
u
.
id
!==
0
)
.
get
(
0
);
if
(
selectedUsers
.
length
===
0
)
{
return
'
Unassigned
'
;
}
else
if
(
selectedUsers
.
length
===
1
)
{
return
firstUser
.
name
;
}
else
if
(
isSelected
)
{
const
otherSelected
=
selectedUsers
.
filter
(
s
=>
s
!==
selectedUser
.
id
);
return
`
${
selectedUser
.
name
}
+
${
otherSelected
.
length
}
more`
;
}
else
{
return
`
${
firstUser
.
name
}
+
${
selectedUsers
.
length
-
1
}
more`
;
}
};
if
(
$dropdown
.
data
(
'
multiSelect
'
))
{
$
(
'
.assign-to-me-link
'
).
on
(
'
click
'
,
e
=>
{
assignYourself
();
e
.
preventDefault
();
checkMaxSelect
();
$
(
e
.
currentTarget
).
hide
();
const
currentUserInfo
=
$dropdown
.
data
(
'
currentUserInfo
'
);
if
(
$dropdown
.
data
(
'
multiSelect
'
))
{
$dropdown
.
find
(
'
.dropdown-toggle-text
'
).
text
(
getMultiSelectDropdownTitle
(
currentUserInfo
)).
removeClass
(
'
is-default
'
);
assignYourself
();
}
else
{
checkMaxSelect
();
const
$input
=
$
(
`input[name="
${
$dropdown
.
data
(
'
fieldName
'
)}
"]`
);
$input
.
val
(
gon
.
current_user_id
);
const
currentUserInfo
=
$dropdown
.
data
(
'
currentUserInfo
'
);
selectedId
=
$input
.
val
();
$dropdown
$dropdown
.
find
(
'
.dropdown-toggle-text
'
).
text
(
gon
.
current_user_fullname
).
removeClass
(
'
is-default
'
);
.
find
(
'
.dropdown-toggle-text
'
)
}
.
text
(
getMultiSelectDropdownTitle
(
currentUserInfo
))
});
.
removeClass
(
'
is-default
'
);
}
else
{
$block
.
on
(
'
click
'
,
'
.js-assign-yourself
'
,
(
e
)
=>
{
const
$input
=
$
(
`input[name="
${
$dropdown
.
data
(
'
fieldName
'
)}
"]`
);
e
.
preventDefault
();
$input
.
val
(
gon
.
current_user_id
);
return
assignTo
(
_this
.
currentUser
.
id
);
selectedId
=
$input
.
val
();
});
$dropdown
.
find
(
'
.dropdown-toggle-text
'
)
assignTo
=
function
(
selected
)
{
.
text
(
gon
.
current_user_fullname
)
var
data
;
.
removeClass
(
'
is-default
'
);
data
=
{};
}
data
[
abilityName
]
=
{};
});
data
[
abilityName
].
assignee_id
=
selected
!=
null
?
selected
:
null
;
$loading
.
removeClass
(
'
hidden
'
).
fadeIn
();
$block
.
on
(
'
click
'
,
'
.js-assign-yourself
'
,
e
=>
{
$dropdown
.
trigger
(
'
loading.gl.dropdown
'
);
e
.
preventDefault
();
return
assignTo
(
_this
.
currentUser
.
id
);
return
axios
.
put
(
issueURL
,
data
)
});
.
then
(({
data
})
=>
{
assignTo
=
function
(
selected
)
{
var
data
;
data
=
{};
data
[
abilityName
]
=
{};
data
[
abilityName
].
assignee_id
=
selected
!=
null
?
selected
:
null
;
$loading
.
removeClass
(
'
hidden
'
).
fadeIn
();
$dropdown
.
trigger
(
'
loading.gl.dropdown
'
);
return
axios
.
put
(
issueURL
,
data
).
then
(({
data
})
=>
{
var
user
,
tooltipTitle
;
var
user
,
tooltipTitle
;
$dropdown
.
trigger
(
'
loaded.gl.dropdown
'
);
$dropdown
.
trigger
(
'
loaded.gl.dropdown
'
);
$loading
.
fadeOut
();
$loading
.
fadeOut
();
...
@@ -190,14 +214,14 @@ function UsersSelect(currentUser, els, options = {}) {
...
@@ -190,14 +214,14 @@ function UsersSelect(currentUser, els, options = {}) {
user
=
{
user
=
{
name
:
data
.
assignee
.
name
,
name
:
data
.
assignee
.
name
,
username
:
data
.
assignee
.
username
,
username
:
data
.
assignee
.
username
,
avatar
:
data
.
assignee
.
avatar_url
avatar
:
data
.
assignee
.
avatar_url
,
};
};
tooltipTitle
=
_
.
escape
(
user
.
name
);
tooltipTitle
=
_
.
escape
(
user
.
name
);
}
else
{
}
else
{
user
=
{
user
=
{
name
:
'
Unassigned
'
,
name
:
'
Unassigned
'
,
username
:
''
,
username
:
''
,
avatar
:
''
avatar
:
''
,
};
};
tooltipTitle
=
__
(
'
Assignee
'
);
tooltipTitle
=
__
(
'
Assignee
'
);
}
}
...
@@ -205,319 +229,341 @@ function UsersSelect(currentUser, els, options = {}) {
...
@@ -205,319 +229,341 @@ function UsersSelect(currentUser, els, options = {}) {
$collapsedSidebar
.
attr
(
'
title
'
,
tooltipTitle
).
tooltip
(
'
_fixTitle
'
);
$collapsedSidebar
.
attr
(
'
title
'
,
tooltipTitle
).
tooltip
(
'
_fixTitle
'
);
return
$collapsedSidebar
.
html
(
collapsedAssigneeTemplate
(
user
));
return
$collapsedSidebar
.
html
(
collapsedAssigneeTemplate
(
user
));
});
});
};
};
collapsedAssigneeTemplate
=
_
.
template
(
'
<% if( avatar ) { %> <a class="author-link" href="/<%- username %>"> <img width="24" class="avatar avatar-inline s24" alt="" src="<%- avatar %>"> </a> <% } else { %> <i class="fa fa-user"></i> <% } %>
'
);
collapsedAssigneeTemplate
=
_
.
template
(
assigneeTemplate
=
_
.
template
(
'
<% if (username) { %> <a class="author-link bold" href="/<%- username %>"> <% if( avatar ) { %> <img width="32" class="avatar avatar-inline s32" alt="" src="<%- avatar %>"> <% } %> <span class="author"><%- name %></span> <span class="username"> @<%- username %> </span> </a> <% } else { %> <span class="no-value assign-yourself"> No assignee - <a href="#" class="js-assign-yourself"> assign yourself </a> </span> <% } %>
'
);
'
<% if( avatar ) { %> <a class="author-link" href="/<%- username %>"> <img width="24" class="avatar avatar-inline s24" alt="" src="<%- avatar %>"> </a> <% } else { %> <i class="fa fa-user"></i> <% } %>
'
,
return
$dropdown
.
glDropdown
({
);
showMenuAbove
:
showMenuAbove
,
assigneeTemplate
=
_
.
template
(
data
:
function
(
term
,
callback
)
{
'
<% if (username) { %> <a class="author-link bold" href="/<%- username %>"> <% if( avatar ) { %> <img width="32" class="avatar avatar-inline s32" alt="" src="<%- avatar %>"> <% } %> <span class="author"><%- name %></span> <span class="username"> @<%- username %> </span> </a> <% } else { %> <span class="no-value assign-yourself"> No assignee - <a href="#" class="js-assign-yourself"> assign yourself </a> </span> <% } %>
'
,
return
_this
.
users
(
term
,
options
,
function
(
users
)
{
);
// GitLabDropdownFilter returns this.instance
return
$dropdown
.
glDropdown
({
// GitLabDropdownRemote returns this.options.instance
showMenuAbove
:
showMenuAbove
,
const
glDropdown
=
this
.
instance
||
this
.
options
.
instance
;
data
:
function
(
term
,
callback
)
{
glDropdown
.
options
.
processData
(
term
,
users
,
callback
);
return
_this
.
users
(
}.
bind
(
this
));
term
,
},
options
,
processData
:
function
(
term
,
data
,
callback
)
{
function
(
users
)
{
let
users
=
data
;
// GitLabDropdownFilter returns this.instance
// GitLabDropdownRemote returns this.options.instance
// Only show assigned user list when there is no search term
const
glDropdown
=
this
.
instance
||
this
.
options
.
instance
;
if
(
$dropdown
.
hasClass
(
'
js-multiselect
'
)
&&
term
.
length
===
0
)
{
glDropdown
.
options
.
processData
(
term
,
users
,
callback
);
const
selectedInputs
=
getSelectedUserInputs
();
}.
bind
(
this
),
);
// Potential duplicate entries when dealing with issue board
},
// because issue board is also managed by vue
processData
:
function
(
term
,
data
,
callback
)
{
const
selectedUsers
=
_
.
uniq
(
selectedInputs
,
false
,
a
=>
a
.
value
)
let
users
=
data
;
.
filter
((
input
)
=>
{
const
userId
=
parseInt
(
input
.
value
,
10
);
// Only show assigned user list when there is no search term
const
inUsersArray
=
users
.
find
(
u
=>
u
.
id
===
userId
);
if
(
$dropdown
.
hasClass
(
'
js-multiselect
'
)
&&
term
.
length
===
0
)
{
const
selectedInputs
=
getSelectedUserInputs
();
return
!
inUsersArray
&&
userId
!==
0
;
})
// Potential duplicate entries when dealing with issue board
.
map
((
input
)
=>
{
// because issue board is also managed by vue
const
userId
=
parseInt
(
input
.
value
,
10
);
const
selectedUsers
=
_
.
uniq
(
selectedInputs
,
false
,
a
=>
a
.
value
)
const
{
avatarUrl
,
avatar_url
,
name
,
username
}
=
input
.
dataset
;
.
filter
(
input
=>
{
return
{
const
userId
=
parseInt
(
input
.
value
,
10
);
avatar_url
:
avatarUrl
||
avatar_url
,
const
inUsersArray
=
users
.
find
(
u
=>
u
.
id
===
userId
);
id
:
userId
,
name
,
return
!
inUsersArray
&&
userId
!==
0
;
username
,
})
};
.
map
(
input
=>
{
});
const
userId
=
parseInt
(
input
.
value
,
10
);
const
{
avatarUrl
,
avatar_url
,
name
,
username
}
=
input
.
dataset
;
return
{
avatar_url
:
avatarUrl
||
avatar_url
,
id
:
userId
,
name
,
username
,
};
});
users
=
data
.
concat
(
selectedUsers
);
users
=
data
.
concat
(
selectedUsers
);
}
}
let
anyUser
;
let
anyUser
;
let
index
;
let
index
;
let
len
;
let
len
;
let
name
;
let
name
;
let
obj
;
let
obj
;
let
showDivider
;
let
showDivider
;
if
(
term
.
length
===
0
)
{
if
(
term
.
length
===
0
)
{
showDivider
=
0
;
showDivider
=
0
;
if
(
firstUser
)
{
if
(
firstUser
)
{
// Move current user to the front of the list
// Move current user to the front of the list
for
(
index
=
0
,
len
=
users
.
length
;
index
<
len
;
index
+=
1
)
{
for
(
index
=
0
,
len
=
users
.
length
;
index
<
len
;
index
+=
1
)
{
obj
=
users
[
index
];
obj
=
users
[
index
];
if
(
obj
.
username
===
firstUser
)
{
if
(
obj
.
username
===
firstUser
)
{
users
.
splice
(
index
,
1
);
users
.
splice
(
index
,
1
);
users
.
unshift
(
obj
);
users
.
unshift
(
obj
);
break
;
break
;
}
}
}
}
}
}
if
(
showNullUser
)
{
if
(
showNullUser
)
{
showDivider
+=
1
;
showDivider
+=
1
;
users
.
unshift
({
users
.
unshift
({
beforeDivider
:
true
,
beforeDivider
:
true
,
name
:
'
Unassigned
'
,
name
:
'
Unassigned
'
,
id
:
0
,
id
:
0
});
});
}
}
if
(
showAnyUser
)
{
if
(
showAnyUser
)
{
showDivider
+=
1
;
showDivider
+=
1
;
name
=
showAnyUser
;
name
=
showAnyUser
;
if
(
name
===
true
)
{
if
(
name
===
true
)
{
name
=
'
Any User
'
;
name
=
'
Any User
'
;
}
anyUser
=
{
beforeDivider
:
true
,
name
:
name
,
id
:
null
,
};
users
.
unshift
(
anyUser
);
}
}
anyUser
=
{
beforeDivider
:
true
,
name
:
name
,
id
:
null
};
users
.
unshift
(
anyUser
);
}
if
(
showDivider
)
{
if
(
showDivider
)
{
users
.
splice
(
showDivider
,
0
,
'
divider
'
);
users
.
splice
(
showDivider
,
0
,
'
divider
'
);
}
}
if
(
$dropdown
.
hasClass
(
'
js-multiselect
'
))
{
if
(
$dropdown
.
hasClass
(
'
js-multiselect
'
))
{
const
selected
=
getSelected
().
filter
(
i
=>
i
!==
0
);
const
selected
=
getSelected
().
filter
(
i
=>
i
!==
0
);
if
(
selected
.
length
>
0
)
{
if
(
selected
.
length
>
0
)
{
if
(
$dropdown
.
data
(
'
dropdownHeader
'
))
{
if
(
$dropdown
.
data
(
'
dropdownHeader
'
))
{
showDivider
+=
1
;
showDivider
+=
1
;
users
.
splice
(
showDivider
,
0
,
{
users
.
splice
(
showDivider
,
0
,
{
header
:
$dropdown
.
data
(
'
dropdownHeader
'
),
header
:
$dropdown
.
data
(
'
dropdownHeader
'
),
});
});
}
}
const
selectedUsers
=
users
const
selectedUsers
=
users
.
filter
(
u
=>
selected
.
indexOf
(
u
.
id
)
!==
-
1
)
.
filter
(
u
=>
selected
.
indexOf
(
u
.
id
)
!==
-
1
)
.
sort
((
a
,
b
)
=>
a
.
name
>
b
.
name
);
.
sort
((
a
,
b
)
=>
a
.
name
>
b
.
name
);
users
=
users
.
filter
(
u
=>
selected
.
indexOf
(
u
.
id
)
===
-
1
);
users
=
users
.
filter
(
u
=>
selected
.
indexOf
(
u
.
id
)
===
-
1
);
selectedUsers
.
forEach
((
selectedUser
)
=>
{
selectedUsers
.
forEach
(
selectedUser
=>
{
showDivider
+=
1
;
showDivider
+=
1
;
users
.
splice
(
showDivider
,
0
,
selectedUser
);
users
.
splice
(
showDivider
,
0
,
selectedUser
);
});
});
users
.
splice
(
showDivider
+
1
,
0
,
'
divider
'
);
users
.
splice
(
showDivider
+
1
,
0
,
'
divider
'
);
}
}
}
}
}
}
callback
(
users
);
callback
(
users
);
if
(
showMenuAbove
)
{
if
(
showMenuAbove
)
{
$dropdown
.
data
(
'
glDropdown
'
).
positionMenuAbove
();
$dropdown
.
data
(
'
glDropdown
'
).
positionMenuAbove
();
}
}
},
},
filterable
:
true
,
filterable
:
true
,
filterRemote
:
true
,
filterRemote
:
true
,
search
:
{
search
:
{
fields
:
[
'
name
'
,
'
username
'
]
fields
:
[
'
name
'
,
'
username
'
],
},
},
selectable
:
true
,
selectable
:
true
,
fieldName
:
$dropdown
.
data
(
'
fieldName
'
),
fieldName
:
$dropdown
.
data
(
'
fieldName
'
),
toggleLabel
:
function
(
selected
,
el
,
glDropdown
)
{
toggleLabel
:
function
(
selected
,
el
,
glDropdown
)
{
const
inputValue
=
glDropdown
.
filterInput
.
val
();
const
inputValue
=
glDropdown
.
filterInput
.
val
();
if
(
this
.
multiSelect
&&
inputValue
===
''
)
{
if
(
this
.
multiSelect
&&
inputValue
===
''
)
{
// Remove non-users from the fullData array
// Remove non-users from the fullData array
const
users
=
glDropdown
.
filteredFullData
();
const
users
=
glDropdown
.
filteredFullData
();
const
callback
=
glDropdown
.
parseData
.
bind
(
glDropdown
);
const
callback
=
glDropdown
.
parseData
.
bind
(
glDropdown
);
// Update the data model
// Update the data model
this
.
processData
(
inputValue
,
users
,
callback
);
this
.
processData
(
inputValue
,
users
,
callback
);
}
}
if
(
this
.
multiSelect
)
{
if
(
this
.
multiSelect
)
{
return
getMultiSelectDropdownTitle
(
selected
,
$
(
el
).
hasClass
(
'
is-active
'
));
return
getMultiSelectDropdownTitle
(
selected
,
$
(
el
).
hasClass
(
'
is-active
'
));
}
}
if
(
selected
&&
'
id
'
in
selected
&&
$
(
el
).
hasClass
(
'
is-active
'
))
{
if
(
selected
&&
'
id
'
in
selected
&&
$
(
el
).
hasClass
(
'
is-active
'
))
{
$dropdown
.
find
(
'
.dropdown-toggle-text
'
).
removeClass
(
'
is-default
'
);
$dropdown
.
find
(
'
.dropdown-toggle-text
'
).
removeClass
(
'
is-default
'
);
if
(
selected
.
text
)
{
if
(
selected
.
text
)
{
return
selected
.
text
;
return
selected
.
text
;
}
else
{
return
selected
.
name
;
}
}
else
{
}
else
{
return
selected
.
name
;
$dropdown
.
find
(
'
.dropdown-toggle-text
'
).
addClass
(
'
is-default
'
);
return
defaultLabel
;
}
},
defaultLabel
:
defaultLabel
,
hidden
:
function
(
e
)
{
if
(
$dropdown
.
hasClass
(
'
js-multiselect
'
))
{
emitSidebarEvent
(
'
sidebar.saveAssignees
'
);
}
}
}
else
{
$dropdown
.
find
(
'
.dropdown-toggle-text
'
).
addClass
(
'
is-default
'
);
return
defaultLabel
;
}
},
defaultLabel
:
defaultLabel
,
hidden
:
function
(
e
)
{
if
(
$dropdown
.
hasClass
(
'
js-multiselect
'
))
{
emitSidebarEvent
(
'
sidebar.saveAssignees
'
);
}
if
(
!
$dropdown
.
data
(
'
alwaysShowSelectbox
'
))
{
$selectbox
.
hide
();
// Recalculate where .value is because vue might have changed it
if
(
!
$dropdown
.
data
(
'
alwaysShowSelectbox
'
))
{
$block
=
$selectbox
.
closest
(
'
.block
'
);
$selectbox
.
hide
();
$value
=
$block
.
find
(
'
.value
'
);
// display:block overrides the hide-collapse rule
$value
.
css
(
'
display
'
,
''
);
}
},
multiSelect
:
$dropdown
.
hasClass
(
'
js-multiselect
'
),
inputMeta
:
$dropdown
.
data
(
'
inputMeta
'
),
clicked
:
function
(
options
)
{
const
{
$el
,
e
,
isMarking
}
=
options
;
const
user
=
options
.
selectedObj
;
if
(
$dropdown
.
hasClass
(
'
js-multiselect
'
))
{
const
isActive
=
$el
.
hasClass
(
'
is-active
'
);
const
previouslySelected
=
$dropdown
.
closest
(
'
.selectbox
'
)
.
find
(
"
input[name='
"
+
(
$dropdown
.
data
(
'
fieldName
'
))
+
"
'][value!=0]
"
);
// Enables support for limiting the number of users selected
// Automatically removes the first on the list if more users are selected
checkMaxSelect
();
if
(
user
.
beforeDivider
&&
user
.
name
.
toLowerCase
()
===
'
unassigned
'
)
{
// Recalculate where .value is because vue might have changed it
// Unassigned selected
$block
=
$selectbox
.
closest
(
'
.block
'
);
previouslySelected
.
each
((
index
,
element
)
=>
{
$value
=
$block
.
find
(
'
.value
'
);
const
id
=
parseInt
(
element
.
value
,
10
);
// display:block overrides the hide-collapse rule
element
.
remove
();
$value
.
css
(
'
display
'
,
''
);
});
}
emitSidebarEvent
(
'
sidebar.removeAllAssignees
'
);
},
}
else
if
(
isActive
)
{
multiSelect
:
$dropdown
.
hasClass
(
'
js-multiselect
'
),
// user selected
inputMeta
:
$dropdown
.
data
(
'
inputMeta
'
),
emitSidebarEvent
(
'
sidebar.addAssignee
'
,
user
);
clicked
:
function
(
options
)
{
const
{
$el
,
e
,
isMarking
}
=
options
;
const
user
=
options
.
selectedObj
;
// Remove unassigned selection (if it was previously selected)
if
(
$dropdown
.
hasClass
(
'
js-multiselect
'
))
{
const
unassignedSelected
=
$dropdown
.
closest
(
'
.selectbox
'
)
const
isActive
=
$el
.
hasClass
(
'
is-active
'
);
.
find
(
"
input[name='
"
+
(
$dropdown
.
data
(
'
fieldName
'
))
+
"
'][value=0]
"
);
const
previouslySelected
=
$dropdown
.
closest
(
'
.selectbox
'
)
.
find
(
"
input[name='
"
+
$dropdown
.
data
(
'
fieldName
'
)
+
"
'][value!=0]
"
);
// Enables support for limiting the number of users selected
// Automatically removes the first on the list if more users are selected
checkMaxSelect
();
if
(
user
.
beforeDivider
&&
user
.
name
.
toLowerCase
()
===
'
unassigned
'
)
{
// Unassigned selected
previouslySelected
.
each
((
index
,
element
)
=>
{
const
id
=
parseInt
(
element
.
value
,
10
);
element
.
remove
();
});
emitSidebarEvent
(
'
sidebar.removeAllAssignees
'
);
}
else
if
(
isActive
)
{
// user selected
emitSidebarEvent
(
'
sidebar.addAssignee
'
,
user
);
// Remove unassigned selection (if it was previously selected)
const
unassignedSelected
=
$dropdown
.
closest
(
'
.selectbox
'
)
.
find
(
"
input[name='
"
+
$dropdown
.
data
(
'
fieldName
'
)
+
"
'][value=0]
"
);
if
(
unassignedSelected
)
{
unassignedSelected
.
remove
();
}
}
else
{
if
(
previouslySelected
.
length
===
0
)
{
// Select unassigned because there is no more selected users
this
.
addInput
(
$dropdown
.
data
(
'
fieldName
'
),
0
,
{});
}
if
(
unassignedSelected
)
{
// User unselected
unassignedSelected
.
remove
();
emitSidebarEvent
(
'
sidebar.removeAssignee
'
,
user
);
}
}
else
{
if
(
previouslySelected
.
length
===
0
)
{
// Select unassigned because there is no more selected users
this
.
addInput
(
$dropdown
.
data
(
'
fieldName
'
),
0
,
{});
}
}
// User unselected
if
(
getSelected
().
find
(
u
=>
u
===
gon
.
current_user_id
))
{
emitSidebarEvent
(
'
sidebar.removeAssignee
'
,
user
);
$
(
'
.assign-to-me-link
'
).
hide
();
}
else
{
$
(
'
.assign-to-me-link
'
).
show
();
}
}
}
if
(
getSelected
().
find
(
u
=>
u
===
gon
.
current_user_id
))
{
var
isIssueIndex
,
isMRIndex
,
page
,
selected
;
$
(
'
.assign-to-me-link
'
).
hide
();
page
=
$
(
'
body
'
).
attr
(
'
data-page
'
);
}
else
{
isIssueIndex
=
page
===
'
projects:issues:index
'
;
$
(
'
.assign-to-me-link
'
).
show
();
isMRIndex
=
page
===
page
&&
page
===
'
projects:merge_requests:index
'
;
if
(
$dropdown
.
hasClass
(
'
js-filter-bulk-update
'
)
||
$dropdown
.
hasClass
(
'
js-issuable-form-dropdown
'
)
)
{
e
.
preventDefault
();
const
isSelecting
=
user
.
id
!==
selectedId
;
selectedId
=
isSelecting
?
user
.
id
:
selectedIdDefault
;
if
(
selectedId
===
gon
.
current_user_id
)
{
$
(
'
.assign-to-me-link
'
).
hide
();
}
else
{
$
(
'
.assign-to-me-link
'
).
show
();
}
return
;
}
if
(
$el
.
closest
(
'
.add-issues-modal
'
).
length
)
{
ModalStore
.
store
.
filter
[
$dropdown
.
data
(
'
fieldName
'
)]
=
user
.
id
;
}
else
if
(
handleClick
)
{
e
.
preventDefault
();
handleClick
(
user
,
isMarking
);
}
else
if
(
$dropdown
.
hasClass
(
'
js-filter-submit
'
)
&&
(
isIssueIndex
||
isMRIndex
))
{
return
Issuable
.
filterResults
(
$dropdown
.
closest
(
'
form
'
));
}
else
if
(
$dropdown
.
hasClass
(
'
js-filter-submit
'
))
{
return
$dropdown
.
closest
(
'
form
'
).
submit
();
}
else
if
(
!
$dropdown
.
hasClass
(
'
js-multiselect
'
))
{
selected
=
$dropdown
.
closest
(
'
.selectbox
'
)
.
find
(
"
input[name='
"
+
$dropdown
.
data
(
'
fieldName
'
)
+
"
']
"
)
.
val
();
return
assignTo
(
selected
);
}
}
}
var
isIssueIndex
,
isMRIndex
,
page
,
selected
;
// Automatically close dropdown after assignee is selected
page
=
$
(
'
body
'
).
attr
(
'
data-page
'
);
// since CE has no multiple assignees
isIssueIndex
=
page
===
'
projects:issues:index
'
;
// EE does not have a max-select
isMRIndex
=
(
page
===
page
&&
page
===
'
projects:merge_requests:index
'
);
if
(
if
(
$dropdown
.
hasClass
(
'
js-filter-bulk-update
'
)
||
$dropdown
.
hasClass
(
'
js-issuable-form-dropdown
'
))
{
$dropdown
.
data
(
'
maxSelect
'
)
&&
e
.
preventDefault
();
getSelected
().
length
===
$dropdown
.
data
(
'
maxSelect
'
)
)
{
// Close the dropdown
$dropdown
.
dropdown
(
'
toggle
'
);
}
},
id
:
function
(
user
)
{
return
user
.
id
;
},
opened
:
function
(
e
)
{
const
$el
=
$
(
e
.
currentTarget
);
const
selected
=
getSelected
();
if
(
$dropdown
.
hasClass
(
'
js-issue-board-sidebar
'
)
&&
selected
.
length
===
0
)
{
this
.
addInput
(
$dropdown
.
data
(
'
fieldName
'
),
0
,
{});
}
$el
.
find
(
'
.is-active
'
).
removeClass
(
'
is-active
'
);
const
isSelecting
=
(
user
.
id
!==
selectedId
);
function
highlightSelected
(
id
)
{
selectedId
=
isSelecting
?
user
.
id
:
selectedIdDefault
;
$el
.
find
(
`li[data-user-id="
${
id
}
"] .dropdown-menu-user-link`
).
addClass
(
'
is-active
'
);
}
if
(
selectedId
===
gon
.
current_user_id
)
{
if
(
selected
.
length
>
0
)
{
$
(
'
.assign-to-me-link
'
).
hide
();
getSelected
().
forEach
(
selectedId
=>
highlightSelected
(
selectedId
));
}
else
if
(
$dropdown
.
hasClass
(
'
js-issue-board-sidebar
'
))
{
highlightSelected
(
0
);
}
else
{
}
else
{
$
(
'
.assign-to-me-link
'
).
show
(
);
highlightSelected
(
selectedId
);
}
}
return
;
},
}
updateLabel
:
$dropdown
.
data
(
'
dropdownTitle
'
),
if
(
$el
.
closest
(
'
.add-issues-modal
'
).
length
)
{
renderRow
:
function
(
user
)
{
ModalStore
.
store
.
filter
[
$dropdown
.
data
(
'
fieldName
'
)]
=
user
.
id
;
var
avatar
,
img
,
listClosingTags
,
listWithName
,
listWithUserName
,
username
;
}
else
if
(
handleClick
)
{
username
=
user
.
username
?
'
@
'
+
user
.
username
:
''
;
e
.
preventDefault
();
avatar
=
user
.
avatar_url
?
user
.
avatar_url
:
gon
.
default_avatar_url
;
handleClick
(
user
,
isMarking
);
}
else
if
(
$dropdown
.
hasClass
(
'
js-filter-submit
'
)
&&
(
isIssueIndex
||
isMRIndex
))
{
return
Issuable
.
filterResults
(
$dropdown
.
closest
(
'
form
'
));
}
else
if
(
$dropdown
.
hasClass
(
'
js-filter-submit
'
))
{
return
$dropdown
.
closest
(
'
form
'
).
submit
();
}
else
if
(
!
$dropdown
.
hasClass
(
'
js-multiselect
'
))
{
selected
=
$dropdown
.
closest
(
'
.selectbox
'
).
find
(
"
input[name='
"
+
(
$dropdown
.
data
(
'
fieldName
'
))
+
"
']
"
).
val
();
return
assignTo
(
selected
);
}
// Automatically close dropdown after assignee is selected
// since CE has no multiple assignees
// EE does not have a max-select
if
(
$dropdown
.
data
(
'
maxSelect
'
)
&&
getSelected
().
length
===
$dropdown
.
data
(
'
maxSelect
'
))
{
// Close the dropdown
$dropdown
.
dropdown
(
'
toggle
'
);
}
},
id
:
function
(
user
)
{
return
user
.
id
;
},
opened
:
function
(
e
)
{
const
$el
=
$
(
e
.
currentTarget
);
const
selected
=
getSelected
();
if
(
$dropdown
.
hasClass
(
'
js-issue-board-sidebar
'
)
&&
selected
.
length
===
0
)
{
this
.
addInput
(
$dropdown
.
data
(
'
fieldName
'
),
0
,
{});
}
$el
.
find
(
'
.is-active
'
).
removeClass
(
'
is-active
'
);
function
highlightSelected
(
id
)
{
$el
.
find
(
`li[data-user-id="
${
id
}
"] .dropdown-menu-user-link`
).
addClass
(
'
is-active
'
);
}
if
(
selected
.
length
>
0
)
{
let
selected
=
false
;
getSelected
().
forEach
(
selectedId
=>
highlightSelected
(
selectedId
));
}
else
if
(
$dropdown
.
hasClass
(
'
js-issue-board-sidebar
'
))
{
highlightSelected
(
0
);
}
else
{
highlightSelected
(
selectedId
);
}
},
updateLabel
:
$dropdown
.
data
(
'
dropdownTitle
'
),
renderRow
:
function
(
user
)
{
var
avatar
,
img
,
listClosingTags
,
listWithName
,
listWithUserName
,
username
;
username
=
user
.
username
?
"
@
"
+
user
.
username
:
""
;
avatar
=
user
.
avatar_url
?
user
.
avatar_url
:
gon
.
default_avatar_url
;
let
selected
=
false
;
if
(
this
.
multiSelect
)
{
selected
=
getSelected
().
find
(
u
=>
user
.
id
===
u
);
if
(
this
.
multiSelect
)
{
const
{
fieldName
}
=
this
;
selected
=
getSelected
().
find
(
u
=>
user
.
id
===
u
);
const
field
=
$dropdown
.
closest
(
'
.selectbox
'
)
.
find
(
"
input[name='
"
+
fieldName
+
"
'][value='
"
+
user
.
id
+
"
']
"
);
const
{
fieldName
}
=
this
;
if
(
field
.
length
)
{
const
field
=
$dropdown
.
closest
(
'
.selectbox
'
).
find
(
"
input[name='
"
+
fieldName
+
"
'][value='
"
+
user
.
id
+
"
']
"
)
;
selected
=
true
;
}
if
(
field
.
length
)
{
}
else
{
selected
=
true
;
selected
=
user
.
id
===
selectedId
;
}
}
}
else
{
selected
=
user
.
id
===
selectedId
;
}
img
=
""
;
img
=
''
;
if
(
user
.
beforeDivider
!=
null
)
{
if
(
user
.
beforeDivider
!=
null
)
{
`<li><a href='#' class='
${
selected
===
true
?
'
is-active
'
:
''
}
'>
${
_
.
escape
(
user
.
name
)}
</a></li>`
;
`<li><a href='#' class='
${
selected
===
true
?
'
is-active
'
:
''
}
'>
${
_
.
escape
(
}
else
{
user
.
name
,
img
=
"
<img src='
"
+
avatar
+
"
' class='avatar avatar-inline' width='32' />
"
;
)}
</a></li>`
;
}
}
else
{
img
=
"
<img src='
"
+
avatar
+
"
' class='avatar avatar-inline' width='32' />
"
;
}
return
`
return
`
<li data-user-id=
${
user
.
id
}
>
<li data-user-id=
${
user
.
id
}
>
<a href='#' class='dropdown-menu-user-link
${
selected
===
true
?
'
is-active
'
:
''
}
'>
<a href='#' class='dropdown-menu-user-link
${
selected
===
true
?
'
is-active
'
:
''
}
'>
${
img
}
${
img
}
...
@@ -528,114 +574,117 @@ function UsersSelect(currentUser, els, options = {}) {
...
@@ -528,114 +574,117 @@ function UsersSelect(currentUser, els, options = {}) {
</a>
</a>
</li>
</li>
`
;
`
;
}
},
});
});
};
};
})(
this
));
})(
this
),
$
(
'
.ajax-users-select
'
).
each
((
function
(
_this
)
{
);
return
function
(
i
,
select
)
{
$
(
'
.ajax-users-select
'
).
each
(
var
firstUser
,
showAnyUser
,
showEmailUser
,
showNullUser
;
(
function
(
_this
)
{
var
options
=
{};
return
function
(
i
,
select
)
{
options
.
skipLdap
=
$
(
select
).
hasClass
(
'
skip_ldap
'
);
var
firstUser
,
showAnyUser
,
showEmailUser
,
showNullUser
;
options
.
projectId
=
$
(
select
).
data
(
'
projectId
'
);
var
options
=
{};
options
.
groupId
=
$
(
select
).
data
(
'
groupId
'
);
options
.
skipLdap
=
$
(
select
).
hasClass
(
'
skip_ldap
'
);
options
.
showCurrentUser
=
$
(
select
).
data
(
'
currentUser
'
);
options
.
projectId
=
$
(
select
).
data
(
'
projectId
'
);
options
.
authorId
=
$
(
select
).
data
(
'
authorId
'
);
options
.
groupId
=
$
(
select
).
data
(
'
groupId
'
);
options
.
skipUsers
=
$
(
select
).
data
(
'
skipUsers
'
);
options
.
showCurrentUser
=
$
(
select
).
data
(
'
currentUser
'
);
showNullUser
=
$
(
select
).
data
(
'
nullUser
'
);
options
.
authorId
=
$
(
select
).
data
(
'
authorId
'
);
showAnyUser
=
$
(
select
).
data
(
'
anyUser
'
);
options
.
skipUsers
=
$
(
select
).
data
(
'
skipUsers
'
);
showEmailUser
=
$
(
select
).
data
(
'
emailUser
'
);
showNullUser
=
$
(
select
).
data
(
'
nullUser
'
);
firstUser
=
$
(
select
).
data
(
'
firstUser
'
);
showAnyUser
=
$
(
select
).
data
(
'
anyUser
'
);
return
$
(
select
).
select2
({
showEmailUser
=
$
(
select
).
data
(
'
emailUser
'
);
placeholder
:
"
Search for a user
"
,
firstUser
=
$
(
select
).
data
(
'
firstUser
'
);
multiple
:
$
(
select
).
hasClass
(
'
multiselect
'
),
return
$
(
select
).
select2
({
minimumInputLength
:
0
,
placeholder
:
'
Search for a user
'
,
query
:
function
(
query
)
{
multiple
:
$
(
select
).
hasClass
(
'
multiselect
'
),
return
_this
.
users
(
query
.
term
,
options
,
function
(
users
)
{
minimumInputLength
:
0
,
var
anyUser
,
data
,
emailUser
,
index
,
len
,
name
,
nullUser
,
obj
,
ref
;
query
:
function
(
query
)
{
data
=
{
return
_this
.
users
(
query
.
term
,
options
,
function
(
users
)
{
results
:
users
var
anyUser
,
data
,
emailUser
,
index
,
len
,
name
,
nullUser
,
obj
,
ref
;
};
data
=
{
if
(
query
.
term
.
length
===
0
)
{
results
:
users
,
if
(
firstUser
)
{
};
// Move current user to the front of the list
if
(
query
.
term
.
length
===
0
)
{
ref
=
data
.
results
;
if
(
firstUser
)
{
// Move current user to the front of the list
for
(
index
=
0
,
len
=
ref
.
length
;
index
<
len
;
index
+=
1
)
{
ref
=
data
.
results
;
obj
=
ref
[
index
];
if
(
obj
.
username
===
firstUser
)
{
for
(
index
=
0
,
len
=
ref
.
length
;
index
<
len
;
index
+=
1
)
{
data
.
results
.
splice
(
index
,
1
);
obj
=
ref
[
index
];
data
.
results
.
unshift
(
obj
);
if
(
obj
.
username
===
firstUser
)
{
break
;
data
.
results
.
splice
(
index
,
1
);
data
.
results
.
unshift
(
obj
);
break
;
}
}
}
}
}
}
if
(
showNullUser
)
{
if
(
showNullUser
)
{
nullUser
=
{
nullUser
=
{
name
:
'
Unassigned
'
,
name
:
'
Unassigned
'
,
id
:
0
,
id
:
0
};
};
data
.
results
.
unshift
(
nullUser
);
data
.
results
.
unshift
(
nullUser
);
}
if
(
showAnyUser
)
{
name
=
showAnyUser
;
if
(
name
===
true
)
{
name
=
'
Any User
'
;
}
}
anyUser
=
{
if
(
showAnyUser
)
{
name
:
name
,
name
=
showAnyUser
;
id
:
null
if
(
name
===
true
)
{
name
=
'
Any User
'
;
}
anyUser
=
{
name
:
name
,
id
:
null
,
};
data
.
results
.
unshift
(
anyUser
);
}
}
if
(
showEmailUser
&&
data
.
results
.
length
===
0
&&
query
.
term
.
match
(
/^
[^
@
]
+@
[^
@
]
+$/
))
{
var
trimmed
=
query
.
term
.
trim
();
emailUser
=
{
name
:
'
Invite "
'
+
trimmed
+
'
" by email
'
,
username
:
trimmed
,
id
:
trimmed
,
invite
:
true
,
};
};
data
.
results
.
unshift
(
any
User
);
data
.
results
.
unshift
(
email
User
);
}
}
}
return
query
.
callback
(
data
);
if
(
showEmailUser
&&
data
.
results
.
length
===
0
&&
query
.
term
.
match
(
/^
[^
@
]
+@
[^
@
]
+$/
))
{
});
var
trimmed
=
query
.
term
.
trim
();
},
emailUser
=
{
initSelection
:
function
()
{
name
:
"
Invite
\"
"
+
trimmed
+
"
\"
by email
"
,
var
args
;
username
:
trimmed
,
args
=
1
<=
arguments
.
length
?
[].
slice
.
call
(
arguments
,
0
)
:
[];
id
:
trimmed
,
return
_this
.
initSelection
.
apply
(
_this
,
args
);
invite
:
true
},
};
formatResult
:
function
()
{
data
.
results
.
unshift
(
emailUser
);
var
args
;
}
args
=
1
<=
arguments
.
length
?
[].
slice
.
call
(
arguments
,
0
)
:
[];
return
query
.
callback
(
data
);
return
_this
.
formatResult
.
apply
(
_this
,
args
);
});
},
},
formatSelection
:
function
()
{
initSelection
:
function
()
{
var
args
;
var
args
;
args
=
1
<=
arguments
.
length
?
[].
slice
.
call
(
arguments
,
0
)
:
[];
args
=
1
<=
arguments
.
length
?
[].
slice
.
call
(
arguments
,
0
)
:
[];
return
_this
.
formatSelection
.
apply
(
_this
,
args
);
return
_this
.
initSelection
.
apply
(
_this
,
args
);
},
},
dropdownCssClass
:
'
ajax-users-dropdown
'
,
formatResult
:
function
()
{
// we do not want to escape markup since we are displaying html in results
var
args
;
escapeMarkup
:
function
(
m
)
{
args
=
1
<=
arguments
.
length
?
[].
slice
.
call
(
arguments
,
0
)
:
[];
return
m
;
return
_this
.
formatResult
.
apply
(
_this
,
args
);
},
},
});
formatSelection
:
function
()
{
};
var
args
;
})(
this
),
args
=
1
<=
arguments
.
length
?
[].
slice
.
call
(
arguments
,
0
)
:
[];
);
return
_this
.
formatSelection
.
apply
(
_this
,
args
);
},
dropdownCssClass
:
"
ajax-users-dropdown
"
,
// we do not want to escape markup since we are displaying html in results
escapeMarkup
:
function
(
m
)
{
return
m
;
}
});
};
})(
this
));
}
}
UsersSelect
.
prototype
.
initSelection
=
function
(
element
,
callback
)
{
UsersSelect
.
prototype
.
initSelection
=
function
(
element
,
callback
)
{
var
id
,
nullUser
;
var
id
,
nullUser
;
id
=
$
(
element
).
val
();
id
=
$
(
element
).
val
();
if
(
id
===
"
0
"
)
{
if
(
id
===
'
0
'
)
{
nullUser
=
{
nullUser
=
{
name
:
'
Unassigned
'
name
:
'
Unassigned
'
,
};
};
return
callback
(
nullUser
);
return
callback
(
nullUser
);
}
else
if
(
id
!==
""
)
{
}
else
if
(
id
!==
''
)
{
return
this
.
user
(
id
,
callback
);
return
this
.
user
(
id
,
callback
);
}
}
};
};
...
@@ -647,7 +696,17 @@ UsersSelect.prototype.formatResult = function(user) {
...
@@ -647,7 +696,17 @@ UsersSelect.prototype.formatResult = function(user) {
}
else
{
}
else
{
avatar
=
gon
.
default_avatar_url
;
avatar
=
gon
.
default_avatar_url
;
}
}
return
"
<div class='user-result
"
+
(
!
user
.
username
?
'
no-username
'
:
void
0
)
+
"
'> <div class='user-image'><img class='avatar avatar-inline s32' src='
"
+
avatar
+
"
'></div> <div class='user-name dropdown-menu-user-full-name'>
"
+
_
.
escape
(
user
.
name
)
+
"
</div> <div class='user-username dropdown-menu-user-username'>
"
+
(
!
user
.
invite
?
"
@
"
+
_
.
escape
(
user
.
username
)
:
""
)
+
"
</div> </div>
"
;
return
(
"
<div class='user-result
"
+
(
!
user
.
username
?
'
no-username
'
:
void
0
)
+
"
'> <div class='user-image'><img class='avatar avatar-inline s32' src='
"
+
avatar
+
"
'></div> <div class='user-name dropdown-menu-user-full-name'>
"
+
_
.
escape
(
user
.
name
)
+
"
</div> <div class='user-username dropdown-menu-user-username'>
"
+
(
!
user
.
invite
?
'
@
'
+
_
.
escape
(
user
.
username
)
:
''
)
+
'
</div> </div>
'
);
};
};
UsersSelect
.
prototype
.
formatSelection
=
function
(
user
)
{
UsersSelect
.
prototype
.
formatSelection
=
function
(
user
)
{
...
@@ -662,10 +721,9 @@ UsersSelect.prototype.user = function(user_id, callback) {
...
@@ -662,10 +721,9 @@ UsersSelect.prototype.user = function(user_id, callback) {
var
url
;
var
url
;
url
=
this
.
buildUrl
(
this
.
userPath
);
url
=
this
.
buildUrl
(
this
.
userPath
);
url
=
url
.
replace
(
'
:id
'
,
user_id
);
url
=
url
.
replace
(
'
:id
'
,
user_id
);
return
axios
.
get
(
url
)
return
axios
.
get
(
url
).
then
(({
data
})
=>
{
.
then
(({
data
})
=>
{
callback
(
data
);
callback
(
data
);
});
});
};
};
// Return users list. Filtered by query
// Return users list. Filtered by query
...
@@ -682,12 +740,11 @@ UsersSelect.prototype.users = function(query, options, callback) {
...
@@ -682,12 +740,11 @@ UsersSelect.prototype.users = function(query, options, callback) {
todo_state_filter
:
options
.
todoStateFilter
||
null
,
todo_state_filter
:
options
.
todoStateFilter
||
null
,
current_user
:
options
.
showCurrentUser
||
null
,
current_user
:
options
.
showCurrentUser
||
null
,
author_id
:
options
.
authorId
||
null
,
author_id
:
options
.
authorId
||
null
,
skip_users
:
options
.
skipUsers
||
null
skip_users
:
options
.
skipUsers
||
null
,
};
};
return
axios
.
get
(
url
,
{
params
})
return
axios
.
get
(
url
,
{
params
}).
then
(({
data
})
=>
{
.
then
(({
data
})
=>
{
callback
(
data
);
callback
(
data
);
});
});
};
};
UsersSelect
.
prototype
.
buildUrl
=
function
(
url
)
{
UsersSelect
.
prototype
.
buildUrl
=
function
(
url
)
{
...
...
app/assets/javascripts/zen_mode.js
View file @
c559bcca
...
@@ -47,16 +47,26 @@ export default class ZenMode {
...
@@ -47,16 +47,26 @@ export default class ZenMode {
e
.
preventDefault
();
e
.
preventDefault
();
return
$
(
e
.
currentTarget
).
trigger
(
'
zen_mode:leave
'
);
return
$
(
e
.
currentTarget
).
trigger
(
'
zen_mode:leave
'
);
});
});
$
(
document
).
on
(
'
zen_mode:enter
'
,
(
function
(
_this
)
{
$
(
document
).
on
(
return
function
(
e
)
{
'
zen_mode:enter
'
,
return
_this
.
enter
(
$
(
e
.
target
).
closest
(
'
.md-area
'
).
find
(
'
.zen-backdrop
'
));
(
function
(
_this
)
{
};
return
function
(
e
)
{
})(
this
));
return
_this
.
enter
(
$
(
document
).
on
(
'
zen_mode:leave
'
,
(
function
(
_this
)
{
$
(
e
.
target
)
return
function
(
e
)
{
.
closest
(
'
.md-area
'
)
return
_this
.
exit
();
.
find
(
'
.zen-backdrop
'
),
};
);
})(
this
));
};
})(
this
),
);
$
(
document
).
on
(
'
zen_mode:leave
'
,
(
function
(
_this
)
{
return
function
(
e
)
{
return
_this
.
exit
();
};
})(
this
),
);
$
(
document
).
on
(
'
keydown
'
,
function
(
e
)
{
$
(
document
).
on
(
'
keydown
'
,
function
(
e
)
{
// Esc
// Esc
if
(
e
.
keyCode
===
27
)
{
if
(
e
.
keyCode
===
27
)
{
...
@@ -93,7 +103,7 @@ export default class ZenMode {
...
@@ -93,7 +103,7 @@ export default class ZenMode {
scrollTo
(
zen_area
)
{
scrollTo
(
zen_area
)
{
return
$
.
scrollTo
(
zen_area
,
0
,
{
return
$
.
scrollTo
(
zen_area
,
0
,
{
offset
:
-
150
offset
:
-
150
,
});
});
}
}
}
}
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