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