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
e820c228
Commit
e820c228
authored
Dec 23, 2020
by
Lukas Eipert
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Run prettier on 48 files - 18 of 73
Part of our prettier migration; changing the arrow-parens style.
parent
2f8dbd48
Changes
48
Show whitespace changes
Inline
Side-by-side
Showing
48 changed files
with
191 additions
and
191 deletions
+191
-191
app/assets/javascripts/issue_show/components/fields/description_template.vue
...pts/issue_show/components/fields/description_template.vue
+1
-1
app/assets/javascripts/issue_show/issue.js
app/assets/javascripts/issue_show/issue.js
+1
-1
app/assets/javascripts/issue_show/utils/parse_data.js
app/assets/javascripts/issue_show/utils/parse_data.js
+1
-1
app/assets/javascripts/issues_list/components/issuable.vue
app/assets/javascripts/issues_list/components/issuable.vue
+1
-1
app/assets/javascripts/issues_list/components/issuables_list_app.vue
...javascripts/issues_list/components/issuables_list_app.vue
+4
-4
app/assets/javascripts/issues_list/index.js
app/assets/javascripts/issues_list/index.js
+1
-1
app/assets/javascripts/jira_connect/index.js
app/assets/javascripts/jira_connect/index.js
+5
-5
app/assets/javascripts/jira_import/components/jira_import_form.vue
...s/javascripts/jira_import/components/jira_import_form.vue
+2
-2
app/assets/javascripts/jira_import/utils/cache_update.js
app/assets/javascripts/jira_import/utils/cache_update.js
+1
-1
app/assets/javascripts/jira_import/utils/jira_import_utils.js
...assets/javascripts/jira_import/utils/jira_import_utils.js
+7
-7
app/assets/javascripts/jobs/components/job_app.vue
app/assets/javascripts/jobs/components/job_app.vue
+1
-1
app/assets/javascripts/jobs/components/log/line.vue
app/assets/javascripts/jobs/components/log/line.vue
+2
-2
app/assets/javascripts/jobs/components/manual_variables_form.vue
...ets/javascripts/jobs/components/manual_variables_form.vue
+1
-1
app/assets/javascripts/jobs/components/trigger_block.vue
app/assets/javascripts/jobs/components/trigger_block.vue
+1
-1
app/assets/javascripts/jobs/store/actions.js
app/assets/javascripts/jobs/store/actions.js
+3
-3
app/assets/javascripts/jobs/store/getters.js
app/assets/javascripts/jobs/store/getters.js
+12
-12
app/assets/javascripts/jobs/store/utils.js
app/assets/javascripts/jobs/store/utils.js
+2
-2
app/assets/javascripts/labels_select.js
app/assets/javascripts/labels_select.js
+9
-9
app/assets/javascripts/lazy_loader.js
app/assets/javascripts/lazy_loader.js
+5
-5
app/assets/javascripts/lib/chrome_84_icon_fix.js
app/assets/javascripts/lib/chrome_84_icon_fix.js
+2
-2
app/assets/javascripts/lib/dompurify.js
app/assets/javascripts/lib/dompurify.js
+4
-4
app/assets/javascripts/lib/graphql.js
app/assets/javascripts/lib/graphql.js
+2
-2
app/assets/javascripts/lib/utils/ajax_cache.js
app/assets/javascripts/lib/utils/ajax_cache.js
+1
-1
app/assets/javascripts/lib/utils/apollo_startup_js_link.js
app/assets/javascripts/lib/utils/apollo_startup_js_link.js
+8
-8
app/assets/javascripts/lib/utils/autosave.js
app/assets/javascripts/lib/utils/autosave.js
+2
-2
app/assets/javascripts/lib/utils/axios_startup_calls.js
app/assets/javascripts/lib/utils/axios_startup_calls.js
+4
-4
app/assets/javascripts/lib/utils/axios_utils.js
app/assets/javascripts/lib/utils/axios_utils.js
+5
-5
app/assets/javascripts/lib/utils/bootstrap_linked_tabs.js
app/assets/javascripts/lib/utils/bootstrap_linked_tabs.js
+1
-1
app/assets/javascripts/lib/utils/chart_utils.js
app/assets/javascripts/lib/utils/chart_utils.js
+2
-2
app/assets/javascripts/lib/utils/color_utils.js
app/assets/javascripts/lib/utils/color_utils.js
+2
-2
app/assets/javascripts/lib/utils/common_utils.js
app/assets/javascripts/lib/utils/common_utils.js
+30
-30
app/assets/javascripts/lib/utils/css_utils.js
app/assets/javascripts/lib/utils/css_utils.js
+1
-1
app/assets/javascripts/lib/utils/datetime_range.js
app/assets/javascripts/lib/utils/datetime_range.js
+9
-9
app/assets/javascripts/lib/utils/datetime_utility.js
app/assets/javascripts/lib/utils/datetime_utility.js
+20
-20
app/assets/javascripts/lib/utils/dom_utils.js
app/assets/javascripts/lib/utils/dom_utils.js
+3
-3
app/assets/javascripts/lib/utils/forms.js
app/assets/javascripts/lib/utils/forms.js
+6
-6
app/assets/javascripts/lib/utils/grammar.js
app/assets/javascripts/lib/utils/grammar.js
+1
-1
app/assets/javascripts/lib/utils/icon_utils.js
app/assets/javascripts/lib/utils/icon_utils.js
+3
-3
app/assets/javascripts/lib/utils/notify.js
app/assets/javascripts/lib/utils/notify.js
+1
-1
app/assets/javascripts/lib/utils/number_utils.js
app/assets/javascripts/lib/utils/number_utils.js
+1
-1
app/assets/javascripts/lib/utils/poll.js
app/assets/javascripts/lib/utils/poll.js
+2
-2
app/assets/javascripts/lib/utils/poll_until_complete.js
app/assets/javascripts/lib/utils/poll_until_complete.js
+1
-1
app/assets/javascripts/lib/utils/set.js
app/assets/javascripts/lib/utils/set.js
+1
-1
app/assets/javascripts/lib/utils/simple_poll.js
app/assets/javascripts/lib/utils/simple_poll.js
+1
-1
app/assets/javascripts/lib/utils/sticky.js
app/assets/javascripts/lib/utils/sticky.js
+1
-1
app/assets/javascripts/lib/utils/text_markdown.js
app/assets/javascripts/lib/utils/text_markdown.js
+2
-2
app/assets/javascripts/lib/utils/text_utility.js
app/assets/javascripts/lib/utils/text_utility.js
+14
-14
app/assets/javascripts/lib/utils/type_utility.js
app/assets/javascripts/lib/utils/type_utility.js
+1
-1
No files found.
app/assets/javascripts/issue_show/components/fields/description_template.vue
View file @
e820c228
...
...
@@ -34,7 +34,7 @@ export default {
mounted
()
{
// Create the editor for the template
const
editor
=
document
.
querySelector
(
'
.detail-page-description .note-textarea
'
)
||
{};
editor
.
setValue
=
val
=>
{
editor
.
setValue
=
(
val
)
=>
{
this
.
formState
.
description
=
val
;
};
editor
.
getValue
=
()
=>
this
.
formState
.
description
;
...
...
app/assets/javascripts/issue_show/issue.js
View file @
e820c228
...
...
@@ -57,6 +57,6 @@ export function initIssueHeaderActions(store) {
reportAbusePath
:
el
.
dataset
.
reportAbusePath
,
submitAsSpamPath
:
el
.
dataset
.
submitAsSpamPath
,
},
render
:
createElement
=>
createElement
(
HeaderActions
),
render
:
(
createElement
)
=>
createElement
(
HeaderActions
),
});
}
app/assets/javascripts/issue_show/utils/parse_data.js
View file @
e820c228
...
...
@@ -4,7 +4,7 @@ import { sanitize } from '~/lib/dompurify';
// We currently load + parse the data from the issue app and related merge request
let
cachedParsedData
;
export
const
parseIssuableData
=
el
=>
{
export
const
parseIssuableData
=
(
el
)
=>
{
try
{
if
(
cachedParsedData
)
return
cachedParsedData
;
...
...
app/assets/javascripts/issues_list/components/issuable.vue
View file @
e820c228
...
...
@@ -110,7 +110,7 @@ export default {
return
getDayDifference
(
new
Date
(
this
.
issuable
.
created_at
),
new
Date
())
<
1
;
},
labelIdsString
()
{
return
JSON
.
stringify
(
this
.
issuable
.
labels
.
map
(
l
=>
l
.
id
));
return
JSON
.
stringify
(
this
.
issuable
.
labels
.
map
(
(
l
)
=>
l
.
id
));
},
milestoneDueDate
()
{
const
{
due_date
:
dueDate
}
=
this
.
issuable
.
milestone
||
{};
...
...
app/assets/javascripts/issues_list/components/issuables_list_app.vue
View file @
e820c228
...
...
@@ -208,7 +208,7 @@ export default {
},
mounted
()
{
if
(
this
.
canBulkEdit
)
{
this
.
unsubscribeToggleBulkEdit
=
issueableEventHub
.
$on
(
'
issuables:toggleBulkEdit
'
,
val
=>
{
this
.
unsubscribeToggleBulkEdit
=
issueableEventHub
.
$on
(
'
issuables:toggleBulkEdit
'
,
(
val
)
=>
{
this
.
isBulkEditing
=
val
;
});
}
...
...
@@ -223,7 +223,7 @@ export default {
return
Boolean
(
this
.
selection
[
issuableId
]);
},
setSelection
(
ids
)
{
ids
.
forEach
(
id
=>
{
ids
.
forEach
(
(
id
)
=>
{
this
.
select
(
id
,
true
);
});
},
...
...
@@ -254,7 +254,7 @@ export default {
per_page
:
this
.
itemsPerPage
,
},
})
.
then
(
response
=>
{
.
then
(
(
response
)
=>
{
this
.
loading
=
false
;
this
.
issuables
=
response
.
data
;
this
.
totalItems
=
Number
(
response
.
headers
[
'
x-total
'
]);
...
...
@@ -335,7 +335,7 @@ export default {
handleFilter
(
filters
)
{
let
search
=
null
;
filters
.
forEach
(
filter
=>
{
filters
.
forEach
(
(
filter
)
=>
{
if
(
typeof
filter
===
'
string
'
)
{
search
=
filter
;
}
...
...
app/assets/javascripts/issues_list/index.js
View file @
e820c228
...
...
@@ -40,7 +40,7 @@ function mountIssuablesListApp() {
return
;
}
document
.
querySelectorAll
(
'
.js-issuables-list
'
).
forEach
(
el
=>
{
document
.
querySelectorAll
(
'
.js-issuables-list
'
).
forEach
(
(
el
)
=>
{
const
{
canBulkEdit
,
emptyStateMeta
=
{},
scopedLabelsAvailable
,
...
data
}
=
el
.
dataset
;
return
new
Vue
({
...
...
app/assets/javascripts/jira_connect/index.js
View file @
e820c228
...
...
@@ -27,7 +27,7 @@ const initJiraFormHandlers = () => {
alert
(
error
);
};
AP
.
getLocation
(
location
=>
{
AP
.
getLocation
(
(
location
)
=>
{
$
(
'
.js-jira-connect-sign-in
'
).
each
(
function
updateSignInLink
()
{
const
updatedLink
=
`
${
$
(
this
).
attr
(
'
href
'
)}
?return_to=
${
location
}
`
;
$
(
this
).
attr
(
'
href
'
,
updatedLink
);
...
...
@@ -38,7 +38,7 @@ const initJiraFormHandlers = () => {
const
actionUrl
=
$
(
this
).
attr
(
'
action
'
);
e
.
preventDefault
();
AP
.
context
.
getToken
(
token
=>
{
AP
.
context
.
getToken
(
(
token
)
=>
{
// eslint-disable-next-line no-jquery/no-ajax
$
.
post
(
actionUrl
,
{
jwt
:
token
,
...
...
@@ -46,7 +46,7 @@ const initJiraFormHandlers = () => {
format
:
'
json
'
,
})
.
done
(
reqComplete
)
.
fail
(
err
=>
reqFailed
(
err
,
'
Failed to add namespace. Please try again.
'
));
.
fail
(
(
err
)
=>
reqFailed
(
err
,
'
Failed to add namespace. Please try again.
'
));
});
});
...
...
@@ -54,7 +54,7 @@ const initJiraFormHandlers = () => {
const
href
=
$
(
this
).
attr
(
'
href
'
);
e
.
preventDefault
();
AP
.
context
.
getToken
(
token
=>
{
AP
.
context
.
getToken
(
(
token
)
=>
{
// eslint-disable-next-line no-jquery/no-ajax
$
.
ajax
({
url
:
href
,
...
...
@@ -65,7 +65,7 @@ const initJiraFormHandlers = () => {
},
})
.
done
(
reqComplete
)
.
fail
(
err
=>
reqFailed
(
err
,
'
Failed to remove namespace. Please try again.
'
));
.
fail
(
(
err
)
=>
reqFailed
(
err
,
'
Failed to remove namespace. Please try again.
'
));
});
});
};
...
...
app/assets/javascripts/jira_import/components/jira_import_form.vue
View file @
e820c228
...
...
@@ -118,7 +118,7 @@ export default {
this
.
getJiraUserMapping
();
this
.
searchUsers
()
.
then
(
data
=>
{
.
then
(
(
data
)
=>
{
this
.
initialUsers
=
data
;
})
.
catch
(()
=>
{});
...
...
@@ -219,7 +219,7 @@ export default {
}
},
updateMapping
(
jiraAccountId
,
gitlabId
,
gitlabUsername
)
{
this
.
userMappings
=
this
.
userMappings
.
map
(
userMapping
=>
this
.
userMappings
=
this
.
userMappings
.
map
(
(
userMapping
)
=>
userMapping
.
jiraAccountId
===
jiraAccountId
?
{
...
userMapping
,
...
...
app/assets/javascripts/jira_import/utils/cache_update.js
View file @
e820c228
...
...
@@ -20,7 +20,7 @@ export const addInProgressImportToStore = (store, jiraImportStart, fullPath) =>
store
.
writeQuery
({
...
queryDetails
,
data
:
produce
(
sourceData
,
draftData
=>
{
data
:
produce
(
sourceData
,
(
draftData
)
=>
{
draftData
.
project
.
jiraImportStatus
=
IMPORT_STATE
.
SCHEDULED
;
// eslint-disable-line no-param-reassign
// eslint-disable-next-line no-param-reassign
draftData
.
project
.
jiraImports
.
nodes
=
[
...
...
app/assets/javascripts/jira_import/utils/jira_import_utils.js
View file @
e820c228
...
...
@@ -9,10 +9,10 @@ export const IMPORT_STATE = {
STARTED
:
'
started
'
,
};
export
const
isInProgress
=
state
=>
export
const
isInProgress
=
(
state
)
=>
state
===
IMPORT_STATE
.
SCHEDULED
||
state
===
IMPORT_STATE
.
STARTED
;
export
const
isFinished
=
state
=>
state
===
IMPORT_STATE
.
FINISHED
;
export
const
isFinished
=
(
state
)
=>
state
===
IMPORT_STATE
.
FINISHED
;
/**
* Converts the list of Jira projects into a format consumable by GlFormSelect.
...
...
@@ -22,7 +22,7 @@ export const isFinished = state => state === IMPORT_STATE.FINISHED;
* @param {string} projects[].name - Jira project name
* @returns {Object[]} - List of Jira projects in a format consumable by GlFormSelect
*/
export
const
extractJiraProjectsOptions
=
projects
=>
export
const
extractJiraProjectsOptions
=
(
projects
)
=>
projects
.
map
(({
key
,
name
})
=>
({
text
:
`
${
name
}
(
${
key
}
)`
,
value
:
key
}));
/**
...
...
@@ -32,10 +32,10 @@ export const extractJiraProjectsOptions = projects =>
* @param {string} jiraImports[].jiraProjectKey - Jira project key
* @returns {string} - A label title
*/
const
calculateJiraImportLabelTitle
=
jiraImports
=>
{
const
calculateJiraImportLabelTitle
=
(
jiraImports
)
=>
{
const
mostRecentJiraProjectKey
=
last
(
jiraImports
)?.
jiraProjectKey
;
const
jiraProjectImportCount
=
jiraImports
.
filter
(
jiraImport
=>
jiraImport
.
jiraProjectKey
===
mostRecentJiraProjectKey
,
(
jiraImport
)
=>
jiraImport
.
jiraProjectKey
===
mostRecentJiraProjectKey
,
).
length
;
return
`jira-import::
${
mostRecentJiraProjectKey
}
-
${
jiraProjectImportCount
}
`
;
};
...
...
@@ -50,7 +50,7 @@ const calculateJiraImportLabelTitle = jiraImports => {
* @returns {string} - The label color associated with the given labelTitle
*/
const
calculateJiraImportLabelColor
=
(
labelTitle
,
labels
)
=>
labels
.
find
(
label
=>
label
.
title
===
labelTitle
)?.
color
;
labels
.
find
(
(
label
)
=>
label
.
title
===
labelTitle
)?.
color
;
/**
* Calculates the label for the most recent Jira import.
...
...
@@ -91,7 +91,7 @@ export const shouldShowFinishedAlert = (labelTitle, importStatus) => {
*
* @param {string} labelTitle - Jira import label, for checking localStorage
*/
export
const
setFinishedAlertHideMap
=
labelTitle
=>
{
export
const
setFinishedAlertHideMap
=
(
labelTitle
)
=>
{
const
finishedAlertHideMap
=
JSON
.
parse
(
localStorage
.
getItem
(
JIRA_IMPORT_SUCCESS_ALERT_HIDE_MAP_KEY
))
||
{};
...
...
app/assets/javascripts/jobs/components/job_app.vue
View file @
e820c228
...
...
@@ -134,7 +134,7 @@ export default {
if
(
isEmpty
(
oldVal
)
&&
!
isEmpty
(
newVal
.
pipeline
))
{
const
stages
=
this
.
job
.
pipeline
.
details
.
stages
||
[];
const
defaultStage
=
stages
.
find
(
stage
=>
stage
&&
stage
.
name
===
this
.
selectedStage
);
const
defaultStage
=
stages
.
find
(
(
stage
)
=>
stage
&&
stage
.
name
===
this
.
selectedStage
);
if
(
defaultStage
)
{
this
.
fetchJobsForStage
(
defaultStage
);
...
...
app/assets/javascripts/jobs/components/log/line.vue
View file @
e820c228
...
...
@@ -18,7 +18,7 @@ export default {
render
(
h
,
{
props
})
{
const
{
line
,
path
}
=
props
;
const
chars
=
line
.
content
.
map
(
content
=>
{
const
chars
=
line
.
content
.
map
(
(
content
)
=>
{
return
h
(
'
span
'
,
{
...
...
@@ -26,7 +26,7 @@ export default {
},
// Simple "tokenization": Split text in chunks of text
// which alternate between text and urls.
content
.
text
.
split
(
linkRegex
).
map
(
chunk
=>
{
content
.
text
.
split
(
linkRegex
).
map
(
(
chunk
)
=>
{
// Return normal string for non-links
if
(
!
chunk
.
match
(
linkRegex
))
{
return
chunk
;
...
...
app/assets/javascripts/jobs/components/manual_variables_form.vue
View file @
e820c228
...
...
@@ -94,7 +94,7 @@ export default {
},
deleteVariable
(
id
)
{
this
.
variables
.
splice
(
this
.
variables
.
findIndex
(
el
=>
el
.
id
===
id
),
this
.
variables
.
findIndex
(
(
el
)
=>
el
.
id
===
id
),
1
,
);
},
...
...
app/assets/javascripts/jobs/components/trigger_block.vue
View file @
e820c228
...
...
@@ -27,7 +27,7 @@ export default {
return
this
.
showVariableValues
?
__
(
'
Hide values
'
)
:
__
(
'
Reveal values
'
);
},
hasValues
()
{
return
this
.
trigger
.
variables
.
some
(
v
=>
v
.
value
);
return
this
.
trigger
.
variables
.
some
(
(
v
)
=>
v
.
value
);
},
},
methods
:
{
...
...
app/assets/javascripts/jobs/store/actions.js
View file @
e820c228
...
...
@@ -188,7 +188,7 @@ export const fetchTrace = ({ dispatch, state }) =>
dispatch
(
'
startPollingTrace
'
);
}
})
.
catch
(
e
=>
.
catch
(
(
e
)
=>
e
.
response
.
status
===
httpStatusCodes
.
FORBIDDEN
?
dispatch
(
'
receiveTraceUnauthorizedError
'
)
:
dispatch
(
'
receiveTraceError
'
),
...
...
@@ -244,7 +244,7 @@ export const fetchJobsForStage = ({ dispatch }, stage = {}) => {
},
})
.
then
(({
data
})
=>
{
const
retriedJobs
=
data
.
retried
.
map
(
job
=>
({
...
job
,
retried
:
true
}));
const
retriedJobs
=
data
.
retried
.
map
(
(
job
)
=>
({
...
job
,
retried
:
true
}));
const
jobs
=
data
.
latest_statuses
.
concat
(
retriedJobs
);
dispatch
(
'
receiveJobsForStageSuccess
'
,
jobs
);
...
...
@@ -259,7 +259,7 @@ export const receiveJobsForStageError = ({ commit }) => {
};
export
const
triggerManualJob
=
({
state
,
dispatch
},
variables
)
=>
{
const
parsedVariables
=
variables
.
map
(
variable
=>
{
const
parsedVariables
=
variables
.
map
(
(
variable
)
=>
{
const
copyVar
=
{
...
variable
};
delete
copyVar
.
id
;
return
copyVar
;
...
...
app/assets/javascripts/jobs/store/getters.js
View file @
e820c228
import
{
isEmpty
,
isString
}
from
'
lodash
'
;
import
{
isScrolledToBottom
}
from
'
~/lib/utils/scroll_utils
'
;
export
const
headerTime
=
state
=>
(
state
.
job
.
started
?
state
.
job
.
started
:
state
.
job
.
created_at
);
export
const
headerTime
=
(
state
)
=>
(
state
.
job
.
started
?
state
.
job
.
started
:
state
.
job
.
created_at
);
export
const
hasForwardDeploymentFailure
=
state
=>
export
const
hasForwardDeploymentFailure
=
(
state
)
=>
state
?.
job
?.
failure_reason
===
'
forward_deployment_failure
'
;
export
const
hasUnmetPrerequisitesFailure
=
state
=>
export
const
hasUnmetPrerequisitesFailure
=
(
state
)
=>
state
?.
job
?.
failure_reason
===
'
unmet_prerequisites
'
;
export
const
shouldRenderCalloutMessage
=
state
=>
export
const
shouldRenderCalloutMessage
=
(
state
)
=>
!
isEmpty
(
state
.
job
.
status
)
&&
!
isEmpty
(
state
.
job
.
callout_message
);
/**
* When job has not started the key will be null
* When job started the key will be a string with a date.
*/
export
const
shouldRenderTriggeredLabel
=
state
=>
isString
(
state
.
job
.
started
);
export
const
shouldRenderTriggeredLabel
=
(
state
)
=>
isString
(
state
.
job
.
started
);
export
const
hasEnvironment
=
state
=>
!
isEmpty
(
state
.
job
.
deployment_status
);
export
const
hasEnvironment
=
(
state
)
=>
!
isEmpty
(
state
.
job
.
deployment_status
);
/**
* Checks if it the job has trace.
* Used to check if it should render the job log or the empty state
* @returns {Boolean}
*/
export
const
hasTrace
=
state
=>
export
const
hasTrace
=
(
state
)
=>
state
.
job
.
has_trace
||
(
!
isEmpty
(
state
.
job
.
status
)
&&
state
.
job
.
status
.
group
===
'
running
'
);
export
const
emptyStateIllustration
=
state
=>
export
const
emptyStateIllustration
=
(
state
)
=>
(
state
.
job
&&
state
.
job
.
status
&&
state
.
job
.
status
.
illustration
)
||
{};
export
const
emptyStateAction
=
state
=>
export
const
emptyStateAction
=
(
state
)
=>
(
state
.
job
&&
state
.
job
.
status
&&
state
.
job
.
status
.
action
)
||
null
;
/**
...
...
@@ -40,12 +40,12 @@ export const emptyStateAction = state =>
*
* @returns {Boolean}
*/
export
const
shouldRenderSharedRunnerLimitWarning
=
state
=>
export
const
shouldRenderSharedRunnerLimitWarning
=
(
state
)
=>
!
isEmpty
(
state
.
job
.
runners
)
&&
!
isEmpty
(
state
.
job
.
runners
.
quota
)
&&
state
.
job
.
runners
.
quota
.
used
>=
state
.
job
.
runners
.
quota
.
limit
;
export
const
isScrollingDown
=
state
=>
isScrolledToBottom
()
&&
!
state
.
isTraceComplete
;
export
const
isScrollingDown
=
(
state
)
=>
isScrolledToBottom
()
&&
!
state
.
isTraceComplete
;
export
const
hasRunnersForProject
=
state
=>
export
const
hasRunnersForProject
=
(
state
)
=>
state
.
job
.
runners
.
available
&&
!
state
.
job
.
runners
.
online
;
app/assets/javascripts/jobs/store/utils.js
View file @
e820c228
...
...
@@ -43,7 +43,7 @@ export const parseHeaderLine = (line = {}, lineNumber) => ({
* @param Object durationLine
*/
export
function
addDurationToHeader
(
data
,
durationLine
)
{
data
.
forEach
(
el
=>
{
data
.
forEach
(
(
el
)
=>
{
if
(
el
.
line
&&
el
.
line
.
section
===
durationLine
.
section
)
{
el
.
line
.
section_duration
=
durationLine
.
section_duration
;
}
...
...
@@ -72,7 +72,7 @@ export const isCollapsibleSection = (acc = [], last = {}, section = {}) =>
* @param Array acc
* @returns Number
*/
export
const
getIncrementalLineNumber
=
acc
=>
{
export
const
getIncrementalLineNumber
=
(
acc
)
=>
{
let
lineNumberValue
;
const
lastIndex
=
acc
.
length
-
1
;
const
lastElement
=
acc
[
lastIndex
];
...
...
app/assets/javascripts/labels_select.js
View file @
e820c228
...
...
@@ -124,15 +124,15 @@ export default class LabelsSelect {
const
toRemoveIds
=
Array
.
from
(
$form
.
find
(
`input[type="hidden"][name="
${
fieldName
}
"]`
),
)
.
map
(
el
=>
el
.
value
)
.
map
(
(
el
)
=>
el
.
value
)
.
map
(
Number
);
data
.
labels
.
forEach
(
label
=>
{
data
.
labels
.
forEach
(
(
label
)
=>
{
const
index
=
toRemoveIds
.
indexOf
(
label
.
id
);
toRemoveIds
.
splice
(
index
,
1
);
});
toRemoveIds
.
forEach
(
id
=>
{
toRemoveIds
.
forEach
(
(
id
)
=>
{
$form
.
find
(
`input[type="hidden"][name="
${
fieldName
}
"][value="
${
id
}
"]`
)
.
last
()
...
...
@@ -157,7 +157,7 @@ export default class LabelsSelect {
const
labelUrl
=
$dropdown
.
attr
(
'
data-labels
'
);
axios
.
get
(
labelUrl
)
.
then
(
res
=>
{
.
then
(
(
res
)
=>
{
let
{
data
}
=
res
;
if
(
$dropdown
.
hasClass
(
'
js-extra-options
'
))
{
const
extraData
=
[];
...
...
@@ -390,7 +390,7 @@ export default class LabelsSelect {
);
}
else
{
let
{
labels
}
=
boardsStore
.
detail
.
issue
;
labels
=
labels
.
filter
(
selectedLabel
=>
selectedLabel
.
id
!==
label
.
id
);
labels
=
labels
.
filter
(
(
selectedLabel
)
=>
selectedLabel
.
id
!==
label
.
id
);
boardsStore
.
detail
.
issue
.
labels
=
labels
;
}
...
...
@@ -401,12 +401,12 @@ export default class LabelsSelect {
.
update
(
$dropdown
.
attr
(
'
data-issue-update
'
))
.
then
(()
=>
{
if
(
isScopedLabel
(
label
))
{
const
prevIds
=
oldLabels
.
map
(
label
=>
label
.
id
);
const
newIds
=
boardsStore
.
detail
.
issue
.
labels
.
map
(
label
=>
label
.
id
);
const
differentIds
=
prevIds
.
filter
(
x
=>
!
newIds
.
includes
(
x
));
const
prevIds
=
oldLabels
.
map
(
(
label
)
=>
label
.
id
);
const
newIds
=
boardsStore
.
detail
.
issue
.
labels
.
map
(
(
label
)
=>
label
.
id
);
const
differentIds
=
prevIds
.
filter
(
(
x
)
=>
!
newIds
.
includes
(
x
));
$dropdown
.
data
(
'
marked
'
,
newIds
);
$dropdownMenu
.
find
(
differentIds
.
map
(
id
=>
`[data-label-id="
${
id
}
"]`
).
join
(
'
,
'
))
.
find
(
differentIds
.
map
(
(
id
)
=>
`[data-label-id="
${
id
}
"]`
).
join
(
'
,
'
))
.
removeClass
(
'
is-active
'
);
}
})
...
...
app/assets/javascripts/lazy_loader.js
View file @
e820c228
...
...
@@ -28,10 +28,10 @@ export default class LazyLoader {
const
lazyImages
=
[].
slice
.
call
(
document
.
querySelectorAll
(
'
.lazy
'
));
if
(
LazyLoader
.
supportsNativeLazyLoading
())
{
lazyImages
.
forEach
(
img
=>
LazyLoader
.
loadImage
(
img
));
lazyImages
.
forEach
(
(
img
)
=>
LazyLoader
.
loadImage
(
img
));
}
else
if
(
LazyLoader
.
supportsIntersectionObserver
())
{
if
(
this
.
intersectionObserver
)
{
lazyImages
.
forEach
(
img
=>
this
.
intersectionObserver
.
observe
(
img
));
lazyImages
.
forEach
(
(
img
)
=>
this
.
intersectionObserver
.
observe
(
img
));
}
}
else
if
(
lazyImages
.
length
)
{
this
.
lazyImages
=
lazyImages
;
...
...
@@ -98,8 +98,8 @@ export default class LazyLoader {
});
};
onIntersection
=
entries
=>
{
entries
.
forEach
(
entry
=>
{
onIntersection
=
(
entries
)
=>
{
entries
.
forEach
(
(
entry
)
=>
{
// We are using `intersectionRatio > 0` over `isIntersecting`, as some browsers did not ship the latter
// See: https://gitlab.com/gitlab-org/gitlab-foss/issues/54407
if
(
entry
.
intersectionRatio
>
0
)
{
...
...
@@ -126,7 +126,7 @@ export default class LazyLoader {
const
visHeight
=
scrollTop
+
window
.
innerHeight
+
SCROLL_THRESHOLD
;
// Loading Images which are in the current viewport or close to them
this
.
lazyImages
=
this
.
lazyImages
.
filter
(
selectedImage
=>
{
this
.
lazyImages
=
this
.
lazyImages
.
filter
(
(
selectedImage
)
=>
{
if
(
selectedImage
.
getAttribute
(
'
data-src
'
))
{
const
imgBoundRect
=
selectedImage
.
getBoundingClientRect
();
const
imgTop
=
scrollTop
+
imgBoundRect
.
top
;
...
...
app/assets/javascripts/lib/chrome_84_icon_fix.js
View file @
e820c228
...
...
@@ -30,7 +30,7 @@ document.addEventListener('DOMContentLoaded', async () => {
const
fixSVGs
=
()
=>
{
requestIdleCallback
(()
=>
{
document
.
querySelectorAll
(
`use:not([
${
SKIP_ATTRIBUTE
}
])`
).
forEach
(
use
=>
{
document
.
querySelectorAll
(
`use:not([
${
SKIP_ATTRIBUTE
}
])`
).
forEach
(
(
use
)
=>
{
const
href
=
use
?.
getAttribute
(
'
href
'
)
??
use
?.
getAttribute
(
'
xlink:href
'
)
??
''
;
if
(
href
.
includes
(
window
.
gon
.
sprite_icons
))
{
...
...
@@ -60,7 +60,7 @@ document.addEventListener('DOMContentLoaded', async () => {
div
.
classList
.
add
(
'
hidden
'
);
const
result
=
await
fetch
(
url
);
div
.
innerHTML
=
await
result
.
text
();
div
.
querySelectorAll
(
'
[id]
'
).
forEach
(
node
=>
{
div
.
querySelectorAll
(
'
[id]
'
).
forEach
(
(
node
)
=>
{
node
.
setAttribute
(
'
id
'
,
`
${
prefix
}
-
${
node
.
getAttribute
(
'
id
'
)}
`
);
});
document
.
body
.
append
(
div
);
...
...
app/assets/javascripts/lib/dompurify.js
View file @
e820c228
...
...
@@ -11,9 +11,9 @@ const defaultConfig = {
const
getAllowedIconUrls
=
(
gon
=
window
.
gon
)
=>
[
gon
.
sprite_file_icons
,
gon
.
sprite_icons
].
filter
(
Boolean
);
const
isUrlAllowed
=
url
=>
getAllowedIconUrls
().
some
(
allowedUrl
=>
url
.
startsWith
(
allowedUrl
));
const
isUrlAllowed
=
(
url
)
=>
getAllowedIconUrls
().
some
((
allowedUrl
)
=>
url
.
startsWith
(
allowedUrl
));
const
isHrefSafe
=
url
=>
const
isHrefSafe
=
(
url
)
=>
isUrlAllowed
(
url
)
||
isUrlAllowed
(
relativePathToAbsolute
(
url
,
getBaseURL
()));
const
removeUnsafeHref
=
(
node
,
attr
)
=>
{
...
...
@@ -36,7 +36,7 @@ const removeUnsafeHref = (node, attr) => {
*
* @param {Object} node - Node to sanitize
*/
const
sanitizeSvgIcon
=
node
=>
{
const
sanitizeSvgIcon
=
(
node
)
=>
{
removeUnsafeHref
(
node
,
'
href
'
);
// Note: `xlink:href` is deprecated, but still in use
...
...
@@ -44,7 +44,7 @@ const sanitizeSvgIcon = node => {
removeUnsafeHref
(
node
,
'
xlink:href
'
);
};
addHook
(
'
afterSanitizeAttributes
'
,
node
=>
{
addHook
(
'
afterSanitizeAttributes
'
,
(
node
)
=>
{
if
(
node
.
tagName
.
toLowerCase
()
===
'
use
'
)
{
sanitizeSvgIcon
(
node
);
}
...
...
app/assets/javascripts/lib/graphql.js
View file @
e820c228
...
...
@@ -36,13 +36,13 @@ export default (resolvers = {}, config = {}) => {
};
const
uploadsLink
=
ApolloLink
.
split
(
operation
=>
operation
.
getContext
().
hasUpload
||
operation
.
getContext
().
isSingleRequest
,
(
operation
)
=>
operation
.
getContext
().
hasUpload
||
operation
.
getContext
().
isSingleRequest
,
createUploadLink
(
httpOptions
),
new
BatchHttpLink
(
httpOptions
),
);
const
performanceBarLink
=
new
ApolloLink
((
operation
,
forward
)
=>
{
return
forward
(
operation
).
map
(
response
=>
{
return
forward
(
operation
).
map
(
(
response
)
=>
{
const
httpResponse
=
operation
.
getContext
().
response
;
if
(
PerformanceBarService
.
interceptor
)
{
...
...
app/assets/javascripts/lib/utils/ajax_cache.js
View file @
e820c228
...
...
@@ -25,7 +25,7 @@ class AjaxCache extends Cache {
this
.
internalStorage
[
endpoint
]
=
data
;
delete
this
.
pendingRequests
[
endpoint
];
})
.
catch
(
e
=>
{
.
catch
(
(
e
)
=>
{
const
error
=
new
Error
(
`
${
endpoint
}
:
${
e
.
message
}
`
);
error
.
textStatus
=
e
.
message
;
...
...
app/assets/javascripts/lib/utils/apollo_startup_js_link.js
View file @
e820c228
...
...
@@ -7,7 +7,7 @@ import { isEqual, pickBy } from 'lodash';
* @param obj
* @returns {Dictionary<unknown>}
*/
const
pickDefinedValues
=
obj
=>
pickBy
(
obj
,
x
=>
x
!==
undefined
);
const
pickDefinedValues
=
(
obj
)
=>
pickBy
(
obj
,
(
x
)
=>
x
!==
undefined
);
/**
* Compares two set of variables, order independent
...
...
@@ -28,9 +28,9 @@ export class StartupJSLink extends ApolloLink {
// Extract operationNames from the queries and ensure that we can
// match operationName => element from result array
parseStartupCalls
(
calls
)
{
calls
.
forEach
(
call
=>
{
calls
.
forEach
(
(
call
)
=>
{
const
{
query
,
variables
,
fetchCall
}
=
call
;
const
operationName
=
parse
(
query
)?.
definitions
?.
find
(
x
=>
x
.
kind
===
'
OperationDefinition
'
)
const
operationName
=
parse
(
query
)?.
definitions
?.
find
(
(
x
)
=>
x
.
kind
===
'
OperationDefinition
'
)
?.
name
?.
value
;
if
(
operationName
)
{
...
...
@@ -71,9 +71,9 @@ export class StartupJSLink extends ApolloLink {
return
forward
(
operation
);
}
return
new
Observable
(
observer
=>
{
return
new
Observable
(
(
observer
)
=>
{
fetchCall
.
then
(
response
=>
{
.
then
(
(
response
)
=>
{
// Handle HTTP errors
if
(
!
response
.
ok
)
{
throw
new
Error
(
'
fetchCall failed
'
);
...
...
@@ -81,7 +81,7 @@ export class StartupJSLink extends ApolloLink {
operation
.
setContext
({
response
});
return
response
.
json
();
})
.
then
(
result
=>
{
.
then
(
(
result
)
=>
{
if
(
result
&&
(
result
.
errors
||
!
result
.
data
))
{
throw
new
Error
(
'
Received GraphQL error
'
);
}
...
...
@@ -92,10 +92,10 @@ export class StartupJSLink extends ApolloLink {
})
.
catch
(()
=>
{
forward
(
operation
).
subscribe
({
next
:
result
=>
{
next
:
(
result
)
=>
{
observer
.
next
(
result
);
},
error
:
error
=>
{
error
:
(
error
)
=>
{
observer
.
error
(
error
);
},
complete
:
observer
.
complete
.
bind
(
observer
),
...
...
app/assets/javascripts/lib/utils/autosave.js
View file @
e820c228
import
{
capitalizeFirstCharacter
}
from
'
~/lib/utils/text_utility
'
;
export
const
clearDraft
=
autosaveKey
=>
{
export
const
clearDraft
=
(
autosaveKey
)
=>
{
try
{
window
.
localStorage
.
removeItem
(
`autosave/
${
autosaveKey
}
`
);
}
catch
(
e
)
{
...
...
@@ -9,7 +9,7 @@ export const clearDraft = autosaveKey => {
}
};
export
const
getDraft
=
autosaveKey
=>
{
export
const
getDraft
=
(
autosaveKey
)
=>
{
try
{
return
window
.
localStorage
.
getItem
(
`autosave/
${
autosaveKey
}
`
);
}
catch
(
e
)
{
...
...
app/assets/javascripts/lib/utils/axios_startup_calls.js
View file @
e820c228
...
...
@@ -3,9 +3,9 @@ import { mergeUrlParams } from './url_utility';
// We should probably not couple this utility to `gon.gitlab_url`
// Also, this would replace occurrences that aren't at the beginning of the string
const
removeGitLabUrl
=
url
=>
url
.
replace
(
gon
.
gitlab_url
,
''
);
const
removeGitLabUrl
=
(
url
)
=>
url
.
replace
(
gon
.
gitlab_url
,
''
);
const
getFullUrl
=
req
=>
{
const
getFullUrl
=
(
req
)
=>
{
const
url
=
removeGitLabUrl
(
req
.
url
);
return
mergeUrlParams
(
req
.
params
||
{},
url
,
{
sort
:
true
});
};
...
...
@@ -36,7 +36,7 @@ const handleStartupCall = async ({ fetchCall }, req) => {
});
};
const
setupAxiosStartupCalls
=
axios
=>
{
const
setupAxiosStartupCalls
=
(
axios
)
=>
{
const
{
startup_calls
:
startupCalls
}
=
window
.
gl
||
{};
if
(
!
startupCalls
||
isEmpty
(
startupCalls
))
{
...
...
@@ -45,7 +45,7 @@ const setupAxiosStartupCalls = axios => {
const
remainingCalls
=
new
Map
(
Object
.
entries
(
startupCalls
));
const
interceptor
=
axios
.
interceptors
.
request
.
use
(
async
req
=>
{
const
interceptor
=
axios
.
interceptors
.
request
.
use
(
async
(
req
)
=>
{
const
fullUrl
=
getFullUrl
(
req
);
const
startupCall
=
remainingCalls
.
get
(
fullUrl
);
...
...
app/assets/javascripts/lib/utils/axios_utils.js
View file @
e820c228
...
...
@@ -9,7 +9,7 @@ axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
// Maintain a global counter for active requests
// see: spec/support/wait_for_requests.rb
axios
.
interceptors
.
request
.
use
(
config
=>
{
axios
.
interceptors
.
request
.
use
(
(
config
)
=>
{
window
.
pendingRequests
=
window
.
pendingRequests
||
0
;
window
.
pendingRequests
+=
1
;
return
config
;
...
...
@@ -19,11 +19,11 @@ setupAxiosStartupCalls(axios);
// Remove the global counter
axios
.
interceptors
.
response
.
use
(
response
=>
{
(
response
)
=>
{
window
.
pendingRequests
-=
1
;
return
response
;
},
err
=>
{
(
err
)
=>
{
window
.
pendingRequests
-=
1
;
return
Promise
.
reject
(
err
);
},
...
...
@@ -37,8 +37,8 @@ window.addEventListener('beforeunload', () => {
// Ignore AJAX errors caused by requests
// being cancelled due to browser navigation
axios
.
interceptors
.
response
.
use
(
response
=>
response
,
err
=>
suppressAjaxErrorsDuringNavigation
(
err
,
isUserNavigating
),
(
response
)
=>
response
,
(
err
)
=>
suppressAjaxErrorsDuringNavigation
(
err
,
isUserNavigating
),
);
export
default
axios
;
...
...
app/assets/javascripts/lib/utils/bootstrap_linked_tabs.js
View file @
e820c228
...
...
@@ -68,7 +68,7 @@ export default class LinkedTabs {
// since this is a custom event we need jQuery :(
$
(
document
)
.
off
(
'
shown.bs.tab
'
,
tabSelector
)
.
on
(
'
shown.bs.tab
'
,
tabSelector
,
e
=>
this
.
tabShown
(
e
));
.
on
(
'
shown.bs.tab
'
,
tabSelector
,
(
e
)
=>
this
.
tabShown
(
e
));
this
.
activateTab
(
this
.
action
);
}
...
...
app/assets/javascripts/lib/utils/chart_utils.js
View file @
e820c228
...
...
@@ -34,7 +34,7 @@ const commonChartOptions = () => ({
legend
:
false
,
});
export
const
barChartOptions
=
shouldAdjustFontSize
=>
({
export
const
barChartOptions
=
(
shouldAdjustFontSize
)
=>
({
...
commonChartOptions
(),
scales
:
{
...
yAxesConfig
(
shouldAdjustFontSize
),
...
...
@@ -89,7 +89,7 @@ export const lineChartOptions = ({ width, numberOfPoints, shouldAdjustFontSize }
* @param {Array} data
* @returns {[*, *]}
*/
export
const
firstAndLastY
=
data
=>
{
export
const
firstAndLastY
=
(
data
)
=>
{
const
[
firstEntry
]
=
data
;
const
[
lastEntry
]
=
data
.
slice
(
-
1
);
...
...
app/assets/javascripts/lib/utils/color_utils.js
View file @
e820c228
...
...
@@ -4,7 +4,7 @@
* @param hex string
* @returns array|null
*/
export
const
hexToRgb
=
hex
=>
{
export
const
hexToRgb
=
(
hex
)
=>
{
// Expand shorthand form (e.g. "03F") to full form (e.g. "0033FF")
const
shorthandRegex
=
/^#
?([
a-f
\d])([
a-f
\d])([
a-f
\d])
$/i
;
const
fullHex
=
hex
.
replace
(
shorthandRegex
,
(
_m
,
r
,
g
,
b
)
=>
r
+
r
+
g
+
g
+
b
+
b
);
...
...
@@ -15,7 +15,7 @@ export const hexToRgb = hex => {
:
null
;
};
export
const
textColorForBackground
=
backgroundColor
=>
{
export
const
textColorForBackground
=
(
backgroundColor
)
=>
{
const
[
r
,
g
,
b
]
=
hexToRgb
(
backgroundColor
);
if
(
r
+
g
+
b
>
500
)
{
...
...
app/assets/javascripts/lib/utils/common_utils.js
View file @
e820c228
...
...
@@ -54,7 +54,7 @@ export const getCspNonceValue = () => {
return
metaTag
&&
metaTag
.
content
;
};
export
const
rstrip
=
val
=>
{
export
const
rstrip
=
(
val
)
=>
{
if
(
val
)
{
return
val
.
replace
(
/
\s
+$/
,
''
);
}
...
...
@@ -149,13 +149,13 @@ export const isInViewport = (el, offset = {}) => {
);
};
export
const
parseUrl
=
url
=>
{
export
const
parseUrl
=
(
url
)
=>
{
const
parser
=
document
.
createElement
(
'
a
'
);
parser
.
href
=
url
;
return
parser
;
};
export
const
parseUrlPathname
=
url
=>
{
export
const
parseUrlPathname
=
(
url
)
=>
{
const
parsedUrl
=
parseUrl
(
url
);
// parsedUrl.pathname will return an absolute path for Firefox and a relative path for IE11
// We have to make sure we always have an absolute path.
...
...
@@ -166,8 +166,8 @@ const splitPath = (path = '') => path.replace(/^\?/, '').split('&');
export
const
urlParamsToArray
=
(
path
=
''
)
=>
splitPath
(
path
)
.
filter
(
param
=>
param
.
length
>
0
)
.
map
(
param
=>
{
.
filter
(
(
param
)
=>
param
.
length
>
0
)
.
map
(
(
param
)
=>
{
const
split
=
param
.
split
(
'
=
'
);
return
[
decodeURI
(
split
[
0
]),
split
[
1
]].
join
(
'
=
'
);
});
...
...
@@ -209,13 +209,13 @@ export const urlParamsToObject = (path = '') =>
return
data
;
},
{});
export
const
isMetaKey
=
e
=>
e
.
metaKey
||
e
.
ctrlKey
||
e
.
altKey
||
e
.
shiftKey
;
export
const
isMetaKey
=
(
e
)
=>
e
.
metaKey
||
e
.
ctrlKey
||
e
.
altKey
||
e
.
shiftKey
;
// Identify following special clicks
// 1) Cmd + Click on Mac (e.metaKey)
// 2) Ctrl + Click on PC (e.ctrlKey)
// 3) Middle-click or Mouse Wheel Click (e.which is 2)
export
const
isMetaClick
=
e
=>
e
.
metaKey
||
e
.
ctrlKey
||
e
.
which
===
2
;
export
const
isMetaClick
=
(
e
)
=>
e
.
metaKey
||
e
.
ctrlKey
||
e
.
which
===
2
;
export
const
contentTop
=
()
=>
{
const
isDesktop
=
breakpointInstance
.
isDesktop
();
...
...
@@ -277,7 +277,7 @@ export const scrollToElement = (element, options = {}) => {
);
};
export
const
scrollToElementWithContext
=
element
=>
{
export
const
scrollToElementWithContext
=
(
element
)
=>
{
const
offsetMultiplier
=
-
0.1
;
return
scrollToElement
(
element
,
{
offset
:
window
.
innerHeight
*
offsetMultiplier
});
};
...
...
@@ -287,7 +287,7 @@ export const scrollToElementWithContext = element => {
* each browser screen repaint.
* @param {Function} fn
*/
export
const
debounceByAnimationFrame
=
fn
=>
{
export
const
debounceByAnimationFrame
=
(
fn
)
=>
{
let
requestId
;
return
function
debounced
(...
args
)
{
...
...
@@ -334,7 +334,7 @@ const handleSelectedRange = (range, restrictToNode) => {
return
range
.
cloneContents
();
};
export
const
getSelectedFragment
=
restrictToNode
=>
{
export
const
getSelectedFragment
=
(
restrictToNode
)
=>
{
const
selection
=
window
.
getSelection
();
if
(
selection
.
rangeCount
===
0
)
return
null
;
// Most usages of the selection only want text from a part of the page (e.g. discussion)
...
...
@@ -390,10 +390,10 @@ export const insertText = (target, text) => {
this will take in the headers from an API response and normalize them
this way we don't run into production issues when nginx gives us lowercased header keys
*/
export
const
normalizeHeaders
=
headers
=>
{
export
const
normalizeHeaders
=
(
headers
)
=>
{
const
upperCaseHeaders
=
{};
Object
.
keys
(
headers
||
{}).
forEach
(
e
=>
{
Object
.
keys
(
headers
||
{}).
forEach
(
(
e
)
=>
{
upperCaseHeaders
[
e
.
toUpperCase
()]
=
headers
[
e
];
});
...
...
@@ -406,7 +406,7 @@ export const normalizeHeaders = headers => {
* @param {Object} paginationInformation
* @returns {Object}
*/
export
const
parseIntPagination
=
paginationInformation
=>
({
export
const
parseIntPagination
=
(
paginationInformation
)
=>
({
perPage
:
parseInt
(
paginationInformation
[
'
X-PER-PAGE
'
],
10
),
page
:
parseInt
(
paginationInformation
[
'
X-PAGE
'
],
10
),
total
:
parseInt
(
paginationInformation
[
'
X-TOTAL
'
],
10
),
...
...
@@ -445,10 +445,10 @@ export const parseQueryStringIntoObject = (query = '') => {
*/
export
const
objectToQueryString
=
(
params
=
{})
=>
Object
.
keys
(
params
)
.
map
(
param
=>
`
${
param
}
=
${
params
[
param
]}
`
)
.
map
(
(
param
)
=>
`
${
param
}
=
${
params
[
param
]}
`
)
.
join
(
'
&
'
);
export
const
buildUrlWithCurrentLocation
=
param
=>
{
export
const
buildUrlWithCurrentLocation
=
(
param
)
=>
{
if
(
param
)
return
`
${
window
.
location
.
pathname
}${
param
}
`
;
return
window
.
location
.
pathname
;
...
...
@@ -460,7 +460,7 @@ export const buildUrlWithCurrentLocation = param => {
*
* @param {String} param
*/
export
const
historyPushState
=
newUrl
=>
{
export
const
historyPushState
=
(
newUrl
)
=>
{
window
.
history
.
pushState
({},
document
.
title
,
newUrl
);
};
...
...
@@ -470,7 +470,7 @@ export const historyPushState = newUrl => {
*
* @param {String} param
*/
export
const
historyReplaceState
=
newUrl
=>
{
export
const
historyReplaceState
=
(
newUrl
)
=>
{
window
.
history
.
replaceState
({},
document
.
title
,
newUrl
);
};
...
...
@@ -482,7 +482,7 @@ export const historyReplaceState = newUrl => {
* @param {String} value
* @returns {Boolean}
*/
export
const
parseBoolean
=
value
=>
(
value
&&
value
.
toString
())
===
'
true
'
;
export
const
parseBoolean
=
(
value
)
=>
(
value
&&
value
.
toString
())
===
'
true
'
;
export
const
BACKOFF_TIMEOUT
=
'
BACKOFF_TIMEOUT
'
;
...
...
@@ -529,7 +529,7 @@ export const backOff = (fn, timeout = 60000) => {
let
timeElapsed
=
0
;
return
new
Promise
((
resolve
,
reject
)
=>
{
const
stop
=
arg
=>
(
arg
instanceof
Error
?
reject
(
arg
)
:
resolve
(
arg
));
const
stop
=
(
arg
)
=>
(
arg
instanceof
Error
?
reject
(
arg
)
:
resolve
(
arg
));
const
next
=
()
=>
{
if
(
timeElapsed
<
timeout
)
{
...
...
@@ -548,7 +548,7 @@ export const backOff = (fn, timeout = 60000) => {
export
const
createOverlayIcon
=
(
iconPath
,
overlayPath
)
=>
{
const
faviconImage
=
document
.
createElement
(
'
img
'
);
return
new
Promise
(
resolve
=>
{
return
new
Promise
(
(
resolve
)
=>
{
faviconImage
.
onload
=
()
=>
{
const
size
=
32
;
...
...
@@ -594,7 +594,7 @@ export const createOverlayIcon = (iconPath, overlayPath) => {
});
};
export
const
setFaviconOverlay
=
overlayPath
=>
{
export
const
setFaviconOverlay
=
(
overlayPath
)
=>
{
const
faviconEl
=
document
.
getElementById
(
'
favicon
'
);
if
(
!
faviconEl
)
{
...
...
@@ -603,7 +603,7 @@ export const setFaviconOverlay = overlayPath => {
const
iconPath
=
faviconEl
.
getAttribute
(
'
data-original-href
'
);
return
createOverlayIcon
(
iconPath
,
overlayPath
).
then
(
faviconWithOverlayUrl
=>
return
createOverlayIcon
(
iconPath
,
overlayPath
).
then
(
(
faviconWithOverlayUrl
)
=>
faviconEl
.
setAttribute
(
'
href
'
,
faviconWithOverlayUrl
),
);
};
...
...
@@ -617,7 +617,7 @@ export const resetFavicon = () => {
}
};
export
const
setCiStatusFavicon
=
pageUrl
=>
export
const
setCiStatusFavicon
=
(
pageUrl
)
=>
axios
.
get
(
pageUrl
)
.
then
(({
data
})
=>
{
...
...
@@ -626,7 +626,7 @@ export const setCiStatusFavicon = pageUrl =>
}
return
resetFavicon
();
})
.
catch
(
error
=>
{
.
catch
(
(
error
)
=>
{
resetFavicon
();
throw
error
;
});
...
...
@@ -728,7 +728,7 @@ export const convertObjectPropsToCamelCase = (obj = {}, options = {}) =>
export
const
convertObjectPropsToSnakeCase
=
(
obj
=
{},
options
=
{})
=>
convertObjectProps
(
convertToSnakeCase
,
obj
,
options
);
export
const
imagePath
=
imgUrl
=>
export
const
imagePath
=
(
imgUrl
)
=>
`
${
gon
.
asset_host
||
''
}${
gon
.
relative_url_root
||
''
}
/assets/
${
imgUrl
}
`
;
export
const
addSelectOnFocusBehaviour
=
(
selector
=
'
.js-select-on-focus
'
)
=>
{
...
...
@@ -737,7 +737,7 @@ export const addSelectOnFocusBehaviour = (selector = '.js-select-on-focus') => {
$
(
selector
).
on
(
'
focusin
'
,
function
selectOnFocusCallback
()
{
$
(
this
)
.
select
()
.
one
(
'
mouseup
'
,
e
=>
{
.
one
(
'
mouseup
'
,
(
e
)
=>
{
e
.
preventDefault
();
});
});
...
...
@@ -833,7 +833,7 @@ export const searchBy = (query = '', searchSpace = {}) => {
const
normalizedQuery
=
query
.
toLowerCase
();
const
matches
=
targetKeys
.
filter
(
item
=>
{
.
filter
(
(
item
)
=>
{
const
searchItem
=
`
${
searchSpace
[
item
]}
`
.
toLowerCase
();
return
(
...
...
@@ -867,9 +867,9 @@ export const isScopedLabel = ({ title = '' }) => title.indexOf('::') !== -1;
// Methods to set and get Cookie
export
const
setCookie
=
(
name
,
value
)
=>
Cookies
.
set
(
name
,
value
,
{
expires
:
365
});
export
const
getCookie
=
name
=>
Cookies
.
get
(
name
);
export
const
getCookie
=
(
name
)
=>
Cookies
.
get
(
name
);
export
const
removeCookie
=
name
=>
Cookies
.
remove
(
name
);
export
const
removeCookie
=
(
name
)
=>
Cookies
.
remove
(
name
);
/**
* Returns the status of a feature flag.
...
...
@@ -884,4 +884,4 @@ export const removeCookie = name => Cookies.remove(name);
* @param {String} flag Feature flag
* @returns {Boolean} on/off
*/
export
const
isFeatureFlagEnabled
=
flag
=>
window
.
gon
.
features
?.[
flag
];
export
const
isFeatureFlagEnabled
=
(
flag
)
=>
window
.
gon
.
features
?.[
flag
];
app/assets/javascripts/lib/utils/css_utils.js
View file @
e820c228
export
function
loadCSSFile
(
path
)
{
return
new
Promise
(
resolve
=>
{
return
new
Promise
(
(
resolve
)
=>
{
if
(
!
path
)
resolve
();
if
(
document
.
querySelector
(
`link[href="
${
path
}
"]`
))
{
...
...
app/assets/javascripts/lib/utils/datetime_range.js
View file @
e820c228
...
...
@@ -7,7 +7,7 @@ const MINIMUM_DATE = new Date(0);
const
DEFAULT_DIRECTION
=
'
before
'
;
const
durationToMillis
=
duration
=>
{
const
durationToMillis
=
(
duration
)
=>
{
if
(
Object
.
entries
(
duration
).
length
===
1
&&
Number
.
isFinite
(
duration
.
seconds
))
{
return
secondsToMilliseconds
(
duration
.
seconds
);
}
...
...
@@ -19,9 +19,9 @@ const dateMinusDuration = (date, duration) => new Date(date.getTime() - duration
const
datePlusDuration
=
(
date
,
duration
)
=>
new
Date
(
date
.
getTime
()
+
durationToMillis
(
duration
));
const
isValidDuration
=
duration
=>
Boolean
(
duration
&&
Number
.
isFinite
(
duration
.
seconds
));
const
isValidDuration
=
(
duration
)
=>
Boolean
(
duration
&&
Number
.
isFinite
(
duration
.
seconds
));
const
isValidDateString
=
dateString
=>
{
const
isValidDateString
=
(
dateString
)
=>
{
if
(
typeof
dateString
!==
'
string
'
||
!
dateString
.
trim
())
{
return
false
;
}
...
...
@@ -225,7 +225,7 @@ export function getRangeType(range) {
*
* @returns {FixedRange} An object with a start and end in ISO8601 format.
*/
export
const
convertToFixedRange
=
dateTimeRange
=>
export
const
convertToFixedRange
=
(
dateTimeRange
)
=>
handlers
[
getRangeType
(
dateTimeRange
)](
dateTimeRange
);
/**
...
...
@@ -242,7 +242,7 @@ export const convertToFixedRange = dateTimeRange =>
* @param {Object} timeRange - A time range object
* @returns Copy of time range
*/
const
pruneTimeRange
=
timeRange
=>
{
const
pruneTimeRange
=
(
timeRange
)
=>
{
const
res
=
pick
(
timeRange
,
[
'
start
'
,
'
end
'
,
'
anchor
'
,
'
duration
'
,
'
direction
'
]);
if
(
res
.
direction
===
DEFAULT_DIRECTION
)
{
return
omit
(
res
,
'
direction
'
);
...
...
@@ -272,7 +272,7 @@ export const isEqualTimeRanges = (timeRange, other) => {
* @param {Array} timeRanges - Array of time tanges (haystack)
*/
export
const
findTimeRange
=
(
timeRange
,
timeRanges
)
=>
timeRanges
.
find
(
element
=>
isEqualTimeRanges
(
element
,
timeRange
));
timeRanges
.
find
(
(
element
)
=>
isEqualTimeRanges
(
element
,
timeRange
));
// Time Ranges as URL Parameters Utils
...
...
@@ -289,11 +289,11 @@ export const timeRangeParamNames = ['start', 'end', 'anchor', 'duration_seconds'
* @param {Object} A time range
* @returns key-value pairs object that can be used as parameters in a URL.
*/
export
const
timeRangeToParams
=
timeRange
=>
{
export
const
timeRangeToParams
=
(
timeRange
)
=>
{
let
params
=
pruneTimeRange
(
timeRange
);
if
(
timeRange
.
duration
)
{
const
durationParms
=
{};
Object
.
keys
(
timeRange
.
duration
).
forEach
(
key
=>
{
Object
.
keys
(
timeRange
.
duration
).
forEach
(
(
key
)
=>
{
durationParms
[
`duration_
${
key
}
`
]
=
timeRange
.
duration
[
key
].
toString
();
});
params
=
{
...
durationParms
,
...
params
};
...
...
@@ -309,7 +309,7 @@ export const timeRangeToParams = timeRange => {
*
* @param {params} params - key-value pairs object.
*/
export
const
timeRangeFromParams
=
params
=>
{
export
const
timeRangeFromParams
=
(
params
)
=>
{
const
timeRangeParams
=
pick
(
params
,
timeRangeParamNames
);
let
range
=
Object
.
entries
(
timeRangeParams
).
reduce
((
acc
,
[
key
,
val
])
=>
{
// unflatten duration
...
...
app/assets/javascripts/lib/utils/datetime_utility.js
View file @
e820c228
...
...
@@ -12,7 +12,7 @@ window.timeago = timeago;
*
* @param {Date} date
*/
export
const
newDate
=
date
=>
(
date
instanceof
Date
?
new
Date
(
date
.
getTime
())
:
new
Date
());
export
const
newDate
=
(
date
)
=>
(
date
instanceof
Date
?
new
Date
(
date
.
getTime
())
:
new
Date
());
/**
* Returns i18n month names array.
...
...
@@ -21,7 +21,7 @@ export const newDate = date => (date instanceof Date ? new Date(date.getTime())
*
* @param {Boolean} abbreviated
*/
export
const
getMonthNames
=
abbreviated
=>
{
export
const
getMonthNames
=
(
abbreviated
)
=>
{
if
(
abbreviated
)
{
return
[
s__
(
'
Jan
'
),
...
...
@@ -74,7 +74,7 @@ export const getWeekdayNames = () => [
* @param {date} date
* @returns {String}
*/
export
const
getDayName
=
date
=>
export
const
getDayName
=
(
date
)
=>
[
__
(
'
Sunday
'
),
__
(
'
Monday
'
),
...
...
@@ -242,7 +242,7 @@ export const getDayDifference = (a, b) => {
* @param {Number} seconds
* @return {String}
*/
export
const
timeIntervalInWords
=
intervalInSeconds
=>
{
export
const
timeIntervalInWords
=
(
intervalInSeconds
)
=>
{
const
secondsInteger
=
parseInt
(
intervalInSeconds
,
10
);
const
minutes
=
Math
.
floor
(
secondsInteger
/
60
);
const
seconds
=
secondsInteger
-
minutes
*
60
;
...
...
@@ -316,7 +316,7 @@ export const monthInWords = (date, abbreviated = false) => {
*
* @param {Date} date
*/
export
const
totalDaysInMonth
=
date
=>
{
export
const
totalDaysInMonth
=
(
date
)
=>
{
if
(
!
date
)
{
return
0
;
}
...
...
@@ -329,7 +329,7 @@ export const totalDaysInMonth = date => {
*
* @param {Array} quarter
*/
export
const
totalDaysInQuarter
=
quarter
=>
export
const
totalDaysInQuarter
=
(
quarter
)
=>
quarter
.
reduce
((
acc
,
month
)
=>
acc
+
totalDaysInMonth
(
month
),
0
);
/**
...
...
@@ -338,7 +338,7 @@ export const totalDaysInQuarter = quarter =>
*
* @param {Date} date
*/
export
const
getSundays
=
date
=>
{
export
const
getSundays
=
(
date
)
=>
{
if
(
!
date
)
{
return
[];
}
...
...
@@ -449,7 +449,7 @@ window.gl.utils = {
* @param milliseconds
* @returns {string}
*/
export
const
formatTime
=
milliseconds
=>
{
export
const
formatTime
=
(
milliseconds
)
=>
{
const
remainingSeconds
=
Math
.
floor
(
milliseconds
/
1000
)
%
60
;
const
remainingMinutes
=
Math
.
floor
(
milliseconds
/
1000
/
60
)
%
60
;
const
remainingHours
=
Math
.
floor
(
milliseconds
/
1000
/
60
/
60
);
...
...
@@ -468,7 +468,7 @@ export const formatTime = milliseconds => {
* @param {String} dateString Date in yyyy-mm-dd format
* @return {Date} UTC format
*/
export
const
parsePikadayDate
=
dateString
=>
{
export
const
parsePikadayDate
=
(
dateString
)
=>
{
const
parts
=
dateString
.
split
(
'
-
'
);
const
year
=
parseInt
(
parts
[
0
],
10
);
const
month
=
parseInt
(
parts
[
1
]
-
1
,
10
);
...
...
@@ -482,7 +482,7 @@ export const parsePikadayDate = dateString => {
* @param {Date} date UTC format
* @return {String} Date formatted in yyyy-mm-dd
*/
export
const
pikadayToString
=
date
=>
{
export
const
pikadayToString
=
(
date
)
=>
{
const
day
=
pad
(
date
.
getDate
());
const
month
=
pad
(
date
.
getMonth
()
+
1
);
const
year
=
date
.
getFullYear
();
...
...
@@ -523,7 +523,7 @@ export const parseSeconds = (
let
unorderedMinutes
=
Math
.
abs
(
seconds
/
SECONDS_PER_MINUTE
);
return
mapValues
(
timePeriodConstraints
,
minutesPerPeriod
=>
{
return
mapValues
(
timePeriodConstraints
,
(
minutesPerPeriod
)
=>
{
if
(
minutesPerPeriod
===
0
)
{
return
0
;
}
...
...
@@ -567,7 +567,7 @@ export const stringifyTime = (timeObject, fullNameFormat = false) => {
* @param endDate date string that the time difference is calculated for
* @return {Number} number of milliseconds remaining until the given date
*/
export
const
calculateRemainingMilliseconds
=
endDate
=>
{
export
const
calculateRemainingMilliseconds
=
(
endDate
)
=>
{
const
remainingMilliseconds
=
new
Date
(
endDate
).
getTime
()
-
Date
.
now
();
return
Math
.
max
(
remainingMilliseconds
,
0
);
};
...
...
@@ -598,7 +598,7 @@ export const getDateInFuture = (date, daysInFuture) =>
* @param {Date} date
* @returns boolean
*/
export
const
isValidDate
=
date
=>
date
instanceof
Date
&&
!
Number
.
isNaN
(
date
.
getTime
());
export
const
isValidDate
=
(
date
)
=>
date
instanceof
Date
&&
!
Number
.
isNaN
(
date
.
getTime
());
/*
* Appending T00:00:00 makes JS assume local time and prevents it from shifting the date
...
...
@@ -606,7 +606,7 @@ export const isValidDate = date => date instanceof Date && !Number.isNaN(date.ge
* be consistent with the "edit issue -> due date" UI.
*/
export
const
newDateAsLocaleTime
=
date
=>
{
export
const
newDateAsLocaleTime
=
(
date
)
=>
{
const
suffix
=
'
T00:00:00
'
;
return
new
Date
(
`
${
date
}${
suffix
}
`
);
};
...
...
@@ -620,7 +620,7 @@ export const endOfDayTime = 'T23:59:59Z';
* @param {Function} formatter
* @return {Any[]} an array of formatted dates between 2 given dates (including start&end date)
*/
export
const
getDatesInRange
=
(
d1
,
d2
,
formatter
=
x
=>
x
)
=>
{
export
const
getDatesInRange
=
(
d1
,
d2
,
formatter
=
(
x
)
=>
x
)
=>
{
if
(
!
(
d1
instanceof
Date
)
||
!
(
d2
instanceof
Date
))
{
return
[];
}
...
...
@@ -643,7 +643,7 @@ export const getDatesInRange = (d1, d2, formatter = x => x) => {
* @param {Number} seconds
* @return {Number} number of milliseconds
*/
export
const
secondsToMilliseconds
=
seconds
=>
seconds
*
1000
;
export
const
secondsToMilliseconds
=
(
seconds
)
=>
seconds
*
1000
;
/**
* Converts the supplied number of seconds to days.
...
...
@@ -651,7 +651,7 @@ export const secondsToMilliseconds = seconds => seconds * 1000;
* @param {Number} seconds
* @return {Number} number of days
*/
export
const
secondsToDays
=
seconds
=>
Math
.
round
(
seconds
/
86400
);
export
const
secondsToDays
=
(
seconds
)
=>
Math
.
round
(
seconds
/
86400
);
/**
* Converts a numeric utc offset in seconds to +/- hours
...
...
@@ -662,7 +662,7 @@ export const secondsToDays = seconds => Math.round(seconds / 86400);
*
* @return {String} the + or - offset in hours
*/
export
const
secondsToHours
=
offset
=>
{
export
const
secondsToHours
=
(
offset
)
=>
{
const
parsed
=
parseInt
(
offset
,
10
);
if
(
Number
.
isNaN
(
parsed
)
||
parsed
===
0
)
{
return
`0`
;
...
...
@@ -687,7 +687,7 @@ export const nDaysAfter = (date, numberOfDays) =>
* @param {Date} date the initial date
* @return {Date} the date following the date provided
*/
export
const
dayAfter
=
date
=>
new
Date
(
newDate
(
date
).
setDate
(
date
.
getDate
()
+
1
));
export
const
dayAfter
=
(
date
)
=>
new
Date
(
newDate
(
date
).
setDate
(
date
.
getDate
()
+
1
));
/**
* Mimics the behaviour of the rails distance_of_time_in_words function
...
...
@@ -795,7 +795,7 @@ export const differenceInMilliseconds = (startDate, endDate = Date.now()) => {
*
* @return {Date} the date at the first day of the month
*/
export
const
dateAtFirstDayOfMonth
=
date
=>
new
Date
(
newDate
(
date
).
setDate
(
1
));
export
const
dateAtFirstDayOfMonth
=
(
date
)
=>
new
Date
(
newDate
(
date
).
setDate
(
1
));
/**
* A utility function which checks if two dates match.
...
...
app/assets/javascripts/lib/utils/dom_utils.js
View file @
e820c228
...
...
@@ -6,7 +6,7 @@ import { isInIssuePage, isInMRPage, isInEpicPage } from './common_utils';
*
* @param element DOM element to check
*/
export
const
hasHorizontalOverflow
=
element
=>
export
const
hasHorizontalOverflow
=
(
element
)
=>
Boolean
(
element
&&
element
.
scrollWidth
>
element
.
offsetWidth
);
export
const
addClassIfElementExists
=
(
element
,
className
)
=>
{
...
...
@@ -64,7 +64,7 @@ export const parseBooleanDataAttributes = ({ dataset }, names) =>
* @param {HTMLElement} element The element to test
* @returns {Boolean} `true` if the element is currently visible, otherwise false
*/
export
const
isElementVisible
=
element
=>
export
const
isElementVisible
=
(
element
)
=>
Boolean
(
element
.
offsetWidth
||
element
.
offsetHeight
||
element
.
getClientRects
().
length
);
/**
...
...
@@ -76,4 +76,4 @@ export const isElementVisible = element =>
* @param {HTMLElement} element The element to test
* @returns {Boolean} `true` if the element is currently hidden, otherwise false
*/
export
const
isElementHidden
=
element
=>
!
isElementVisible
(
element
);
export
const
isElementHidden
=
(
element
)
=>
!
isElementVisible
(
element
);
app/assets/javascripts/lib/utils/forms.js
View file @
e820c228
export
const
serializeFormEntries
=
entries
=>
export
const
serializeFormEntries
=
(
entries
)
=>
entries
.
reduce
((
acc
,
{
name
,
value
})
=>
Object
.
assign
(
acc
,
{
[
name
]:
value
}),
{});
export
const
serializeForm
=
form
=>
{
export
const
serializeForm
=
(
form
)
=>
{
const
fdata
=
new
FormData
(
form
);
const
entries
=
Array
.
from
(
fdata
.
keys
()).
map
(
key
=>
{
const
entries
=
Array
.
from
(
fdata
.
keys
()).
map
(
(
key
)
=>
{
let
val
=
fdata
.
getAll
(
key
);
// Microsoft Edge has a bug in FormData.getAll() that returns an undefined
// value for each form element that does not match the given key:
// https://github.com/jimmywarting/FormData/issues/80
val
=
val
.
filter
(
n
=>
n
);
val
=
val
.
filter
(
(
n
)
=>
n
);
return
{
name
:
key
,
value
:
val
.
length
===
1
?
val
[
0
]
:
val
};
});
...
...
@@ -27,7 +27,7 @@ export const serializeForm = form => {
* @example
* returns true for '', [], null, undefined
*/
export
const
isEmptyValue
=
value
=>
value
==
null
||
value
.
length
===
0
;
export
const
isEmptyValue
=
(
value
)
=>
value
==
null
||
value
.
length
===
0
;
/**
* A form object serializer
...
...
@@ -42,7 +42,7 @@ export const isEmptyValue = value => value == null || value.length === 0;
* Returns
* {"project": "hello", "username": "john"}
*/
export
const
serializeFormObject
=
form
=>
export
const
serializeFormObject
=
(
form
)
=>
Object
.
fromEntries
(
Object
.
entries
(
form
).
reduce
((
acc
,
[
name
,
{
value
}])
=>
{
if
(
!
isEmptyValue
(
value
))
{
...
...
app/assets/javascripts/lib/utils/grammar.js
View file @
e820c228
...
...
@@ -16,7 +16,7 @@ import { sprintf, s__ } from '~/locale';
*
* @param {String[]} items
*/
export
const
toNounSeriesText
=
items
=>
{
export
const
toNounSeriesText
=
(
items
)
=>
{
if
(
items
.
length
===
0
)
{
return
''
;
}
else
if
(
items
.
length
===
1
)
{
...
...
app/assets/javascripts/lib/utils/icon_utils.js
View file @
e820c228
...
...
@@ -9,7 +9,7 @@ const getSvgDom = memoize(() =>
axios
.
get
(
gon
.
sprite_icons
)
.
then
(({
data
:
svgs
})
=>
new
DOMParser
().
parseFromString
(
svgs
,
'
text/xml
'
))
.
catch
(
e
=>
{
.
catch
(
(
e
)
=>
{
getSvgDom
.
cache
.
clear
();
throw
e
;
...
...
@@ -34,9 +34,9 @@ export const clearSvgIconPathContentCache = () => {
* @param {String} name - Icon name
* @returns A promise that resolves to the svg path
*/
export
const
getSvgIconPathContent
=
name
=>
export
const
getSvgIconPathContent
=
(
name
)
=>
getSvgDom
()
.
then
(
doc
=>
{
.
then
(
(
doc
)
=>
{
return
doc
.
querySelector
(
`#
${
name
}
path`
).
getAttribute
(
'
d
'
);
})
.
catch
(()
=>
null
);
app/assets/javascripts/lib/utils/notify.js
View file @
e820c228
...
...
@@ -32,7 +32,7 @@ function notifyMe(message, body, icon, onclick) {
// If it's okay let's create a notification
return
notificationGranted
(
message
,
opts
,
onclick
);
}
else
if
(
Notification
.
permission
!==
'
denied
'
)
{
return
Notification
.
requestPermission
(
permission
=>
{
return
Notification
.
requestPermission
(
(
permission
)
=>
{
// If the user accepts, let's create a notification
if
(
permission
===
'
granted
'
)
{
return
notificationGranted
(
message
,
opts
,
onclick
);
...
...
app/assets/javascripts/lib/utils/number_utils.js
View file @
e820c228
...
...
@@ -112,7 +112,7 @@ export const isOdd = (number = 0) => number % 2;
* @param {Array} arr An array of numbers
* @returns {Number} The median of the given array
*/
export
const
median
=
arr
=>
{
export
const
median
=
(
arr
)
=>
{
const
middle
=
Math
.
floor
(
arr
.
length
/
2
);
const
sorted
=
arr
.
sort
((
a
,
b
)
=>
a
-
b
);
return
arr
.
length
%
2
!==
0
?
sorted
[
middle
]
:
(
sorted
[
middle
-
1
]
+
sorted
[
middle
])
/
2
;
...
...
app/assets/javascripts/lib/utils/poll.js
View file @
e820c228
...
...
@@ -102,11 +102,11 @@ export default class Poll {
notificationCallback
(
true
);
return
resource
[
method
](
data
)
.
then
(
response
=>
{
.
then
(
(
response
)
=>
{
this
.
checkConditions
(
response
);
notificationCallback
(
false
);
})
.
catch
(
error
=>
{
.
catch
(
(
error
)
=>
{
notificationCallback
(
false
);
if
(
error
.
status
===
httpStatusCodes
.
ABORTED
)
{
return
;
...
...
app/assets/javascripts/lib/utils/poll_until_complete.js
View file @
e820c228
...
...
@@ -29,7 +29,7 @@ export default (url, config = {}) =>
},
data
:
{
url
,
config
},
method
:
'
axiosGet
'
,
successCallback
:
response
=>
{
successCallback
:
(
response
)
=>
{
if
(
response
.
status
===
httpStatusCodes
.
OK
)
{
resolve
(
response
);
eTagPoll
.
stop
();
...
...
app/assets/javascripts/lib/utils/set.js
View file @
e820c228
...
...
@@ -5,4 +5,4 @@
* @returns {boolean}
*/
export
const
isSubset
=
(
subset
,
superset
)
=>
Array
.
from
(
subset
).
every
(
value
=>
superset
.
has
(
value
));
Array
.
from
(
subset
).
every
(
(
value
)
=>
superset
.
has
(
value
));
app/assets/javascripts/lib/utils/simple_poll.js
View file @
e820c228
...
...
@@ -4,7 +4,7 @@ export default (fn, { interval = 2000, timeout = 60000 } = {}) => {
const
startTime
=
Date
.
now
();
return
new
Promise
((
resolve
,
reject
)
=>
{
const
stop
=
arg
=>
(
arg
instanceof
Error
?
reject
(
arg
)
:
resolve
(
arg
));
const
stop
=
(
arg
)
=>
(
arg
instanceof
Error
?
reject
(
arg
)
:
resolve
(
arg
));
const
next
=
()
=>
{
if
(
timeout
===
0
||
differenceInMilliseconds
(
startTime
)
<
timeout
)
{
setTimeout
(
fn
.
bind
(
null
,
next
,
stop
),
interval
);
...
...
app/assets/javascripts/lib/utils/sticky.js
View file @
e820c228
...
...
@@ -67,6 +67,6 @@ export const stickyMonitor = (el, stickyTop, insertPlaceholder = true) => {
* - If the current environment supports `position: sticky`, do nothing.
* - Can receive an iterable element list (NodeList, jQuery collection, etc.) or single HTMLElement.
*/
export
const
polyfillSticky
=
el
=>
{
export
const
polyfillSticky
=
(
el
)
=>
{
StickyFill
.
add
(
el
);
};
app/assets/javascripts/lib/utils/text_markdown.js
View file @
e820c228
...
...
@@ -220,7 +220,7 @@ export function insertMarkdownText({
:
blockTagText
(
text
,
textArea
,
blockTag
,
selected
);
}
else
{
textToInsert
=
selectedSplit
.
map
(
val
=>
{
.
map
(
(
val
)
=>
{
if
(
tag
.
indexOf
(
textPlaceholder
)
>
-
1
)
{
return
tag
.
replace
(
textPlaceholder
,
val
);
}
...
...
@@ -349,7 +349,7 @@ export function addEditorMarkdownListeners(editor) {
// eslint-disable-next-line @gitlab/no-global-event-off
$
(
'
.js-md
'
)
.
off
(
'
click
'
)
.
on
(
'
click
'
,
e
=>
{
.
on
(
'
click
'
,
(
e
)
=>
{
const
{
mdTag
,
mdBlock
,
mdPrepend
,
mdSelect
}
=
$
(
e
.
currentTarget
).
data
();
insertMarkdownText
({
...
...
app/assets/javascripts/lib/utils/text_utility.js
View file @
e820c228
...
...
@@ -14,7 +14,7 @@ import {
* @param {String} text
* @returns {String}
*/
export
const
addDelimiter
=
text
=>
export
const
addDelimiter
=
(
text
)
=>
text
?
text
.
toString
().
replace
(
/
\B(?=(\d{3})
+
(?!\d))
/g
,
'
,
'
)
:
text
;
/**
...
...
@@ -23,7 +23,7 @@ export const addDelimiter = text =>
* @param {Number} count
* @return {Number|String}
*/
export
const
highCountTrim
=
count
=>
(
count
>
99
?
'
99+
'
:
count
);
export
const
highCountTrim
=
(
count
)
=>
(
count
>
99
?
'
99+
'
:
count
);
/**
* Converts first char to uppercase and replaces the given separator with spaces
...
...
@@ -43,7 +43,7 @@ export const humanize = (string, separator = '_') => {
* @param {*} str
* @returns {String}
*/
export
const
dasherize
=
str
=>
str
.
replace
(
/
[
_
\s]
+/g
,
'
-
'
);
export
const
dasherize
=
(
str
)
=>
str
.
replace
(
/
[
_
\s]
+/g
,
'
-
'
);
/**
* Replaces whitespace and non-sluggish characters with a given separator
...
...
@@ -69,7 +69,7 @@ export const slugify = (str, separator = '-') => {
* @param {String} str
* @returns {String}
*/
export
const
slugifyWithUnderscore
=
str
=>
slugify
(
str
,
'
_
'
);
export
const
slugifyWithUnderscore
=
(
str
)
=>
slugify
(
str
,
'
_
'
);
/**
* Truncates given text
...
...
@@ -158,7 +158,7 @@ export const truncateWidth = (string, options = {}) => {
* @param {String} sha
* @returns {String}
*/
export
const
truncateSha
=
sha
=>
sha
.
substring
(
0
,
8
);
export
const
truncateSha
=
(
sha
)
=>
sha
.
substring
(
0
,
8
);
const
ELLIPSIS_CHAR
=
'
…
'
;
export
const
truncatePathMiddleToLength
=
(
text
,
maxWidth
)
=>
{
...
...
@@ -166,7 +166,7 @@ export const truncatePathMiddleToLength = (text, maxWidth) => {
let
ellipsisCount
=
0
;
while
(
returnText
.
length
>=
maxWidth
)
{
const
textSplit
=
returnText
.
split
(
'
/
'
).
filter
(
s
=>
s
!==
ELLIPSIS_CHAR
);
const
textSplit
=
returnText
.
split
(
'
/
'
).
filter
(
(
s
)
=>
s
!==
ELLIPSIS_CHAR
);
if
(
textSplit
.
length
===
0
)
{
// There are n - 1 path separators for n segments, so 2n - 1 <= maxWidth
...
...
@@ -243,7 +243,7 @@ export const stripHtml = (string, replace = '') => {
* // returns "trailingUnderscore_"
* convertToCamelCase('trailing_underscore_')
*/
export
const
convertToCamelCase
=
string
=>
export
const
convertToCamelCase
=
(
string
)
=>
string
.
replace
(
/
([
a-z0-9
])
_
([
a-z0-9
])
/gi
,
(
match
,
p1
,
p2
)
=>
`
${
p1
}${
p2
.
toUpperCase
()}
`
);
/**
...
...
@@ -251,7 +251,7 @@ export const convertToCamelCase = string =>
*
* @param {*} string
*/
export
const
convertToSnakeCase
=
string
=>
export
const
convertToSnakeCase
=
(
string
)
=>
slugifyWithUnderscore
((
string
.
match
(
/
([
a-zA-Z
][^
A-Z
]
*
)
/g
)
||
[
string
]).
join
(
'
'
));
/**
...
...
@@ -260,7 +260,7 @@ export const convertToSnakeCase = string =>
*
* @param {*} string
*/
export
const
convertToSentenceCase
=
string
=>
{
export
const
convertToSentenceCase
=
(
string
)
=>
{
const
splitWord
=
string
.
split
(
'
'
).
map
((
word
,
index
)
=>
(
index
>
0
?
word
.
toLowerCase
()
:
word
));
return
splitWord
.
join
(
'
'
);
...
...
@@ -273,7 +273,7 @@ export const convertToSentenceCase = string => {
* @param {String} string
* @returns {String}
*/
export
const
convertToTitleCase
=
string
=>
string
.
replace
(
/
\b[
a-z
]
/g
,
s
=>
s
.
toUpperCase
());
export
const
convertToTitleCase
=
(
string
)
=>
string
.
replace
(
/
\b[
a-z
]
/g
,
(
s
)
=>
s
.
toUpperCase
());
const
unicodeConversion
=
[
[
/
[
ÀÁÂÃÅĀĂĄ
]
/g
,
'
A
'
],
...
...
@@ -340,7 +340,7 @@ const unicodeConversion = [
* @param {String} string
* @returns {String}
*/
export
const
convertUnicodeToAscii
=
string
=>
{
export
const
convertUnicodeToAscii
=
(
string
)
=>
{
let
convertedString
=
string
;
unicodeConversion
.
forEach
(([
regex
,
replacer
])
=>
{
...
...
@@ -356,7 +356,7 @@ export const convertUnicodeToAscii = string => {
*
* @param {*} string
*/
export
const
splitCamelCase
=
string
=>
export
const
splitCamelCase
=
(
string
)
=>
string
.
replace
(
/
([
A-Z
]
+
)([
A-Z
][
a-z
])
/g
,
'
$1 $2
'
)
.
replace
(
/
([
a-z
\d])([
A-Z
])
/g
,
'
$1 $2
'
)
...
...
@@ -398,7 +398,7 @@ export const truncateNamespace = (string = '') => {
* @param {String} obj The object to test
* @returns {Boolean}
*/
export
const
hasContent
=
obj
=>
isString
(
obj
)
&&
obj
.
trim
()
!==
''
;
export
const
hasContent
=
(
obj
)
=>
isString
(
obj
)
&&
obj
.
trim
()
!==
''
;
/**
* A utility function that validates if a
...
...
@@ -408,7 +408,7 @@ export const hasContent = obj => isString(obj) && obj.trim() !== '';
*
* @return {Boolean} true if valid
*/
export
const
isValidSha1Hash
=
str
=>
{
export
const
isValidSha1Hash
=
(
str
)
=>
{
return
/^
[
0-9a-f
]{5,40}
$/
.
test
(
str
);
};
...
...
app/assets/javascripts/lib/utils/type_utility.js
View file @
e820c228
export
const
isObject
=
obj
=>
obj
&&
obj
.
constructor
===
Object
;
export
const
isObject
=
(
obj
)
=>
obj
&&
obj
.
constructor
===
Object
;
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