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
0
Merge Requests
0
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
Léo-Paul Géneau
gitlab-ce
Commits
d2ee2eab
Commit
d2ee2eab
authored
Oct 10, 2018
by
Mike Greiling
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Prettify app/assets/javascripts/pages
parent
d87e88a6
Changes
46
Hide whitespace changes
Inline
Side-by-side
Showing
46 changed files
with
1001 additions
and
780 deletions
+1001
-780
app/assets/javascripts/pages/admin/abuse_reports/abuse_reports.js
...ts/javascripts/pages/admin/abuse_reports/abuse_reports.js
+1
-1
app/assets/javascripts/pages/admin/admin.js
app/assets/javascripts/pages/admin/admin.js
+9
-6
app/assets/javascripts/pages/admin/application_settings/account_and_limits.js
...ts/pages/admin/application_settings/account_and_limits.js
+6
-2
app/assets/javascripts/pages/admin/broadcast_messages/broadcast_message.js
...ripts/pages/admin/broadcast_messages/broadcast_message.js
+20
-16
app/assets/javascripts/pages/admin/jobs/index/components/stop_jobs_modal.vue
...pts/pages/admin/jobs/index/components/stop_jobs_modal.vue
+34
-31
app/assets/javascripts/pages/admin/projects/index.js
app/assets/javascripts/pages/admin/projects/index.js
+2
-1
app/assets/javascripts/pages/admin/projects/index/components/delete_project_modal.vue
.../admin/projects/index/components/delete_project_modal.vue
+71
-68
app/assets/javascripts/pages/admin/projects/index/index.js
app/assets/javascripts/pages/admin/projects/index/index.js
+1
-1
app/assets/javascripts/pages/admin/users/components/delete_user_modal.vue
...cripts/pages/admin/users/components/delete_user_modal.vue
+96
-91
app/assets/javascripts/pages/admin/users/index.js
app/assets/javascripts/pages/admin/users/index.js
+4
-2
app/assets/javascripts/pages/admin/users/new/index.js
app/assets/javascripts/pages/admin/users/new/index.js
+4
-2
app/assets/javascripts/pages/dashboard/todos/index/todos.js
app/assets/javascripts/pages/dashboard/todos/index/todos.js
+9
-6
app/assets/javascripts/pages/milestones/shared/components/delete_milestone_modal.vue
...s/milestones/shared/components/delete_milestone_modal.vue
+96
-73
app/assets/javascripts/pages/milestones/shared/delete_milestone_modal_init.js
...ts/pages/milestones/shared/delete_milestone_modal_init.js
+10
-6
app/assets/javascripts/pages/milestones/shared/promote_milestone_modal_init.js
...s/pages/milestones/shared/promote_milestone_modal_init.js
+10
-6
app/assets/javascripts/pages/profiles/index.js
app/assets/javascripts/pages/profiles/index.js
+5
-2
app/assets/javascripts/pages/profiles/two_factor_auths/index.js
...sets/javascripts/pages/profiles/two_factor_auths/index.js
+3
-1
app/assets/javascripts/pages/projects/branches/new/index.js
app/assets/javascripts/pages/projects/branches/new/index.js
+8
-3
app/assets/javascripts/pages/projects/graphs/charts/index.js
app/assets/javascripts/pages/projects/graphs/charts/index.js
+13
-9
app/assets/javascripts/pages/projects/graphs/show/index.js
app/assets/javascripts/pages/projects/graphs/show/index.js
+2
-1
app/assets/javascripts/pages/projects/graphs/show/stat_graph_contributors.js
...pts/pages/projects/graphs/show/stat_graph_contributors.js
+51
-40
app/assets/javascripts/pages/projects/graphs/show/stat_graph_contributors_graph.js
...ges/projects/graphs/show/stat_graph_contributors_graph.js
+148
-73
app/assets/javascripts/pages/projects/graphs/show/stat_graph_contributors_util.js
...ages/projects/graphs/show/stat_graph_contributors_util.js
+35
-29
app/assets/javascripts/pages/projects/init_blob.js
app/assets/javascripts/pages/projects/init_blob.js
+2
-1
app/assets/javascripts/pages/projects/init_form.js
app/assets/javascripts/pages/projects/init_form.js
+1
-1
app/assets/javascripts/pages/projects/issues/show.js
app/assets/javascripts/pages/projects/issues/show.js
+1
-1
app/assets/javascripts/pages/projects/labels/components/promote_label_modal.vue
.../pages/projects/labels/components/promote_label_modal.vue
+69
-55
app/assets/javascripts/pages/projects/labels/index/index.js
app/assets/javascripts/pages/projects/labels/index/index.js
+10
-6
app/assets/javascripts/pages/projects/network/network.js
app/assets/javascripts/pages/projects/network/network.js
+6
-4
app/assets/javascripts/pages/projects/pipeline_schedules/index/index.js
...ascripts/pages/projects/pipeline_schedules/index/index.js
+13
-9
app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/interval_pattern_input.vue
...ne_schedules/shared/components/interval_pattern_input.vue
+51
-51
app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/pipeline_schedules_callout.vue
...chedules/shared/components/pipeline_schedules_callout.vue
+23
-23
app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/target_branch_dropdown.js
...ine_schedules/shared/components/target_branch_dropdown.js
+1
-2
app/assets/javascripts/pages/projects/pipeline_schedules/shared/init_form.js
...pts/pages/projects/pipeline_schedules/shared/init_form.js
+3
-1
app/assets/javascripts/pages/projects/pipelines/charts/index.js
...sets/javascripts/pages/projects/pipelines/charts/index.js
+34
-25
app/assets/javascripts/pages/projects/pipelines/index/index.js
...ssets/javascripts/pages/projects/pipelines/index/index.js
+35
-31
app/assets/javascripts/pages/projects/pipelines/init_pipelines.js
...ts/javascripts/pages/projects/pipelines/init_pipelines.js
+5
-2
app/assets/javascripts/pages/projects/shared/permissions/components/project_feature_setting.vue
...shared/permissions/components/project_feature_setting.vue
+56
-58
app/assets/javascripts/pages/projects/shared/permissions/components/project_setting_row.vue
...cts/shared/permissions/components/project_setting_row.vue
+18
-18
app/assets/javascripts/pages/projects/shared/permissions/constants.js
...avascripts/pages/projects/shared/permissions/constants.js
+4
-2
app/assets/javascripts/pages/projects/shared/project_avatar.js
...ssets/javascripts/pages/projects/shared/project_avatar.js
+3
-2
app/assets/javascripts/pages/projects/wikis/index.js
app/assets/javascripts/pages/projects/wikis/index.js
+2
-1
app/assets/javascripts/pages/search/show/search.js
app/assets/javascripts/pages/search/show/search.js
+16
-9
app/assets/javascripts/pages/sessions/new/signin_tabs_memoizer.js
...ts/javascripts/pages/sessions/new/signin_tabs_memoizer.js
+1
-1
app/assets/javascripts/pages/sessions/new/username_validator.js
...sets/javascripts/pages/sessions/new/username_validator.js
+5
-5
app/assets/javascripts/pages/users/index.js
app/assets/javascripts/pages/users/index.js
+4
-2
No files found.
app/assets/javascripts/pages/admin/abuse_reports/abuse_reports.js
View file @
d2ee2eab
...
...
@@ -31,7 +31,7 @@ export default class AbuseReports {
$messageCellElement
.
text
(
originalMessage
);
}
else
{
$messageCellElement
.
data
(
'
messageTruncated
'
,
'
true
'
);
$messageCellElement
.
text
(
`
${
originalMessage
.
substr
(
0
,
(
MAX_MESSAGE_LENGTH
-
3
)
)}
...`
);
$messageCellElement
.
text
(
`
${
originalMessage
.
substr
(
0
,
MAX_MESSAGE_LENGTH
-
3
)}
...`
);
}
}
}
app/assets/javascripts/pages/admin/admin.js
View file @
d2ee2eab
...
...
@@ -23,7 +23,7 @@ export default function adminInit() {
}
});
$
(
'
body
'
).
on
(
'
click
'
,
'
.js-toggle-colors-link
'
,
(
e
)
=>
{
$
(
'
body
'
).
on
(
'
click
'
,
'
.js-toggle-colors-link
'
,
e
=>
{
e
.
preventDefault
();
$
(
'
.js-toggle-colors-container
'
).
toggleClass
(
'
hide
'
);
});
...
...
@@ -33,12 +33,15 @@ export default function adminInit() {
$
(
this
).
tab
(
'
show
'
);
});
$
(
'
.log-bottom
'
).
on
(
'
click
'
,
(
e
)
=>
{
$
(
'
.log-bottom
'
).
on
(
'
click
'
,
e
=>
{
e
.
preventDefault
();
const
$visibleLog
=
$
(
'
.file-content:visible
'
);
$visibleLog
.
animate
({
scrollTop
:
$visibleLog
.
find
(
'
ol
'
).
height
(),
},
'
fast
'
);
$visibleLog
.
animate
(
{
scrollTop
:
$visibleLog
.
find
(
'
ol
'
).
height
(),
},
'
fast
'
,
);
});
$
(
'
.change-owner-link
'
).
on
(
'
click
'
,
function
changeOwnerLinkClick
(
e
)
{
...
...
@@ -47,7 +50,7 @@ export default function adminInit() {
modal
.
show
();
});
$
(
'
.change-owner-cancel-link
'
).
on
(
'
click
'
,
(
e
)
=>
{
$
(
'
.change-owner-cancel-link
'
).
on
(
'
click
'
,
e
=>
{
e
.
preventDefault
();
modal
.
hide
();
$
(
'
.change-owner-link
'
).
show
();
...
...
app/assets/javascripts/pages/admin/application_settings/account_and_limits.js
View file @
d2ee2eab
import
{
__
}
from
'
~/locale
'
;
export
const
PLACEHOLDER_USER_EXTERNAL_DEFAULT_TRUE
=
__
(
'
Regex pattern
'
);
export
const
PLACEHOLDER_USER_EXTERNAL_DEFAULT_FALSE
=
__
(
'
To define internal users, first enable new users set to external
'
);
export
const
PLACEHOLDER_USER_EXTERNAL_DEFAULT_FALSE
=
__
(
'
To define internal users, first enable new users set to external
'
,
);
function
setUserInternalRegexPlaceholder
(
checkbox
)
{
const
userInternalRegex
=
document
.
getElementById
(
'
application_setting_user_default_internal_regex
'
);
const
userInternalRegex
=
document
.
getElementById
(
'
application_setting_user_default_internal_regex
'
,
);
if
(
checkbox
&&
userInternalRegex
)
{
if
(
checkbox
.
checked
)
{
userInternalRegex
.
readOnly
=
false
;
...
...
app/assets/javascripts/pages/admin/broadcast_messages/broadcast_message.js
View file @
d2ee2eab
...
...
@@ -17,20 +17,24 @@ export default () => {
const
previewPath
=
$
(
'
textarea#broadcast_message_message
'
).
data
(
'
previewPath
'
);
$
(
'
textarea#broadcast_message_message
'
).
on
(
'
input
'
,
_
.
debounce
(
function
onMessageInput
()
{
const
message
=
$
(
this
).
val
();
if
(
message
===
''
)
{
$
(
'
.js-broadcast-message-preview
'
).
text
(
'
Your message here
'
);
}
else
{
axios
.
post
(
previewPath
,
{
broadcast_message
:
{
message
,
},
})
.
then
(({
data
})
=>
{
$
(
'
.js-broadcast-message-preview
'
).
html
(
data
.
message
);
})
.
catch
(()
=>
flash
(
__
(
'
An error occurred while rendering preview broadcast message
'
)));
}
},
250
));
$
(
'
textarea#broadcast_message_message
'
).
on
(
'
input
'
,
_
.
debounce
(
function
onMessageInput
()
{
const
message
=
$
(
this
).
val
();
if
(
message
===
''
)
{
$
(
'
.js-broadcast-message-preview
'
).
text
(
'
Your message here
'
);
}
else
{
axios
.
post
(
previewPath
,
{
broadcast_message
:
{
message
,
},
})
.
then
(({
data
})
=>
{
$
(
'
.js-broadcast-message-preview
'
).
html
(
data
.
message
);
})
.
catch
(()
=>
flash
(
__
(
'
An error occurred while rendering preview broadcast message
'
)));
}
},
250
),
);
};
app/assets/javascripts/pages/admin/jobs/index/components/stop_jobs_modal.vue
View file @
d2ee2eab
<
script
>
import
axios
from
'
~/lib/utils/axios_utils
'
;
import
createFlash
from
'
~/flash
'
;
import
GlModal
from
'
~/vue_shared/components/gl_modal.vue
'
;
import
{
redirectTo
}
from
'
~/lib/utils/url_utility
'
;
import
{
s__
}
from
'
~/locale
'
;
import
axios
from
'
~/lib/utils/axios_utils
'
;
import
createFlash
from
'
~/flash
'
;
import
GlModal
from
'
~/vue_shared/components/gl_modal.vue
'
;
import
{
redirectTo
}
from
'
~/lib/utils/url_utility
'
;
import
{
s__
}
from
'
~/locale
'
;
export
default
{
components
:
{
GlModal
,
export
default
{
components
:
{
GlModal
,
},
props
:
{
url
:
{
type
:
String
,
required
:
true
,
},
props
:
{
url
:
{
type
:
String
,
required
:
true
,
},
},
computed
:
{
text
()
{
return
s__
(
'
AdminArea|You’re about to stop all jobs.This will halt all current jobs that are running.
'
,
);
},
computed
:
{
text
()
{
return
s__
(
'
AdminArea|You’re about to stop all jobs.This will halt all current jobs that are running.
'
);
},
},
methods
:
{
onSubmit
()
{
return
axios
.
post
(
this
.
url
)
.
then
(
response
=>
{
// follow the rediect to refresh the page
redirectTo
(
response
.
request
.
responseURL
);
})
.
catch
(
error
=>
{
createFlash
(
s__
(
'
AdminArea|Stopping jobs failed
'
));
throw
error
;
});
},
methods
:
{
onSubmit
()
{
return
axios
.
post
(
this
.
url
)
.
then
((
response
)
=>
{
// follow the rediect to refresh the page
redirectTo
(
response
.
request
.
responseURL
);
})
.
catch
((
error
)
=>
{
createFlash
(
s__
(
'
AdminArea|Stopping jobs failed
'
));
throw
error
;
});
},
},
};
},
};
</
script
>
<
template
>
...
...
app/assets/javascripts/pages/admin/projects/index.js
View file @
d2ee2eab
...
...
@@ -4,6 +4,7 @@ import NamespaceSelect from '../../../namespace_select';
document
.
addEventListener
(
'
DOMContentLoaded
'
,
()
=>
{
new
ProjectsList
();
// eslint-disable-line no-new
document
.
querySelectorAll
(
'
.js-namespace-select
'
)
document
.
querySelectorAll
(
'
.js-namespace-select
'
)
.
forEach
(
dropdown
=>
new
NamespaceSelect
({
dropdown
}));
});
app/assets/javascripts/pages/admin/projects/index/components/delete_project_modal.vue
View file @
d2ee2eab
<
script
>
import
_
from
'
underscore
'
;
import
DeprecatedModal
from
'
~/vue_shared/components/deprecated_modal.vue
'
;
import
{
s__
,
sprintf
}
from
'
~/locale
'
;
import
_
from
'
underscore
'
;
import
DeprecatedModal
from
'
~/vue_shared/components/deprecated_modal.vue
'
;
import
{
s__
,
sprintf
}
from
'
~/locale
'
;
export
default
{
components
:
{
DeprecatedModal
,
export
default
{
components
:
{
DeprecatedModal
,
},
props
:
{
deleteProjectUrl
:
{
type
:
String
,
required
:
false
,
default
:
''
,
},
props
:
{
deleteProjectUrl
:
{
type
:
String
,
required
:
false
,
default
:
''
,
},
projectName
:
{
type
:
String
,
required
:
false
,
default
:
''
,
},
csrfToken
:
{
type
:
String
,
required
:
false
,
default
:
''
,
},
projectName
:
{
type
:
String
,
required
:
false
,
default
:
''
,
},
data
()
{
return
{
enteredProjectName
:
''
,
};
csrfToken
:
{
type
:
String
,
required
:
false
,
default
:
''
,
},
computed
:
{
title
()
{
return
sprintf
(
s__
(
'
AdminProjects|Delete Project %{projectName}?
'
),
{
projectName
:
`'
${
_
.
escape
(
this
.
projectName
)}
'`
,
},
false
,
);
},
text
()
{
return
sprintf
(
s__
(
`AdminProjects|
},
data
()
{
return
{
enteredProjectName
:
''
,
};
},
computed
:
{
title
()
{
return
sprintf
(
s__
(
'
AdminProjects|Delete Project %{projectName}?
'
),
{
projectName
:
`'
${
_
.
escape
(
this
.
projectName
)}
'`
,
},
false
,
);
},
text
()
{
return
sprintf
(
s__
(
`AdminProjects|
You’re about to permanently delete the project %{projectName}, its repository,
and all related resources including issues, merge requests, etc.. Once you confirm and press
%{strong_start}Delete project%{strong_end}, it cannot be undone or recovered.`
),
{
projectName
:
`<strong>
${
_
.
escape
(
this
.
projectName
)}
</strong>`
,
strong_start
:
'
<strong>
'
,
strong_end
:
'
</strong>
'
,
},
false
,
);
},
confirmationTextLabel
()
{
return
sprintf
(
s__
(
'
AdminUsers|To confirm, type %{projectName}
'
),
{
projectName
:
`<code>
${
_
.
escape
(
this
.
projectName
)}
</code>`
,
},
false
,
);
},
primaryButtonLabel
()
{
return
s__
(
'
AdminProjects|Delete project
'
);
},
canSubmit
()
{
return
this
.
enteredProjectName
===
this
.
projectName
;
},
{
projectName
:
`<strong>
${
_
.
escape
(
this
.
projectName
)}
</strong>`
,
strong_start
:
'
<strong>
'
,
strong_end
:
'
</strong>
'
,
},
false
,
);
},
confirmationTextLabel
()
{
return
sprintf
(
s__
(
'
AdminUsers|To confirm, type %{projectName}
'
),
{
projectName
:
`<code>
${
_
.
escape
(
this
.
projectName
)}
</code>`
,
},
false
,
);
},
primaryButtonLabel
()
{
return
s__
(
'
AdminProjects|Delete project
'
);
},
canSubmit
()
{
return
this
.
enteredProjectName
===
this
.
projectName
;
},
},
methods
:
{
onCancel
()
{
this
.
enteredProjectName
=
''
;
},
methods
:
{
onCancel
()
{
this
.
enteredProjectName
=
''
;
},
onSubmit
()
{
this
.
$refs
.
form
.
submit
();
this
.
enteredProjectName
=
''
;
},
onSubmit
()
{
this
.
$refs
.
form
.
submit
();
this
.
enteredProjectName
=
''
;
},
};
},
};
</
script
>
<
template
>
...
...
app/assets/javascripts/pages/admin/projects/index/index.js
View file @
d2ee2eab
...
...
@@ -28,7 +28,7 @@ document.addEventListener('DOMContentLoaded', () => {
},
});
$
(
document
).
on
(
'
shown.bs.modal
'
,
(
event
)
=>
{
$
(
document
).
on
(
'
shown.bs.modal
'
,
event
=>
{
if
(
event
.
relatedTarget
.
classList
.
contains
(
'
delete-project-button
'
))
{
const
buttonProps
=
event
.
relatedTarget
.
dataset
;
deleteModal
.
deleteProjectUrl
=
buttonProps
.
deleteProjectUrl
;
...
...
app/assets/javascripts/pages/admin/users/components/delete_user_modal.vue
View file @
d2ee2eab
<
script
>
import
_
from
'
underscore
'
;
import
DeprecatedModal
from
'
~/vue_shared/components/deprecated_modal.vue
'
;
import
{
s__
,
sprintf
}
from
'
~/locale
'
;
import
_
from
'
underscore
'
;
import
DeprecatedModal
from
'
~/vue_shared/components/deprecated_modal.vue
'
;
import
{
s__
,
sprintf
}
from
'
~/locale
'
;
export
default
{
components
:
{
DeprecatedModal
,
export
default
{
components
:
{
DeprecatedModal
,
},
props
:
{
deleteUserUrl
:
{
type
:
String
,
required
:
false
,
default
:
''
,
},
props
:
{
deleteUserUrl
:
{
type
:
String
,
required
:
false
,
default
:
''
,
},
blockUserUrl
:
{
type
:
String
,
required
:
false
,
default
:
''
,
},
deleteContributions
:
{
type
:
Boolean
,
required
:
false
,
default
:
false
,
},
username
:
{
type
:
String
,
required
:
false
,
default
:
''
,
},
csrfToken
:
{
type
:
String
,
required
:
false
,
default
:
''
,
},
blockUserUrl
:
{
type
:
String
,
required
:
false
,
default
:
''
,
},
d
ata
()
{
return
{
enteredUsername
:
''
,
};
d
eleteContributions
:
{
type
:
Boolean
,
required
:
false
,
default
:
false
,
},
computed
:
{
title
()
{
const
keepContributionsTitle
=
s__
(
'
AdminUsers|Delete User %{username}?
'
);
const
deleteContributionsTitle
=
s__
(
'
AdminUsers|Delete User %{username} and contributions?
'
);
username
:
{
type
:
String
,
required
:
false
,
default
:
''
,
},
csrfToken
:
{
type
:
String
,
required
:
false
,
default
:
''
,
},
},
data
()
{
return
{
enteredUsername
:
''
,
};
},
computed
:
{
title
()
{
const
keepContributionsTitle
=
s__
(
'
AdminUsers|Delete User %{username}?
'
);
const
deleteContributionsTitle
=
s__
(
'
AdminUsers|Delete User %{username} and contributions?
'
);
return
sprintf
(
this
.
deleteContributions
?
deleteContributionsTitle
:
keepContributionsTitle
,
{
username
:
`'
${
_
.
escape
(
this
.
username
)}
'`
,
},
false
);
},
text
()
{
const
keepContributionsText
=
s__
(
`AdminArea|
return
sprintf
(
this
.
deleteContributions
?
deleteContributionsTitle
:
keepContributionsTitle
,
{
username
:
`'
${
_
.
escape
(
this
.
username
)}
'`
,
},
false
,
);
},
text
()
{
const
keepContributionsText
=
s__
(
`AdminArea|
You are about to permanently delete the user %{username}.
Issues, merge requests, and groups linked to them will be transferred to a system-wide "Ghost-user".
To avoid data loss, consider using the %{strong_start}block user%{strong_end} feature instead.
Once you %{strong_start}Delete user%{strong_end}, it cannot be undone or recovered.`
);
const
deleteContributionsText
=
s__
(
`AdminArea|
const
deleteContributionsText
=
s__
(
`AdminArea|
You are about to permanently delete the user %{username}.
This will delete all of the issues, merge requests, and groups linked to them.
To avoid data loss, consider using the %{strong_start}block user%{strong_end} feature instead.
Once you %{strong_start}Delete user%{strong_end}, it cannot be undone or recovered.`
);
return
sprintf
(
this
.
deleteContributions
?
deleteContributionsText
:
keepContributionsText
,
{
username
:
`<strong>
${
_
.
escape
(
this
.
username
)}
</strong>`
,
strong_start
:
'
<strong>
'
,
strong_end
:
'
</strong>
'
,
},
false
,
);
},
confirmationTextLabel
()
{
return
sprintf
(
s__
(
'
AdminUsers|To confirm, type %{username}
'
),
{
username
:
`<code>
${
_
.
escape
(
this
.
username
)}
</code>`
,
},
false
,
);
},
primaryButtonLabel
()
{
const
keepContributionsLabel
=
s__
(
'
AdminUsers|Delete user
'
);
const
deleteContributionsLabel
=
s__
(
'
AdminUsers|Delete user and contributions
'
);
return
sprintf
(
this
.
deleteContributions
?
deleteContributionsText
:
keepContributionsText
,
{
username
:
`<strong>
${
_
.
escape
(
this
.
username
)}
</strong>`
,
strong_start
:
'
<strong>
'
,
strong_end
:
'
</strong>
'
,
},
false
,
);
},
confirmationTextLabel
()
{
return
sprintf
(
s__
(
'
AdminUsers|To confirm, type %{username}
'
),
{
username
:
`<code>
${
_
.
escape
(
this
.
username
)}
</code>`
,
},
false
,
);
},
primaryButtonLabel
()
{
const
keepContributionsLabel
=
s__
(
'
AdminUsers|Delete user
'
);
const
deleteContributionsLabel
=
s__
(
'
AdminUsers|Delete user and contributions
'
);
return
this
.
deleteContributions
?
deleteContributionsLabel
:
keepContributionsLabel
;
},
secondaryButtonLabel
()
{
return
s__
(
'
AdminUsers|Block user
'
);
},
canSubmit
()
{
return
this
.
enteredUsername
===
this
.
username
;
},
return
this
.
deleteContributions
?
deleteContributionsLabel
:
keepContributionsLabel
;
},
methods
:
{
onCancel
()
{
this
.
enteredUsername
=
''
;
},
onSecondaryAction
()
{
const
{
form
}
=
this
.
$refs
;
secondaryButtonLabel
()
{
return
s__
(
'
AdminUsers|Block user
'
);
},
canSubmit
()
{
return
this
.
enteredUsername
===
this
.
username
;
},
},
methods
:
{
onCancel
()
{
this
.
enteredUsername
=
''
;
},
onSecondaryAction
()
{
const
{
form
}
=
this
.
$refs
;
form
.
action
=
this
.
blockUserUrl
;
this
.
$refs
.
method
.
value
=
'
put
'
;
form
.
action
=
this
.
blockUserUrl
;
this
.
$refs
.
method
.
value
=
'
put
'
;
form
.
submit
();
},
onSubmit
()
{
this
.
$refs
.
form
.
submit
();
this
.
enteredUsername
=
''
;
},
form
.
submit
();
},
onSubmit
()
{
this
.
$refs
.
form
.
submit
();
this
.
enteredUsername
=
''
;
},
};
},
};
</
script
>
<
template
>
...
...
app/assets/javascripts/pages/admin/users/index.js
View file @
d2ee2eab
...
...
@@ -32,12 +32,14 @@ document.addEventListener('DOMContentLoaded', () => {
},
});
$
(
document
).
on
(
'
shown.bs.modal
'
,
(
event
)
=>
{
$
(
document
).
on
(
'
shown.bs.modal
'
,
event
=>
{
if
(
event
.
relatedTarget
.
classList
.
contains
(
'
delete-user-button
'
))
{
const
buttonProps
=
event
.
relatedTarget
.
dataset
;
deleteModal
.
deleteUserUrl
=
buttonProps
.
deleteUserUrl
;
deleteModal
.
blockUserUrl
=
buttonProps
.
blockUserUrl
;
deleteModal
.
deleteContributions
=
event
.
relatedTarget
.
hasAttribute
(
'
data-delete-contributions
'
);
deleteModal
.
deleteContributions
=
event
.
relatedTarget
.
hasAttribute
(
'
data-delete-contributions
'
,
);
deleteModal
.
username
=
buttonProps
.
username
;
}
});
...
...
app/assets/javascripts/pages/admin/users/new/index.js
View file @
d2ee2eab
...
...
@@ -4,7 +4,9 @@ export default class UserInternalRegexHandler {
constructor
()
{
this
.
regexPattern
=
$
(
'
[data-user-internal-regex-pattern]
'
).
data
(
'
user-internal-regex-pattern
'
);
if
(
this
.
regexPattern
&&
this
.
regexPattern
!==
''
)
{
this
.
regexOptions
=
$
(
'
[data-user-internal-regex-options]
'
).
data
(
'
user-internal-regex-options
'
);
this
.
regexOptions
=
$
(
'
[data-user-internal-regex-options]
'
).
data
(
'
user-internal-regex-options
'
,
);
this
.
external
=
$
(
'
#user_external
'
);
this
.
warningMessage
=
$
(
'
#warning_external_automatically_set
'
);
this
.
addListenerToEmailField
();
...
...
@@ -13,7 +15,7 @@ export default class UserInternalRegexHandler {
}
addListenerToEmailField
()
{
$
(
'
#user_email
'
).
on
(
'
input
'
,
(
event
)
=>
{
$
(
'
#user_email
'
).
on
(
'
input
'
,
event
=>
{
this
.
setExternalCheckbox
(
event
.
currentTarget
.
value
);
});
}
...
...
app/assets/javascripts/pages/dashboard/todos/index/todos.js
View file @
d2ee2eab
...
...
@@ -79,7 +79,8 @@ export default class Todos {
.
then
(({
data
})
=>
{
this
.
updateRowState
(
target
);
this
.
updateBadges
(
data
);
}).
catch
(()
=>
{
})
.
catch
(()
=>
{
this
.
updateRowState
(
target
,
true
);
return
flash
(
__
(
'
Error updating todo status.
'
));
});
...
...
@@ -118,10 +119,12 @@ export default class Todos {
axios
[
target
.
dataset
.
method
](
target
.
dataset
.
href
,
{
ids
:
this
.
todo_ids
,
}).
then
(({
data
})
=>
{
this
.
updateAllState
(
target
,
data
);
this
.
updateBadges
(
data
);
}).
catch
(()
=>
flash
(
__
(
'
Error updating status for all todos.
'
)));
})
.
then
(({
data
})
=>
{
this
.
updateAllState
(
target
,
data
);
this
.
updateBadges
(
data
);
})
.
catch
(()
=>
flash
(
__
(
'
Error updating status for all todos.
'
)));
}
updateAllState
(
target
,
data
)
{
...
...
@@ -133,7 +136,7 @@ export default class Todos {
target
.
removeAttribute
(
'
disabled
'
);
target
.
classList
.
remove
(
'
disabled
'
);
this
.
todo_ids
=
(
target
===
markAllDoneBtn
)
?
data
.
updated_ids
:
[];
this
.
todo_ids
=
target
===
markAllDoneBtn
?
data
.
updated_ids
:
[];
undoAllBtn
.
classList
.
toggle
(
'
hidden
'
);
markAllDoneBtn
.
classList
.
toggle
(
'
hidden
'
);
todoListContainer
.
classList
.
toggle
(
'
hidden
'
);
...
...
app/assets/javascripts/pages/milestones/shared/components/delete_milestone_modal.vue
View file @
d2ee2eab
<
script
>
import
axios
from
'
~/lib/utils/axios_utils
'
;
import
axios
from
'
~/lib/utils/axios_utils
'
;
import
Flash
from
'
~/flash
'
;
import
DeprecatedModal
from
'
~/vue_shared/components/deprecated_modal.vue
'
;
import
{
n__
,
s__
,
sprintf
}
from
'
~/locale
'
;
import
{
redirectTo
}
from
'
~/lib/utils/url_utility
'
;
import
eventHub
from
'
../event_hub
'
;
import
Flash
from
'
~/flash
'
;
import
DeprecatedModal
from
'
~/vue_shared/components/deprecated_modal.vue
'
;
import
{
n__
,
s__
,
sprintf
}
from
'
~/locale
'
;
import
{
redirectTo
}
from
'
~/lib/utils/url_utility
'
;
import
eventHub
from
'
../event_hub
'
;
export
default
{
components
:
{
DeprecatedModal
,
export
default
{
components
:
{
DeprecatedModal
,
},
props
:
{
issueCount
:
{
type
:
Number
,
required
:
true
,
},
props
:
{
issueCount
:
{
type
:
Number
,
required
:
true
,
},
mergeRequestCount
:
{
type
:
Number
,
required
:
true
,
},
milestoneId
:
{
type
:
Number
,
required
:
true
,
},
milestoneTitle
:
{
type
:
String
,
required
:
true
,
},
milestoneUrl
:
{
type
:
String
,
required
:
true
,
},
mergeRequestCount
:
{
type
:
Number
,
required
:
true
,
},
computed
:
{
text
()
{
const
milestoneTitle
=
sprintf
(
'
<strong>%{milestoneTitle}</strong>
'
,
{
milestoneTitle
:
this
.
milestoneTitle
});
if
(
this
.
issueCount
===
0
&&
this
.
mergeRequestCount
===
0
)
{
return
sprintf
(
s__
(
`Milestones|
You’re about to permanently delete the milestone %{milestoneTitle}.
This milestone is not currently used in any issues or merge requests.`
),
{
milestoneTitle
,
},
false
,
);
}
milestoneId
:
{
type
:
Number
,
required
:
true
,
},
milestoneTitle
:
{
type
:
String
,
required
:
true
,
},
milestoneUrl
:
{
type
:
String
,
required
:
true
,
},
},
computed
:
{
text
()
{
const
milestoneTitle
=
sprintf
(
'
<strong>%{milestoneTitle}</strong>
'
,
{
milestoneTitle
:
this
.
milestoneTitle
,
});
if
(
this
.
issueCount
===
0
&&
this
.
mergeRequestCount
===
0
)
{
return
sprintf
(
s__
(
`Milestones|
You’re about to permanently delete the milestone %{milestoneTitle}
and remove it from %{issuesWithCount} and %{mergeRequestsWithCount}
.
Once deleted, it cannot be undone or recovered
.`
),
You’re about to permanently delete the milestone %{milestoneTitle}.
This milestone is not currently used in any issues or merge requests
.`
),
{
milestoneTitle
,
issuesWithCount
:
n__
(
'
%d issue
'
,
'
%d issues
'
,
this
.
issueCount
),
mergeRequestsWithCount
:
n__
(
'
%d merge request
'
,
'
%d merge requests
'
,
this
.
mergeRequestCount
),
},
false
,
);
},
title
()
{
return
sprintf
(
s__
(
'
Milestones|Delete milestone %{milestoneTitle}?
'
),
{
milestoneTitle
:
this
.
milestoneTitle
});
},
},
methods
:
{
onSubmit
()
{
eventHub
.
$emit
(
'
deleteMilestoneModal.requestStarted
'
,
this
.
milestoneUrl
);
}
return
axios
.
delete
(
this
.
milestoneUrl
)
.
then
((
response
)
=>
{
eventHub
.
$emit
(
'
deleteMilestoneModal.requestFinished
'
,
{
milestoneUrl
:
this
.
milestoneUrl
,
successful
:
true
});
return
sprintf
(
s__
(
`Milestones|
You’re about to permanently delete the milestone %{milestoneTitle} and remove it from %{issuesWithCount} and %{mergeRequestsWithCount}.
Once deleted, it cannot be undone or recovered.`
),
{
milestoneTitle
,
issuesWithCount
:
n__
(
'
%d issue
'
,
'
%d issues
'
,
this
.
issueCount
),
mergeRequestsWithCount
:
n__
(
'
%d merge request
'
,
'
%d merge requests
'
,
this
.
mergeRequestCount
,
),
},
false
,
);
},
title
()
{
return
sprintf
(
s__
(
'
Milestones|Delete milestone %{milestoneTitle}?
'
),
{
milestoneTitle
:
this
.
milestoneTitle
,
});
},
},
methods
:
{
onSubmit
()
{
eventHub
.
$emit
(
'
deleteMilestoneModal.requestStarted
'
,
this
.
milestoneUrl
);
// follow the rediect to milestones overview page
redirectTo
(
response
.
request
.
responseURL
);
})
.
catch
((
error
)
=>
{
eventHub
.
$emit
(
'
deleteMilestoneModal.requestFinished
'
,
{
milestoneUrl
:
this
.
milestoneUrl
,
successful
:
false
});
return
axios
.
delete
(
this
.
milestoneUrl
)
.
then
(
response
=>
{
eventHub
.
$emit
(
'
deleteMilestoneModal.requestFinished
'
,
{
milestoneUrl
:
this
.
milestoneUrl
,
successful
:
true
,
});
if
(
error
.
response
&&
error
.
response
.
status
===
404
)
{
Flash
(
sprintf
(
s__
(
'
Milestones|Milestone %{milestoneTitle} was not found
'
),
{
milestoneTitle
:
this
.
milestoneTitle
}));
}
else
{
Flash
(
sprintf
(
s__
(
'
Milestones|Failed to delete milestone %{milestoneTitle}
'
),
{
milestoneTitle
:
this
.
milestoneTitle
}));
}
throw
error
;
// follow the rediect to milestones overview page
redirectTo
(
response
.
request
.
responseURL
);
})
.
catch
(
error
=>
{
eventHub
.
$emit
(
'
deleteMilestoneModal.requestFinished
'
,
{
milestoneUrl
:
this
.
milestoneUrl
,
successful
:
false
,
});
},
if
(
error
.
response
&&
error
.
response
.
status
===
404
)
{
Flash
(
sprintf
(
s__
(
'
Milestones|Milestone %{milestoneTitle} was not found
'
),
{
milestoneTitle
:
this
.
milestoneTitle
,
}),
);
}
else
{
Flash
(
sprintf
(
s__
(
'
Milestones|Failed to delete milestone %{milestoneTitle}
'
),
{
milestoneTitle
:
this
.
milestoneTitle
,
}),
);
}
throw
error
;
});
},
};
},
};
</
script
>
<
template
>
...
...
app/assets/javascripts/pages/milestones/shared/delete_milestone_modal_init.js
View file @
d2ee2eab
...
...
@@ -7,7 +7,9 @@ export default () => {
Vue
.
use
(
Translate
);
const
onRequestFinished
=
({
milestoneUrl
,
successful
})
=>
{
const
button
=
document
.
querySelector
(
`.js-delete-milestone-button[data-milestone-url="
${
milestoneUrl
}
"]`
);
const
button
=
document
.
querySelector
(
`.js-delete-milestone-button[data-milestone-url="
${
milestoneUrl
}
"]`
,
);
if
(
!
successful
)
{
button
.
removeAttribute
(
'
disabled
'
);
...
...
@@ -16,14 +18,16 @@ export default () => {
button
.
querySelector
(
'
.js-loading-icon
'
).
classList
.
add
(
'
hidden
'
);
};
const
onRequestStarted
=
(
milestoneUrl
)
=>
{
const
button
=
document
.
querySelector
(
`.js-delete-milestone-button[data-milestone-url="
${
milestoneUrl
}
"]`
);
const
onRequestStarted
=
milestoneUrl
=>
{
const
button
=
document
.
querySelector
(
`.js-delete-milestone-button[data-milestone-url="
${
milestoneUrl
}
"]`
,
);
button
.
setAttribute
(
'
disabled
'
,
''
);
button
.
querySelector
(
'
.js-loading-icon
'
).
classList
.
remove
(
'
hidden
'
);
eventHub
.
$once
(
'
deleteMilestoneModal.requestFinished
'
,
onRequestFinished
);
};
const
onDeleteButtonClick
=
(
event
)
=>
{
const
onDeleteButtonClick
=
event
=>
{
const
button
=
event
.
currentTarget
;
const
modalProps
=
{
milestoneId
:
parseInt
(
button
.
dataset
.
milestoneId
,
10
),
...
...
@@ -37,12 +41,12 @@ export default () => {
};
const
deleteMilestoneButtons
=
document
.
querySelectorAll
(
'
.js-delete-milestone-button
'
);
deleteMilestoneButtons
.
forEach
(
(
button
)
=>
{
deleteMilestoneButtons
.
forEach
(
button
=>
{
button
.
addEventListener
(
'
click
'
,
onDeleteButtonClick
);
});
eventHub
.
$once
(
'
deleteMilestoneModal.mounted
'
,
()
=>
{
deleteMilestoneButtons
.
forEach
(
(
button
)
=>
{
deleteMilestoneButtons
.
forEach
(
button
=>
{
button
.
removeAttribute
(
'
disabled
'
);
});
});
...
...
app/assets/javascripts/pages/milestones/shared/promote_milestone_modal_init.js
View file @
d2ee2eab
...
...
@@ -7,20 +7,24 @@ Vue.use(Translate);
export
default
()
=>
{
const
onRequestFinished
=
({
milestoneUrl
,
successful
})
=>
{
const
button
=
document
.
querySelector
(
`.js-promote-project-milestone-button[data-url="
${
milestoneUrl
}
"]`
);
const
button
=
document
.
querySelector
(
`.js-promote-project-milestone-button[data-url="
${
milestoneUrl
}
"]`
,
);
if
(
!
successful
)
{
button
.
removeAttribute
(
'
disabled
'
);
}
};
const
onRequestStarted
=
(
milestoneUrl
)
=>
{
const
button
=
document
.
querySelector
(
`.js-promote-project-milestone-button[data-url="
${
milestoneUrl
}
"]`
);
const
onRequestStarted
=
milestoneUrl
=>
{
const
button
=
document
.
querySelector
(
`.js-promote-project-milestone-button[data-url="
${
milestoneUrl
}
"]`
,
);
button
.
setAttribute
(
'
disabled
'
,
''
);
eventHub
.
$once
(
'
promoteMilestoneModal.requestFinished
'
,
onRequestFinished
);
};
const
onDeleteButtonClick
=
(
event
)
=>
{
const
onDeleteButtonClick
=
event
=>
{
const
button
=
event
.
currentTarget
;
const
modalProps
=
{
milestoneTitle
:
button
.
dataset
.
milestoneTitle
,
...
...
@@ -32,12 +36,12 @@ export default () => {
};
const
promoteMilestoneButtons
=
document
.
querySelectorAll
(
'
.js-promote-project-milestone-button
'
);
promoteMilestoneButtons
.
forEach
(
(
button
)
=>
{
promoteMilestoneButtons
.
forEach
(
button
=>
{
button
.
addEventListener
(
'
click
'
,
onDeleteButtonClick
);
});
eventHub
.
$once
(
'
promoteMilestoneModal.mounted
'
,
()
=>
{
promoteMilestoneButtons
.
forEach
(
(
button
)
=>
{
promoteMilestoneButtons
.
forEach
(
button
=>
{
button
.
removeAttribute
(
'
disabled
'
);
});
});
...
...
app/assets/javascripts/pages/profiles/index.js
View file @
d2ee2eab
...
...
@@ -3,9 +3,12 @@ import '~/profile/gl_crop';
import
Profile
from
'
~/profile/profile
'
;
document
.
addEventListener
(
'
DOMContentLoaded
'
,
()
=>
{
$
(
document
).
on
(
'
input.ssh_key
'
,
'
#key_key
'
,
function
()
{
// eslint-disable-line func-names
// eslint-disable-next-line func-names
$
(
document
).
on
(
'
input.ssh_key
'
,
'
#key_key
'
,
function
()
{
const
$title
=
$
(
'
#key_title
'
);
const
comment
=
$
(
this
).
val
().
match
(
/^
\S
+
\S
+
(
.+
)\n?
$/
);
const
comment
=
$
(
this
)
.
val
()
.
match
(
/^
\S
+
\S
+
(
.+
)\n?
$/
);
// Extract the SSH Key title from its comment
if
(
comment
&&
comment
.
length
>
1
)
{
...
...
app/assets/javascripts/pages/profiles/two_factor_auths/index.js
View file @
d2ee2eab
...
...
@@ -5,7 +5,9 @@ document.addEventListener('DOMContentLoaded', () => {
const
twoFactorNode
=
document
.
querySelector
(
'
.js-two-factor-auth
'
);
const
skippable
=
twoFactorNode
.
dataset
.
twoFactorSkippable
===
'
true
'
;
if
(
skippable
)
{
const
button
=
`<a class="btn btn-sm btn-warning float-right" data-method="patch" href="
${
twoFactorNode
.
dataset
.
two_factor_skip_url
}
">Configure it later</a>`
;
const
button
=
`<a class="btn btn-sm btn-warning float-right" data-method="patch" href="
${
twoFactorNode
.
dataset
.
two_factor_skip_url
}
">Configure it later</a>`
;
const
flashAlert
=
document
.
querySelector
(
'
.flash-alert .container-fluid
'
);
if
(
flashAlert
)
flashAlert
.
insertAdjacentHTML
(
'
beforeend
'
,
button
);
}
...
...
app/assets/javascripts/pages/projects/branches/new/index.js
View file @
d2ee2eab
import
$
from
'
jquery
'
;
import
NewBranchForm
from
'
~/new_branch_form
'
;
document
.
addEventListener
(
'
DOMContentLoaded
'
,
()
=>
(
new
NewBranchForm
(
$
(
'
.js-create-branch-form
'
),
JSON
.
parse
(
document
.
getElementById
(
'
availableRefs
'
).
innerHTML
))
));
document
.
addEventListener
(
'
DOMContentLoaded
'
,
()
=>
new
NewBranchForm
(
$
(
'
.js-create-branch-form
'
),
JSON
.
parse
(
document
.
getElementById
(
'
availableRefs
'
).
innerHTML
),
),
);
app/assets/javascripts/pages/projects/graphs/charts/index.js
View file @
d2ee2eab
...
...
@@ -31,14 +31,16 @@ document.addEventListener('DOMContentLoaded', () => {
const
chartData
=
data
=>
({
labels
:
Object
.
keys
(
data
),
datasets
:
[{
fillColor
:
'
rgba(220,220,220,0.5)
'
,
strokeColor
:
'
rgba(220,220,220,1)
'
,
barStrokeWidth
:
1
,
barValueSpacing
:
1
,
barDatasetSpacing
:
1
,
data
:
_
.
values
(
data
),
}],
datasets
:
[
{
fillColor
:
'
rgba(220,220,220,0.5)
'
,
strokeColor
:
'
rgba(220,220,220,1)
'
,
barStrokeWidth
:
1
,
barValueSpacing
:
1
,
barDatasetSpacing
:
1
,
data
:
_
.
values
(
data
),
},
],
});
const
hourData
=
chartData
(
projectChartData
.
hour
);
...
...
@@ -51,7 +53,9 @@ document.addEventListener('DOMContentLoaded', () => {
responsiveChart
(
$
(
'
#month-chart
'
),
monthData
);
const
data
=
projectChartData
.
languages
;
const
ctx
=
$
(
'
#languages-chart
'
).
get
(
0
).
getContext
(
'
2d
'
);
const
ctx
=
$
(
'
#languages-chart
'
)
.
get
(
0
)
.
getContext
(
'
2d
'
);
const
options
=
{
scaleOverlay
:
true
,
responsive
:
true
,
...
...
app/assets/javascripts/pages/projects/graphs/show/index.js
View file @
d2ee2eab
...
...
@@ -7,7 +7,8 @@ import ContributorsStatGraph from './stat_graph_contributors';
document
.
addEventListener
(
'
DOMContentLoaded
'
,
()
=>
{
const
url
=
document
.
querySelector
(
'
.js-graphs-show
'
).
dataset
.
projectGraphPath
;
axios
.
get
(
url
)
axios
.
get
(
url
)
.
then
(({
data
})
=>
{
const
graph
=
new
ContributorsStatGraph
();
graph
.
init
(
data
);
...
...
app/assets/javascripts/pages/projects/graphs/show/stat_graph_contributors.js
View file @
d2ee2eab
...
...
@@ -3,7 +3,11 @@
import
$
from
'
jquery
'
;
import
_
from
'
underscore
'
;
import
{
n__
,
s__
,
createDateTimeFormat
,
sprintf
}
from
'
~/locale
'
;
import
{
ContributorsGraph
,
ContributorsAuthorGraph
,
ContributorsMasterGraph
}
from
'
./stat_graph_contributors_graph
'
;
import
{
ContributorsGraph
,
ContributorsAuthorGraph
,
ContributorsMasterGraph
,
}
from
'
./stat_graph_contributors_graph
'
;
import
ContributorsStatGraphUtil
from
'
./stat_graph_contributors_util
'
;
export
default
(
function
()
{
...
...
@@ -14,7 +18,7 @@ export default (function() {
ContributorsStatGraph
.
prototype
.
init
=
function
(
log
)
{
var
author_commits
,
total_commits
;
this
.
parsed_log
=
ContributorsStatGraphUtil
.
parse_log
(
log
);
this
.
set_current_field
(
"
commits
"
);
this
.
set_current_field
(
'
commits
'
);
total_commits
=
ContributorsStatGraphUtil
.
get_total_data
(
this
.
parsed_log
,
this
.
field
);
author_commits
=
ContributorsStatGraphUtil
.
get_author_data
(
this
.
parsed_log
,
this
.
field
);
this
.
add_master_graph
(
total_commits
);
...
...
@@ -31,23 +35,26 @@ export default (function() {
var
limited_author_data
;
this
.
authors
=
[];
limited_author_data
=
author_data
.
slice
(
0
,
100
);
return
_
.
each
(
limited_author_data
,
(
function
(
_this
)
{
return
function
(
d
)
{
var
author_graph
,
author_header
;
author_header
=
_this
.
create_author_header
(
d
);
$
(
"
.contributors-list
"
).
append
(
author_header
);
author_graph
=
new
ContributorsAuthorGraph
(
d
.
dates
);
_this
.
authors
[
d
.
author_name
]
=
author_graph
;
return
author_graph
.
draw
();
};
})(
this
));
return
_
.
each
(
limited_author_data
,
(
function
(
_this
)
{
return
function
(
d
)
{
var
author_graph
,
author_header
;
author_header
=
_this
.
create_author_header
(
d
);
$
(
'
.contributors-list
'
).
append
(
author_header
);
author_graph
=
new
ContributorsAuthorGraph
(
d
.
dates
);
_this
.
authors
[
d
.
author_name
]
=
author_graph
;
return
author_graph
.
draw
();
};
})(
this
),
);
};
ContributorsStatGraph
.
prototype
.
format_author_commit_info
=
function
(
author
)
{
var
commits
;
commits
=
$
(
'
<span/>
'
,
{
"
class
"
:
'
graph-author-commits-count
'
class
:
'
graph-author-commits-count
'
,
});
commits
.
text
(
n__
(
'
%d commit
'
,
'
%d commits
'
,
author
.
commits
));
return
$
(
'
<span/>
'
).
append
(
commits
);
...
...
@@ -56,13 +63,13 @@ export default (function() {
ContributorsStatGraph
.
prototype
.
create_author_header
=
function
(
author
)
{
var
author_commit_info
,
author_commit_info_span
,
author_email
,
author_name
,
list_item
;
list_item
=
$
(
'
<li/>
'
,
{
"
class
"
:
'
person
'
,
style
:
'
display: block;
'
class
:
'
person
'
,
style
:
'
display: block;
'
,
});
author_name
=
$
(
'
<h4>
'
+
author
.
author_name
+
'
</h4>
'
);
author_email
=
$
(
'
<p class="graph-author-email">
'
+
author
.
author_email
+
'
</p>
'
);
author_commit_info_span
=
$
(
'
<span/>
'
,
{
"
class
"
:
'
commits
'
class
:
'
commits
'
,
});
author_commit_info
=
this
.
format_author_commit_info
(
author
);
author_commit_info_span
.
html
(
author_commit_info
);
...
...
@@ -80,37 +87,41 @@ export default (function() {
};
ContributorsStatGraph
.
prototype
.
redraw_authors
=
function
()
{
$
(
"
ol
"
).
html
(
""
);
$
(
'
ol
'
).
html
(
''
);
const
{
x_domain
}
=
ContributorsGraph
.
prototype
;
const
author_commits
=
ContributorsStatGraphUtil
.
get_author_data
(
this
.
parsed_log
,
this
.
field
,
x_domain
);
return
_
.
each
(
author_commits
,
(
function
(
_this
)
{
return
function
(
d
)
{
_this
.
redraw_author_commit_info
(
d
);
if
(
_this
.
authors
[
d
.
author_name
]
!=
null
)
{
$
(
_this
.
authors
[
d
.
author_name
].
list_item
).
appendTo
(
"
ol
"
);
_this
.
authors
[
d
.
author_name
].
set_data
(
d
.
dates
);
return
_this
.
authors
[
d
.
author_name
].
redraw
();
}
return
''
;
};
})(
this
));
const
author_commits
=
ContributorsStatGraphUtil
.
get_author_data
(
this
.
parsed_log
,
this
.
field
,
x_domain
,
);
return
_
.
each
(
author_commits
,
(
function
(
_this
)
{
return
function
(
d
)
{
_this
.
redraw_author_commit_info
(
d
);
if
(
_this
.
authors
[
d
.
author_name
]
!=
null
)
{
$
(
_this
.
authors
[
d
.
author_name
].
list_item
).
appendTo
(
'
ol
'
);
_this
.
authors
[
d
.
author_name
].
set_data
(
d
.
dates
);
return
_this
.
authors
[
d
.
author_name
].
redraw
();
}
return
''
;
};
})(
this
),
);
};
ContributorsStatGraph
.
prototype
.
set_current_field
=
function
(
field
)
{
return
this
.
field
=
field
;
return
(
this
.
field
=
field
)
;
};
ContributorsStatGraph
.
prototype
.
change_date_header
=
function
()
{
const
{
x_domain
}
=
ContributorsGraph
.
prototype
;
const
formattedDateRange
=
sprintf
(
s__
(
'
ContributorsPage|%{startDate} – %{endDate}
'
),
{
startDate
:
this
.
dateFormat
.
format
(
new
Date
(
x_domain
[
0
])),
endDate
:
this
.
dateFormat
.
format
(
new
Date
(
x_domain
[
1
])),
},
);
const
formattedDateRange
=
sprintf
(
s__
(
'
ContributorsPage|%{startDate} – %{endDate}
'
),
{
startDate
:
this
.
dateFormat
.
format
(
new
Date
(
x_domain
[
0
])),
endDate
:
this
.
dateFormat
.
format
(
new
Date
(
x_domain
[
1
])),
});
return
$
(
'
#date_header
'
).
text
(
formattedDateRange
);
};
...
...
@@ -120,7 +131,7 @@ export default (function() {
if
(
$author
!=
null
)
{
author_list_item
=
$
(
this
.
authors
[
author
.
author_name
].
list_item
);
author_commit_info
=
this
.
format_author_commit_info
(
author
);
return
author_list_item
.
find
(
"
span
"
).
html
(
author_commit_info
);
return
author_list_item
.
find
(
'
span
'
).
html
(
author_commit_info
);
}
return
''
;
};
...
...
app/assets/javascripts/pages/projects/graphs/show/stat_graph_contributors_graph.js
View file @
d2ee2eab
...
...
@@ -11,10 +11,32 @@ import { brushX } from 'd3-brush';
import
{
timeParse
}
from
'
d3-time-format
'
;
import
{
dateTickFormat
}
from
'
~/lib/utils/tick_formats
'
;
const
d3
=
{
extent
,
max
,
select
,
scaleTime
,
scaleLinear
,
axisLeft
,
axisBottom
,
area
,
brushX
,
timeParse
};
const
d3
=
{
extent
,
max
,
select
,
scaleTime
,
scaleLinear
,
axisLeft
,
axisBottom
,
area
,
brushX
,
timeParse
,
};
const
hasProp
=
{}.
hasOwnProperty
;
const
extend
=
function
(
child
,
parent
)
{
for
(
const
key
in
parent
)
{
if
(
hasProp
.
call
(
parent
,
key
))
child
[
key
]
=
parent
[
key
];
}
function
ctor
()
{
this
.
constructor
=
child
;
}
ctor
.
prototype
=
parent
.
prototype
;
child
.
prototype
=
new
ctor
();
child
.
__super__
=
parent
.
prototype
;
return
child
;
};
const
extend
=
function
(
child
,
parent
)
{
for
(
const
key
in
parent
)
{
if
(
hasProp
.
call
(
parent
,
key
))
child
[
key
]
=
parent
[
key
];
}
function
ctor
()
{
this
.
constructor
=
child
;
}
ctor
.
prototype
=
parent
.
prototype
;
child
.
prototype
=
new
ctor
();
child
.
__super__
=
parent
.
prototype
;
return
child
;
};
export
const
ContributorsGraph
=
(
function
()
{
function
ContributorsGraph
()
{}
...
...
@@ -23,7 +45,7 @@ export const ContributorsGraph = (function() {
top
:
20
,
right
:
10
,
bottom
:
30
,
left
:
40
left
:
40
,
};
ContributorsGraph
.
prototype
.
x_domain
=
null
;
...
...
@@ -33,35 +55,39 @@ export const ContributorsGraph = (function() {
ContributorsGraph
.
prototype
.
dates
=
[];
ContributorsGraph
.
prototype
.
determine_width
=
function
(
baseWidth
,
$parentElement
)
{
const
parentPaddingWidth
=
parseFloat
(
$parentElement
.
css
(
'
padding-left
'
))
+
parseFloat
(
$parentElement
.
css
(
'
padding-right
'
));
const
parentPaddingWidth
=
parseFloat
(
$parentElement
.
css
(
'
padding-left
'
))
+
parseFloat
(
$parentElement
.
css
(
'
padding-right
'
));
const
marginWidth
=
this
.
MARGIN
.
left
+
this
.
MARGIN
.
right
;
return
baseWidth
-
parentPaddingWidth
-
marginWidth
;
};
ContributorsGraph
.
set_x_domain
=
function
(
data
)
{
return
ContributorsGraph
.
prototype
.
x_domain
=
data
;
return
(
ContributorsGraph
.
prototype
.
x_domain
=
data
)
;
};
ContributorsGraph
.
set_y_domain
=
function
(
data
)
{
return
ContributorsGraph
.
prototype
.
y_domain
=
[
0
,
d3
.
max
(
data
,
function
(
d
)
{
return
d
.
commits
=
d
.
commits
||
d
.
additions
||
d
.
deletions
;
})
];
return
(
ContributorsGraph
.
prototype
.
y_domain
=
[
0
,
d3
.
max
(
data
,
function
(
d
)
{
return
(
d
.
commits
=
d
.
commits
||
d
.
additions
||
d
.
deletions
);
}),
]);
};
ContributorsGraph
.
init_x_domain
=
function
(
data
)
{
return
ContributorsGraph
.
prototype
.
x_domain
=
d3
.
extent
(
data
,
function
(
d
)
{
return
(
ContributorsGraph
.
prototype
.
x_domain
=
d3
.
extent
(
data
,
function
(
d
)
{
return
d
.
date
;
});
})
)
;
};
ContributorsGraph
.
init_y_domain
=
function
(
data
)
{
return
ContributorsGraph
.
prototype
.
y_domain
=
[
0
,
d3
.
max
(
data
,
function
(
d
)
{
return
d
.
commits
=
d
.
commits
||
d
.
additions
||
d
.
deletions
;
})
];
return
(
ContributorsGraph
.
prototype
.
y_domain
=
[
0
,
d3
.
max
(
data
,
function
(
d
)
{
return
(
d
.
commits
=
d
.
commits
||
d
.
additions
||
d
.
deletions
);
}),
]);
};
ContributorsGraph
.
init_domain
=
function
(
data
)
{
...
...
@@ -70,7 +96,7 @@ export const ContributorsGraph = (function() {
};
ContributorsGraph
.
set_dates
=
function
(
data
)
{
return
ContributorsGraph
.
prototype
.
dates
=
data
;
return
(
ContributorsGraph
.
prototype
.
dates
=
data
)
;
};
ContributorsGraph
.
prototype
.
set_x_domain
=
function
()
{
...
...
@@ -87,20 +113,33 @@ export const ContributorsGraph = (function() {
};
ContributorsGraph
.
prototype
.
create_scale
=
function
(
width
,
height
)
{
this
.
x
=
d3
.
scaleTime
().
range
([
0
,
width
]).
clamp
(
true
);
return
this
.
y
=
d3
.
scaleLinear
().
range
([
height
,
0
]).
nice
();
this
.
x
=
d3
.
scaleTime
()
.
range
([
0
,
width
])
.
clamp
(
true
);
return
(
this
.
y
=
d3
.
scaleLinear
()
.
range
([
height
,
0
])
.
nice
());
};
ContributorsGraph
.
prototype
.
draw_x_axis
=
function
()
{
return
this
.
svg
.
append
(
"
g
"
).
attr
(
"
class
"
,
"
x axis
"
).
attr
(
"
transform
"
,
"
translate(0,
"
+
this
.
height
+
"
)
"
).
call
(
this
.
x_axis
);
return
this
.
svg
.
append
(
'
g
'
)
.
attr
(
'
class
'
,
'
x axis
'
)
.
attr
(
'
transform
'
,
'
translate(0,
'
+
this
.
height
+
'
)
'
)
.
call
(
this
.
x_axis
);
};
ContributorsGraph
.
prototype
.
draw_y_axis
=
function
()
{
return
this
.
svg
.
append
(
"
g
"
).
attr
(
"
class
"
,
"
y axis
"
).
call
(
this
.
y_axis
);
return
this
.
svg
.
append
(
'
g
'
)
.
attr
(
'
class
'
,
'
y axis
'
)
.
call
(
this
.
y_axis
);
};
ContributorsGraph
.
prototype
.
set_data
=
function
(
data
)
{
return
this
.
data
=
data
;
return
(
this
.
data
=
data
)
;
};
return
ContributorsGraph
;
...
...
@@ -137,9 +176,9 @@ export const ContributorsMasterGraph = (function(superClass) {
};
ContributorsMasterGraph
.
prototype
.
parse_dates
=
function
(
data
)
{
const
parseDate
=
d3
.
timeParse
(
"
%Y-%m-%d
"
);
const
parseDate
=
d3
.
timeParse
(
'
%Y-%m-%d
'
);
return
data
.
forEach
(
function
(
d
)
{
return
d
.
date
=
parseDate
(
d
.
date
);
return
(
d
.
date
=
parseDate
(
d
.
date
)
);
});
};
...
...
@@ -148,42 +187,63 @@ export const ContributorsMasterGraph = (function(superClass) {
};
ContributorsMasterGraph
.
prototype
.
create_axes
=
function
()
{
this
.
x_axis
=
d3
.
axisBottom
()
this
.
x_axis
=
d3
.
axisBottom
()
.
scale
(
this
.
x
)
.
tickFormat
(
dateTickFormat
);
return
this
.
y_axis
=
d3
.
axisLeft
().
scale
(
this
.
y
).
ticks
(
5
);
return
(
this
.
y_axis
=
d3
.
axisLeft
()
.
scale
(
this
.
y
)
.
ticks
(
5
));
};
ContributorsMasterGraph
.
prototype
.
create_svg
=
function
()
{
this
.
svg
=
d3
.
select
(
"
#contributors-master
"
)
.
append
(
"
svg
"
)
.
attr
(
"
width
"
,
this
.
width
+
this
.
MARGIN
.
left
+
this
.
MARGIN
.
right
)
.
attr
(
"
height
"
,
this
.
height
+
this
.
MARGIN
.
top
+
this
.
MARGIN
.
bottom
)
.
attr
(
"
class
"
,
"
tint-box
"
)
.
append
(
"
g
"
)
.
attr
(
"
transform
"
,
"
translate(
"
+
this
.
MARGIN
.
left
+
"
,
"
+
this
.
MARGIN
.
top
+
"
)
"
);
this
.
svg
=
d3
.
select
(
'
#contributors-master
'
)
.
append
(
'
svg
'
)
.
attr
(
'
width
'
,
this
.
width
+
this
.
MARGIN
.
left
+
this
.
MARGIN
.
right
)
.
attr
(
'
height
'
,
this
.
height
+
this
.
MARGIN
.
top
+
this
.
MARGIN
.
bottom
)
.
attr
(
'
class
'
,
'
tint-box
'
)
.
append
(
'
g
'
)
.
attr
(
'
transform
'
,
'
translate(
'
+
this
.
MARGIN
.
left
+
'
,
'
+
this
.
MARGIN
.
top
+
'
)
'
);
return
this
.
svg
;
};
ContributorsMasterGraph
.
prototype
.
create_area
=
function
(
x
,
y
)
{
return
this
.
area
=
d3
.
area
().
x
(
function
(
d
)
{
return
x
(
d
.
date
);
}).
y0
(
this
.
height
).
y1
(
function
(
d
)
{
d
.
commits
=
d
.
commits
||
d
.
additions
||
d
.
deletions
;
return
y
(
d
.
commits
);
});
return
(
this
.
area
=
d3
.
area
()
.
x
(
function
(
d
)
{
return
x
(
d
.
date
);
})
.
y0
(
this
.
height
)
.
y1
(
function
(
d
)
{
d
.
commits
=
d
.
commits
||
d
.
additions
||
d
.
deletions
;
return
y
(
d
.
commits
);
}));
};
ContributorsMasterGraph
.
prototype
.
create_brush
=
function
()
{
return
this
.
brush
=
d3
.
brushX
(
this
.
x
).
extent
([[
this
.
x
.
range
()[
0
],
0
],
[
this
.
x
.
range
()[
1
],
this
.
height
]]).
on
(
"
end
"
,
this
.
update_content
);
return
(
this
.
brush
=
d3
.
brushX
(
this
.
x
)
.
extent
([[
this
.
x
.
range
()[
0
],
0
],
[
this
.
x
.
range
()[
1
],
this
.
height
]])
.
on
(
'
end
'
,
this
.
update_content
));
};
ContributorsMasterGraph
.
prototype
.
draw_path
=
function
(
data
)
{
return
this
.
svg
.
append
(
"
path
"
).
datum
(
data
).
attr
(
"
class
"
,
"
area
"
).
attr
(
"
d
"
,
this
.
area
);
return
this
.
svg
.
append
(
'
path
'
)
.
datum
(
data
)
.
attr
(
'
class
'
,
'
area
'
)
.
attr
(
'
d
'
,
this
.
area
);
};
ContributorsMasterGraph
.
prototype
.
add_brush
=
function
()
{
return
this
.
svg
.
append
(
"
g
"
).
attr
(
"
class
"
,
"
selection
"
).
call
(
this
.
brush
).
selectAll
(
"
rect
"
).
attr
(
"
height
"
,
this
.
height
);
return
this
.
svg
.
append
(
'
g
'
)
.
attr
(
'
class
'
,
'
selection
'
)
.
call
(
this
.
brush
)
.
selectAll
(
'
rect
'
)
.
attr
(
'
height
'
,
this
.
height
);
};
ContributorsMasterGraph
.
prototype
.
update_content
=
function
()
{
...
...
@@ -193,7 +253,7 @@ export const ContributorsMasterGraph = (function(superClass) {
}
else
{
ContributorsGraph
.
set_x_domain
(
this
.
x_max_domain
);
}
return
$
(
"
#brush_change
"
).
trigger
(
'
change
'
);
return
$
(
'
#brush_change
'
).
trigger
(
'
change
'
);
};
ContributorsMasterGraph
.
prototype
.
draw
=
function
()
{
...
...
@@ -216,9 +276,9 @@ export const ContributorsMasterGraph = (function(superClass) {
this
.
process_dates
(
this
.
data
);
ContributorsGraph
.
set_y_domain
(
this
.
data
);
this
.
set_y_domain
();
this
.
svg
.
select
(
"
path
"
).
datum
(
this
.
data
);
this
.
svg
.
select
(
"
path
"
).
attr
(
"
d
"
,
this
.
area
);
return
this
.
svg
.
select
(
"
.y.axis
"
).
call
(
this
.
y_axis
);
this
.
svg
.
select
(
'
path
'
).
datum
(
this
.
data
);
this
.
svg
.
select
(
'
path
'
).
attr
(
'
d
'
,
this
.
area
);
return
this
.
svg
.
select
(
'
.y.axis
'
).
call
(
this
.
y_axis
);
};
return
ContributorsMasterGraph
;
...
...
@@ -252,43 +312,58 @@ export const ContributorsAuthorGraph = (function(superClass) {
};
ContributorsAuthorGraph
.
prototype
.
create_axes
=
function
()
{
this
.
x_axis
=
d3
.
axisBottom
()
this
.
x_axis
=
d3
.
axisBottom
()
.
scale
(
this
.
x
)
.
ticks
(
8
)
.
tickFormat
(
dateTickFormat
);
return
this
.
y_axis
=
d3
.
axisLeft
().
scale
(
this
.
y
).
ticks
(
5
);
return
(
this
.
y_axis
=
d3
.
axisLeft
()
.
scale
(
this
.
y
)
.
ticks
(
5
));
};
ContributorsAuthorGraph
.
prototype
.
create_area
=
function
(
x
,
y
)
{
return
this
.
area
=
d3
.
area
().
x
(
function
(
d
)
{
const
parseDate
=
d3
.
timeParse
(
"
%Y-%m-%d
"
);
return
x
(
parseDate
(
d
));
}).
y0
(
this
.
height
).
y1
((
function
(
_this
)
{
return
function
(
d
)
{
if
(
_this
.
data
[
d
]
!=
null
)
{
return
y
(
_this
.
data
[
d
]);
}
else
{
return
y
(
0
);
}
};
})(
this
));
return
(
this
.
area
=
d3
.
area
()
.
x
(
function
(
d
)
{
const
parseDate
=
d3
.
timeParse
(
'
%Y-%m-%d
'
);
return
x
(
parseDate
(
d
));
})
.
y0
(
this
.
height
)
.
y1
(
(
function
(
_this
)
{
return
function
(
d
)
{
if
(
_this
.
data
[
d
]
!=
null
)
{
return
y
(
_this
.
data
[
d
]);
}
else
{
return
y
(
0
);
}
};
})(
this
),
));
};
ContributorsAuthorGraph
.
prototype
.
create_svg
=
function
()
{
const
persons
=
document
.
querySelectorAll
(
'
.person
'
);
this
.
list_item
=
persons
[
persons
.
length
-
1
];
this
.
svg
=
d3
.
select
(
this
.
list_item
)
.
append
(
"
svg
"
)
.
attr
(
"
width
"
,
this
.
width
+
this
.
MARGIN
.
left
+
this
.
MARGIN
.
right
)
.
attr
(
"
height
"
,
this
.
height
+
this
.
MARGIN
.
top
+
this
.
MARGIN
.
bottom
)
.
attr
(
"
class
"
,
"
spark
"
)
.
append
(
"
g
"
)
.
attr
(
"
transform
"
,
"
translate(
"
+
this
.
MARGIN
.
left
+
"
,
"
+
this
.
MARGIN
.
top
+
"
)
"
);
this
.
svg
=
d3
.
select
(
this
.
list_item
)
.
append
(
'
svg
'
)
.
attr
(
'
width
'
,
this
.
width
+
this
.
MARGIN
.
left
+
this
.
MARGIN
.
right
)
.
attr
(
'
height
'
,
this
.
height
+
this
.
MARGIN
.
top
+
this
.
MARGIN
.
bottom
)
.
attr
(
'
class
'
,
'
spark
'
)
.
append
(
'
g
'
)
.
attr
(
'
transform
'
,
'
translate(
'
+
this
.
MARGIN
.
left
+
'
,
'
+
this
.
MARGIN
.
top
+
'
)
'
);
return
this
.
svg
;
};
ContributorsAuthorGraph
.
prototype
.
draw_path
=
function
(
data
)
{
return
this
.
svg
.
append
(
"
path
"
).
datum
(
data
).
attr
(
"
class
"
,
"
area-contributor
"
).
attr
(
"
d
"
,
this
.
area
);
return
this
.
svg
.
append
(
'
path
'
)
.
datum
(
data
)
.
attr
(
'
class
'
,
'
area-contributor
'
)
.
attr
(
'
d
'
,
this
.
area
);
};
ContributorsAuthorGraph
.
prototype
.
draw
=
function
()
{
...
...
@@ -304,10 +379,10 @@ export const ContributorsAuthorGraph = (function(superClass) {
ContributorsAuthorGraph
.
prototype
.
redraw
=
function
()
{
this
.
set_domain
();
this
.
svg
.
select
(
"
path
"
).
datum
(
this
.
dates
);
this
.
svg
.
select
(
"
path
"
).
attr
(
"
d
"
,
this
.
area
);
this
.
svg
.
select
(
"
.x.axis
"
).
call
(
this
.
x_axis
);
return
this
.
svg
.
select
(
"
.y.axis
"
).
call
(
this
.
y_axis
);
this
.
svg
.
select
(
'
path
'
).
datum
(
this
.
dates
);
this
.
svg
.
select
(
'
path
'
).
attr
(
'
d
'
,
this
.
area
);
this
.
svg
.
select
(
'
.x.axis
'
).
call
(
this
.
x_axis
);
return
this
.
svg
.
select
(
'
.y.axis
'
).
call
(
this
.
y_axis
);
};
return
ContributorsAuthorGraph
;
...
...
app/assets/javascripts/pages/projects/graphs/show/stat_graph_contributors_util.js
View file @
d2ee2eab
...
...
@@ -26,12 +26,12 @@ export default {
by_author
=
_
.
toArray
(
by_author
);
return
{
total
:
total
,
by_author
:
by_author
by_author
:
by_author
,
};
},
add_date
:
function
(
date
,
collection
)
{
collection
[
date
]
=
{};
return
collection
[
date
].
date
=
date
;
return
(
collection
[
date
].
date
=
date
)
;
},
add_author
:
function
(
author
,
by_author
,
by_email
)
{
var
data
,
normalized_email
;
...
...
@@ -49,28 +49,28 @@ export default {
return
this
.
store_deletions
(
entry
,
total
,
by_author
);
},
store_commits
:
function
(
total
,
by_author
)
{
this
.
add
(
total
,
"
commits
"
,
1
);
return
this
.
add
(
by_author
,
"
commits
"
,
1
);
this
.
add
(
total
,
'
commits
'
,
1
);
return
this
.
add
(
by_author
,
'
commits
'
,
1
);
},
add
:
function
(
collection
,
field
,
value
)
{
if
(
collection
[
field
]
==
null
)
{
collection
[
field
]
=
0
;
}
return
collection
[
field
]
+=
value
;
return
(
collection
[
field
]
+=
value
)
;
},
store_additions
:
function
(
entry
,
total
,
by_author
)
{
if
(
entry
.
additions
==
null
)
{
entry
.
additions
=
0
;
}
this
.
add
(
total
,
"
additions
"
,
entry
.
additions
);
return
this
.
add
(
by_author
,
"
additions
"
,
entry
.
additions
);
this
.
add
(
total
,
'
additions
'
,
entry
.
additions
);
return
this
.
add
(
by_author
,
'
additions
'
,
entry
.
additions
);
},
store_deletions
:
function
(
entry
,
total
,
by_author
)
{
if
(
entry
.
deletions
==
null
)
{
entry
.
deletions
=
0
;
}
this
.
add
(
total
,
"
deletions
"
,
entry
.
deletions
);
return
this
.
add
(
by_author
,
"
deletions
"
,
entry
.
deletions
);
this
.
add
(
total
,
'
deletions
'
,
entry
.
deletions
);
return
this
.
add
(
by_author
,
'
deletions
'
,
entry
.
deletions
);
},
get_total_data
:
function
(
parsed_log
,
field
)
{
var
log
,
total_data
;
...
...
@@ -95,15 +95,18 @@ export default {
}
log
=
parsed_log
.
by_author
;
author_data
=
[];
_
.
each
(
log
,
(
function
(
_this
)
{
return
function
(
log_entry
)
{
var
parsed_log_entry
;
parsed_log_entry
=
_this
.
parse_log_entry
(
log_entry
,
field
,
date_range
);
if
(
!
_
.
isEmpty
(
parsed_log_entry
.
dates
))
{
return
author_data
.
push
(
parsed_log_entry
);
}
};
})(
this
));
_
.
each
(
log
,
(
function
(
_this
)
{
return
function
(
log_entry
)
{
var
parsed_log_entry
;
parsed_log_entry
=
_this
.
parse_log_entry
(
log_entry
,
field
,
date_range
);
if
(
!
_
.
isEmpty
(
parsed_log_entry
.
dates
))
{
return
author_data
.
push
(
parsed_log_entry
);
}
};
})(
this
),
);
return
_
.
sortBy
(
author_data
,
function
(
d
)
{
return
d
[
field
];
}).
reverse
();
...
...
@@ -120,16 +123,19 @@ export default {
parsed_entry
.
additions
=
0
;
parsed_entry
.
deletions
=
0
;
_
.
each
(
_
.
omit
(
log_entry
,
'
author_name
'
,
'
author_email
'
),
(
function
(
_this
)
{
return
function
(
value
,
key
)
{
if
(
_this
.
in_range
(
value
.
date
,
date_range
))
{
parsed_entry
.
dates
[
value
.
date
]
=
value
[
field
];
parsed_entry
.
commits
+=
value
.
commits
;
parsed_entry
.
additions
+=
value
.
additions
;
return
parsed_entry
.
deletions
+=
value
.
deletions
;
}
};
})(
this
));
_
.
each
(
_
.
omit
(
log_entry
,
'
author_name
'
,
'
author_email
'
),
(
function
(
_this
)
{
return
function
(
value
,
key
)
{
if
(
_this
.
in_range
(
value
.
date
,
date_range
))
{
parsed_entry
.
dates
[
value
.
date
]
=
value
[
field
];
parsed_entry
.
commits
+=
value
.
commits
;
parsed_entry
.
additions
+=
value
.
additions
;
return
(
parsed_entry
.
deletions
+=
value
.
deletions
);
}
};
})(
this
),
);
return
parsed_entry
;
},
in_range
:
function
(
date
,
date_range
)
{
...
...
@@ -139,5 +145,5 @@ export default {
}
else
{
return
false
;
}
}
}
,
};
app/assets/javascripts/pages/projects/init_blob.js
View file @
d2ee2eab
...
...
@@ -16,7 +16,8 @@ export default () => {
);
const
fileBlobPermalinkUrlElement
=
document
.
querySelector
(
'
.js-data-file-blob-permalink-url
'
);
const
fileBlobPermalinkUrl
=
fileBlobPermalinkUrlElement
&&
fileBlobPermalinkUrlElement
.
getAttribute
(
'
href
'
);
const
fileBlobPermalinkUrl
=
fileBlobPermalinkUrlElement
&&
fileBlobPermalinkUrlElement
.
getAttribute
(
'
href
'
);
new
ShortcutsNavigation
();
// eslint-disable-line no-new
...
...
app/assets/javascripts/pages/projects/init_form.js
View file @
d2ee2eab
import
ZenMode
from
'
~/zen_mode
'
;
import
GLForm
from
'
~/gl_form
'
;
export
default
function
(
$formEl
)
{
export
default
function
(
$formEl
)
{
new
ZenMode
();
// eslint-disable-line no-new
new
GLForm
(
$formEl
);
// eslint-disable-line no-new
}
app/assets/javascripts/pages/projects/issues/show.js
View file @
d2ee2eab
...
...
@@ -5,7 +5,7 @@ import ZenMode from '~/zen_mode';
import
'
~/notes/index
'
;
import
initIssueableApp
from
'
~/issue_show
'
;
export
default
function
()
{
export
default
function
()
{
initIssueableApp
();
new
Issue
();
// eslint-disable-line no-new
new
ShortcutsIssuable
();
// eslint-disable-line no-new
...
...
app/assets/javascripts/pages/projects/labels/components/promote_label_modal.vue
View file @
d2ee2eab
<
script
>
import
_
from
'
underscore
'
;
import
axios
from
'
~/lib/utils/axios_utils
'
;
import
createFlash
from
'
~/flash
'
;
import
GlModal
from
'
~/vue_shared/components/gl_modal.vue
'
;
import
{
s__
,
sprintf
}
from
'
~/locale
'
;
import
{
visitUrl
}
from
'
~/lib/utils/url_utility
'
;
import
eventHub
from
'
../event_hub
'
;
import
_
from
'
underscore
'
;
import
axios
from
'
~/lib/utils/axios_utils
'
;
import
createFlash
from
'
~/flash
'
;
import
GlModal
from
'
~/vue_shared/components/gl_modal.vue
'
;
import
{
s__
,
sprintf
}
from
'
~/locale
'
;
import
{
visitUrl
}
from
'
~/lib/utils/url_utility
'
;
import
eventHub
from
'
../event_hub
'
;
export
default
{
components
:
{
GlModal
,
export
default
{
components
:
{
GlModal
,
},
props
:
{
url
:
{
type
:
String
,
required
:
true
,
},
props
:
{
url
:
{
type
:
String
,
required
:
true
,
},
labelTitle
:
{
type
:
String
,
required
:
true
,
},
labelColor
:
{
type
:
String
,
required
:
true
,
},
labelTextColor
:
{
type
:
String
,
required
:
true
,
},
groupName
:
{
type
:
String
,
required
:
true
,
},
labelTitle
:
{
type
:
String
,
required
:
true
,
},
computed
:
{
text
()
{
return
sprintf
(
s__
(
`Labels|Promoting %{labelTitle} will make it available for all projects inside %{groupName}.
Existing project labels with the same title will be merged. This action cannot be reversed.`
),
{
labelColor
:
{
type
:
String
,
required
:
true
,
},
labelTextColor
:
{
type
:
String
,
required
:
true
,
},
groupName
:
{
type
:
String
,
required
:
true
,
},
},
computed
:
{
text
()
{
return
sprintf
(
s__
(
`Labels|Promoting %{labelTitle} will make it available for all projects inside %{groupName}.
Existing project labels with the same title will be merged. This action cannot be reversed.`
),
{
labelTitle
:
this
.
labelTitle
,
groupName
:
this
.
groupName
,
});
},
title
()
{
const
label
=
`<span
},
);
},
title
()
{
const
label
=
`<span
class="label color-label"
style="background-color:
${
this
.
labelColor
}
; color:
${
this
.
labelTextColor
}
;"
>
${
_
.
escape
(
this
.
labelTitle
)}
</span>`
;
return
sprintf
(
s__
(
'
Labels|<span>Promote label</span> %{labelTitle} <span>to Group Label?</span>
'
),
{
return
sprintf
(
s__
(
'
Labels|<span>Promote label</span> %{labelTitle} <span>to Group Label?</span>
'
),
{
labelTitle
:
label
,
},
false
);
},
},
false
,
);
},
methods
:
{
onSubmit
()
{
eventHub
.
$emit
(
'
promoteLabelModal.requestStarted
'
,
this
.
url
);
return
axios
.
post
(
this
.
url
,
{
params
:
{
format
:
'
json
'
}
})
.
then
((
response
)
=>
{
eventHub
.
$emit
(
'
promoteLabelModal.requestFinished
'
,
{
labelUrl
:
this
.
url
,
successful
:
true
});
visitUrl
(
response
.
data
.
url
);
})
.
catch
((
error
)
=>
{
eventHub
.
$emit
(
'
promoteLabelModal.requestFinished
'
,
{
labelUrl
:
this
.
url
,
successful
:
false
});
createFlash
(
error
);
},
methods
:
{
onSubmit
()
{
eventHub
.
$emit
(
'
promoteLabelModal.requestStarted
'
,
this
.
url
);
return
axios
.
post
(
this
.
url
,
{
params
:
{
format
:
'
json
'
}
})
.
then
(
response
=>
{
eventHub
.
$emit
(
'
promoteLabelModal.requestFinished
'
,
{
labelUrl
:
this
.
url
,
successful
:
true
,
});
visitUrl
(
response
.
data
.
url
);
})
.
catch
(
error
=>
{
eventHub
.
$emit
(
'
promoteLabelModal.requestFinished
'
,
{
labelUrl
:
this
.
url
,
successful
:
false
,
});
},
createFlash
(
error
);
});
},
};
},
};
</
script
>
<
template
>
<gl-modal
...
...
app/assets/javascripts/pages/projects/labels/index/index.js
View file @
d2ee2eab
...
...
@@ -10,20 +10,24 @@ const initLabelIndex = () => {
initLabels
();
const
onRequestFinished
=
({
labelUrl
,
successful
})
=>
{
const
button
=
document
.
querySelector
(
`.js-promote-project-label-button[data-url="
${
labelUrl
}
"]`
);
const
button
=
document
.
querySelector
(
`.js-promote-project-label-button[data-url="
${
labelUrl
}
"]`
,
);
if
(
!
successful
)
{
button
.
removeAttribute
(
'
disabled
'
);
}
};
const
onRequestStarted
=
(
labelUrl
)
=>
{
const
button
=
document
.
querySelector
(
`.js-promote-project-label-button[data-url="
${
labelUrl
}
"]`
);
const
onRequestStarted
=
labelUrl
=>
{
const
button
=
document
.
querySelector
(
`.js-promote-project-label-button[data-url="
${
labelUrl
}
"]`
,
);
button
.
setAttribute
(
'
disabled
'
,
''
);
eventHub
.
$once
(
'
promoteLabelModal.requestFinished
'
,
onRequestFinished
);
};
const
onDeleteButtonClick
=
(
event
)
=>
{
const
onDeleteButtonClick
=
event
=>
{
const
button
=
event
.
currentTarget
;
const
modalProps
=
{
labelTitle
:
button
.
dataset
.
labelTitle
,
...
...
@@ -37,12 +41,12 @@ const initLabelIndex = () => {
};
const
promoteLabelButtons
=
document
.
querySelectorAll
(
'
.js-promote-project-label-button
'
);
promoteLabelButtons
.
forEach
(
(
button
)
=>
{
promoteLabelButtons
.
forEach
(
button
=>
{
button
.
addEventListener
(
'
click
'
,
onDeleteButtonClick
);
});
eventHub
.
$once
(
'
promoteLabelModal.mounted
'
,
()
=>
{
promoteLabelButtons
.
forEach
(
(
button
)
=>
{
promoteLabelButtons
.
forEach
(
button
=>
{
button
.
removeAttribute
(
'
disabled
'
);
});
});
...
...
app/assets/javascripts/pages/projects/network/network.js
View file @
d2ee2eab
...
...
@@ -6,13 +6,15 @@ import BranchGraph from '../../../network/branch_graph';
export
default
(
function
()
{
function
Network
(
opts
)
{
var
vph
;
$
(
"
#filter_ref
"
).
click
(
function
()
{
return
$
(
this
).
closest
(
'
form
'
).
submit
();
$
(
'
#filter_ref
'
).
click
(
function
()
{
return
$
(
this
)
.
closest
(
'
form
'
)
.
submit
();
});
this
.
branch_graph
=
new
BranchGraph
(
$
(
"
.network-graph
"
),
opts
);
this
.
branch_graph
=
new
BranchGraph
(
$
(
'
.network-graph
'
),
opts
);
vph
=
$
(
window
).
height
()
-
250
;
$
(
'
.network-graph
'
).
css
({
'
height
'
:
vph
+
'
px
'
height
:
vph
+
'
px
'
,
});
}
...
...
app/assets/javascripts/pages/projects/pipeline_schedules/index/index.js
View file @
d2ee2eab
import
Vue
from
'
vue
'
;
import
PipelineSchedulesCallout
from
'
../shared/components/pipeline_schedules_callout.vue
'
;
document
.
addEventListener
(
'
DOMContentLoaded
'
,
()
=>
new
Vue
({
el
:
'
#pipeline-schedules-callout
'
,
components
:
{
'
pipeline-schedules-callout
'
:
PipelineSchedulesCallout
,
},
render
(
createElement
)
{
return
createElement
(
'
pipeline-schedules-callout
'
);
},
}));
document
.
addEventListener
(
'
DOMContentLoaded
'
,
()
=>
new
Vue
({
el
:
'
#pipeline-schedules-callout
'
,
components
:
{
'
pipeline-schedules-callout
'
:
PipelineSchedulesCallout
,
},
render
(
createElement
)
{
return
createElement
(
'
pipeline-schedules-callout
'
);
},
}),
);
app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/interval_pattern_input.vue
View file @
d2ee2eab
<
script
>
import
_
from
'
underscore
'
;
import
_
from
'
underscore
'
;
export
default
{
props
:
{
initialCronInterval
:
{
type
:
String
,
required
:
false
,
default
:
''
,
},
},
data
()
{
return
{
inputNameAttribute
:
'
schedule[cron]
'
,
cronInterval
:
this
.
initialCronInterval
,
cronIntervalPresets
:
{
everyDay
:
'
0 4 * * *
'
,
everyWeek
:
'
0 4 * * 0
'
,
everyMonth
:
'
0 4 1 * *
'
,
},
cronSyntaxUrl
:
'
https://en.wikipedia.org/wiki/Cron
'
,
customInputEnabled
:
false
,
};
export
default
{
props
:
{
initialCronInterval
:
{
type
:
String
,
required
:
false
,
default
:
''
,
},
computed
:
{
intervalIsPreset
()
{
return
_
.
contains
(
this
.
cronIntervalPresets
,
this
.
cronInterval
);
},
// The text input is editable when there's a custom interval, or when it's
// a preset interval and the user clicks the 'custom' radio button
isEditable
()
{
return
!!
(
this
.
customInputEnabled
||
!
this
.
intervalIsPreset
);
},
data
()
{
return
{
inputNameAttribute
:
'
schedule[cron]
'
,
cronInterval
:
this
.
initialCronInterval
,
cronIntervalPresets
:
{
everyDay
:
'
0 4 * * *
'
,
everyWeek
:
'
0 4 * * 0
'
,
everyMonth
:
'
0 4 1 * *
'
,
},
cronSyntaxUrl
:
'
https://en.wikipedia.org/wiki/Cron
'
,
customInputEnabled
:
false
,
};
},
computed
:
{
intervalIsPreset
()
{
return
_
.
contains
(
this
.
cronIntervalPresets
,
this
.
cronInterval
);
},
watch
:
{
cronInterval
()
{
// updates field validation state when model changes, as
// glFieldError only updates on input.
this
.
$nextTick
(()
=>
{
gl
.
pipelineScheduleFieldErrors
.
updateFormValidityState
();
});
},
// The text input is editable when there's a custom interval, or when it's
// a preset interval and the user clicks the 'custom' radio button
isEditable
()
{
return
!!
(
this
.
customInputEnabled
||
!
this
.
intervalIsPreset
);
},
created
()
{
if
(
this
.
intervalIsPreset
)
{
this
.
enableCustomInput
=
false
;
}
},
watch
:
{
cronInterval
()
{
// updates field validation state when model changes, as
// glFieldError only updates on input.
this
.
$nextTick
(()
=>
{
gl
.
pipelineScheduleFieldErrors
.
updateFormValidityState
();
});
},
methods
:
{
toggleCustomInput
(
shouldEnable
)
{
this
.
customInputEnabled
=
shouldEnable
;
},
created
()
{
if
(
this
.
intervalIsPreset
)
{
this
.
enableCustomInput
=
false
;
}
},
methods
:
{
toggleCustomInput
(
shouldEnable
)
{
this
.
customInputEnabled
=
shouldEnable
;
if
(
shouldEnable
)
{
// We need to change the value so other radios don't remain selected
// because the model (cronInterval) hasn't changed. The server trims it.
this
.
cronInterval
=
`
${
this
.
cronInterval
}
`
;
}
},
if
(
shouldEnable
)
{
// We need to change the value so other radios don't remain selected
// because the model (cronInterval) hasn't changed. The server trims it.
this
.
cronInterval
=
`
${
this
.
cronInterval
}
`
;
}
},
};
},
};
</
script
>
<
template
>
...
...
app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/pipeline_schedules_callout.vue
View file @
d2ee2eab
<
script
>
import
Vue
from
'
vue
'
;
import
Cookies
from
'
js-cookie
'
;
import
Translate
from
'
../../../../../vue_shared/translate
'
;
import
illustrationSvg
from
'
../icons/intro_illustration.svg
'
;
import
Vue
from
'
vue
'
;
import
Cookies
from
'
js-cookie
'
;
import
Translate
from
'
../../../../../vue_shared/translate
'
;
import
illustrationSvg
from
'
../icons/intro_illustration.svg
'
;
Vue
.
use
(
Translate
);
Vue
.
use
(
Translate
);
const
cookieKey
=
'
pipeline_schedules_callout_dismissed
'
;
const
cookieKey
=
'
pipeline_schedules_callout_dismissed
'
;
export
default
{
name
:
'
PipelineSchedulesCallout
'
,
data
()
{
return
{
docsUrl
:
document
.
getElementById
(
'
pipeline-schedules-callout
'
).
dataset
.
docsUrl
,
calloutDismissed
:
Cookies
.
get
(
cookieKey
)
===
'
true
'
,
};
export
default
{
name
:
'
PipelineSchedulesCallout
'
,
data
()
{
return
{
docsUrl
:
document
.
getElementById
(
'
pipeline-schedules-callout
'
).
dataset
.
docsUrl
,
calloutDismissed
:
Cookies
.
get
(
cookieKey
)
===
'
true
'
,
};
},
created
()
{
this
.
illustrationSvg
=
illustrationSvg
;
},
methods
:
{
dismissCallout
()
{
this
.
calloutDismissed
=
true
;
Cookies
.
set
(
cookieKey
,
this
.
calloutDismissed
,
{
expires
:
365
});
},
created
()
{
this
.
illustrationSvg
=
illustrationSvg
;
},
methods
:
{
dismissCallout
()
{
this
.
calloutDismissed
=
true
;
Cookies
.
set
(
cookieKey
,
this
.
calloutDismissed
,
{
expires
:
365
});
},
},
};
},
};
</
script
>
<
template
>
<div
...
...
app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/target_branch_dropdown.js
View file @
d2ee2eab
...
...
@@ -26,8 +26,7 @@ export default class TargetBranchDropdown {
}
formatBranchesList
()
{
return
this
.
$dropdown
.
data
(
'
data
'
)
.
map
(
val
=>
({
name
:
val
}));
return
this
.
$dropdown
.
data
(
'
data
'
).
map
(
val
=>
({
name
:
val
}));
}
setDropdownToggle
()
{
...
...
app/assets/javascripts/pages/projects/pipeline_schedules/shared/init_form.js
View file @
d2ee2eab
...
...
@@ -11,7 +11,9 @@ Vue.use(Translate);
function
initIntervalPatternInput
()
{
const
intervalPatternMount
=
document
.
getElementById
(
'
interval-pattern-input
'
);
const
initialCronInterval
=
intervalPatternMount
?
intervalPatternMount
.
dataset
.
initialInterval
:
''
;
const
initialCronInterval
=
intervalPatternMount
?
intervalPatternMount
.
dataset
.
initialInterval
:
''
;
return
new
Vue
({
el
:
intervalPatternMount
,
...
...
app/assets/javascripts/pages/projects/pipelines/charts/index.js
View file @
d2ee2eab
...
...
@@ -7,26 +7,29 @@ const options = {
maintainAspectRatio
:
false
,
};
const
buildChart
=
(
chartScope
)
=>
{
const
buildChart
=
chartScope
=>
{
const
data
=
{
labels
:
chartScope
.
labels
,
datasets
:
[{
fillColor
:
'
#707070
'
,
strokeColor
:
'
#707070
'
,
pointColor
:
'
#707070
'
,
pointStrokeColor
:
'
#EEE
'
,
data
:
chartScope
.
totalValues
,
},
{
fillColor
:
'
#1aaa55
'
,
strokeColor
:
'
#1aaa55
'
,
pointColor
:
'
#1aaa55
'
,
pointStrokeColor
:
'
#fff
'
,
data
:
chartScope
.
successValues
,
},
datasets
:
[
{
fillColor
:
'
#707070
'
,
strokeColor
:
'
#707070
'
,
pointColor
:
'
#707070
'
,
pointStrokeColor
:
'
#EEE
'
,
data
:
chartScope
.
totalValues
,
},
{
fillColor
:
'
#1aaa55
'
,
strokeColor
:
'
#1aaa55
'
,
pointColor
:
'
#1aaa55
'
,
pointStrokeColor
:
'
#fff
'
,
data
:
chartScope
.
successValues
,
},
],
};
const
ctx
=
$
(
`#
${
chartScope
.
scope
}
Chart`
).
get
(
0
).
getContext
(
'
2d
'
);
const
ctx
=
$
(
`#
${
chartScope
.
scope
}
Chart`
)
.
get
(
0
)
.
getContext
(
'
2d
'
);
new
Chart
(
ctx
).
Line
(
data
,
options
);
};
...
...
@@ -36,14 +39,16 @@ document.addEventListener('DOMContentLoaded', () => {
const
chartsData
=
JSON
.
parse
(
document
.
getElementById
(
'
pipelinesChartsData
'
).
innerHTML
);
const
data
=
{
labels
:
chartTimesData
.
labels
,
datasets
:
[{
fillColor
:
'
rgba(220,220,220,0.5)
'
,
strokeColor
:
'
rgba(220,220,220,1)
'
,
barStrokeWidth
:
1
,
barValueSpacing
:
1
,
barDatasetSpacing
:
1
,
data
:
chartTimesData
.
values
,
}],
datasets
:
[
{
fillColor
:
'
rgba(220,220,220,0.5)
'
,
strokeColor
:
'
rgba(220,220,220,1)
'
,
barStrokeWidth
:
1
,
barValueSpacing
:
1
,
barDatasetSpacing
:
1
,
data
:
chartTimesData
.
values
,
},
],
};
if
(
window
.
innerWidth
<
768
)
{
...
...
@@ -51,7 +56,11 @@ document.addEventListener('DOMContentLoaded', () => {
options
.
scaleFontSize
=
8
;
}
new
Chart
(
$
(
'
#build_timesChart
'
).
get
(
0
).
getContext
(
'
2d
'
)).
Bar
(
data
,
options
);
new
Chart
(
$
(
'
#build_timesChart
'
)
.
get
(
0
)
.
getContext
(
'
2d
'
),
).
Bar
(
data
,
options
);
chartsData
.
forEach
(
scope
=>
buildChart
(
scope
));
});
app/assets/javascripts/pages/projects/pipelines/index/index.js
View file @
d2ee2eab
...
...
@@ -6,35 +6,39 @@ import { convertPermissionToBoolean } from '../../../../lib/utils/common_utils';
Vue
.
use
(
Translate
);
document
.
addEventListener
(
'
DOMContentLoaded
'
,
()
=>
new
Vue
({
el
:
'
#pipelines-list-vue
'
,
components
:
{
pipelinesComponent
,
},
data
()
{
return
{
store
:
new
PipelinesStore
(),
};
},
created
()
{
this
.
dataset
=
document
.
querySelector
(
this
.
$options
.
el
).
dataset
;
},
render
(
createElement
)
{
return
createElement
(
'
pipelines-component
'
,
{
props
:
{
store
:
this
.
store
,
endpoint
:
this
.
dataset
.
endpoint
,
helpPagePath
:
this
.
dataset
.
helpPagePath
,
emptyStateSvgPath
:
this
.
dataset
.
emptyStateSvgPath
,
errorStateSvgPath
:
this
.
dataset
.
errorStateSvgPath
,
noPipelinesSvgPath
:
this
.
dataset
.
noPipelinesSvgPath
,
autoDevopsPath
:
this
.
dataset
.
helpAutoDevopsPath
,
newPipelinePath
:
this
.
dataset
.
newPipelinePath
,
canCreatePipeline
:
convertPermissionToBoolean
(
this
.
dataset
.
canCreatePipeline
),
hasGitlabCi
:
convertPermissionToBoolean
(
this
.
dataset
.
hasGitlabCi
),
ciLintPath
:
this
.
dataset
.
ciLintPath
,
resetCachePath
:
this
.
dataset
.
resetCachePath
,
document
.
addEventListener
(
'
DOMContentLoaded
'
,
()
=>
new
Vue
({
el
:
'
#pipelines-list-vue
'
,
components
:
{
pipelinesComponent
,
},
});
},
}));
data
()
{
return
{
store
:
new
PipelinesStore
(),
};
},
created
()
{
this
.
dataset
=
document
.
querySelector
(
this
.
$options
.
el
).
dataset
;
},
render
(
createElement
)
{
return
createElement
(
'
pipelines-component
'
,
{
props
:
{
store
:
this
.
store
,
endpoint
:
this
.
dataset
.
endpoint
,
helpPagePath
:
this
.
dataset
.
helpPagePath
,
emptyStateSvgPath
:
this
.
dataset
.
emptyStateSvgPath
,
errorStateSvgPath
:
this
.
dataset
.
errorStateSvgPath
,
noPipelinesSvgPath
:
this
.
dataset
.
noPipelinesSvgPath
,
autoDevopsPath
:
this
.
dataset
.
helpAutoDevopsPath
,
newPipelinePath
:
this
.
dataset
.
newPipelinePath
,
canCreatePipeline
:
convertPermissionToBoolean
(
this
.
dataset
.
canCreatePipeline
),
hasGitlabCi
:
convertPermissionToBoolean
(
this
.
dataset
.
hasGitlabCi
),
ciLintPath
:
this
.
dataset
.
ciLintPath
,
resetCachePath
:
this
.
dataset
.
resetCachePath
,
},
});
},
}),
);
app/assets/javascripts/pages/projects/pipelines/init_pipelines.js
View file @
d2ee2eab
...
...
@@ -2,9 +2,12 @@ import Pipelines from '~/pipelines';
export
default
()
=>
{
const
{
controllerAction
}
=
document
.
querySelector
(
'
.js-pipeline-container
'
).
dataset
;
const
pipelineStatusUrl
=
`
${
document
.
querySelector
(
'
.js-pipeline-tab-link a
'
).
getAttribute
(
'
href
'
)}
/status.json`
;
const
pipelineStatusUrl
=
`
${
document
.
querySelector
(
'
.js-pipeline-tab-link a
'
)
.
getAttribute
(
'
href
'
)}
/status.json`
;
new
Pipelines
({
// eslint-disable-line no-new
// eslint-disable-next-line no-new
new
Pipelines
({
initTabs
:
true
,
pipelineStatusUrl
,
tabsOptions
:
{
...
...
app/assets/javascripts/pages/projects/shared/permissions/components/project_feature_setting.vue
View file @
d2ee2eab
<
script
>
import
projectFeatureToggle
from
'
../../../../../vue_shared/components/toggle_button.vue
'
;
import
projectFeatureToggle
from
'
../../../../../vue_shared/components/toggle_button.vue
'
;
export
default
{
components
:
{
projectFeatureToggle
,
},
export
default
{
components
:
{
projectFeatureToggle
,
},
model
:
{
prop
:
'
value
'
,
event
:
'
change
'
,
},
model
:
{
prop
:
'
value
'
,
event
:
'
change
'
,
},
props
:
{
name
:
{
type
:
String
,
required
:
false
,
default
:
''
,
},
options
:
{
type
:
Array
,
required
:
false
,
default
:
()
=>
[],
},
value
:
{
type
:
Number
,
required
:
false
,
default
:
0
,
},
disabledInput
:
{
type
:
Boolean
,
required
:
false
,
default
:
false
,
},
props
:
{
name
:
{
type
:
String
,
required
:
false
,
default
:
''
,
},
options
:
{
type
:
Array
,
required
:
false
,
default
:
()
=>
[],
},
value
:
{
type
:
Number
,
required
:
false
,
default
:
0
,
},
disabledInput
:
{
type
:
Boolean
,
required
:
false
,
default
:
false
,
},
},
computed
:
{
featureEnabled
()
{
return
this
.
value
!==
0
;
},
computed
:
{
featureEnabled
()
{
return
this
.
value
!==
0
;
},
displayOptions
()
{
if
(
this
.
featureEnabled
)
{
return
this
.
options
;
}
return
[
[
0
,
'
Enable feature to choose access level
'
],
];
},
displayOptions
()
{
if
(
this
.
featureEnabled
)
{
return
this
.
options
;
}
return
[[
0
,
'
Enable feature to choose access level
'
]];
},
displaySelectInput
()
{
return
this
.
disabledInput
||
!
this
.
featureEnabled
||
this
.
displayOptions
.
length
<
2
;
},
displaySelectInput
()
{
return
this
.
disabledInput
||
!
this
.
featureEnabled
||
this
.
displayOptions
.
length
<
2
;
},
},
methods
:
{
toggleFeature
(
featureEnabled
)
{
if
(
featureEnabled
===
false
||
this
.
options
.
length
<
1
)
{
this
.
$emit
(
'
change
'
,
0
);
}
else
{
const
[
firstOptionValue
]
=
this
.
options
[
this
.
options
.
length
-
1
];
this
.
$emit
(
'
change
'
,
firstOptionValue
);
}
},
methods
:
{
toggleFeature
(
featureEnabled
)
{
if
(
featureEnabled
===
false
||
this
.
options
.
length
<
1
)
{
this
.
$emit
(
'
change
'
,
0
);
}
else
{
const
[
firstOptionValue
]
=
this
.
options
[
this
.
options
.
length
-
1
];
this
.
$emit
(
'
change
'
,
firstOptionValue
);
}
},
selectOption
(
e
)
{
this
.
$emit
(
'
change
'
,
Number
(
e
.
target
.
value
));
},
selectOption
(
e
)
{
this
.
$emit
(
'
change
'
,
Number
(
e
.
target
.
value
));
},
};
},
};
</
script
>
<
template
>
...
...
app/assets/javascripts/pages/projects/shared/permissions/components/project_setting_row.vue
View file @
d2ee2eab
<
script
>
export
default
{
props
:
{
label
:
{
type
:
String
,
required
:
false
,
default
:
null
,
},
helpPath
:
{
type
:
String
,
required
:
false
,
default
:
null
,
},
helpText
:
{
type
:
String
,
required
:
false
,
default
:
null
,
},
export
default
{
props
:
{
label
:
{
type
:
String
,
required
:
false
,
default
:
null
,
},
};
helpPath
:
{
type
:
String
,
required
:
false
,
default
:
null
,
},
helpText
:
{
type
:
String
,
required
:
false
,
default
:
null
,
},
},
};
</
script
>
<
template
>
...
...
app/assets/javascripts/pages/projects/shared/permissions/constants.js
View file @
d2ee2eab
...
...
@@ -5,7 +5,9 @@ export const visibilityOptions = {
};
export
const
visibilityLevelDescriptions
=
{
[
visibilityOptions
.
PRIVATE
]:
'
The project is accessible only by members of the project. Access must be granted explicitly to each user.
'
,
[
visibilityOptions
.
PRIVATE
]:
'
The project is accessible only by members of the project. Access must be granted explicitly to each user.
'
,
[
visibilityOptions
.
INTERNAL
]:
'
The project can be accessed by any user who is logged in.
'
,
[
visibilityOptions
.
PUBLIC
]:
'
The project can be accessed by anyone, regardless of authentication.
'
,
[
visibilityOptions
.
PUBLIC
]:
'
The project can be accessed by anyone, regardless of authentication.
'
,
};
app/assets/javascripts/pages/projects/shared/project_avatar.js
View file @
d2ee2eab
...
...
@@ -8,8 +8,9 @@ export default function projectAvatar() {
$
(
'
.js-project-avatar-input
'
).
bind
(
'
change
'
,
function
onClickAvatarInput
()
{
const
form
=
$
(
this
).
closest
(
'
form
'
);
// eslint-disable-next-line no-useless-escape
const
filename
=
$
(
this
).
val
().
replace
(
/^.*
[\\\/]
/
,
''
);
const
filename
=
$
(
this
)
.
val
()
.
replace
(
/^.*
[\\\/]
/
,
''
);
// eslint-disable-line no-useless-escape
return
form
.
find
(
'
.js-avatar-filename
'
).
text
(
filename
);
});
}
app/assets/javascripts/pages/projects/wikis/index.js
View file @
d2ee2eab
...
...
@@ -21,7 +21,8 @@ document.addEventListener('DOMContentLoaded', () => {
const
{
deleteWikiUrl
,
pageTitle
}
=
deleteWikiModalWrapperEl
.
dataset
;
new
Vue
({
// eslint-disable-line no-new
// eslint-disable-next-line no-new
new
Vue
({
el
:
deleteWikiModalWrapperEl
,
data
:
{
deleteWikiUrl
:
''
,
...
...
app/assets/javascripts/pages/search/show/search.js
View file @
d2ee2eab
...
...
@@ -22,7 +22,7 @@ export default class Search {
fields
:
[
'
full_name
'
],
},
data
(
term
,
callback
)
{
return
Api
.
groups
(
term
,
{},
(
data
)
=>
{
return
Api
.
groups
(
term
,
{},
data
=>
{
data
.
unshift
({
full_name
:
'
Any
'
,
});
...
...
@@ -37,7 +37,7 @@ export default class Search {
return
obj
.
full_name
;
},
toggleLabel
(
obj
)
{
return
`
${
(
$groupDropdown
.
data
(
'
defaultLabel
'
)
)}
${
obj
.
full_name
}
`
;
return
`
${
$groupDropdown
.
data
(
'
defaultLabel
'
)}
${
obj
.
full_name
}
`
;
},
clicked
:
()
=>
Search
.
submitSearch
(),
});
...
...
@@ -52,7 +52,7 @@ export default class Search {
},
data
:
(
term
,
callback
)
=>
{
this
.
getProjectsData
(
term
)
.
then
(
(
data
)
=>
{
.
then
(
data
=>
{
data
.
unshift
({
name_with_namespace
:
'
Any
'
,
});
...
...
@@ -70,7 +70,7 @@ export default class Search {
return
obj
.
name_with_namespace
;
},
toggleLabel
(
obj
)
{
return
`
${
(
$projectDropdown
.
data
(
'
defaultLabel
'
)
)}
${
obj
.
name_with_namespace
}
`
;
return
`
${
$projectDropdown
.
data
(
'
defaultLabel
'
)}
${
obj
.
name_with_namespace
}
`
;
},
clicked
:
()
=>
Search
.
submitSearch
(),
});
...
...
@@ -99,17 +99,24 @@ export default class Search {
}
clearSearchField
()
{
return
$
(
this
.
searchInput
).
val
(
''
).
trigger
(
'
keyup
'
).
focus
();
return
$
(
this
.
searchInput
)
.
val
(
''
)
.
trigger
(
'
keyup
'
)
.
focus
();
}
getProjectsData
(
term
)
{
return
new
Promise
(
(
resolve
)
=>
{
return
new
Promise
(
resolve
=>
{
if
(
this
.
groupId
)
{
Api
.
groupProjects
(
this
.
groupId
,
term
,
{},
resolve
);
}
else
{
Api
.
projects
(
term
,
{
order_by
:
'
id
'
,
},
resolve
);
Api
.
projects
(
term
,
{
order_by
:
'
id
'
,
},
resolve
,
);
}
});
}
...
...
app/assets/javascripts/pages/sessions/new/signin_tabs_memoizer.js
View file @
d2ee2eab
...
...
@@ -20,7 +20,7 @@ export default class SigninTabsMemoizer {
bootstrap
()
{
const
tabs
=
document
.
querySelectorAll
(
this
.
tabSelector
);
if
(
tabs
.
length
>
0
)
{
tabs
[
0
].
addEventListener
(
'
click
'
,
(
e
)
=>
{
tabs
[
0
].
addEventListener
(
'
click
'
,
e
=>
{
if
(
e
.
target
&&
e
.
target
.
nodeName
===
'
A
'
)
{
const
anchorName
=
e
.
target
.
getAttribute
(
'
href
'
);
this
.
saveData
(
anchorName
);
...
...
app/assets/javascripts/pages/sessions/new/username_validator.js
View file @
d2ee2eab
...
...
@@ -22,10 +22,10 @@ export default class UsernameValidator {
available
:
false
,
valid
:
false
,
pending
:
false
,
empty
:
true
empty
:
true
,
};
const
debounceTimeout
=
_
.
debounce
(
(
username
)
=>
{
const
debounceTimeout
=
_
.
debounce
(
username
=>
{
this
.
validateUsername
(
username
);
},
debounceTimeoutDuration
);
...
...
@@ -81,7 +81,8 @@ export default class UsernameValidator {
this
.
state
.
pending
=
true
;
this
.
state
.
available
=
false
;
this
.
renderState
();
axios
.
get
(
`
${
gon
.
relative_url_root
}
/users/
${
username
}
/exists`
)
axios
.
get
(
`
${
gon
.
relative_url_root
}
/users/
${
username
}
/exists`
)
.
then
(({
data
})
=>
this
.
setAvailabilityState
(
data
.
exists
))
.
catch
(()
=>
flash
(
__
(
'
An error occurred while validating username
'
)));
}
...
...
@@ -100,8 +101,7 @@ export default class UsernameValidator {
clearFieldValidationState
()
{
this
.
inputElement
.
siblings
(
'
p
'
).
hide
();
this
.
inputElement
.
removeClass
(
invalidInputClass
)
.
removeClass
(
successInputClass
);
this
.
inputElement
.
removeClass
(
invalidInputClass
).
removeClass
(
successInputClass
);
}
setUnavailableState
()
{
...
...
app/assets/javascripts/pages/users/index.js
View file @
d2ee2eab
...
...
@@ -13,10 +13,12 @@ function initUserProfile(action) {
new
UserTabs
({
parentEl
:
'
.user-profile
'
,
action
});
// hide project limit message
$
(
'
.hide-project-limit-message
'
).
on
(
'
click
'
,
(
e
)
=>
{
$
(
'
.hide-project-limit-message
'
).
on
(
'
click
'
,
e
=>
{
e
.
preventDefault
();
Cookies
.
set
(
'
hide_project_limit_message
'
,
'
false
'
);
$
(
this
).
parents
(
'
.project-limit-message
'
).
remove
();
$
(
this
)
.
parents
(
'
.project-limit-message
'
)
.
remove
();
});
}
...
...
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