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
dfb08243
Commit
dfb08243
authored
Oct 24, 2018
by
Mike Greiling
Committed by
Tim Zallmann
Oct 24, 2018
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Prettify all the things (part 7)
parent
f8f1466a
Changes
48
Hide whitespace changes
Inline
Side-by-side
Showing
48 changed files
with
826 additions
and
679 deletions
+826
-679
app/assets/javascripts/breadcrumb.js
app/assets/javascripts/breadcrumb.js
+8
-7
app/assets/javascripts/build_artifacts.js
app/assets/javascripts/build_artifacts.js
+11
-7
app/assets/javascripts/ci_variable_list/ajax_variable_list.js
...assets/javascripts/ci_variable_list/ajax_variable_list.js
+29
-27
app/assets/javascripts/ci_variable_list/ci_variable_list.js
app/assets/javascripts/ci_variable_list/ci_variable_list.js
+21
-16
app/assets/javascripts/ci_variable_list/native_form_variable_list.js
...javascripts/ci_variable_list/native_form_variable_list.js
+1
-4
app/assets/javascripts/clusters/stores/clusters_store.js
app/assets/javascripts/clusters/stores/clusters_store.js
+2
-6
app/assets/javascripts/comment_type_toggle.js
app/assets/javascripts/comment_type_toggle.js
+32
-24
app/assets/javascripts/commit/image_file.js
app/assets/javascripts/commit/image_file.js
+179
-141
app/assets/javascripts/commit/pipelines/pipelines_bundle.js
app/assets/javascripts/commit/pipelines/pipelines_bundle.js
+6
-4
app/assets/javascripts/commit/pipelines/pipelines_table.vue
app/assets/javascripts/commit/pipelines/pipelines_table.vue
+59
-63
app/assets/javascripts/commit_merge_requests.js
app/assets/javascripts/commit_merge_requests.js
+4
-3
app/assets/javascripts/commits.js
app/assets/javascripts/commits.js
+27
-11
app/assets/javascripts/commons/bootstrap.js
app/assets/javascripts/commons/bootstrap.js
+10
-2
app/assets/javascripts/confirm_danger_modal.js
app/assets/javascripts/confirm_danger_modal.js
+14
-10
app/assets/javascripts/contextual_sidebar.js
app/assets/javascripts/contextual_sidebar.js
+5
-2
app/assets/javascripts/create_item_dropdown.js
app/assets/javascripts/create_item_dropdown.js
+5
-8
app/assets/javascripts/create_label.js
app/assets/javascripts/create_label.js
+31
-32
app/assets/javascripts/deploy_keys/components/app.vue
app/assets/javascripts/deploy_keys/components/app.vue
+4
-2
app/assets/javascripts/deploy_keys/service/index.js
app/assets/javascripts/deploy_keys/service/index.js
+3
-6
app/assets/javascripts/diff.js
app/assets/javascripts/diff.js
+9
-5
app/assets/javascripts/dropzone_input.js
app/assets/javascripts/dropzone_input.js
+26
-15
app/assets/javascripts/emoji/support/is_emoji_unicode_supported.js
...s/javascripts/emoji/support/is_emoji_unicode_supported.js
+30
-25
app/assets/javascripts/experimental_flags.js
app/assets/javascripts/experimental_flags.js
+1
-1
app/assets/javascripts/files_comment_button.js
app/assets/javascripts/files_comment_button.js
+8
-4
app/assets/javascripts/filterable_list.js
app/assets/javascripts/filterable_list.js
+16
-9
app/assets/javascripts/flash.js
app/assets/javascripts/flash.js
+17
-16
app/assets/javascripts/fly_out_nav.js
app/assets/javascripts/fly_out_nav.js
+33
-19
app/assets/javascripts/gl_field_error.js
app/assets/javascripts/gl_field_error.js
+2
-1
app/assets/javascripts/gl_field_errors.js
app/assets/javascripts/gl_field_errors.js
+9
-5
app/assets/javascripts/gl_form.js
app/assets/javascripts/gl_form.js
+12
-7
app/assets/javascripts/group_avatar.js
app/assets/javascripts/group_avatar.js
+3
-2
app/assets/javascripts/group_label_subscription.js
app/assets/javascripts/group_label_subscription.js
+7
-3
app/assets/javascripts/groups/components/item_stats.vue
app/assets/javascripts/groups/components/item_stats.vue
+36
-36
app/assets/javascripts/groups/components/item_stats_value.vue
...assets/javascripts/groups/components/item_stats_value.vue
+43
-43
app/assets/javascripts/groups/new_group_child.js
app/assets/javascripts/groups/new_group_child.js
+12
-10
app/assets/javascripts/groups/store/groups_store.js
app/assets/javascripts/groups/store/groups_store.js
+12
-11
app/assets/javascripts/groups/transfer_dropdown.js
app/assets/javascripts/groups/transfer_dropdown.js
+1
-1
app/assets/javascripts/groups_select.js
app/assets/javascripts/groups_select.js
+6
-3
app/assets/javascripts/helpers/avatar_helper.js
app/assets/javascripts/helpers/avatar_helper.js
+3
-1
app/assets/javascripts/image_diff/image_diff.js
app/assets/javascripts/image_diff/image_diff.js
+4
-2
app/assets/javascripts/image_diff/init_discussion_tab.js
app/assets/javascripts/image_diff/init_discussion_tab.js
+2
-1
app/assets/javascripts/image_diff/replaced_image_diff.js
app/assets/javascripts/image_diff/replaced_image_diff.js
+7
-8
app/assets/javascripts/importer_status.js
app/assets/javascripts/importer_status.js
+62
-60
app/assets/javascripts/init_changes_dropdown.js
app/assets/javascripts/init_changes_dropdown.js
+1
-1
app/assets/javascripts/init_notes.js
app/assets/javascripts/init_notes.js
+1
-7
app/assets/javascripts/integrations/integration_settings_form.js
...ets/javascripts/integrations/integration_settings_form.js
+3
-2
app/assets/javascripts/issuable/auto_width_dropdown_select.js
...assets/javascripts/issuable/auto_width_dropdown_select.js
+4
-1
app/assets/javascripts/issuable_bulk_update_actions.js
app/assets/javascripts/issuable_bulk_update_actions.js
+5
-5
No files found.
app/assets/javascripts/breadcrumb.js
View file @
dfb08243
import
$
from
'
jquery
'
;
import
$
from
'
jquery
'
;
export
const
addTooltipToEl
=
(
el
)
=>
{
export
const
addTooltipToEl
=
el
=>
{
const
textEl
=
el
.
querySelector
(
'
.js-breadcrumb-item-text
'
);
const
textEl
=
el
.
querySelector
(
'
.js-breadcrumb-item-text
'
);
if
(
textEl
&&
textEl
.
scrollWidth
>
textEl
.
offsetWidth
)
{
if
(
textEl
&&
textEl
.
scrollWidth
>
textEl
.
offsetWidth
)
{
...
@@ -14,17 +14,18 @@ export default () => {
...
@@ -14,17 +14,18 @@ export default () => {
const
breadcrumbs
=
document
.
querySelector
(
'
.js-breadcrumbs-list
'
);
const
breadcrumbs
=
document
.
querySelector
(
'
.js-breadcrumbs-list
'
);
if
(
breadcrumbs
)
{
if
(
breadcrumbs
)
{
const
topLevelLinks
=
[...
breadcrumbs
.
children
].
filter
(
el
=>
!
el
.
classList
.
contains
(
'
dropdown
'
))
const
topLevelLinks
=
[...
breadcrumbs
.
children
]
.
filter
(
el
=>
!
el
.
classList
.
contains
(
'
dropdown
'
))
.
map
(
el
=>
el
.
querySelector
(
'
a
'
))
.
map
(
el
=>
el
.
querySelector
(
'
a
'
))
.
filter
(
el
=>
el
);
.
filter
(
el
=>
el
);
const
$expander
=
$
(
'
.js-breadcrumbs-collapsed-expander
'
);
const
$expander
=
$
(
'
.js-breadcrumbs-collapsed-expander
'
);
topLevelLinks
.
forEach
(
el
=>
addTooltipToEl
(
el
));
topLevelLinks
.
forEach
(
el
=>
addTooltipToEl
(
el
));
$expander
.
closest
(
'
.dropdown
'
)
$expander
.
closest
(
'
.dropdown
'
)
.
on
(
'
show.bs.dropdown hide.bs.dropdown
'
,
e
=>
{
.
on
(
'
show.bs.dropdown hide.bs.dropdown
'
,
(
e
)
=>
{
$
(
'
.js-breadcrumbs-collapsed-expander
'
,
e
.
currentTarget
)
$
(
'
.js-breadcrumbs-collapsed-expander
'
,
e
.
currentTarget
)
.
toggleClass
(
'
open
'
)
.
toggleClass
(
'
open
'
)
.
tooltip
(
'
hide
'
);
.
tooltip
(
'
hide
'
);
});
});
}
}
};
};
app/assets/javascripts/build_artifacts.js
View file @
dfb08243
...
@@ -12,16 +12,16 @@ export default class BuildArtifacts {
...
@@ -12,16 +12,16 @@ export default class BuildArtifacts {
}
}
// eslint-disable-next-line class-methods-use-this
// eslint-disable-next-line class-methods-use-this
disablePropagation
()
{
disablePropagation
()
{
$
(
'
.top-block
'
).
on
(
'
click
'
,
'
.download
'
,
function
(
e
)
{
$
(
'
.top-block
'
).
on
(
'
click
'
,
'
.download
'
,
function
(
e
)
{
return
e
.
stopPropagation
();
return
e
.
stopPropagation
();
});
});
return
$
(
'
.tree-holder
'
).
on
(
'
click
'
,
'
tr[data-link] a
'
,
function
(
e
)
{
return
$
(
'
.tree-holder
'
).
on
(
'
click
'
,
'
tr[data-link] a
'
,
function
(
e
)
{
return
e
.
stopImmediatePropagation
();
return
e
.
stopImmediatePropagation
();
});
});
}
}
// eslint-disable-next-line class-methods-use-this
// eslint-disable-next-line class-methods-use-this
setupEntryClick
()
{
setupEntryClick
()
{
return
$
(
'
.tree-holder
'
).
on
(
'
click
'
,
'
tr[data-link]
'
,
function
()
{
return
$
(
'
.tree-holder
'
).
on
(
'
click
'
,
'
tr[data-link]
'
,
function
()
{
visitUrl
(
this
.
dataset
.
link
,
convertPermissionToBoolean
(
this
.
dataset
.
externalLink
));
visitUrl
(
this
.
dataset
.
link
,
convertPermissionToBoolean
(
this
.
dataset
.
externalLink
));
});
});
}
}
...
@@ -37,11 +37,15 @@ export default class BuildArtifacts {
...
@@ -37,11 +37,15 @@ export default class BuildArtifacts {
// We want the tooltip to show if you hover anywhere on the row
// We want the tooltip to show if you hover anywhere on the row
// But be placed below and in the middle of the file name
// But be placed below and in the middle of the file name
$
(
'
.js-artifact-tree-row
'
)
$
(
'
.js-artifact-tree-row
'
)
.
on
(
'
mouseenter
'
,
(
e
)
=>
{
.
on
(
'
mouseenter
'
,
e
=>
{
$
(
e
.
currentTarget
).
find
(
'
.js-artifact-tree-tooltip
'
).
tooltip
(
'
show
'
);
$
(
e
.
currentTarget
)
.
find
(
'
.js-artifact-tree-tooltip
'
)
.
tooltip
(
'
show
'
);
})
})
.
on
(
'
mouseleave
'
,
(
e
)
=>
{
.
on
(
'
mouseleave
'
,
e
=>
{
$
(
e
.
currentTarget
).
find
(
'
.js-artifact-tree-tooltip
'
).
tooltip
(
'
hide
'
);
$
(
e
.
currentTarget
)
.
find
(
'
.js-artifact-tree-tooltip
'
)
.
tooltip
(
'
hide
'
);
});
});
}
}
}
}
app/assets/javascripts/ci_variable_list/ajax_variable_list.js
View file @
dfb08243
...
@@ -7,11 +7,13 @@ import statusCodes from '../lib/utils/http_status';
...
@@ -7,11 +7,13 @@ import statusCodes from '../lib/utils/http_status';
import
VariableList
from
'
./ci_variable_list
'
;
import
VariableList
from
'
./ci_variable_list
'
;
function
generateErrorBoxContent
(
errors
)
{
function
generateErrorBoxContent
(
errors
)
{
const
errorList
=
[].
concat
(
errors
).
map
(
errorString
=>
`
const
errorList
=
[].
concat
(
errors
).
map
(
errorString
=>
`
<li>
<li>
${
_
.
escape
(
errorString
)}
${
_
.
escape
(
errorString
)}
</li>
</li>
`
);
`
,
);
return
`
return
`
<p>
<p>
...
@@ -25,13 +27,7 @@ function generateErrorBoxContent(errors) {
...
@@ -25,13 +27,7 @@ function generateErrorBoxContent(errors) {
// Used for the variable list on CI/CD projects/groups settings page
// Used for the variable list on CI/CD projects/groups settings page
export
default
class
AjaxVariableList
{
export
default
class
AjaxVariableList
{
constructor
({
constructor
({
container
,
saveButton
,
errorBox
,
formField
=
'
variables
'
,
saveEndpoint
})
{
container
,
saveButton
,
errorBox
,
formField
=
'
variables
'
,
saveEndpoint
,
})
{
this
.
container
=
container
;
this
.
container
=
container
;
this
.
saveButton
=
saveButton
;
this
.
saveButton
=
saveButton
;
this
.
errorBox
=
errorBox
;
this
.
errorBox
=
errorBox
;
...
@@ -58,18 +54,21 @@ export default class AjaxVariableList {
...
@@ -58,18 +54,21 @@ export default class AjaxVariableList {
// to match it up in `updateRowsWithPersistedVariables`
// to match it up in `updateRowsWithPersistedVariables`
this
.
variableList
.
toggleEnableRow
(
false
);
this
.
variableList
.
toggleEnableRow
(
false
);
return
axios
.
patch
(
this
.
saveEndpoint
,
{
return
axios
variables_attributes
:
this
.
variableList
.
getAllData
(),
.
patch
(
},
{
this
.
saveEndpoint
,
// We want to be able to process the `res.data` from a 400 error response
{
// and print the validation messages such as duplicate variable keys
variables_attributes
:
this
.
variableList
.
getAllData
(),
validateStatus
:
status
=>
(
},
status
>=
statusCodes
.
OK
&&
{
status
<
statusCodes
.
MULTIPLE_CHOICES
// We want to be able to process the `res.data` from a 400 error response
)
||
// and print the validation messages such as duplicate variable keys
status
===
statusCodes
.
BAD_REQUEST
,
validateStatus
:
status
=>
})
(
status
>=
statusCodes
.
OK
&&
status
<
statusCodes
.
MULTIPLE_CHOICES
)
||
.
then
((
res
)
=>
{
status
===
statusCodes
.
BAD_REQUEST
,
},
)
.
then
(
res
=>
{
loadingIcon
.
classList
.
toggle
(
'
hide
'
,
true
);
loadingIcon
.
classList
.
toggle
(
'
hide
'
,
true
);
this
.
variableList
.
toggleEnableRow
(
true
);
this
.
variableList
.
toggleEnableRow
(
true
);
...
@@ -90,18 +89,21 @@ export default class AjaxVariableList {
...
@@ -90,18 +89,21 @@ export default class AjaxVariableList {
}
}
updateRowsWithPersistedVariables
(
persistedVariables
=
[])
{
updateRowsWithPersistedVariables
(
persistedVariables
=
[])
{
const
persistedVariableMap
=
[].
concat
(
persistedVariables
).
reduce
((
variableMap
,
variable
)
=>
({
const
persistedVariableMap
=
[].
concat
(
persistedVariables
).
reduce
(
...
variableMap
,
(
variableMap
,
variable
)
=>
({
[
variable
.
key
]:
variable
,
...
variableMap
,
}),
{});
[
variable
.
key
]:
variable
,
}),
{},
);
this
.
container
.
querySelectorAll
(
'
.js-row
'
).
forEach
(
(
row
)
=>
{
this
.
container
.
querySelectorAll
(
'
.js-row
'
).
forEach
(
row
=>
{
// If we submitted a row that was destroyed, remove it so we don't try
// If we submitted a row that was destroyed, remove it so we don't try
// to destroy it again which would cause a BE error
// to destroy it again which would cause a BE error
const
destroyInput
=
row
.
querySelector
(
'
.js-ci-variable-input-destroy
'
);
const
destroyInput
=
row
.
querySelector
(
'
.js-ci-variable-input-destroy
'
);
if
(
convertPermissionToBoolean
(
destroyInput
.
value
))
{
if
(
convertPermissionToBoolean
(
destroyInput
.
value
))
{
row
.
remove
();
row
.
remove
();
// Update the ID input so any future edits and `_destroy` will apply on the BE
// Update the ID input so any future edits and `_destroy` will apply on the BE
}
else
{
}
else
{
const
key
=
row
.
querySelector
(
'
.js-ci-variable-input-key
'
).
value
;
const
key
=
row
.
querySelector
(
'
.js-ci-variable-input-key
'
).
value
;
const
persistedVariable
=
persistedVariableMap
[
key
];
const
persistedVariable
=
persistedVariableMap
[
key
];
...
...
app/assets/javascripts/ci_variable_list/ci_variable_list.js
View file @
dfb08243
...
@@ -16,10 +16,7 @@ function createEnvironmentItem(value) {
...
@@ -16,10 +16,7 @@ function createEnvironmentItem(value) {
}
}
export
default
class
VariableList
{
export
default
class
VariableList
{
constructor
({
constructor
({
container
,
formField
})
{
container
,
formField
,
})
{
this
.
$container
=
$
(
container
);
this
.
$container
=
$
(
container
);
this
.
formField
=
formField
;
this
.
formField
=
formField
;
this
.
environmentDropdownMap
=
new
WeakMap
();
this
.
environmentDropdownMap
=
new
WeakMap
();
...
@@ -71,7 +68,7 @@ export default class VariableList {
...
@@ -71,7 +68,7 @@ export default class VariableList {
this
.
initRow
(
rowEl
);
this
.
initRow
(
rowEl
);
});
});
this
.
$container
.
on
(
'
click
'
,
'
.js-row-remove-button
'
,
(
e
)
=>
{
this
.
$container
.
on
(
'
click
'
,
'
.js-row-remove-button
'
,
e
=>
{
e
.
preventDefault
();
e
.
preventDefault
();
this
.
removeRow
(
$
(
e
.
currentTarget
).
closest
(
'
.js-row
'
));
this
.
removeRow
(
$
(
e
.
currentTarget
).
closest
(
'
.js-row
'
));
});
});
...
@@ -81,7 +78,7 @@ export default class VariableList {
...
@@ -81,7 +78,7 @@ export default class VariableList {
.
join
(
'
,
'
);
.
join
(
'
,
'
);
// Remove any empty rows except the last row
// Remove any empty rows except the last row
this
.
$container
.
on
(
'
blur
'
,
inputSelector
,
(
e
)
=>
{
this
.
$container
.
on
(
'
blur
'
,
inputSelector
,
e
=>
{
const
$row
=
$
(
e
.
currentTarget
).
closest
(
'
.js-row
'
);
const
$row
=
$
(
e
.
currentTarget
).
closest
(
'
.js-row
'
);
if
(
$row
.
is
(
'
:not(:last-child)
'
)
&&
!
this
.
checkIfRowTouched
(
$row
))
{
if
(
$row
.
is
(
'
:not(:last-child)
'
)
&&
!
this
.
checkIfRowTouched
(
$row
))
{
...
@@ -136,7 +133,7 @@ export default class VariableList {
...
@@ -136,7 +133,7 @@ export default class VariableList {
$rowClone
.
removeAttr
(
'
data-is-persisted
'
);
$rowClone
.
removeAttr
(
'
data-is-persisted
'
);
// Reset the inputs to their defaults
// Reset the inputs to their defaults
Object
.
keys
(
this
.
inputMap
).
forEach
(
(
name
)
=>
{
Object
.
keys
(
this
.
inputMap
).
forEach
(
name
=>
{
const
entry
=
this
.
inputMap
[
name
];
const
entry
=
this
.
inputMap
[
name
];
$rowClone
.
find
(
entry
.
selector
).
val
(
entry
.
default
);
$rowClone
.
find
(
entry
.
selector
).
val
(
entry
.
default
);
});
});
...
@@ -171,7 +168,7 @@ export default class VariableList {
...
@@ -171,7 +168,7 @@ export default class VariableList {
}
}
checkIfRowTouched
(
$row
)
{
checkIfRowTouched
(
$row
)
{
return
Object
.
keys
(
this
.
inputMap
).
some
(
(
name
)
=>
{
return
Object
.
keys
(
this
.
inputMap
).
some
(
name
=>
{
const
entry
=
this
.
inputMap
[
name
];
const
entry
=
this
.
inputMap
[
name
];
const
$el
=
$row
.
find
(
entry
.
selector
);
const
$el
=
$row
.
find
(
entry
.
selector
);
return
$el
.
length
&&
$el
.
val
()
!==
entry
.
default
;
return
$el
.
length
&&
$el
.
val
()
!==
entry
.
default
;
...
@@ -190,11 +187,14 @@ export default class VariableList {
...
@@ -190,11 +187,14 @@ export default class VariableList {
getAllData
()
{
getAllData
()
{
// Ignore the last empty row because we don't want to try persist
// Ignore the last empty row because we don't want to try persist
// a blank variable and run into validation problems.
// a blank variable and run into validation problems.
const
validRows
=
this
.
$container
.
find
(
'
.js-row
'
).
toArray
().
slice
(
0
,
-
1
);
const
validRows
=
this
.
$container
.
find
(
'
.js-row
'
)
.
toArray
()
.
slice
(
0
,
-
1
);
return
validRows
.
map
(
(
rowEl
)
=>
{
return
validRows
.
map
(
rowEl
=>
{
const
resultant
=
{};
const
resultant
=
{};
Object
.
keys
(
this
.
inputMap
).
forEach
(
(
name
)
=>
{
Object
.
keys
(
this
.
inputMap
).
forEach
(
name
=>
{
const
entry
=
this
.
inputMap
[
name
];
const
entry
=
this
.
inputMap
[
name
];
const
$input
=
$
(
rowEl
).
find
(
entry
.
selector
);
const
$input
=
$
(
rowEl
).
find
(
entry
.
selector
);
if
(
$input
.
length
)
{
if
(
$input
.
length
)
{
...
@@ -207,11 +207,16 @@ export default class VariableList {
...
@@ -207,11 +207,16 @@ export default class VariableList {
}
}
getEnvironmentValues
()
{
getEnvironmentValues
()
{
const
valueMap
=
this
.
$container
.
find
(
this
.
inputMap
.
environment_scope
.
selector
).
toArray
()
const
valueMap
=
this
.
$container
.
reduce
((
prevValueMap
,
envInput
)
=>
({
.
find
(
this
.
inputMap
.
environment_scope
.
selector
)
...
prevValueMap
,
.
toArray
()
[
envInput
.
value
]:
envInput
.
value
,
.
reduce
(
}),
{});
(
prevValueMap
,
envInput
)
=>
({
...
prevValueMap
,
[
envInput
.
value
]:
envInput
.
value
,
}),
{},
);
return
Object
.
keys
(
valueMap
).
map
(
createEnvironmentItem
);
return
Object
.
keys
(
valueMap
).
map
(
createEnvironmentItem
);
}
}
...
...
app/assets/javascripts/ci_variable_list/native_form_variable_list.js
View file @
dfb08243
...
@@ -2,10 +2,7 @@ import $ from 'jquery';
...
@@ -2,10 +2,7 @@ import $ from 'jquery';
import
VariableList
from
'
./ci_variable_list
'
;
import
VariableList
from
'
./ci_variable_list
'
;
// Used for the variable list on scheduled pipeline edit page
// Used for the variable list on scheduled pipeline edit page
export
default
function
setupNativeFormVariableList
({
export
default
function
setupNativeFormVariableList
({
container
,
formField
=
'
variables
'
})
{
container
,
formField
=
'
variables
'
,
})
{
const
$container
=
$
(
container
);
const
$container
=
$
(
container
);
const
variableList
=
new
VariableList
({
const
variableList
=
new
VariableList
({
...
...
app/assets/javascripts/clusters/stores/clusters_store.js
View file @
dfb08243
...
@@ -76,12 +76,8 @@ export default class ClusterStore {
...
@@ -76,12 +76,8 @@ export default class ClusterStore {
this
.
state
.
status
=
serverState
.
status
;
this
.
state
.
status
=
serverState
.
status
;
this
.
state
.
statusReason
=
serverState
.
status_reason
;
this
.
state
.
statusReason
=
serverState
.
status_reason
;
serverState
.
applications
.
forEach
((
serverAppEntry
)
=>
{
serverState
.
applications
.
forEach
(
serverAppEntry
=>
{
const
{
const
{
name
:
appId
,
status
,
status_reason
:
statusReason
}
=
serverAppEntry
;
name
:
appId
,
status
,
status_reason
:
statusReason
,
}
=
serverAppEntry
;
this
.
state
.
applications
[
appId
]
=
{
this
.
state
.
applications
[
appId
]
=
{
...(
this
.
state
.
applications
[
appId
]
||
{}),
...(
this
.
state
.
applications
[
appId
]
||
{}),
...
...
app/assets/javascripts/comment_type_toggle.js
View file @
dfb08243
...
@@ -24,36 +24,44 @@ class CommentTypeToggle {
...
@@ -24,36 +24,44 @@ class CommentTypeToggle {
setConfig
()
{
setConfig
()
{
const
config
=
{
const
config
=
{
InputSetter
:
[{
InputSetter
:
[
input
:
this
.
noteTypeInput
,
{
valueAttribute
:
'
data-value
'
,
input
:
this
.
noteTypeInput
,
},
valueAttribute
:
'
data-value
'
,
{
},
input
:
this
.
submitButton
,
{
valueAttribute
:
'
data-submit-text
'
,
input
:
this
.
submitButton
,
}],
valueAttribute
:
'
data-submit-text
'
,
},
],
};
};
if
(
this
.
closeButton
)
{
if
(
this
.
closeButton
)
{
config
.
InputSetter
.
push
({
config
.
InputSetter
.
push
(
input
:
this
.
closeButton
,
{
valueAttribute
:
'
data-close-text
'
,
input
:
this
.
closeButton
,
},
{
valueAttribute
:
'
data-close-text
'
,
input
:
this
.
closeButton
,
},
valueAttribute
:
'
data-close-text
'
,
{
inputAttribute
:
'
data-alternative-text
'
,
input
:
this
.
closeButton
,
});
valueAttribute
:
'
data-close-text
'
,
inputAttribute
:
'
data-alternative-text
'
,
},
);
}
}
if
(
this
.
reopenButton
)
{
if
(
this
.
reopenButton
)
{
config
.
InputSetter
.
push
({
config
.
InputSetter
.
push
(
input
:
this
.
reopenButton
,
{
valueAttribute
:
'
data-reopen-text
'
,
input
:
this
.
reopenButton
,
},
{
valueAttribute
:
'
data-reopen-text
'
,
input
:
this
.
reopenButton
,
},
valueAttribute
:
'
data-reopen-text
'
,
{
inputAttribute
:
'
data-alternative-text
'
,
input
:
this
.
reopenButton
,
});
valueAttribute
:
'
data-reopen-text
'
,
inputAttribute
:
'
data-alternative-text
'
,
},
);
}
}
return
config
;
return
config
;
...
...
app/assets/javascripts/commit/image_file.js
View file @
dfb08243
...
@@ -9,44 +9,60 @@ const viewModes = ['two-up', 'swipe'];
...
@@ -9,44 +9,60 @@ const viewModes = ['two-up', 'swipe'];
export
default
class
ImageFile
{
export
default
class
ImageFile
{
constructor
(
file
)
{
constructor
(
file
)
{
this
.
file
=
file
;
this
.
file
=
file
;
this
.
requestImageInfo
(
$
(
'
.two-up.view .frame.deleted img
'
,
this
.
file
),
(
function
(
_this
)
{
this
.
requestImageInfo
(
return
function
(
deletedWidth
,
deletedHeight
)
{
$
(
'
.two-up.view .frame.deleted img
'
,
this
.
file
),
return
_this
.
requestImageInfo
(
$
(
'
.two-up.view .frame.added img
'
,
_this
.
file
),
function
(
width
,
height
)
{
(
function
(
_this
)
{
_this
.
initViewModes
();
return
function
(
deletedWidth
,
deletedHeight
)
{
return
_this
.
requestImageInfo
(
$
(
'
.two-up.view .frame.added img
'
,
_this
.
file
),
function
(
// Load two-up view after images are loaded
width
,
// so that we can display the correct width and height information
height
,
const
$images
=
$
(
'
.two-up.view img
'
,
_this
.
file
);
)
{
_this
.
initViewModes
();
$images
.
waitForImages
(
function
()
{
_this
.
initView
(
'
two-up
'
);
// Load two-up view after images are loaded
// so that we can display the correct width and height information
const
$images
=
$
(
'
.two-up.view img
'
,
_this
.
file
);
$images
.
waitForImages
(
function
()
{
_this
.
initView
(
'
two-up
'
);
});
});
});
}
)
;
};
}
;
}
)(
this
),
})(
this
)
);
);
}
}
initViewModes
()
{
initViewModes
()
{
const
viewMode
=
viewModes
[
0
];
const
viewMode
=
viewModes
[
0
];
$
(
'
.view-modes
'
,
this
.
file
).
removeClass
(
'
hide
'
);
$
(
'
.view-modes
'
,
this
.
file
).
removeClass
(
'
hide
'
);
$
(
'
.view-modes-menu
'
,
this
.
file
).
on
(
'
click
'
,
'
li
'
,
(
function
(
_this
)
{
$
(
'
.view-modes-menu
'
,
this
.
file
).
on
(
return
function
(
event
)
{
'
click
'
,
if
(
!
$
(
event
.
currentTarget
).
hasClass
(
'
active
'
))
{
'
li
'
,
return
_this
.
activateViewMode
(
event
.
currentTarget
.
className
);
(
function
(
_this
)
{
}
return
function
(
event
)
{
};
if
(
!
$
(
event
.
currentTarget
).
hasClass
(
'
active
'
))
{
})(
this
));
return
_this
.
activateViewMode
(
event
.
currentTarget
.
className
);
}
};
})(
this
),
);
return
this
.
activateViewMode
(
viewMode
);
return
this
.
activateViewMode
(
viewMode
);
}
}
activateViewMode
(
viewMode
)
{
activateViewMode
(
viewMode
)
{
$
(
'
.view-modes-menu li
'
,
this
.
file
).
removeClass
(
'
active
'
).
filter
(
"
.
"
+
viewMode
).
addClass
(
'
active
'
);
$
(
'
.view-modes-menu li
'
,
this
.
file
)
return
$
(
"
.view:visible:not(.
"
+
viewMode
+
"
)
"
,
this
.
file
).
fadeOut
(
200
,
(
function
(
_this
)
{
.
removeClass
(
'
active
'
)
return
function
()
{
.
filter
(
'
.
'
+
viewMode
)
$
(
"
.view.
"
+
viewMode
,
_this
.
file
).
fadeIn
(
200
);
.
addClass
(
'
active
'
);
return
_this
.
initView
(
viewMode
);
return
$
(
'
.view:visible:not(.
'
+
viewMode
+
'
)
'
,
this
.
file
).
fadeOut
(
};
200
,
})(
this
));
(
function
(
_this
)
{
return
function
()
{
$
(
'
.view.
'
+
viewMode
,
_this
.
file
).
fadeIn
(
200
);
return
_this
.
initView
(
viewMode
);
};
})(
this
),
);
}
}
initView
(
viewMode
)
{
initView
(
viewMode
)
{
...
@@ -63,135 +79,154 @@ export default class ImageFile {
...
@@ -63,135 +79,154 @@ export default class ImageFile {
$body
.
css
(
'
user-select
'
,
'
none
'
);
$body
.
css
(
'
user-select
'
,
'
none
'
);
});
});
$body
.
off
(
'
mouseup
'
).
off
(
'
mousemove
'
).
on
(
'
mouseup
'
,
function
()
{
$body
dragging
=
false
;
.
off
(
'
mouseup
'
)
$body
.
css
(
'
user-select
'
,
''
);
.
off
(
'
mousemove
'
)
})
.
on
(
'
mouseup
'
,
function
()
{
.
on
(
'
mousemove
'
,
function
(
e
)
{
dragging
=
false
;
var
left
;
$body
.
css
(
'
user-select
'
,
''
);
if
(
!
dragging
)
return
;
})
.
on
(
'
mousemove
'
,
function
(
e
)
{
left
=
e
.
pageX
-
(
$offsetEl
.
offset
().
left
+
padding
);
var
left
;
if
(
!
dragging
)
return
;
callback
(
e
,
left
);
});
left
=
e
.
pageX
-
(
$offsetEl
.
offset
().
left
+
padding
);
callback
(
e
,
left
);
});
}
}
prepareFrames
(
view
)
{
prepareFrames
(
view
)
{
var
maxHeight
,
maxWidth
;
var
maxHeight
,
maxWidth
;
maxWidth
=
0
;
maxWidth
=
0
;
maxHeight
=
0
;
maxHeight
=
0
;
$
(
'
.frame
'
,
view
).
each
((
function
(
_this
)
{
$
(
'
.frame
'
,
view
)
return
function
(
index
,
frame
)
{
.
each
(
var
height
,
width
;
(
function
(
_this
)
{
width
=
$
(
frame
).
width
();
return
function
(
index
,
frame
)
{
height
=
$
(
frame
).
height
();
var
height
,
width
;
maxWidth
=
width
>
maxWidth
?
width
:
maxWidth
;
width
=
$
(
frame
).
width
();
return
maxHeight
=
height
>
maxHeight
?
height
:
maxHeight
;
height
=
$
(
frame
).
height
();
};
maxWidth
=
width
>
maxWidth
?
width
:
maxWidth
;
})(
this
)).
css
({
return
(
maxHeight
=
height
>
maxHeight
?
height
:
maxHeight
);
width
:
maxWidth
,
};
height
:
maxHeight
})(
this
),
});
)
.
css
({
width
:
maxWidth
,
height
:
maxHeight
,
});
return
[
maxWidth
,
maxHeight
];
return
[
maxWidth
,
maxHeight
];
}
}
views
=
{
views
=
{
'
two-up
'
:
function
()
{
'
two-up
'
:
function
()
{
return
$
(
'
.two-up.view .wrap
'
,
this
.
file
).
each
((
function
(
_this
)
{
return
$
(
'
.two-up.view .wrap
'
,
this
.
file
).
each
(
return
function
(
index
,
wrap
)
{
(
function
(
_this
)
{
$
(
'
img
'
,
wrap
).
each
(
function
()
{
return
function
(
index
,
wrap
)
{
var
currentWidth
;
$
(
'
img
'
,
wrap
).
each
(
function
()
{
currentWidth
=
$
(
this
).
width
();
var
currentWidth
;
if
(
currentWidth
>
availWidth
/
2
)
{
currentWidth
=
$
(
this
).
width
();
return
$
(
this
).
width
(
availWidth
/
2
);
if
(
currentWidth
>
availWidth
/
2
)
{
}
return
$
(
this
).
width
(
availWidth
/
2
);
});
}
return
_this
.
requestImageInfo
(
$
(
'
img
'
,
wrap
),
function
(
width
,
height
)
{
});
$
(
'
.image-info .meta-width
'
,
wrap
).
text
(
width
+
"
px
"
);
return
_this
.
requestImageInfo
(
$
(
'
img
'
,
wrap
),
function
(
width
,
height
)
{
$
(
'
.image-info .meta-height
'
,
wrap
).
text
(
height
+
"
px
"
);
$
(
'
.image-info .meta-width
'
,
wrap
).
text
(
width
+
'
px
'
);
return
$
(
'
.image-info
'
,
wrap
).
removeClass
(
'
hide
'
);
$
(
'
.image-info .meta-height
'
,
wrap
).
text
(
height
+
'
px
'
);
});
return
$
(
'
.image-info
'
,
wrap
).
removeClass
(
'
hide
'
);
};
});
})(
this
));
};
})(
this
),
);
},
},
'
swipe
'
:
function
()
{
swipe
()
{
var
maxHeight
,
maxWidth
;
var
maxHeight
,
maxWidth
;
maxWidth
=
0
;
maxWidth
=
0
;
maxHeight
=
0
;
maxHeight
=
0
;
return
$
(
'
.swipe.view
'
,
this
.
file
).
each
((
function
(
_this
)
{
return
$
(
'
.swipe.view
'
,
this
.
file
).
each
(
return
function
(
index
,
view
)
{
(
function
(
_this
)
{
var
$swipeWrap
,
$swipeBar
,
$swipeFrame
,
wrapPadding
,
ref
;
return
function
(
index
,
view
)
{
ref
=
_this
.
prepareFrames
(
view
),
[
maxWidth
,
maxHeight
]
=
ref
;
var
$swipeWrap
,
$swipeBar
,
$swipeFrame
,
wrapPadding
,
ref
;
$swipeFrame
=
$
(
'
.swipe-frame
'
,
view
);
(
ref
=
_this
.
prepareFrames
(
view
)),
([
maxWidth
,
maxHeight
]
=
ref
);
$swipeWrap
=
$
(
'
.swipe-wrap
'
,
view
);
$swipeFrame
=
$
(
'
.swipe-frame
'
,
view
);
$swipeBar
=
$
(
'
.swipe-bar
'
,
view
);
$swipeWrap
=
$
(
'
.swipe-wrap
'
,
view
);
$swipeBar
=
$
(
'
.swipe-bar
'
,
view
);
$swipeFrame
.
css
({
width
:
maxWidth
+
16
,
$swipeFrame
.
css
({
height
:
maxHeight
+
28
width
:
maxWidth
+
16
,
});
height
:
maxHeight
+
28
,
$swipeWrap
.
css
({
});
width
:
maxWidth
+
1
,
$swipeWrap
.
css
({
height
:
maxHeight
+
2
width
:
maxWidth
+
1
,
});
height
:
maxHeight
+
2
,
// Set swipeBar left position to match image frame
});
$swipeBar
.
css
({
// Set swipeBar left position to match image frame
left
:
1
$swipeBar
.
css
({
});
left
:
1
,
});
wrapPadding
=
parseInt
(
$swipeWrap
.
css
(
'
right
'
).
replace
(
'
px
'
,
''
),
10
);
wrapPadding
=
parseInt
(
$swipeWrap
.
css
(
'
right
'
).
replace
(
'
px
'
,
''
),
10
);
_this
.
initDraggable
(
$swipeBar
,
wrapPadding
,
function
(
e
,
left
)
{
if
(
left
>
0
&&
left
<
$swipeFrame
.
width
()
-
(
wrapPadding
*
2
))
{
_this
.
initDraggable
(
$swipeBar
,
wrapPadding
,
function
(
e
,
left
)
{
$swipeWrap
.
width
((
maxWidth
+
1
)
-
left
);
if
(
left
>
0
&&
left
<
$swipeFrame
.
width
()
-
wrapPadding
*
2
)
{
$swipeBar
.
css
(
'
left
'
,
left
);
$swipeWrap
.
width
(
maxWidth
+
1
-
left
);
}
$swipeBar
.
css
(
'
left
'
,
left
);
});
}
};
});
})(
this
));
};
})(
this
),
);
},
},
'
onion-skin
'
:
function
()
{
'
onion-skin
'
:
function
()
{
var
dragTrackWidth
,
maxHeight
,
maxWidth
;
var
dragTrackWidth
,
maxHeight
,
maxWidth
;
maxWidth
=
0
;
maxWidth
=
0
;
maxHeight
=
0
;
maxHeight
=
0
;
dragTrackWidth
=
$
(
'
.drag-track
'
,
this
.
file
).
width
()
-
$
(
'
.dragger
'
,
this
.
file
).
width
();
dragTrackWidth
=
$
(
'
.drag-track
'
,
this
.
file
).
width
()
-
$
(
'
.dragger
'
,
this
.
file
).
width
();
return
$
(
'
.onion-skin.view
'
,
this
.
file
).
each
((
function
(
_this
)
{
return
$
(
'
.onion-skin.view
'
,
this
.
file
).
each
(
return
function
(
index
,
view
)
{
(
function
(
_this
)
{
var
$frame
,
$track
,
$dragger
,
$frameAdded
,
framePadding
,
ref
,
dragging
=
false
;
return
function
(
index
,
view
)
{
ref
=
_this
.
prepareFrames
(
view
),
[
maxWidth
,
maxHeight
]
=
ref
;
var
$frame
,
$frame
=
$
(
'
.onion-skin-frame
'
,
view
);
$track
,
$frameAdded
=
$
(
'
.frame.added
'
,
view
);
$dragger
,
$track
=
$
(
'
.drag-track
'
,
view
);
$frameAdded
,
$dragger
=
$
(
'
.dragger
'
,
$track
);
framePadding
,
ref
,
$frame
.
css
({
dragging
=
false
;
width
:
maxWidth
+
16
,
(
ref
=
_this
.
prepareFrames
(
view
)),
([
maxWidth
,
maxHeight
]
=
ref
);
height
:
maxHeight
+
28
$frame
=
$
(
'
.onion-skin-frame
'
,
view
);
});
$frameAdded
=
$
(
'
.frame.added
'
,
view
);
$
(
'
.swipe-wrap
'
,
view
).
css
({
$track
=
$
(
'
.drag-track
'
,
view
);
width
:
maxWidth
+
1
,
$dragger
=
$
(
'
.dragger
'
,
$track
);
height
:
maxHeight
+
2
});
$frame
.
css
({
$dragger
.
css
({
width
:
maxWidth
+
16
,
left
:
dragTrackWidth
height
:
maxHeight
+
28
,
});
});
$
(
'
.swipe-wrap
'
,
view
).
css
({
$frameAdded
.
css
(
'
opacity
'
,
1
);
width
:
maxWidth
+
1
,
framePadding
=
parseInt
(
$frameAdded
.
css
(
'
right
'
).
replace
(
'
px
'
,
''
),
10
);
height
:
maxHeight
+
2
,
});
_this
.
initDraggable
(
$dragger
,
framePadding
,
function
(
e
,
left
)
{
$dragger
.
css
({
var
opacity
=
left
/
dragTrackWidth
;
left
:
dragTrackWidth
,
});
if
(
opacity
>=
0
&&
opacity
<=
1
)
{
$dragger
.
css
(
'
left
'
,
left
);
$frameAdded
.
css
(
'
opacity
'
,
1
);
$frameAdded
.
css
(
'
opacity
'
,
opacity
);
framePadding
=
parseInt
(
$frameAdded
.
css
(
'
right
'
).
replace
(
'
px
'
,
''
),
10
);
}
});
_this
.
initDraggable
(
$dragger
,
framePadding
,
function
(
e
,
left
)
{
};
var
opacity
=
left
/
dragTrackWidth
;
})(
this
));
}
if
(
opacity
>=
0
&&
opacity
<=
1
)
{
}
$dragger
.
css
(
'
left
'
,
left
);
$frameAdded
.
css
(
'
opacity
'
,
opacity
);
}
});
};
})(
this
),
);
},
};
requestImageInfo
(
img
,
callback
)
{
requestImageInfo
(
img
,
callback
)
{
const
domImg
=
img
.
get
(
0
);
const
domImg
=
img
.
get
(
0
);
...
@@ -199,11 +234,14 @@ export default class ImageFile {
...
@@ -199,11 +234,14 @@ export default class ImageFile {
if
(
domImg
.
complete
)
{
if
(
domImg
.
complete
)
{
return
callback
.
call
(
this
,
domImg
.
naturalWidth
,
domImg
.
naturalHeight
);
return
callback
.
call
(
this
,
domImg
.
naturalWidth
,
domImg
.
naturalHeight
);
}
else
{
}
else
{
return
img
.
on
(
'
load
'
,
(
function
(
_this
)
{
return
img
.
on
(
return
function
()
{
'
load
'
,
return
callback
.
call
(
_this
,
domImg
.
naturalWidth
,
domImg
.
naturalHeight
);
(
function
(
_this
)
{
};
return
function
()
{
})(
this
));
return
callback
.
call
(
_this
,
domImg
.
naturalWidth
,
domImg
.
naturalHeight
);
};
})(
this
),
);
}
}
}
}
}
}
...
...
app/assets/javascripts/commit/pipelines/pipelines_bundle.js
View file @
dfb08243
...
@@ -19,11 +19,13 @@ export default () => {
...
@@ -19,11 +19,13 @@ export default () => {
const
pipelineTableViewEl
=
document
.
querySelector
(
'
#commit-pipeline-table-view
'
);
const
pipelineTableViewEl
=
document
.
querySelector
(
'
#commit-pipeline-table-view
'
);
if
(
pipelineTableViewEl
)
{
if
(
pipelineTableViewEl
)
{
// Update MR and Commits tabs
// Update MR and Commits tabs
pipelineTableViewEl
.
addEventListener
(
'
update-pipelines-count
'
,
(
event
)
=>
{
pipelineTableViewEl
.
addEventListener
(
'
update-pipelines-count
'
,
event
=>
{
if
(
event
.
detail
.
pipelines
&&
if
(
event
.
detail
.
pipelines
&&
event
.
detail
.
pipelines
.
count
&&
event
.
detail
.
pipelines
.
count
&&
event
.
detail
.
pipelines
.
count
.
all
)
{
event
.
detail
.
pipelines
.
count
.
all
)
{
const
badge
=
document
.
querySelector
(
'
.js-pipelines-mr-count
'
);
const
badge
=
document
.
querySelector
(
'
.js-pipelines-mr-count
'
);
badge
.
textContent
=
event
.
detail
.
pipelines
.
count
.
all
;
badge
.
textContent
=
event
.
detail
.
pipelines
.
count
.
all
;
...
...
app/assets/javascripts/commit/pipelines/pipelines_table.vue
View file @
dfb08243
<
script
>
<
script
>
import
PipelinesService
from
'
../../pipelines/services/pipelines_service
'
;
import
PipelinesService
from
'
../../pipelines/services/pipelines_service
'
;
import
PipelineStore
from
'
../../pipelines/stores/pipelines_store
'
;
import
PipelineStore
from
'
../../pipelines/stores/pipelines_store
'
;
import
pipelinesMixin
from
'
../../pipelines/mixins/pipelines
'
;
import
pipelinesMixin
from
'
../../pipelines/mixins/pipelines
'
;
export
default
{
export
default
{
mixins
:
[
mixins
:
[
pipelinesMixin
],
pipelinesMixin
,
props
:
{
],
endpoint
:
{
props
:
{
type
:
String
,
endpoint
:
{
required
:
true
,
type
:
String
,
required
:
true
,
},
helpPagePath
:
{
type
:
String
,
required
:
true
,
},
autoDevopsHelpPath
:
{
type
:
String
,
required
:
true
,
},
errorStateSvgPath
:
{
type
:
String
,
required
:
true
,
},
viewType
:
{
type
:
String
,
required
:
false
,
default
:
'
child
'
,
},
},
},
helpPagePath
:
{
type
:
String
,
required
:
true
,
},
autoDevopsHelpPath
:
{
type
:
String
,
required
:
true
,
},
errorStateSvgPath
:
{
type
:
String
,
required
:
true
,
},
viewType
:
{
type
:
String
,
required
:
false
,
default
:
'
child
'
,
},
},
data
()
{
data
()
{
const
store
=
new
PipelineStore
();
const
store
=
new
PipelineStore
();
return
{
return
{
store
,
store
,
state
:
store
.
state
,
state
:
store
.
state
,
};
};
},
},
computed
:
{
computed
:
{
shouldRenderTable
()
{
shouldRenderTable
()
{
return
!
this
.
isLoading
&&
return
!
this
.
isLoading
&&
this
.
state
.
pipelines
.
length
>
0
&&
!
this
.
hasError
;
this
.
state
.
pipelines
.
length
>
0
&&
!
this
.
hasError
;
},
shouldRenderErrorState
()
{
return
this
.
hasError
&&
!
this
.
isLoading
;
},
},
},
created
()
{
shouldRenderErrorState
()
{
this
.
service
=
new
PipelinesService
(
this
.
endpoint
)
;
return
this
.
hasError
&&
!
this
.
isLoading
;
},
},
methods
:
{
},
successCallback
(
resp
)
{
created
()
{
// depending of the endpoint the response can either bring a `pipelines` key or not.
this
.
service
=
new
PipelinesService
(
this
.
endpoint
);
const
pipelines
=
resp
.
data
.
pipelines
||
resp
.
data
;
},
this
.
setCommonData
(
pipelines
);
methods
:
{
successCallback
(
resp
)
{
// depending of the endpoint the response can either bring a `pipelines` key or not.
const
pipelines
=
resp
.
data
.
pipelines
||
resp
.
data
;
this
.
setCommonData
(
pipelines
);
const
updatePipelinesEvent
=
new
CustomEvent
(
'
update-pipelines-count
'
,
{
const
updatePipelinesEvent
=
new
CustomEvent
(
'
update-pipelines-count
'
,
{
detail
:
{
detail
:
{
pipelines
:
resp
.
data
,
pipelines
:
resp
.
data
,
},
},
});
});
// notifiy to update the count in tabs
// notifiy to update the count in tabs
if
(
this
.
$el
.
parentElement
)
{
if
(
this
.
$el
.
parentElement
)
{
this
.
$el
.
parentElement
.
dispatchEvent
(
updatePipelinesEvent
);
this
.
$el
.
parentElement
.
dispatchEvent
(
updatePipelinesEvent
);
}
}
},
},
},
};
},
};
</
script
>
</
script
>
<
template
>
<
template
>
<div
class=
"content-list pipelines"
>
<div
class=
"content-list pipelines"
>
...
...
app/assets/javascripts/commit_merge_requests.js
View file @
dfb08243
...
@@ -50,7 +50,7 @@ export function createContent(mergeRequests) {
...
@@ -50,7 +50,7 @@ export function createContent(mergeRequests) {
if
(
mergeRequests
.
length
===
0
)
{
if
(
mergeRequests
.
length
===
0
)
{
$content
.
text
(
s__
(
'
Commits|No related merge requests found
'
));
$content
.
text
(
s__
(
'
Commits|No related merge requests found
'
));
}
else
{
}
else
{
mergeRequests
.
forEach
(
(
mergeRequest
)
=>
{
mergeRequests
.
forEach
(
mergeRequest
=>
{
const
$header
=
createHeader
(
$content
.
children
().
length
,
mergeRequests
.
length
);
const
$header
=
createHeader
(
$content
.
children
().
length
,
mergeRequests
.
length
);
const
$item
=
createItem
(
mergeRequest
);
const
$item
=
createItem
(
mergeRequest
);
$content
.
append
(
$header
);
$content
.
append
(
$header
);
...
@@ -64,8 +64,9 @@ export function createContent(mergeRequests) {
...
@@ -64,8 +64,9 @@ export function createContent(mergeRequests) {
export
function
fetchCommitMergeRequests
()
{
export
function
fetchCommitMergeRequests
()
{
const
$container
=
$
(
'
.merge-requests
'
);
const
$container
=
$
(
'
.merge-requests
'
);
axios
.
get
(
$container
.
data
(
'
projectCommitPath
'
))
axios
.
then
((
response
)
=>
{
.
get
(
$container
.
data
(
'
projectCommitPath
'
))
.
then
(
response
=>
{
const
$content
=
createContent
(
response
.
data
);
const
$content
=
createContent
(
response
.
data
);
$container
.
html
(
$content
);
$container
.
html
(
$content
);
...
...
app/assets/javascripts/commits.js
View file @
dfb08243
...
@@ -32,22 +32,31 @@ export default class CommitsList {
...
@@ -32,22 +32,31 @@ export default class CommitsList {
if
(
search
===
this
.
lastSearch
)
return
Promise
.
resolve
();
if
(
search
===
this
.
lastSearch
)
return
Promise
.
resolve
();
const
commitsUrl
=
`
${
form
.
attr
(
'
action
'
)}
?
${
form
.
serialize
()}
`
;
const
commitsUrl
=
`
${
form
.
attr
(
'
action
'
)}
?
${
form
.
serialize
()}
`
;
this
.
content
.
fadeTo
(
'
fast
'
,
0.5
);
this
.
content
.
fadeTo
(
'
fast
'
,
0.5
);
const
params
=
form
.
serializeArray
().
reduce
((
acc
,
obj
)
=>
Object
.
assign
(
acc
,
{
const
params
=
form
.
serializeArray
().
reduce
(
[
obj
.
name
]:
obj
.
value
,
(
acc
,
obj
)
=>
}),
{});
Object
.
assign
(
acc
,
{
[
obj
.
name
]:
obj
.
value
,
}),
{},
);
return
axios
.
get
(
form
.
attr
(
'
action
'
),
{
return
axios
params
,
.
get
(
form
.
attr
(
'
action
'
),
{
})
params
,
})
.
then
(({
data
})
=>
{
.
then
(({
data
})
=>
{
this
.
lastSearch
=
search
;
this
.
lastSearch
=
search
;
this
.
content
.
html
(
data
.
html
);
this
.
content
.
html
(
data
.
html
);
this
.
content
.
fadeTo
(
'
fast
'
,
1.0
);
this
.
content
.
fadeTo
(
'
fast
'
,
1.0
);
// Change url so if user reload a page - search results are saved
// Change url so if user reload a page - search results are saved
window
.
history
.
replaceState
({
window
.
history
.
replaceState
(
page
:
commitsUrl
,
{
},
document
.
title
,
commitsUrl
);
page
:
commitsUrl
,
},
document
.
title
,
commitsUrl
,
);
})
})
.
catch
(()
=>
{
.
catch
(()
=>
{
this
.
content
.
fadeTo
(
'
fast
'
,
1.0
);
this
.
content
.
fadeTo
(
'
fast
'
,
1.0
);
...
@@ -75,8 +84,15 @@ export default class CommitsList {
...
@@ -75,8 +84,15 @@ export default class CommitsList {
processedData
=
$processedData
.
not
(
`li.js-commit-header[data-day='
${
loadedShownDayFirst
}
']`
);
processedData
=
$processedData
.
not
(
`li.js-commit-header[data-day='
${
loadedShownDayFirst
}
']`
);
// Update commits count in the previous commits header.
// Update commits count in the previous commits header.
commitsCount
+=
Number
(
$
(
processedData
).
nextUntil
(
'
li.js-commit-header
'
).
first
().
find
(
'
li.commit
'
).
length
);
commitsCount
+=
Number
(
$commitsHeadersLast
.
find
(
'
span.commits-count
'
).
text
(
`
${
commitsCount
}
${
pluralize
(
'
commit
'
,
commitsCount
)}
`
);
$
(
processedData
)
.
nextUntil
(
'
li.js-commit-header
'
)
.
first
()
.
find
(
'
li.commit
'
).
length
,
);
$commitsHeadersLast
.
find
(
'
span.commits-count
'
)
.
text
(
`
${
commitsCount
}
${
pluralize
(
'
commit
'
,
commitsCount
)}
`
);
}
}
localTimeAgo
(
$processedData
.
find
(
'
.js-timeago
'
));
localTimeAgo
(
$processedData
.
find
(
'
.js-timeago
'
));
...
...
app/assets/javascripts/commons/bootstrap.js
View file @
dfb08243
...
@@ -5,6 +5,14 @@ import 'bootstrap';
...
@@ -5,6 +5,14 @@ import 'bootstrap';
// custom jQuery functions
// custom jQuery functions
$
.
fn
.
extend
({
$
.
fn
.
extend
({
disable
()
{
return
$
(
this
).
prop
(
'
disabled
'
,
true
).
addClass
(
'
disabled
'
);
},
disable
()
{
enable
()
{
return
$
(
this
).
prop
(
'
disabled
'
,
false
).
removeClass
(
'
disabled
'
);
},
return
$
(
this
)
.
prop
(
'
disabled
'
,
true
)
.
addClass
(
'
disabled
'
);
},
enable
()
{
return
$
(
this
)
.
prop
(
'
disabled
'
,
false
)
.
removeClass
(
'
disabled
'
);
},
});
});
app/assets/javascripts/confirm_danger_modal.js
View file @
dfb08243
...
@@ -13,19 +13,23 @@ function openConfirmDangerModal($form, text) {
...
@@ -13,19 +13,23 @@ function openConfirmDangerModal($form, text) {
$submit
.
disable
();
$submit
.
disable
();
$input
.
focus
();
$input
.
focus
();
$
(
'
.js-confirm-danger-input
'
).
off
(
'
input
'
).
on
(
'
input
'
,
function
handleInput
()
{
$
(
'
.js-confirm-danger-input
'
)
const
confirmText
=
rstrip
(
$
(
this
).
val
());
.
off
(
'
input
'
)
if
(
confirmText
===
confirmTextMatch
)
{
.
on
(
'
input
'
,
function
handleInput
()
{
$submit
.
enable
();
const
confirmText
=
rstrip
(
$
(
this
).
val
());
}
else
{
if
(
confirmText
===
confirmTextMatch
)
{
$submit
.
disable
();
$submit
.
enable
();
}
}
else
{
});
$submit
.
disable
();
$
(
'
.js-confirm-danger-submit
'
).
off
(
'
click
'
).
on
(
'
click
'
,
()
=>
$form
.
submit
());
}
});
$
(
'
.js-confirm-danger-submit
'
)
.
off
(
'
click
'
)
.
on
(
'
click
'
,
()
=>
$form
.
submit
());
}
}
export
default
function
initConfirmDangerModal
()
{
export
default
function
initConfirmDangerModal
()
{
$
(
document
).
on
(
'
click
'
,
'
.js-confirm-danger
'
,
(
e
)
=>
{
$
(
document
).
on
(
'
click
'
,
'
.js-confirm-danger
'
,
e
=>
{
e
.
preventDefault
();
e
.
preventDefault
();
const
$btn
=
$
(
e
.
target
);
const
$btn
=
$
(
e
.
target
);
const
$form
=
$btn
.
closest
(
'
form
'
);
const
$form
=
$btn
.
closest
(
'
form
'
);
...
...
app/assets/javascripts/contextual_sidebar.js
View file @
dfb08243
...
@@ -20,8 +20,11 @@ export default class ContextualSidebar {
...
@@ -20,8 +20,11 @@ export default class ContextualSidebar {
}
}
bindEvents
()
{
bindEvents
()
{
document
.
addEventListener
(
'
click
'
,
(
e
)
=>
{
document
.
addEventListener
(
'
click
'
,
e
=>
{
if
(
!
e
.
target
.
closest
(
'
.nav-sidebar
'
)
&&
(
bp
.
getBreakpointSize
()
===
'
sm
'
||
bp
.
getBreakpointSize
()
===
'
md
'
))
{
if
(
!
e
.
target
.
closest
(
'
.nav-sidebar
'
)
&&
(
bp
.
getBreakpointSize
()
===
'
sm
'
||
bp
.
getBreakpointSize
()
===
'
md
'
)
)
{
this
.
toggleCollapsedSidebar
(
true
);
this
.
toggleCollapsedSidebar
(
true
);
}
}
});
});
...
...
app/assets/javascripts/create_item_dropdown.js
View file @
dfb08243
...
@@ -36,7 +36,7 @@ export default class CreateItemDropdown {
...
@@ -36,7 +36,7 @@ export default class CreateItemDropdown {
},
},
selectable
:
true
,
selectable
:
true
,
toggleLabel
(
selected
)
{
toggleLabel
(
selected
)
{
return
(
selected
&&
'
id
'
in
selected
)
?
_
.
escape
(
selected
.
title
)
:
this
.
defaultToggleLabel
;
return
selected
&&
'
id
'
in
selected
?
_
.
escape
(
selected
.
title
)
:
this
.
defaultToggleLabel
;
},
},
fieldName
:
this
.
fieldName
,
fieldName
:
this
.
fieldName
,
text
(
item
)
{
text
(
item
)
{
...
@@ -46,7 +46,7 @@ export default class CreateItemDropdown {
...
@@ -46,7 +46,7 @@ export default class CreateItemDropdown {
return
_
.
escape
(
item
.
id
);
return
_
.
escape
(
item
.
id
);
},
},
onFilter
:
this
.
toggleCreateNewButton
.
bind
(
this
),
onFilter
:
this
.
toggleCreateNewButton
.
bind
(
this
),
clicked
:
(
options
)
=>
{
clicked
:
options
=>
{
options
.
e
.
preventDefault
();
options
.
e
.
preventDefault
();
this
.
onSelect
();
this
.
onSelect
();
},
},
...
@@ -77,9 +77,8 @@ export default class CreateItemDropdown {
...
@@ -77,9 +77,8 @@ export default class CreateItemDropdown {
getData
(
term
,
callback
)
{
getData
(
term
,
callback
)
{
this
.
getDataOption
(
term
,
(
data
=
[])
=>
{
this
.
getDataOption
(
term
,
(
data
=
[])
=>
{
// Ensure the selected item isn't already in the data to avoid duplicates
// Ensure the selected item isn't already in the data to avoid duplicates
const
alreadyHasSelectedItem
=
this
.
selectedItem
&&
data
.
some
(
item
=>
const
alreadyHasSelectedItem
=
item
.
id
===
this
.
selectedItem
.
id
,
this
.
selectedItem
&&
data
.
some
(
item
=>
item
.
id
===
this
.
selectedItem
.
id
);
);
let
uniqueData
=
data
;
let
uniqueData
=
data
;
if
(
!
alreadyHasSelectedItem
)
{
if
(
!
alreadyHasSelectedItem
)
{
...
@@ -106,9 +105,7 @@ export default class CreateItemDropdown {
...
@@ -106,9 +105,7 @@ export default class CreateItemDropdown {
if
(
newValue
)
{
if
(
newValue
)
{
this
.
selectedItem
=
this
.
createNewItemFromValue
(
newValue
);
this
.
selectedItem
=
this
.
createNewItemFromValue
(
newValue
);
this
.
$dropdownContainer
this
.
$dropdownContainer
.
find
(
'
.js-dropdown-create-new-item code
'
).
text
(
newValue
);
.
find
(
'
.js-dropdown-create-new-item code
'
)
.
text
(
newValue
);
}
}
this
.
toggleFooter
(
!
newValue
);
this
.
toggleFooter
(
!
newValue
);
...
...
app/assets/javascripts/create_label.js
View file @
dfb08243
...
@@ -37,7 +37,7 @@ export default class CreateLabelDropdown {
...
@@ -37,7 +37,7 @@ export default class CreateLabelDropdown {
addBinding
()
{
addBinding
()
{
const
self
=
this
;
const
self
=
this
;
this
.
$colorSuggestions
.
on
(
'
click
'
,
function
(
e
)
{
this
.
$colorSuggestions
.
on
(
'
click
'
,
function
(
e
)
{
const
$this
=
$
(
this
);
const
$this
=
$
(
this
);
self
.
addColorValue
(
e
,
$this
);
self
.
addColorValue
(
e
,
$this
);
});
});
...
@@ -47,7 +47,7 @@ export default class CreateLabelDropdown {
...
@@ -47,7 +47,7 @@ export default class CreateLabelDropdown {
this
.
$dropdownBack
.
on
(
'
click
'
,
this
.
resetForm
.
bind
(
this
));
this
.
$dropdownBack
.
on
(
'
click
'
,
this
.
resetForm
.
bind
(
this
));
this
.
$cancelButton
.
on
(
'
click
'
,
function
(
e
)
{
this
.
$cancelButton
.
on
(
'
click
'
,
function
(
e
)
{
e
.
preventDefault
();
e
.
preventDefault
();
e
.
stopPropagation
();
e
.
stopPropagation
();
...
@@ -79,13 +79,9 @@ export default class CreateLabelDropdown {
...
@@ -79,13 +79,9 @@ export default class CreateLabelDropdown {
}
}
resetForm
()
{
resetForm
()
{
this
.
$newLabelField
this
.
$newLabelField
.
val
(
''
).
trigger
(
'
change
'
);
.
val
(
''
)
.
trigger
(
'
change
'
);
this
.
$newColorField
this
.
$newColorField
.
val
(
''
).
trigger
(
'
change
'
);
.
val
(
''
)
.
trigger
(
'
change
'
);
this
.
$colorPreview
this
.
$colorPreview
.
css
(
'
background-color
'
,
''
)
.
css
(
'
background-color
'
,
''
)
...
@@ -97,31 +93,34 @@ export default class CreateLabelDropdown {
...
@@ -97,31 +93,34 @@ export default class CreateLabelDropdown {
e
.
preventDefault
();
e
.
preventDefault
();
e
.
stopPropagation
();
e
.
stopPropagation
();
Api
.
newLabel
(
this
.
namespacePath
,
this
.
projectPath
,
{
Api
.
newLabel
(
title
:
this
.
$newLabelField
.
val
(),
this
.
namespacePath
,
color
:
this
.
$newColorField
.
val
(),
this
.
projectPath
,
},
(
label
)
=>
{
{
this
.
$newLabelCreateButton
.
enable
();
title
:
this
.
$newLabelField
.
val
(),
color
:
this
.
$newColorField
.
val
(),
if
(
label
.
message
)
{
},
let
errors
;
label
=>
{
this
.
$newLabelCreateButton
.
enable
();
if
(
typeof
label
.
message
===
'
string
'
)
{
errors
=
label
.
message
;
if
(
label
.
message
)
{
let
errors
;
if
(
typeof
label
.
message
===
'
string
'
)
{
errors
=
label
.
message
;
}
else
{
errors
=
Object
.
keys
(
label
.
message
)
.
map
(
key
=>
`
${
humanize
(
key
)}
${
label
.
message
[
key
].
join
(
'
,
'
)}
`
)
.
join
(
'
<br/>
'
);
}
this
.
$newLabelError
.
html
(
errors
).
show
();
}
else
{
}
else
{
errors
=
Object
.
keys
(
label
.
message
).
map
(
key
=>
this
.
$dropdownBack
.
trigger
(
'
click
'
);
`
${
humanize
(
key
)}
${
label
.
message
[
key
].
join
(
'
,
'
)}
`
,
).
join
(
'
<br/>
'
);
}
this
.
$newLabelError
$
(
document
).
trigger
(
'
created.label
'
,
label
);
.
html
(
errors
)
}
.
show
();
},
}
else
{
);
this
.
$dropdownBack
.
trigger
(
'
click
'
);
$
(
document
).
trigger
(
'
created.label
'
,
label
);
}
});
}
}
}
}
app/assets/javascripts/deploy_keys/components/app.vue
View file @
dfb08243
...
@@ -95,8 +95,10 @@ export default {
...
@@ -95,8 +95,10 @@ export default {
.
catch
(()
=>
new
Flash
(
s__
(
'
DeployKeys|Error enabling deploy key
'
)));
.
catch
(()
=>
new
Flash
(
s__
(
'
DeployKeys|Error enabling deploy key
'
)));
},
},
disableKey
(
deployKey
,
callback
)
{
disableKey
(
deployKey
,
callback
)
{
// eslint-disable-next-line no-alert
if
(
if
(
window
.
confirm
(
s__
(
'
DeployKeys|You are going to remove this deploy key. Are you sure?
'
)))
{
// eslint-disable-next-line no-alert
window
.
confirm
(
s__
(
'
DeployKeys|You are going to remove this deploy key. Are you sure?
'
))
)
{
this
.
service
this
.
service
.
disableKey
(
deployKey
.
id
)
.
disableKey
(
deployKey
.
id
)
.
then
(
this
.
fetchKeys
)
.
then
(
this
.
fetchKeys
)
...
...
app/assets/javascripts/deploy_keys/service/index.js
View file @
dfb08243
...
@@ -8,17 +8,14 @@ export default class DeployKeysService {
...
@@ -8,17 +8,14 @@ export default class DeployKeysService {
}
}
getKeys
()
{
getKeys
()
{
return
this
.
axios
.
get
()
return
this
.
axios
.
get
().
then
(
response
=>
response
.
data
);
.
then
(
response
=>
response
.
data
);
}
}
enableKey
(
id
)
{
enableKey
(
id
)
{
return
this
.
axios
.
put
(
`
${
id
}
/enable`
)
return
this
.
axios
.
put
(
`
${
id
}
/enable`
).
then
(
response
=>
response
.
data
);
.
then
(
response
=>
response
.
data
);
}
}
disableKey
(
id
)
{
disableKey
(
id
)
{
return
this
.
axios
.
put
(
`
${
id
}
/disable`
)
return
this
.
axios
.
put
(
`
${
id
}
/disable`
).
then
(
response
=>
response
.
data
);
.
then
(
response
=>
response
.
data
);
}
}
}
}
app/assets/javascripts/diff.js
View file @
dfb08243
...
@@ -21,9 +21,12 @@ export default class Diff {
...
@@ -21,9 +21,12 @@ export default class Diff {
});
});
const
tab
=
document
.
getElementById
(
'
diffs
'
);
const
tab
=
document
.
getElementById
(
'
diffs
'
);
if
(
!
tab
||
(
tab
&&
tab
.
dataset
&&
tab
.
dataset
.
isLocked
!==
''
))
FilesCommentButton
.
init
(
$diffFile
);
if
(
!
tab
||
(
tab
&&
tab
.
dataset
&&
tab
.
dataset
.
isLocked
!==
''
))
FilesCommentButton
.
init
(
$diffFile
);
const
firstFile
=
$
(
'
.files
'
).
first
().
get
(
0
);
const
firstFile
=
$
(
'
.files
'
)
.
first
()
.
get
(
0
);
const
canCreateNote
=
firstFile
&&
firstFile
.
hasAttribute
(
'
data-can-create-note
'
);
const
canCreateNote
=
firstFile
&&
firstFile
.
hasAttribute
(
'
data-can-create-note
'
);
$diffFile
.
each
((
index
,
file
)
=>
imageDiffHelper
.
initImageDiff
(
file
,
canCreateNote
));
$diffFile
.
each
((
index
,
file
)
=>
imageDiffHelper
.
initImageDiff
(
file
,
canCreateNote
));
...
@@ -73,9 +76,10 @@ export default class Diff {
...
@@ -73,9 +76,10 @@ export default class Diff {
const
view
=
file
.
data
(
'
view
'
);
const
view
=
file
.
data
(
'
view
'
);
const
params
=
{
since
,
to
,
bottom
,
offset
,
unfold
,
view
};
const
params
=
{
since
,
to
,
bottom
,
offset
,
unfold
,
view
};
axios
.
get
(
link
,
{
params
})
axios
.
then
(({
data
})
=>
$target
.
parent
().
replaceWith
(
data
))
.
get
(
link
,
{
params
})
.
catch
(()
=>
flash
(
__
(
'
An error occurred while loading diff
'
)));
.
then
(({
data
})
=>
$target
.
parent
().
replaceWith
(
data
))
.
catch
(()
=>
flash
(
__
(
'
An error occurred while loading diff
'
)));
}
}
openAnchoredDiff
(
cb
)
{
openAnchoredDiff
(
cb
)
{
...
...
app/assets/javascripts/dropzone_input.js
View file @
dfb08243
...
@@ -136,7 +136,7 @@ export default function dropzoneInput(form) {
...
@@ -136,7 +136,7 @@ export default function dropzoneInput(form) {
// removeAllFiles(true) stops uploading files (if any)
// removeAllFiles(true) stops uploading files (if any)
// and remove them from dropzone files queue.
// and remove them from dropzone files queue.
$cancelButton
.
on
(
'
click
'
,
(
e
)
=>
{
$cancelButton
.
on
(
'
click
'
,
e
=>
{
e
.
preventDefault
();
e
.
preventDefault
();
e
.
stopPropagation
();
e
.
stopPropagation
();
Dropzone
.
forElement
(
$formDropzone
.
get
(
0
)).
removeAllFiles
(
true
);
Dropzone
.
forElement
(
$formDropzone
.
get
(
0
)).
removeAllFiles
(
true
);
...
@@ -146,8 +146,10 @@ export default function dropzoneInput(form) {
...
@@ -146,8 +146,10 @@ export default function dropzoneInput(form) {
// clear dropzone files queue, change status of failed files to undefined,
// clear dropzone files queue, change status of failed files to undefined,
// and add that files to the dropzone files queue again.
// and add that files to the dropzone files queue again.
// addFile() adds file to dropzone files queue and upload it.
// addFile() adds file to dropzone files queue and upload it.
$retryLink
.
on
(
'
click
'
,
(
e
)
=>
{
$retryLink
.
on
(
'
click
'
,
e
=>
{
const
dropzoneInstance
=
Dropzone
.
forElement
(
e
.
target
.
closest
(
'
.js-main-target-form
'
).
querySelector
(
'
.div-dropzone
'
));
const
dropzoneInstance
=
Dropzone
.
forElement
(
e
.
target
.
closest
(
'
.js-main-target-form
'
).
querySelector
(
'
.div-dropzone
'
),
);
const
failedFiles
=
dropzoneInstance
.
files
;
const
failedFiles
=
dropzoneInstance
.
files
;
e
.
preventDefault
();
e
.
preventDefault
();
...
@@ -156,7 +158,7 @@ export default function dropzoneInput(form) {
...
@@ -156,7 +158,7 @@ export default function dropzoneInput(form) {
// uploading of files that are being uploaded at the moment.
// uploading of files that are being uploaded at the moment.
dropzoneInstance
.
removeAllFiles
(
true
);
dropzoneInstance
.
removeAllFiles
(
true
);
failedFiles
.
map
(
(
failedFile
)
=>
{
failedFiles
.
map
(
failedFile
=>
{
const
file
=
failedFile
;
const
file
=
failedFile
;
if
(
file
.
status
===
Dropzone
.
ERROR
)
{
if
(
file
.
status
===
Dropzone
.
ERROR
)
{
...
@@ -168,7 +170,7 @@ export default function dropzoneInput(form) {
...
@@ -168,7 +170,7 @@ export default function dropzoneInput(form) {
});
});
});
});
// eslint-disable-next-line consistent-return
// eslint-disable-next-line consistent-return
handlePaste
=
(
event
)
=>
{
handlePaste
=
event
=>
{
const
pasteEvent
=
event
.
originalEvent
;
const
pasteEvent
=
event
.
originalEvent
;
if
(
pasteEvent
.
clipboardData
&&
pasteEvent
.
clipboardData
.
items
)
{
if
(
pasteEvent
.
clipboardData
&&
pasteEvent
.
clipboardData
.
items
)
{
const
image
=
isImage
(
pasteEvent
);
const
image
=
isImage
(
pasteEvent
);
...
@@ -182,7 +184,7 @@ export default function dropzoneInput(form) {
...
@@ -182,7 +184,7 @@ export default function dropzoneInput(form) {
}
}
};
};
isImage
=
(
data
)
=>
{
isImage
=
data
=>
{
let
i
=
0
;
let
i
=
0
;
while
(
i
<
data
.
clipboardData
.
items
.
length
)
{
while
(
i
<
data
.
clipboardData
.
items
.
length
)
{
const
item
=
data
.
clipboardData
.
items
[
i
];
const
item
=
data
.
clipboardData
.
items
[
i
];
...
@@ -203,8 +205,12 @@ export default function dropzoneInput(form) {
...
@@ -203,8 +205,12 @@ export default function dropzoneInput(form) {
const
caretStart
=
textarea
.
selectionStart
;
const
caretStart
=
textarea
.
selectionStart
;
const
caretEnd
=
textarea
.
selectionEnd
;
const
caretEnd
=
textarea
.
selectionEnd
;
const
textEnd
=
$
(
child
).
val
().
length
;
const
textEnd
=
$
(
child
).
val
().
length
;
const
beforeSelection
=
$
(
child
).
val
().
substring
(
0
,
caretStart
);
const
beforeSelection
=
$
(
child
)
const
afterSelection
=
$
(
child
).
val
().
substring
(
caretEnd
,
textEnd
);
.
val
()
.
substring
(
0
,
caretStart
);
const
afterSelection
=
$
(
child
)
.
val
()
.
substring
(
caretEnd
,
textEnd
);
$
(
child
).
val
(
beforeSelection
+
formattedText
+
afterSelection
);
$
(
child
).
val
(
beforeSelection
+
formattedText
+
afterSelection
);
textarea
.
setSelectionRange
(
caretStart
+
formattedText
.
length
,
caretEnd
+
formattedText
.
length
);
textarea
.
setSelectionRange
(
caretStart
+
formattedText
.
length
,
caretEnd
+
formattedText
.
length
);
textarea
.
style
.
height
=
`
${
textarea
.
scrollHeight
}
px`
;
textarea
.
style
.
height
=
`
${
textarea
.
scrollHeight
}
px`
;
...
@@ -212,11 +218,11 @@ export default function dropzoneInput(form) {
...
@@ -212,11 +218,11 @@ export default function dropzoneInput(form) {
return
formTextarea
.
trigger
(
'
input
'
);
return
formTextarea
.
trigger
(
'
input
'
);
};
};
addFileToForm
=
(
path
)
=>
{
addFileToForm
=
path
=>
{
$
(
form
).
append
(
`<input type="hidden" name="files[]" value="
${
_
.
escape
(
path
)}
">`
);
$
(
form
).
append
(
`<input type="hidden" name="files[]" value="
${
_
.
escape
(
path
)}
">`
);
};
};
getFilename
=
(
e
)
=>
{
getFilename
=
e
=>
{
let
value
;
let
value
;
if
(
window
.
clipboardData
&&
window
.
clipboardData
.
getData
)
{
if
(
window
.
clipboardData
&&
window
.
clipboardData
.
getData
)
{
value
=
window
.
clipboardData
.
getData
(
'
Text
'
);
value
=
window
.
clipboardData
.
getData
(
'
Text
'
);
...
@@ -231,7 +237,7 @@ export default function dropzoneInput(form) {
...
@@ -231,7 +237,7 @@ export default function dropzoneInput(form) {
const
closeSpinner
=
()
=>
$uploadingProgressContainer
.
addClass
(
'
hide
'
);
const
closeSpinner
=
()
=>
$uploadingProgressContainer
.
addClass
(
'
hide
'
);
const
showError
=
(
message
)
=>
{
const
showError
=
message
=>
{
$uploadingErrorContainer
.
removeClass
(
'
hide
'
);
$uploadingErrorContainer
.
removeClass
(
'
hide
'
);
$uploadingErrorMessage
.
html
(
message
);
$uploadingErrorMessage
.
html
(
message
);
};
};
...
@@ -252,14 +258,15 @@ export default function dropzoneInput(form) {
...
@@ -252,14 +258,15 @@ export default function dropzoneInput(form) {
showSpinner
();
showSpinner
();
closeAlertMessage
();
closeAlertMessage
();
axios
.
post
(
uploadsPath
,
formData
)
axios
.
post
(
uploadsPath
,
formData
)
.
then
(({
data
})
=>
{
.
then
(({
data
})
=>
{
const
md
=
data
.
link
.
markdown
;
const
md
=
data
.
link
.
markdown
;
insertToTextArea
(
filename
,
md
);
insertToTextArea
(
filename
,
md
);
closeSpinner
();
closeSpinner
();
})
})
.
catch
(
(
e
)
=>
{
.
catch
(
e
=>
{
showError
(
e
.
response
.
data
.
message
);
showError
(
e
.
response
.
data
.
message
);
closeSpinner
();
closeSpinner
();
});
});
...
@@ -267,7 +274,8 @@ export default function dropzoneInput(form) {
...
@@ -267,7 +274,8 @@ export default function dropzoneInput(form) {
updateAttachingMessage
=
(
files
,
messageContainer
)
=>
{
updateAttachingMessage
=
(
files
,
messageContainer
)
=>
{
let
attachingMessage
;
let
attachingMessage
;
const
filesCount
=
files
.
filter
(
file
=>
file
.
status
===
'
uploading
'
||
file
.
status
===
'
queued
'
).
length
;
const
filesCount
=
files
.
filter
(
file
=>
file
.
status
===
'
uploading
'
||
file
.
status
===
'
queued
'
)
.
length
;
// Dinamycally change uploading files text depending on files number in
// Dinamycally change uploading files text depending on files number in
// dropzone files queue.
// dropzone files queue.
...
@@ -282,7 +290,10 @@ export default function dropzoneInput(form) {
...
@@ -282,7 +290,10 @@ export default function dropzoneInput(form) {
form
.
find
(
'
.markdown-selector
'
).
click
(
function
onMarkdownClick
(
e
)
{
form
.
find
(
'
.markdown-selector
'
).
click
(
function
onMarkdownClick
(
e
)
{
e
.
preventDefault
();
e
.
preventDefault
();
$
(
this
).
closest
(
'
.gfm-form
'
).
find
(
'
.div-dropzone
'
).
click
();
$
(
this
)
.
closest
(
'
.gfm-form
'
)
.
find
(
'
.div-dropzone
'
)
.
click
();
formTextarea
.
focus
();
formTextarea
.
focus
();
});
});
...
...
app/assets/javascripts/emoji/support/is_emoji_unicode_supported.js
View file @
dfb08243
...
@@ -13,9 +13,11 @@ const rainbowCodePoint = 127752; // parseInt('1F308', 16)
...
@@ -13,9 +13,11 @@ const rainbowCodePoint = 127752; // parseInt('1F308', 16)
function
isRainbowFlagEmoji
(
emojiUnicode
)
{
function
isRainbowFlagEmoji
(
emojiUnicode
)
{
const
characters
=
Array
.
from
(
emojiUnicode
);
const
characters
=
Array
.
from
(
emojiUnicode
);
// Length 4 because flags are made of 2 characters which are surrogate pairs
// Length 4 because flags are made of 2 characters which are surrogate pairs
return
emojiUnicode
.
length
===
4
&&
return
(
emojiUnicode
.
length
===
4
&&
characters
[
0
].
codePointAt
(
0
)
===
baseFlagCodePoint
&&
characters
[
0
].
codePointAt
(
0
)
===
baseFlagCodePoint
&&
characters
[
1
].
codePointAt
(
0
)
===
rainbowCodePoint
;
characters
[
1
].
codePointAt
(
0
)
===
rainbowCodePoint
);
}
}
// Chrome <57 renders keycaps oddly
// Chrome <57 renders keycaps oddly
...
@@ -26,22 +28,28 @@ function isKeycapEmoji(emojiUnicode) {
...
@@ -26,22 +28,28 @@ function isKeycapEmoji(emojiUnicode) {
}
}
// Check for a skin tone variation emoji which aren't always supported
// Check for a skin tone variation emoji which aren't always supported
const
tone1
=
127995
;
// parseInt('1F3FB', 16)
const
tone1
=
127995
;
// parseInt('1F3FB', 16)
const
tone5
=
127999
;
// parseInt('1F3FF', 16)
const
tone5
=
127999
;
// parseInt('1F3FF', 16)
function
isSkinToneComboEmoji
(
emojiUnicode
)
{
function
isSkinToneComboEmoji
(
emojiUnicode
)
{
return
emojiUnicode
.
length
>
2
&&
Array
.
from
(
emojiUnicode
).
some
((
char
)
=>
{
return
(
const
cp
=
char
.
codePointAt
(
0
);
emojiUnicode
.
length
>
2
&&
return
cp
>=
tone1
&&
cp
<=
tone5
;
Array
.
from
(
emojiUnicode
).
some
(
char
=>
{
});
const
cp
=
char
.
codePointAt
(
0
);
return
cp
>=
tone1
&&
cp
<=
tone5
;
})
);
}
}
// macOS supports most skin tone emoji's but
// macOS supports most skin tone emoji's but
// doesn't support the skin tone versions of horse racing
// doesn't support the skin tone versions of horse racing
const
horseRacingCodePoint
=
127943
;
// parseInt('1F3C7', 16)
const
horseRacingCodePoint
=
127943
;
// parseInt('1F3C7', 16)
function
isHorceRacingSkinToneComboEmoji
(
emojiUnicode
)
{
function
isHorceRacingSkinToneComboEmoji
(
emojiUnicode
)
{
const
firstCharacter
=
Array
.
from
(
emojiUnicode
)[
0
];
const
firstCharacter
=
Array
.
from
(
emojiUnicode
)[
0
];
return
firstCharacter
&&
firstCharacter
.
codePointAt
(
0
)
===
horseRacingCodePoint
&&
return
(
isSkinToneComboEmoji
(
emojiUnicode
);
firstCharacter
&&
firstCharacter
.
codePointAt
(
0
)
===
horseRacingCodePoint
&&
isSkinToneComboEmoji
(
emojiUnicode
)
);
}
}
// Check for `family_*`, `kiss_*`, `couple_*`
// Check for `family_*`, `kiss_*`, `couple_*`
...
@@ -52,7 +60,7 @@ const personEndCodePoint = 128105; // parseInt('1F469', 16)
...
@@ -52,7 +60,7 @@ const personEndCodePoint = 128105; // parseInt('1F469', 16)
function
isPersonZwjEmoji
(
emojiUnicode
)
{
function
isPersonZwjEmoji
(
emojiUnicode
)
{
let
hasPersonEmoji
=
false
;
let
hasPersonEmoji
=
false
;
let
hasZwj
=
false
;
let
hasZwj
=
false
;
Array
.
from
(
emojiUnicode
).
forEach
(
(
character
)
=>
{
Array
.
from
(
emojiUnicode
).
forEach
(
character
=>
{
const
cp
=
character
.
codePointAt
(
0
);
const
cp
=
character
.
codePointAt
(
0
);
if
(
cp
===
zwj
)
{
if
(
cp
===
zwj
)
{
hasZwj
=
true
;
hasZwj
=
true
;
...
@@ -80,10 +88,7 @@ function checkFlagEmojiSupport(unicodeSupportMap, emojiUnicode) {
...
@@ -80,10 +88,7 @@ function checkFlagEmojiSupport(unicodeSupportMap, emojiUnicode) {
// in `isEmojiUnicodeSupported` logic
// in `isEmojiUnicodeSupported` logic
function
checkSkinToneModifierSupport
(
unicodeSupportMap
,
emojiUnicode
)
{
function
checkSkinToneModifierSupport
(
unicodeSupportMap
,
emojiUnicode
)
{
const
isSkinToneResult
=
isSkinToneComboEmoji
(
emojiUnicode
);
const
isSkinToneResult
=
isSkinToneComboEmoji
(
emojiUnicode
);
return
(
return
(
unicodeSupportMap
.
skinToneModifier
&&
isSkinToneResult
)
||
!
isSkinToneResult
;
(
unicodeSupportMap
.
skinToneModifier
&&
isSkinToneResult
)
||
!
isSkinToneResult
);
}
}
// Helper func so we don't have to run `isHorceRacingSkinToneComboEmoji` twice
// Helper func so we don't have to run `isHorceRacingSkinToneComboEmoji` twice
...
@@ -91,8 +96,7 @@ function checkSkinToneModifierSupport(unicodeSupportMap, emojiUnicode) {
...
@@ -91,8 +96,7 @@ function checkSkinToneModifierSupport(unicodeSupportMap, emojiUnicode) {
function
checkHorseRacingSkinToneComboEmojiSupport
(
unicodeSupportMap
,
emojiUnicode
)
{
function
checkHorseRacingSkinToneComboEmojiSupport
(
unicodeSupportMap
,
emojiUnicode
)
{
const
isHorseRacingSkinToneResult
=
isHorceRacingSkinToneComboEmoji
(
emojiUnicode
);
const
isHorseRacingSkinToneResult
=
isHorceRacingSkinToneComboEmoji
(
emojiUnicode
);
return
(
return
(
(
unicodeSupportMap
.
horseRacing
&&
isHorseRacingSkinToneResult
)
||
(
unicodeSupportMap
.
horseRacing
&&
isHorseRacingSkinToneResult
)
||
!
isHorseRacingSkinToneResult
!
isHorseRacingSkinToneResult
);
);
}
}
...
@@ -100,10 +104,7 @@ function checkHorseRacingSkinToneComboEmojiSupport(unicodeSupportMap, emojiUnico
...
@@ -100,10 +104,7 @@ function checkHorseRacingSkinToneComboEmojiSupport(unicodeSupportMap, emojiUnico
// in `isEmojiUnicodeSupported` logic
// in `isEmojiUnicodeSupported` logic
function
checkPersonEmojiSupport
(
unicodeSupportMap
,
emojiUnicode
)
{
function
checkPersonEmojiSupport
(
unicodeSupportMap
,
emojiUnicode
)
{
const
isPersonZwjResult
=
isPersonZwjEmoji
(
emojiUnicode
);
const
isPersonZwjResult
=
isPersonZwjEmoji
(
emojiUnicode
);
return
(
return
(
unicodeSupportMap
.
personZwj
&&
isPersonZwjResult
)
||
!
isPersonZwjResult
;
(
unicodeSupportMap
.
personZwj
&&
isPersonZwjResult
)
||
!
isPersonZwjResult
);
}
}
// Takes in a support map and determines whether
// Takes in a support map and determines whether
...
@@ -111,16 +112,20 @@ function checkPersonEmojiSupport(unicodeSupportMap, emojiUnicode) {
...
@@ -111,16 +112,20 @@ function checkPersonEmojiSupport(unicodeSupportMap, emojiUnicode) {
//
//
// Combines all the edge case tests into a one-stop shop method
// Combines all the edge case tests into a one-stop shop method
function
isEmojiUnicodeSupported
(
unicodeSupportMap
=
{},
emojiUnicode
,
unicodeVersion
)
{
function
isEmojiUnicodeSupported
(
unicodeSupportMap
=
{},
emojiUnicode
,
unicodeVersion
)
{
const
isOlderThanChrome57
=
unicodeSupportMap
.
meta
&&
unicodeSupportMap
.
meta
.
isChrome
&&
const
isOlderThanChrome57
=
unicodeSupportMap
.
meta
&&
unicodeSupportMap
.
meta
.
isChrome
&&
unicodeSupportMap
.
meta
.
chromeVersion
<
57
;
unicodeSupportMap
.
meta
.
chromeVersion
<
57
;
// For comments about each scenario, see the comments above each individual respective function
// For comments about each scenario, see the comments above each individual respective function
return
unicodeSupportMap
[
unicodeVersion
]
&&
return
(
unicodeSupportMap
[
unicodeVersion
]
&&
!
(
isOlderThanChrome57
&&
isKeycapEmoji
(
emojiUnicode
))
&&
!
(
isOlderThanChrome57
&&
isKeycapEmoji
(
emojiUnicode
))
&&
checkFlagEmojiSupport
(
unicodeSupportMap
,
emojiUnicode
)
&&
checkFlagEmojiSupport
(
unicodeSupportMap
,
emojiUnicode
)
&&
checkSkinToneModifierSupport
(
unicodeSupportMap
,
emojiUnicode
)
&&
checkSkinToneModifierSupport
(
unicodeSupportMap
,
emojiUnicode
)
&&
checkHorseRacingSkinToneComboEmojiSupport
(
unicodeSupportMap
,
emojiUnicode
)
&&
checkHorseRacingSkinToneComboEmojiSupport
(
unicodeSupportMap
,
emojiUnicode
)
&&
checkPersonEmojiSupport
(
unicodeSupportMap
,
emojiUnicode
);
checkPersonEmojiSupport
(
unicodeSupportMap
,
emojiUnicode
)
);
}
}
export
{
export
{
...
...
app/assets/javascripts/experimental_flags.js
View file @
dfb08243
...
@@ -2,7 +2,7 @@ import $ from 'jquery';
...
@@ -2,7 +2,7 @@ import $ from 'jquery';
import
Cookies
from
'
js-cookie
'
;
import
Cookies
from
'
js-cookie
'
;
export
default
()
=>
{
export
default
()
=>
{
$
(
'
.js-experiment-feature-toggle
'
).
on
(
'
change
'
,
(
e
)
=>
{
$
(
'
.js-experiment-feature-toggle
'
).
on
(
'
change
'
,
e
=>
{
const
el
=
e
.
target
;
const
el
=
e
.
target
;
Cookies
.
set
(
el
.
name
,
el
.
value
,
{
Cookies
.
set
(
el
.
name
,
el
.
value
,
{
...
...
app/assets/javascripts/files_comment_button.js
View file @
dfb08243
...
@@ -25,13 +25,15 @@ export default {
...
@@ -25,13 +25,15 @@ export default {
if
(
!
this
.
userCanCreateNote
)
{
if
(
!
this
.
userCanCreateNote
)
{
// data-can-create-note is an empty string when true, otherwise undefined
// data-can-create-note is an empty string when true, otherwise undefined
this
.
userCanCreateNote
=
$diffFile
.
closest
(
DIFF_CONTAINER_SELECTOR
).
data
(
'
canCreateNote
'
)
===
''
;
this
.
userCanCreateNote
=
$diffFile
.
closest
(
DIFF_CONTAINER_SELECTOR
).
data
(
'
canCreateNote
'
)
===
''
;
}
}
this
.
isParallelView
=
Cookies
.
get
(
'
diff_view
'
)
===
'
parallel
'
;
this
.
isParallelView
=
Cookies
.
get
(
'
diff_view
'
)
===
'
parallel
'
;
if
(
this
.
userCanCreateNote
)
{
if
(
this
.
userCanCreateNote
)
{
$diffFile
.
on
(
'
mouseover
'
,
LINE_COLUMN_CLASSES
,
e
=>
this
.
showButton
(
this
.
isParallelView
,
e
))
$diffFile
.
on
(
'
mouseover
'
,
LINE_COLUMN_CLASSES
,
e
=>
this
.
showButton
(
this
.
isParallelView
,
e
))
.
on
(
'
mouseleave
'
,
LINE_COLUMN_CLASSES
,
e
=>
this
.
hideButton
(
this
.
isParallelView
,
e
));
.
on
(
'
mouseleave
'
,
LINE_COLUMN_CLASSES
,
e
=>
this
.
hideButton
(
this
.
isParallelView
,
e
));
}
}
},
},
...
@@ -64,9 +66,11 @@ export default {
...
@@ -64,9 +66,11 @@ export default {
},
},
validateButtonParent
(
buttonParentElement
)
{
validateButtonParent
(
buttonParentElement
)
{
return
!
buttonParentElement
.
classList
.
contains
(
EMPTY_CELL_CLASS
)
&&
return
(
!
buttonParentElement
.
classList
.
contains
(
EMPTY_CELL_CLASS
)
&&
!
buttonParentElement
.
classList
.
contains
(
UNFOLDABLE_LINE_CLASS
)
&&
!
buttonParentElement
.
classList
.
contains
(
UNFOLDABLE_LINE_CLASS
)
&&
!
buttonParentElement
.
classList
.
contains
(
NO_COMMENT_CLASS
)
&&
!
buttonParentElement
.
classList
.
contains
(
NO_COMMENT_CLASS
)
&&
!
buttonParentElement
.
parentNode
.
classList
.
contains
(
DIFF_EXPANDED_CLASS
);
!
buttonParentElement
.
parentNode
.
classList
.
contains
(
DIFF_EXPANDED_CLASS
)
);
},
},
};
};
app/assets/javascripts/filterable_list.js
View file @
dfb08243
...
@@ -65,12 +65,15 @@ export default class FilterableList {
...
@@ -65,12 +65,15 @@ export default class FilterableList {
this
.
isBusy
=
true
;
this
.
isBusy
=
true
;
return
axios
.
get
(
this
.
getFilterEndpoint
(),
{
return
axios
params
,
.
get
(
this
.
getFilterEndpoint
(),
{
}).
then
((
res
)
=>
{
params
,
this
.
onFilterSuccess
(
res
,
params
);
})
this
.
onFilterComplete
();
.
then
(
res
=>
{
}).
catch
(()
=>
this
.
onFilterComplete
());
this
.
onFilterSuccess
(
res
,
params
);
this
.
onFilterComplete
();
})
.
catch
(()
=>
this
.
onFilterComplete
());
}
}
onFilterSuccess
(
response
,
queryData
)
{
onFilterSuccess
(
response
,
queryData
)
{
...
@@ -81,9 +84,13 @@ export default class FilterableList {
...
@@ -81,9 +84,13 @@ export default class FilterableList {
// Change url so if user reload a page - search results are saved
// Change url so if user reload a page - search results are saved
const
currentPath
=
this
.
getPagePath
(
queryData
);
const
currentPath
=
this
.
getPagePath
(
queryData
);
return
window
.
history
.
replaceState
({
return
window
.
history
.
replaceState
(
page
:
currentPath
,
{
},
document
.
title
,
currentPath
);
page
:
currentPath
,
},
document
.
title
,
currentPath
,
);
}
}
onFilterComplete
()
{
onFilterComplete
()
{
...
...
app/assets/javascripts/flash.js
View file @
dfb08243
...
@@ -8,14 +8,19 @@ const hideFlash = (flashEl, fadeTransition = true) => {
...
@@ -8,14 +8,19 @@ const hideFlash = (flashEl, fadeTransition = true) => {
});
});
}
}
flashEl
.
addEventListener
(
'
transitionend
'
,
()
=>
{
flashEl
.
addEventListener
(
flashEl
.
remove
();
'
transitionend
'
,
window
.
dispatchEvent
(
new
Event
(
'
resize
'
));
()
=>
{
if
(
document
.
body
.
classList
.
contains
(
'
flash-shown
'
))
document
.
body
.
classList
.
remove
(
'
flash-shown
'
);
flashEl
.
remove
();
},
{
window
.
dispatchEvent
(
new
Event
(
'
resize
'
));
once
:
true
,
if
(
document
.
body
.
classList
.
contains
(
'
flash-shown
'
))
passive
:
true
,
document
.
body
.
classList
.
remove
(
'
flash-shown
'
);
});
},
{
once
:
true
,
passive
:
true
,
},
);
if
(
!
fadeTransition
)
flashEl
.
dispatchEvent
(
new
Event
(
'
transitionend
'
));
if
(
!
fadeTransition
)
flashEl
.
dispatchEvent
(
new
Event
(
'
transitionend
'
));
};
};
...
@@ -84,7 +89,9 @@ const createFlash = function createFlash(
...
@@ -84,7 +89,9 @@ const createFlash = function createFlash(
flashEl
.
innerHTML
+=
createAction
(
actionConfig
);
flashEl
.
innerHTML
+=
createAction
(
actionConfig
);
if
(
actionConfig
.
clickHandler
)
{
if
(
actionConfig
.
clickHandler
)
{
flashEl
.
querySelector
(
'
.flash-action
'
).
addEventListener
(
'
click
'
,
e
=>
actionConfig
.
clickHandler
(
e
));
flashEl
.
querySelector
(
'
.flash-action
'
)
.
addEventListener
(
'
click
'
,
e
=>
actionConfig
.
clickHandler
(
e
));
}
}
}
}
...
@@ -95,11 +102,5 @@ const createFlash = function createFlash(
...
@@ -95,11 +102,5 @@ const createFlash = function createFlash(
return
flashContainer
;
return
flashContainer
;
};
};
export
{
export
{
createFlash
as
default
,
createFlashEl
,
createAction
,
hideFlash
,
removeFlashClickListener
};
createFlash
as
default
,
createFlashEl
,
createAction
,
hideFlash
,
removeFlashClickListener
,
};
window
.
Flash
=
createFlash
;
window
.
Flash
=
createFlash
;
app/assets/javascripts/fly_out_nav.js
View file @
dfb08243
...
@@ -11,9 +11,13 @@ let sidebar;
...
@@ -11,9 +11,13 @@ let sidebar;
export
const
mousePos
=
[];
export
const
mousePos
=
[];
export
const
setSidebar
=
(
el
)
=>
{
sidebar
=
el
;
};
export
const
setSidebar
=
el
=>
{
sidebar
=
el
;
};
export
const
getOpenMenu
=
()
=>
currentOpenMenu
;
export
const
getOpenMenu
=
()
=>
currentOpenMenu
;
export
const
setOpenMenu
=
(
menu
=
null
)
=>
{
currentOpenMenu
=
menu
;
};
export
const
setOpenMenu
=
(
menu
=
null
)
=>
{
currentOpenMenu
=
menu
;
};
export
const
slope
=
(
a
,
b
)
=>
(
b
.
y
-
a
.
y
)
/
(
b
.
x
-
a
.
x
);
export
const
slope
=
(
a
,
b
)
=>
(
b
.
y
-
a
.
y
)
/
(
b
.
x
-
a
.
x
);
...
@@ -21,9 +25,10 @@ let headerHeight = 50;
...
@@ -21,9 +25,10 @@ let headerHeight = 50;
export
const
getHeaderHeight
=
()
=>
headerHeight
;
export
const
getHeaderHeight
=
()
=>
headerHeight
;
export
const
isSidebarCollapsed
=
()
=>
sidebar
&&
sidebar
.
classList
.
contains
(
'
sidebar-collapsed-desktop
'
);
export
const
isSidebarCollapsed
=
()
=>
sidebar
&&
sidebar
.
classList
.
contains
(
'
sidebar-collapsed-desktop
'
);
export
const
canShowActiveSubItems
=
(
el
)
=>
{
export
const
canShowActiveSubItems
=
el
=>
{
if
(
el
.
classList
.
contains
(
'
active
'
)
&&
!
isSidebarCollapsed
())
{
if
(
el
.
classList
.
contains
(
'
active
'
)
&&
!
isSidebarCollapsed
())
{
return
false
;
return
false
;
}
}
...
@@ -31,7 +36,10 @@ export const canShowActiveSubItems = (el) => {
...
@@ -31,7 +36,10 @@ export const canShowActiveSubItems = (el) => {
return
true
;
return
true
;
};
};
export
const
canShowSubItems
=
()
=>
bp
.
getBreakpointSize
()
===
'
sm
'
||
bp
.
getBreakpointSize
()
===
'
md
'
||
bp
.
getBreakpointSize
()
===
'
lg
'
;
export
const
canShowSubItems
=
()
=>
bp
.
getBreakpointSize
()
===
'
sm
'
||
bp
.
getBreakpointSize
()
===
'
md
'
||
bp
.
getBreakpointSize
()
===
'
lg
'
;
export
const
getHideSubItemsInterval
=
()
=>
{
export
const
getHideSubItemsInterval
=
()
=>
{
if
(
!
currentOpenMenu
||
!
mousePos
.
length
)
return
0
;
if
(
!
currentOpenMenu
||
!
mousePos
.
length
)
return
0
;
...
@@ -41,11 +49,12 @@ export const getHideSubItemsInterval = () => {
...
@@ -41,11 +49,12 @@ export const getHideSubItemsInterval = () => {
const
currentMousePosY
=
currentMousePos
.
y
;
const
currentMousePosY
=
currentMousePos
.
y
;
const
[
menuTop
,
menuBottom
]
=
menuCornerLocs
;
const
[
menuTop
,
menuBottom
]
=
menuCornerLocs
;
if
(
currentMousePosY
<
menuTop
.
y
||
if
(
currentMousePosY
<
menuTop
.
y
||
currentMousePosY
>
menuBottom
.
y
)
return
0
;
currentMousePosY
>
menuBottom
.
y
)
return
0
;
if
(
slope
(
prevMousePos
,
menuBottom
)
<
slope
(
currentMousePos
,
menuBottom
)
&&
if
(
slope
(
prevMousePos
,
menuTop
)
>
slope
(
currentMousePos
,
menuTop
))
{
slope
(
prevMousePos
,
menuBottom
)
<
slope
(
currentMousePos
,
menuBottom
)
&&
slope
(
prevMousePos
,
menuTop
)
>
slope
(
currentMousePos
,
menuTop
)
)
{
return
HIDE_INTERVAL_TIMEOUT
;
return
HIDE_INTERVAL_TIMEOUT
;
}
}
...
@@ -56,11 +65,12 @@ export const calculateTop = (boundingRect, outerHeight) => {
...
@@ -56,11 +65,12 @@ export const calculateTop = (boundingRect, outerHeight) => {
const
windowHeight
=
window
.
innerHeight
;
const
windowHeight
=
window
.
innerHeight
;
const
bottomOverflow
=
windowHeight
-
(
boundingRect
.
top
+
outerHeight
);
const
bottomOverflow
=
windowHeight
-
(
boundingRect
.
top
+
outerHeight
);
return
bottomOverflow
<
0
?
(
boundingRect
.
top
-
outerHeight
)
+
boundingRect
.
height
:
return
bottomOverflow
<
0
boundingRect
.
top
;
?
boundingRect
.
top
-
outerHeight
+
boundingRect
.
height
:
boundingRect
.
top
;
};
};
export
const
hideMenu
=
(
el
)
=>
{
export
const
hideMenu
=
el
=>
{
if
(
!
el
)
return
;
if
(
!
el
)
return
;
const
parentEl
=
el
.
parentNode
;
const
parentEl
=
el
.
parentNode
;
...
@@ -101,7 +111,7 @@ export const moveSubItemsToPosition = (el, subItems) => {
...
@@ -101,7 +111,7 @@ export const moveSubItemsToPosition = (el, subItems) => {
}
}
};
};
export
const
showSubLevelItems
=
(
el
)
=>
{
export
const
showSubLevelItems
=
el
=>
{
const
subItems
=
el
.
querySelector
(
'
.sidebar-sub-level-items
'
);
const
subItems
=
el
.
querySelector
(
'
.sidebar-sub-level-items
'
);
const
isIconOnly
=
subItems
&&
subItems
.
classList
.
contains
(
'
is-fly-out-only
'
);
const
isIconOnly
=
subItems
&&
subItems
.
classList
.
contains
(
'
is-fly-out-only
'
);
...
@@ -128,16 +138,20 @@ export const mouseEnterTopItems = (el, timeout = getHideSubItemsInterval()) => {
...
@@ -128,16 +138,20 @@ export const mouseEnterTopItems = (el, timeout = getHideSubItemsInterval()) => {
},
timeout
);
},
timeout
);
};
};
export
const
mouseLeaveTopItem
=
(
el
)
=>
{
export
const
mouseLeaveTopItem
=
el
=>
{
const
subItems
=
el
.
querySelector
(
'
.sidebar-sub-level-items
'
);
const
subItems
=
el
.
querySelector
(
'
.sidebar-sub-level-items
'
);
if
(
!
canShowSubItems
()
||
!
canShowActiveSubItems
(
el
)
||
if
(
(
subItems
&&
subItems
===
currentOpenMenu
))
return
;
!
canShowSubItems
()
||
!
canShowActiveSubItems
(
el
)
||
(
subItems
&&
subItems
===
currentOpenMenu
)
)
return
;
el
.
classList
.
remove
(
IS_OVER_CLASS
);
el
.
classList
.
remove
(
IS_OVER_CLASS
);
};
};
export
const
documentMouseMove
=
(
e
)
=>
{
export
const
documentMouseMove
=
e
=>
{
mousePos
.
push
({
mousePos
.
push
({
x
:
e
.
clientX
,
x
:
e
.
clientX
,
y
:
e
.
clientY
,
y
:
e
.
clientY
,
...
@@ -146,7 +160,7 @@ export const documentMouseMove = (e) => {
...
@@ -146,7 +160,7 @@ export const documentMouseMove = (e) => {
if
(
mousePos
.
length
>
6
)
mousePos
.
shift
();
if
(
mousePos
.
length
>
6
)
mousePos
.
shift
();
};
};
export
const
subItemsMouseLeave
=
(
relatedTarget
)
=>
{
export
const
subItemsMouseLeave
=
relatedTarget
=>
{
clearTimeout
(
timeoutId
);
clearTimeout
(
timeoutId
);
if
(
relatedTarget
&&
!
relatedTarget
.
closest
(
`.
${
IS_OVER_CLASS
}
`
))
{
if
(
relatedTarget
&&
!
relatedTarget
.
closest
(
`.
${
IS_OVER_CLASS
}
`
))
{
...
@@ -174,7 +188,7 @@ export default () => {
...
@@ -174,7 +188,7 @@ export default () => {
headerHeight
=
document
.
querySelector
(
'
.nav-sidebar
'
).
offsetTop
;
headerHeight
=
document
.
querySelector
(
'
.nav-sidebar
'
).
offsetTop
;
items
.
forEach
(
(
el
)
=>
{
items
.
forEach
(
el
=>
{
const
subItems
=
el
.
querySelector
(
'
.sidebar-sub-level-items
'
);
const
subItems
=
el
.
querySelector
(
'
.sidebar-sub-level-items
'
);
if
(
subItems
)
{
if
(
subItems
)
{
...
...
app/assets/javascripts/gl_field_error.js
View file @
dfb08243
...
@@ -116,7 +116,8 @@ export default class GlFieldError {
...
@@ -116,7 +116,8 @@ export default class GlFieldError {
this
.
form
.
focusOnFirstInvalid
.
apply
(
this
.
form
);
this
.
form
.
focusOnFirstInvalid
.
apply
(
this
.
form
);
// For UX, wait til after first invalid submission to check each keyup
// For UX, wait til after first invalid submission to check each keyup
this
.
inputElement
.
off
(
'
keyup.fieldValidator
'
)
this
.
inputElement
.
off
(
'
keyup.fieldValidator
'
)
.
on
(
'
keyup.fieldValidator
'
,
this
.
updateValidity
.
bind
(
this
));
.
on
(
'
keyup.fieldValidator
'
,
this
.
updateValidity
.
bind
(
this
));
}
}
...
...
app/assets/javascripts/gl_field_errors.js
View file @
dfb08243
...
@@ -16,9 +16,12 @@ export default class GlFieldErrors {
...
@@ -16,9 +16,12 @@ export default class GlFieldErrors {
initValidators
()
{
initValidators
()
{
// register selectors here as needed
// register selectors here as needed
const
validateSelectors
=
[
'
:text
'
,
'
:password
'
,
'
[type=email]
'
]
const
validateSelectors
=
[
'
:text
'
,
'
:password
'
,
'
[type=email]
'
]
.
map
(
selector
=>
`input
${
selector
}
`
).
join
(
'
,
'
);
.
map
(
selector
=>
`input
${
selector
}
`
)
.
join
(
'
,
'
);
this
.
state
.
inputs
=
this
.
form
.
find
(
validateSelectors
).
toArray
()
this
.
state
.
inputs
=
this
.
form
.
find
(
validateSelectors
)
.
toArray
()
.
filter
(
input
=>
!
input
.
classList
.
contains
(
customValidationFlag
))
.
filter
(
input
=>
!
input
.
classList
.
contains
(
customValidationFlag
))
.
map
(
input
=>
new
GlFieldError
({
input
,
formErrors
:
this
}));
.
map
(
input
=>
new
GlFieldError
({
input
,
formErrors
:
this
}));
...
@@ -42,7 +45,7 @@ export default class GlFieldErrors {
...
@@ -42,7 +45,7 @@ export default class GlFieldErrors {
/* Public method for triggering validity updates manually */
/* Public method for triggering validity updates manually */
updateFormValidityState
()
{
updateFormValidityState
()
{
this
.
state
.
inputs
.
forEach
(
(
field
)
=>
{
this
.
state
.
inputs
.
forEach
(
field
=>
{
if
(
field
.
state
.
submitted
)
{
if
(
field
.
state
.
submitted
)
{
field
.
updateValidity
();
field
.
updateValidity
();
}
}
...
@@ -50,8 +53,9 @@ export default class GlFieldErrors {
...
@@ -50,8 +53,9 @@ export default class GlFieldErrors {
}
}
focusOnFirstInvalid
()
{
focusOnFirstInvalid
()
{
const
firstInvalid
=
this
.
state
.
inputs
const
firstInvalid
=
this
.
state
.
inputs
.
filter
(
.
filter
(
input
=>
!
input
.
inputDomElement
.
validity
.
valid
)[
0
];
input
=>
!
input
.
inputDomElement
.
validity
.
valid
,
)[
0
];
firstInvalid
.
inputElement
.
focus
();
firstInvalid
.
inputElement
.
focus
();
}
}
}
}
app/assets/javascripts/gl_form.js
View file @
dfb08243
...
@@ -39,7 +39,10 @@ export default class GLForm {
...
@@ -39,7 +39,10 @@ export default class GLForm {
this
.
form
.
find
(
'
.div-dropzone
'
).
remove
();
this
.
form
.
find
(
'
.div-dropzone
'
).
remove
();
this
.
form
.
addClass
(
'
gfm-form
'
);
this
.
form
.
addClass
(
'
gfm-form
'
);
// remove notify commit author checkbox for non-commit notes
// remove notify commit author checkbox for non-commit notes
gl
.
utils
.
disableButtonIfEmptyField
(
this
.
form
.
find
(
'
.js-note-text
'
),
this
.
form
.
find
(
'
.js-comment-button, .js-note-new-discussion
'
));
gl
.
utils
.
disableButtonIfEmptyField
(
this
.
form
.
find
(
'
.js-note-text
'
),
this
.
form
.
find
(
'
.js-comment-button, .js-note-new-discussion
'
),
);
this
.
autoComplete
=
new
GfmAutoComplete
(
gl
.
GfmAutoComplete
&&
gl
.
GfmAutoComplete
.
dataSources
);
this
.
autoComplete
=
new
GfmAutoComplete
(
gl
.
GfmAutoComplete
&&
gl
.
GfmAutoComplete
.
dataSources
);
this
.
autoComplete
.
setup
(
this
.
form
.
find
(
'
.js-gfm-input
'
),
this
.
enableGFM
);
this
.
autoComplete
.
setup
(
this
.
form
.
find
(
'
.js-gfm-input
'
),
this
.
enableGFM
);
dropzoneInput
(
this
.
form
);
dropzoneInput
(
this
.
form
);
...
@@ -55,11 +58,9 @@ export default class GLForm {
...
@@ -55,11 +58,9 @@ export default class GLForm {
}
}
setupAutosize
()
{
setupAutosize
()
{
this
.
textarea
.
off
(
'
autosize:resized
'
)
this
.
textarea
.
off
(
'
autosize:resized
'
).
on
(
'
autosize:resized
'
,
this
.
setHeightData
.
bind
(
this
));
.
on
(
'
autosize:resized
'
,
this
.
setHeightData
.
bind
(
this
));
this
.
textarea
.
off
(
'
mouseup.autosize
'
)
this
.
textarea
.
off
(
'
mouseup.autosize
'
).
on
(
'
mouseup.autosize
'
,
this
.
destroyAutosize
.
bind
(
this
));
.
on
(
'
mouseup.autosize
'
,
this
.
destroyAutosize
.
bind
(
this
));
setTimeout
(()
=>
{
setTimeout
(()
=>
{
autosize
(
this
.
textarea
);
autosize
(
this
.
textarea
);
...
@@ -91,10 +92,14 @@ export default class GLForm {
...
@@ -91,10 +92,14 @@ export default class GLForm {
addEventListeners
()
{
addEventListeners
()
{
this
.
textarea
.
on
(
'
focus
'
,
function
focusTextArea
()
{
this
.
textarea
.
on
(
'
focus
'
,
function
focusTextArea
()
{
$
(
this
).
closest
(
'
.md-area
'
).
addClass
(
'
is-focused
'
);
$
(
this
)
.
closest
(
'
.md-area
'
)
.
addClass
(
'
is-focused
'
);
});
});
this
.
textarea
.
on
(
'
blur
'
,
function
blurTextArea
()
{
this
.
textarea
.
on
(
'
blur
'
,
function
blurTextArea
()
{
$
(
this
).
closest
(
'
.md-area
'
).
removeClass
(
'
is-focused
'
);
$
(
this
)
.
closest
(
'
.md-area
'
)
.
removeClass
(
'
is-focused
'
);
});
});
}
}
}
}
app/assets/javascripts/group_avatar.js
View file @
dfb08243
...
@@ -7,8 +7,9 @@ export default function groupAvatar() {
...
@@ -7,8 +7,9 @@ export default function groupAvatar() {
});
});
$
(
'
.js-group-avatar-input
'
).
on
(
'
change
'
,
function
onChangeAvatarInput
()
{
$
(
'
.js-group-avatar-input
'
).
on
(
'
change
'
,
function
onChangeAvatarInput
()
{
const
form
=
$
(
this
).
closest
(
'
form
'
);
const
form
=
$
(
this
).
closest
(
'
form
'
);
// eslint-disable-next-line no-useless-escape
const
filename
=
$
(
this
)
const
filename
=
$
(
this
).
val
().
replace
(
/^.*
[\\\/]
/
,
''
);
.
val
()
.
replace
(
/^.*
[\\\/]
/
,
''
);
// eslint-disable-line no-useless-escape
return
form
.
find
(
'
.js-avatar-filename
'
).
text
(
filename
);
return
form
.
find
(
'
.js-avatar-filename
'
).
text
(
filename
);
});
});
}
}
app/assets/javascripts/group_label_subscription.js
View file @
dfb08243
...
@@ -23,7 +23,8 @@ export default class GroupLabelSubscription {
...
@@ -23,7 +23,8 @@ export default class GroupLabelSubscription {
event
.
preventDefault
();
event
.
preventDefault
();
const
url
=
this
.
$unsubscribeButtons
.
attr
(
'
data-url
'
);
const
url
=
this
.
$unsubscribeButtons
.
attr
(
'
data-url
'
);
axios
.
post
(
url
)
axios
.
post
(
url
)
.
then
(()
=>
{
.
then
(()
=>
{
this
.
toggleSubscriptionButtons
();
this
.
toggleSubscriptionButtons
();
this
.
$unsubscribeButtons
.
removeAttr
(
'
data-url
'
);
this
.
$unsubscribeButtons
.
removeAttr
(
'
data-url
'
);
...
@@ -39,7 +40,8 @@ export default class GroupLabelSubscription {
...
@@ -39,7 +40,8 @@ export default class GroupLabelSubscription {
this
.
$unsubscribeButtons
.
attr
(
'
data-url
'
,
url
);
this
.
$unsubscribeButtons
.
attr
(
'
data-url
'
,
url
);
axios
.
post
(
url
)
axios
.
post
(
url
)
.
then
(()
=>
GroupLabelSubscription
.
setNewTooltip
(
$btn
))
.
then
(()
=>
GroupLabelSubscription
.
setNewTooltip
(
$btn
))
.
then
(()
=>
this
.
toggleSubscriptionButtons
())
.
then
(()
=>
this
.
toggleSubscriptionButtons
())
.
catch
(()
=>
flash
(
__
(
'
There was an error when subscribing to this label.
'
)));
.
catch
(()
=>
flash
(
__
(
'
There was an error when subscribing to this label.
'
)));
...
@@ -58,6 +60,8 @@ export default class GroupLabelSubscription {
...
@@ -58,6 +60,8 @@ export default class GroupLabelSubscription {
const
newTitle
=
tooltipTitles
[
type
];
const
newTitle
=
tooltipTitles
[
type
];
$
(
'
.js-unsubscribe-button
'
,
$button
.
closest
(
'
.label-actions-list
'
))
$
(
'
.js-unsubscribe-button
'
,
$button
.
closest
(
'
.label-actions-list
'
))
.
tooltip
(
'
hide
'
).
attr
(
'
title
'
,
newTitle
).
tooltip
(
'
_fixTitle
'
);
.
tooltip
(
'
hide
'
)
.
attr
(
'
title
'
,
newTitle
)
.
tooltip
(
'
_fixTitle
'
);
}
}
}
}
app/assets/javascripts/groups/components/item_stats.vue
View file @
dfb08243
<
script
>
<
script
>
import
icon
from
'
~/vue_shared/components/icon.vue
'
;
import
icon
from
'
~/vue_shared/components/icon.vue
'
;
import
timeAgoTooltip
from
'
~/vue_shared/components/time_ago_tooltip.vue
'
;
import
timeAgoTooltip
from
'
~/vue_shared/components/time_ago_tooltip.vue
'
;
import
{
import
{
ITEM_TYPE
,
ITEM_TYPE
,
VISIBILITY_TYPE_ICON
,
VISIBILITY_TYPE_ICON
,
GROUP_VISIBILITY_TYPE
,
GROUP_VISIBILITY_TYPE
,
PROJECT_VISIBILITY_TYPE
,
PROJECT_VISIBILITY_TYPE
,
}
from
'
../constants
'
;
}
from
'
../constants
'
;
import
itemStatsValue
from
'
./item_stats_value.vue
'
;
import
itemStatsValue
from
'
./item_stats_value.vue
'
;
export
default
{
export
default
{
components
:
{
components
:
{
icon
,
icon
,
timeAgoTooltip
,
timeAgoTooltip
,
itemStatsValue
,
itemStatsValue
,
},
props
:
{
item
:
{
type
:
Object
,
required
:
true
,
},
},
props
:
{
},
item
:
{
computed
:
{
type
:
Object
,
visibilityIcon
()
{
required
:
true
,
return
VISIBILITY_TYPE_ICON
[
this
.
item
.
visibility
];
},
},
},
computed
:
{
visibilityTooltip
()
{
visibilityIcon
()
{
if
(
this
.
item
.
type
===
ITEM_TYPE
.
GROUP
)
{
return
VISIBILITY_TYPE_ICON
[
this
.
item
.
visibility
];
return
GROUP_VISIBILITY_TYPE
[
this
.
item
.
visibility
];
},
}
visibilityTooltip
()
{
return
PROJECT_VISIBILITY_TYPE
[
this
.
item
.
visibility
];
if
(
this
.
item
.
type
===
ITEM_TYPE
.
GROUP
)
{
return
GROUP_VISIBILITY_TYPE
[
this
.
item
.
visibility
];
}
return
PROJECT_VISIBILITY_TYPE
[
this
.
item
.
visibility
];
},
isProject
()
{
return
this
.
item
.
type
===
ITEM_TYPE
.
PROJECT
;
},
isGroup
()
{
return
this
.
item
.
type
===
ITEM_TYPE
.
GROUP
;
},
},
},
};
isProject
()
{
return
this
.
item
.
type
===
ITEM_TYPE
.
PROJECT
;
},
isGroup
()
{
return
this
.
item
.
type
===
ITEM_TYPE
.
GROUP
;
},
},
};
</
script
>
</
script
>
<
template
>
<
template
>
...
...
app/assets/javascripts/groups/components/item_stats_value.vue
View file @
dfb08243
<
script
>
<
script
>
import
tooltip
from
'
~/vue_shared/directives/tooltip
'
;
import
tooltip
from
'
~/vue_shared/directives/tooltip
'
;
import
icon
from
'
~/vue_shared/components/icon.vue
'
;
import
icon
from
'
~/vue_shared/components/icon.vue
'
;
export
default
{
export
default
{
components
:
{
components
:
{
icon
,
icon
,
},
directives
:
{
tooltip
,
},
props
:
{
title
:
{
type
:
String
,
required
:
false
,
default
:
''
,
},
},
directives
:
{
cssClass
:
{
tooltip
,
type
:
String
,
required
:
false
,
default
:
''
,
},
},
props
:
{
iconName
:
{
title
:
{
type
:
String
,
type
:
String
,
required
:
true
,
required
:
false
,
default
:
''
,
},
cssClass
:
{
type
:
String
,
required
:
false
,
default
:
''
,
},
iconName
:
{
type
:
String
,
required
:
true
,
},
tooltipPlacement
:
{
type
:
String
,
required
:
false
,
default
:
'
bottom
'
,
},
/**
* value could either be number or string
* as `memberCount` is always passed as string
* while `subgroupCount` & `projectCount`
* are always number
*/
value
:
{
type
:
[
Number
,
String
],
required
:
false
,
default
:
''
,
},
},
},
computed
:
{
tooltipPlacement
:
{
isValuePresent
()
{
type
:
String
,
return
this
.
value
!==
''
;
required
:
false
,
}
,
default
:
'
bottom
'
,
},
},
};
/**
* value could either be number or string
* as `memberCount` is always passed as string
* while `subgroupCount` & `projectCount`
* are always number
*/
value
:
{
type
:
[
Number
,
String
],
required
:
false
,
default
:
''
,
},
},
computed
:
{
isValuePresent
()
{
return
this
.
value
!==
''
;
},
},
};
</
script
>
</
script
>
<
template
>
<
template
>
...
...
app/assets/javascripts/groups/new_group_child.js
View file @
dfb08243
...
@@ -37,20 +37,22 @@ export default class NewGroupChild {
...
@@ -37,20 +37,22 @@ export default class NewGroupChild {
getDroplabConfig
()
{
getDroplabConfig
()
{
return
{
return
{
InputSetter
:
[{
InputSetter
:
[
input
:
this
.
newGroupChildButton
,
{
valueAttribute
:
'
data-value
'
,
input
:
this
.
newGroupChildButton
,
inputAttribute
:
'
data-action
'
,
valueAttribute
:
'
data-value
'
,
},
{
inputAttribute
:
'
data-action
'
,
input
:
this
.
newGroupChildButton
,
},
valueAttribute
:
'
data-text
'
,
{
}],
input
:
this
.
newGroupChildButton
,
valueAttribute
:
'
data-text
'
,
},
],
};
};
}
}
bindEvents
()
{
bindEvents
()
{
this
.
newGroupChildButton
this
.
newGroupChildButton
.
addEventListener
(
'
click
'
,
this
.
onClickNewGroupChildButton
.
bind
(
this
));
.
addEventListener
(
'
click
'
,
this
.
onClickNewGroupChildButton
.
bind
(
this
));
}
}
onClickNewGroupChildButton
(
e
)
{
onClickNewGroupChildButton
(
e
)
{
...
...
app/assets/javascripts/groups/store/groups_store.js
View file @
dfb08243
...
@@ -17,13 +17,14 @@ export default class GroupsStore {
...
@@ -17,13 +17,14 @@ export default class GroupsStore {
}
}
setSearchedGroups
(
rawGroups
)
{
setSearchedGroups
(
rawGroups
)
{
const
formatGroups
=
groups
=>
groups
.
map
((
group
)
=>
{
const
formatGroups
=
groups
=>
const
formattedGroup
=
this
.
formatGroupItem
(
group
);
groups
.
map
(
group
=>
{
if
(
formattedGroup
.
children
&&
formattedGroup
.
children
.
length
)
{
const
formattedGroup
=
this
.
formatGroupItem
(
group
);
formattedGroup
.
children
=
formatGroups
(
formattedGroup
.
children
);
if
(
formattedGroup
.
children
&&
formattedGroup
.
children
.
length
)
{
}
formattedGroup
.
children
=
formatGroups
(
formattedGroup
.
children
);
return
formattedGroup
;
}
});
return
formattedGroup
;
});
if
(
rawGroups
&&
rawGroups
.
length
)
{
if
(
rawGroups
&&
rawGroups
.
length
)
{
this
.
state
.
groups
=
formatGroups
(
rawGroups
);
this
.
state
.
groups
=
formatGroups
(
rawGroups
);
...
@@ -62,10 +63,10 @@ export default class GroupsStore {
...
@@ -62,10 +63,10 @@ export default class GroupsStore {
formatGroupItem
(
rawGroupItem
)
{
formatGroupItem
(
rawGroupItem
)
{
const
groupChildren
=
rawGroupItem
.
children
||
[];
const
groupChildren
=
rawGroupItem
.
children
||
[];
const
groupIsOpen
=
(
groupChildren
.
length
>
0
)
||
false
;
const
groupIsOpen
=
groupChildren
.
length
>
0
||
false
;
const
childrenCount
=
this
.
hideProjects
?
const
childrenCount
=
this
.
hideProjects
rawGroupItem
.
subgroup_count
:
?
rawGroupItem
.
subgroup_count
rawGroupItem
.
children_count
;
:
rawGroupItem
.
children_count
;
return
{
return
{
id
:
rawGroupItem
.
id
,
id
:
rawGroupItem
.
id
,
...
...
app/assets/javascripts/groups/transfer_dropdown.js
View file @
dfb08243
...
@@ -22,7 +22,7 @@ export default class TransferDropdown {
...
@@ -22,7 +22,7 @@ export default class TransferDropdown {
search
:
{
fields
:
[
'
text
'
]
},
search
:
{
fields
:
[
'
text
'
]
},
data
:
extraOptions
.
concat
(
this
.
data
),
data
:
extraOptions
.
concat
(
this
.
data
),
text
:
item
=>
item
.
text
,
text
:
item
=>
item
.
text
,
clicked
:
(
options
)
=>
{
clicked
:
options
=>
{
const
{
e
}
=
options
;
const
{
e
}
=
options
;
e
.
preventDefault
();
e
.
preventDefault
();
this
.
assignSelected
(
options
.
selectedObj
);
this
.
assignSelected
(
options
.
selectedObj
);
...
...
app/assets/javascripts/groups_select.js
View file @
dfb08243
...
@@ -23,7 +23,7 @@ export default function groupsSelect() {
...
@@ -23,7 +23,7 @@ export default function groupsSelect() {
axios
[
params
.
type
.
toLowerCase
()](
params
.
url
,
{
axios
[
params
.
type
.
toLowerCase
()](
params
.
url
,
{
params
:
params
.
data
,
params
:
params
.
data
,
})
})
.
then
(
(
res
)
=>
{
.
then
(
res
=>
{
const
results
=
res
.
data
||
[];
const
results
=
res
.
data
||
[];
const
headers
=
normalizeHeaders
(
res
.
headers
);
const
headers
=
normalizeHeaders
(
res
.
headers
);
const
currentPage
=
parseInt
(
headers
[
'
X-PAGE
'
],
10
)
||
0
;
const
currentPage
=
parseInt
(
headers
[
'
X-PAGE
'
],
10
)
||
0
;
...
@@ -36,7 +36,8 @@ export default function groupsSelect() {
...
@@ -36,7 +36,8 @@ export default function groupsSelect() {
more
,
more
,
},
},
});
});
}).
catch
(
params
.
error
);
})
.
catch
(
params
.
error
);
},
},
data
(
search
,
page
)
{
data
(
search
,
page
)
{
return
{
return
{
...
@@ -68,7 +69,9 @@ export default function groupsSelect() {
...
@@ -68,7 +69,9 @@ export default function groupsSelect() {
}
}
},
},
formatResult
(
object
)
{
formatResult
(
object
)
{
return
`<div class='group-result'> <div class='group-name'>
${
object
.
full_name
}
</div> <div class='group-path'>
${
object
.
full_path
}
</div> </div>`
;
return
`<div class='group-result'> <div class='group-name'>
${
object
.
full_name
}
</div> <div class='group-path'>
${
object
.
full_path
}
</div> </div>`
;
},
},
formatSelection
(
object
)
{
formatSelection
(
object
)
{
return
object
.
full_name
;
return
object
.
full_name
;
...
...
app/assets/javascripts/helpers/avatar_helper.js
View file @
dfb08243
...
@@ -19,7 +19,9 @@ export function renderIdenticon(entity, options = {}) {
...
@@ -19,7 +19,9 @@ export function renderIdenticon(entity, options = {}) {
const
bgClass
=
getIdenticonBackgroundClass
(
entity
.
id
);
const
bgClass
=
getIdenticonBackgroundClass
(
entity
.
id
);
const
title
=
getIdenticonTitle
(
entity
.
name
);
const
title
=
getIdenticonTitle
(
entity
.
name
);
return
`<div class="avatar identicon
${
_
.
escape
(
sizeClass
)}
${
_
.
escape
(
bgClass
)}
">
${
_
.
escape
(
title
)}
</div>`
;
return
`<div class="avatar identicon
${
_
.
escape
(
sizeClass
)}
${
_
.
escape
(
bgClass
)}
">
${
_
.
escape
(
title
,
)}
</div>`
;
}
}
export
function
renderAvatar
(
entity
,
options
=
{})
{
export
function
renderAvatar
(
entity
,
options
=
{})
{
...
...
app/assets/javascripts/image_diff/image_diff.js
View file @
dfb08243
...
@@ -60,8 +60,10 @@ export default class ImageDiff {
...
@@ -60,8 +60,10 @@ export default class ImageDiff {
}
}
renderBadge
(
discussionEl
,
index
)
{
renderBadge
(
discussionEl
,
index
)
{
const
imageBadge
=
imageDiffHelper
const
imageBadge
=
imageDiffHelper
.
generateBadgeFromDiscussionDOM
(
.
generateBadgeFromDiscussionDOM
(
this
.
imageFrameEl
,
discussionEl
);
this
.
imageFrameEl
,
discussionEl
,
);
this
.
imageBadges
.
push
(
imageBadge
);
this
.
imageBadges
.
push
(
imageBadge
);
...
...
app/assets/javascripts/image_diff/init_discussion_tab.js
View file @
dfb08243
...
@@ -8,5 +8,6 @@ export default () => {
...
@@ -8,5 +8,6 @@ export default () => {
const
diffFileEls
=
document
.
querySelectorAll
(
'
.timeline-content .diff-file.js-image-file
'
);
const
diffFileEls
=
document
.
querySelectorAll
(
'
.timeline-content .diff-file.js-image-file
'
);
[...
diffFileEls
].
forEach
(
diffFileEl
=>
[...
diffFileEls
].
forEach
(
diffFileEl
=>
imageDiffHelper
.
initImageDiff
(
diffFileEl
,
canCreateNote
,
renderCommentBadge
));
imageDiffHelper
.
initImageDiff
(
diffFileEl
,
canCreateNote
,
renderCommentBadge
),
);
};
};
app/assets/javascripts/image_diff/replaced_image_diff.js
View file @
dfb08243
...
@@ -26,7 +26,7 @@ export default class ReplacedImageDiff extends ImageDiff {
...
@@ -26,7 +26,7 @@ export default class ReplacedImageDiff extends ImageDiff {
this
.
imageEls
=
{};
this
.
imageEls
=
{};
const
viewTypeNames
=
Object
.
getOwnPropertyNames
(
viewTypes
);
const
viewTypeNames
=
Object
.
getOwnPropertyNames
(
viewTypes
);
viewTypeNames
.
forEach
(
(
viewType
)
=>
{
viewTypeNames
.
forEach
(
viewType
=>
{
this
.
imageEls
[
viewType
]
=
this
.
imageFrameEls
[
viewType
].
querySelector
(
'
img
'
);
this
.
imageEls
[
viewType
]
=
this
.
imageFrameEls
[
viewType
].
querySelector
(
'
img
'
);
});
});
}
}
...
@@ -79,13 +79,12 @@ export default class ReplacedImageDiff extends ImageDiff {
...
@@ -79,13 +79,12 @@ export default class ReplacedImageDiff extends ImageDiff {
// Re-render indicator in new view
// Re-render indicator in new view
if
(
indicator
.
removed
)
{
if
(
indicator
.
removed
)
{
const
normalizedIndicator
=
imageDiffHelper
const
normalizedIndicator
=
imageDiffHelper
.
resizeCoordinatesToImageElement
(
this
.
imageEl
,
{
.
resizeCoordinatesToImageElement
(
this
.
imageEl
,
{
x
:
indicator
.
x
,
x
:
indicator
.
x
,
y
:
indicator
.
y
,
y
:
indicator
.
y
,
width
:
indicator
.
image
.
width
,
width
:
indicator
.
image
.
width
,
height
:
indicator
.
image
.
height
,
height
:
indicator
.
image
.
height
,
});
});
imageDiffHelper
.
showCommentIndicator
(
this
.
imageFrameEl
,
normalizedIndicator
);
imageDiffHelper
.
showCommentIndicator
(
this
.
imageFrameEl
,
normalizedIndicator
);
}
}
}
}
...
...
app/assets/javascripts/importer_status.js
View file @
dfb08243
...
@@ -60,66 +60,71 @@ class ImporterStatus {
...
@@ -60,66 +60,71 @@ class ImporterStatus {
attributes
=
Object
.
assign
(
repoData
,
attributes
);
attributes
=
Object
.
assign
(
repoData
,
attributes
);
}
}
return
axios
.
post
(
this
.
importUrl
,
attributes
)
return
axios
.
then
(({
data
})
=>
{
.
post
(
this
.
importUrl
,
attributes
)
const
job
=
$
(
`tr#repo_
${
id
}
`
);
.
then
(({
data
})
=>
{
job
.
attr
(
'
id
'
,
`project_
${
data
.
id
}
`
);
const
job
=
$
(
`tr#repo_
${
id
}
`
);
job
.
attr
(
'
id
'
,
`project_
${
data
.
id
}
`
);
job
.
find
(
'
.import-target
'
).
html
(
`<a href="
${
data
.
full_path
}
">
${
data
.
full_path
}
</a>`
);
$
(
'
table.import-jobs tbody
'
).
prepend
(
job
);
job
.
find
(
'
.import-target
'
).
html
(
`<a href="
${
data
.
full_path
}
">
${
data
.
full_path
}
</a>`
);
$
(
'
table.import-jobs tbody
'
).
prepend
(
job
);
job
.
addClass
(
'
table-active
'
);
const
connectingVerb
=
this
.
ciCdOnly
?
__
(
'
connecting
'
)
:
__
(
'
importing
'
);
job
.
addClass
(
'
table-active
'
);
job
.
find
(
'
.import-actions
'
).
html
(
sprintf
(
const
connectingVerb
=
this
.
ciCdOnly
?
__
(
'
connecting
'
)
:
__
(
'
importing
'
);
_
.
escape
(
__
(
'
%{loadingIcon} Started
'
)),
{
job
.
find
(
'
.import-actions
'
).
html
(
loadingIcon
:
`<i class="fa fa-spinner fa-spin" aria-label="
${
_
.
escape
(
connectingVerb
)}
"></i>`
,
sprintf
(
},
_
.
escape
(
__
(
'
%{loadingIcon} Started
'
)),
false
,
{
));
loadingIcon
:
`<i class="fa fa-spinner fa-spin" aria-label="
${
_
.
escape
(
})
connectingVerb
,
.
catch
((
error
)
=>
{
)}
"></i>`
,
let
details
=
error
;
},
false
,
const
$statusField
=
$
(
`#repo_
${
this
.
id
}
.job-status`
);
),
$statusField
.
text
(
__
(
'
Failed
'
));
);
})
if
(
error
.
response
&&
error
.
response
.
data
&&
error
.
response
.
data
.
errors
)
{
.
catch
(
error
=>
{
details
=
error
.
response
.
data
.
errors
;
let
details
=
error
;
}
const
$statusField
=
$
(
`#repo_
${
this
.
id
}
.job-status`
);
flash
(
sprintf
(
__
(
'
An error occurred while importing project: %{details}
'
),
{
details
}));
$statusField
.
text
(
__
(
'
Failed
'
));
});
if
(
error
.
response
&&
error
.
response
.
data
&&
error
.
response
.
data
.
errors
)
{
details
=
error
.
response
.
data
.
errors
;
}
flash
(
sprintf
(
__
(
'
An error occurred while importing project: %{details}
'
),
{
details
}));
});
}
}
autoUpdate
()
{
autoUpdate
()
{
return
axios
.
get
(
this
.
jobsUrl
)
return
axios
.
get
(
this
.
jobsUrl
).
then
(({
data
=
[]
})
=>
{
.
then
(({
data
=
[]
})
=>
{
data
.
forEach
(
job
=>
{
data
.
forEach
((
job
)
=>
{
const
jobItem
=
$
(
`#project_
${
job
.
id
}
`
);
const
jobItem
=
$
(
`#project_
${
job
.
id
}
`
);
const
statusField
=
jobItem
.
find
(
'
.job-status
'
);
const
statusField
=
jobItem
.
find
(
'
.job-status
'
);
const
spinner
=
'
<i class="fa fa-spinner fa-spin"></i>
'
;
const
spinner
=
'
<i class="fa fa-spinner fa-spin"></i>
'
;
switch
(
job
.
import_status
)
{
switch
(
job
.
import_status
)
{
case
'
finished
'
:
case
'
finished
'
:
jobItem
.
removeClass
(
'
table-active
'
).
addClass
(
'
table-success
'
);
jobItem
.
removeClass
(
'
table-active
'
).
addClass
(
'
table-success
'
);
statusField
.
html
(
`<span><i class="fa fa-check"></i>
${
__
(
'
Done
'
)}
</span>`
);
statusField
.
html
(
`<span><i class="fa fa-check"></i>
${
__
(
'
Done
'
)}
</span>`
);
break
;
break
;
case
'
scheduled
'
:
case
'
scheduled
'
:
statusField
.
html
(
`
${
spinner
}
${
__
(
'
Scheduled
'
)}
`
);
statusField
.
html
(
`
${
spinner
}
${
__
(
'
Scheduled
'
)}
`
);
break
;
break
;
case
'
started
'
:
case
'
started
'
:
statusField
.
html
(
`
${
spinner
}
${
__
(
'
Started
'
)}
`
);
statusField
.
html
(
`
${
spinner
}
${
__
(
'
Started
'
)}
`
);
break
;
break
;
case
'
failed
'
:
case
'
failed
'
:
statusField
.
html
(
__
(
'
Failed
'
));
statusField
.
html
(
__
(
'
Failed
'
));
break
;
break
;
default
:
default
:
statusField
.
html
(
job
.
import_status
);
statusField
.
html
(
job
.
import_status
);
break
;
break
;
}
}
});
});
});
});
}
}
setAutoUpdate
()
{
setAutoUpdate
()
{
...
@@ -141,7 +146,4 @@ function initImporterStatus() {
...
@@ -141,7 +146,4 @@ function initImporterStatus() {
}
}
}
}
export
{
export
{
initImporterStatus
as
default
,
ImporterStatus
};
initImporterStatus
as
default
,
ImporterStatus
,
};
app/assets/javascripts/init_changes_dropdown.js
View file @
dfb08243
import
$
from
'
jquery
'
;
import
$
from
'
jquery
'
;
import
{
stickyMonitor
}
from
'
./lib/utils/sticky
'
;
import
{
stickyMonitor
}
from
'
./lib/utils/sticky
'
;
export
default
(
stickyTop
)
=>
{
export
default
stickyTop
=>
{
stickyMonitor
(
document
.
querySelector
(
'
.js-diff-files-changed
'
),
stickyTop
);
stickyMonitor
(
document
.
querySelector
(
'
.js-diff-files-changed
'
),
stickyTop
);
$
(
'
.js-diff-stats-dropdown
'
).
glDropdown
({
$
(
'
.js-diff-stats-dropdown
'
).
glDropdown
({
...
...
app/assets/javascripts/init_notes.js
View file @
dfb08243
...
@@ -2,13 +2,7 @@ import Notes from './notes';
...
@@ -2,13 +2,7 @@ import Notes from './notes';
export
default
()
=>
{
export
default
()
=>
{
const
dataEl
=
document
.
querySelector
(
'
.js-notes-data
'
);
const
dataEl
=
document
.
querySelector
(
'
.js-notes-data
'
);
const
{
const
{
notesUrl
,
notesIds
,
now
,
diffView
,
enableGFM
}
=
JSON
.
parse
(
dataEl
.
innerHTML
);
notesUrl
,
notesIds
,
now
,
diffView
,
enableGFM
,
}
=
JSON
.
parse
(
dataEl
.
innerHTML
);
// Create a singleton so that we don't need to assign
// Create a singleton so that we don't need to assign
// into the window object, we can just access the current isntance with Notes.instance
// into the window object, we can just access the current isntance with Notes.instance
...
...
app/assets/javascripts/integrations/integration_settings_form.js
View file @
dfb08243
...
@@ -97,7 +97,8 @@ export default class IntegrationSettingsForm {
...
@@ -97,7 +97,8 @@ export default class IntegrationSettingsForm {
testSettings
(
formData
)
{
testSettings
(
formData
)
{
this
.
toggleSubmitBtnState
(
true
);
this
.
toggleSubmitBtnState
(
true
);
return
axios
.
put
(
this
.
testEndPoint
,
formData
)
return
axios
.
put
(
this
.
testEndPoint
,
formData
)
.
then
(({
data
})
=>
{
.
then
(({
data
})
=>
{
if
(
data
.
error
)
{
if
(
data
.
error
)
{
let
flashActions
;
let
flashActions
;
...
@@ -105,7 +106,7 @@ export default class IntegrationSettingsForm {
...
@@ -105,7 +106,7 @@ export default class IntegrationSettingsForm {
if
(
data
.
test_failed
)
{
if
(
data
.
test_failed
)
{
flashActions
=
{
flashActions
=
{
title
:
'
Save anyway
'
,
title
:
'
Save anyway
'
,
clickHandler
:
(
e
)
=>
{
clickHandler
:
e
=>
{
e
.
preventDefault
();
e
.
preventDefault
();
this
.
$form
.
submit
();
this
.
$form
.
submit
();
},
},
...
...
app/assets/javascripts/issuable/auto_width_dropdown_select.js
View file @
dfb08243
...
@@ -27,7 +27,10 @@ class AutoWidthDropdownSelect {
...
@@ -27,7 +27,10 @@ class AutoWidthDropdownSelect {
// We have to look at the parent because
// We have to look at the parent because
// `offsetParent` on a `display: none;` is `null`
// `offsetParent` on a `display: none;` is `null`
const
offsetParentWidth
=
$
(
this
).
parent
().
offsetParent
().
width
();
const
offsetParentWidth
=
$
(
this
)
.
parent
()
.
offsetParent
()
.
width
();
// Reset any width to let it naturally flow
// Reset any width to let it naturally flow
$dropdown
.
css
(
'
width
'
,
'
auto
'
);
$dropdown
.
css
(
'
width
'
,
'
auto
'
);
if
(
$dropdown
.
outerWidth
(
false
)
>
offsetParentWidth
)
{
if
(
$dropdown
.
outerWidth
(
false
)
>
offsetParentWidth
)
{
...
...
app/assets/javascripts/issuable_bulk_update_actions.js
View file @
dfb08243
...
@@ -32,7 +32,7 @@ export default {
...
@@ -32,7 +32,7 @@ export default {
onFormSubmitFailure
()
{
onFormSubmitFailure
()
{
this
.
form
.
find
(
'
[type="submit"]
'
).
enable
();
this
.
form
.
find
(
'
[type="submit"]
'
).
enable
();
return
new
Flash
(
"
Issue update failed
"
);
return
new
Flash
(
'
Issue update failed
'
);
},
},
getSelectedIssues
()
{
getSelectedIssues
()
{
...
@@ -63,7 +63,7 @@ export default {
...
@@ -63,7 +63,7 @@ export default {
const
result
=
[];
const
result
=
[];
const
labelsToKeep
=
this
.
$labelDropdown
.
data
(
'
indeterminate
'
);
const
labelsToKeep
=
this
.
$labelDropdown
.
data
(
'
indeterminate
'
);
this
.
getLabelsFromSelection
().
forEach
(
(
id
)
=>
{
this
.
getLabelsFromSelection
().
forEach
(
id
=>
{
if
(
labelsToKeep
.
indexOf
(
id
)
===
-
1
)
{
if
(
labelsToKeep
.
indexOf
(
id
)
===
-
1
)
{
result
.
push
(
id
);
result
.
push
(
id
);
}
}
...
@@ -89,8 +89,8 @@ export default {
...
@@ -89,8 +89,8 @@ export default {
issuable_ids
:
this
.
form
.
find
(
'
input[name="update[issuable_ids]"]
'
).
val
(),
issuable_ids
:
this
.
form
.
find
(
'
input[name="update[issuable_ids]"]
'
).
val
(),
subscription_event
:
this
.
form
.
find
(
'
input[name="update[subscription_event]"]
'
).
val
(),
subscription_event
:
this
.
form
.
find
(
'
input[name="update[subscription_event]"]
'
).
val
(),
add_label_ids
:
[],
add_label_ids
:
[],
remove_label_ids
:
[]
remove_label_ids
:
[]
,
}
}
,
};
};
if
(
this
.
willUpdateLabels
)
{
if
(
this
.
willUpdateLabels
)
{
formData
.
update
.
add_label_ids
=
this
.
$labelDropdown
.
data
(
'
marked
'
);
formData
.
update
.
add_label_ids
=
this
.
$labelDropdown
.
data
(
'
marked
'
);
...
@@ -134,7 +134,7 @@ export default {
...
@@ -134,7 +134,7 @@ export default {
// Collect unique label IDs for all checked issues
// Collect unique label IDs for all checked issues
this
.
getElement
(
'
.selected-issuable:checked
'
).
each
((
i
,
el
)
=>
{
this
.
getElement
(
'
.selected-issuable:checked
'
).
each
((
i
,
el
)
=>
{
issuableLabels
=
this
.
getElement
(
`#
${
this
.
prefixId
}${
el
.
dataset
.
id
}
`
).
data
(
'
labels
'
);
issuableLabels
=
this
.
getElement
(
`#
${
this
.
prefixId
}${
el
.
dataset
.
id
}
`
).
data
(
'
labels
'
);
issuableLabels
.
forEach
(
(
labelId
)
=>
{
issuableLabels
.
forEach
(
labelId
=>
{
// Store unique IDs
// Store unique IDs
if
(
uniqueIds
.
indexOf
(
labelId
)
===
-
1
)
{
if
(
uniqueIds
.
indexOf
(
labelId
)
===
-
1
)
{
uniqueIds
.
push
(
labelId
);
uniqueIds
.
push
(
labelId
);
...
...
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