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
3271c5f0
Commit
3271c5f0
authored
Oct 10, 2018
by
Mike Greiling
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Prettify vue_shared modules
parent
8b7c86ea
Changes
28
Hide whitespace changes
Inline
Side-by-side
Showing
28 changed files
with
914 additions
and
925 deletions
+914
-925
app/assets/javascripts/vue_shared/components/bar_chart.vue
app/assets/javascripts/vue_shared/components/bar_chart.vue
+5
-5
app/assets/javascripts/vue_shared/components/deprecated_modal.vue
...ts/javascripts/vue_shared/components/deprecated_modal.vue
+75
-75
app/assets/javascripts/vue_shared/components/file_icon/file_icon_map.js
...ascripts/vue_shared/components/file_icon/file_icon_map.js
+1
-3
app/assets/javascripts/vue_shared/components/gl_modal.vue
app/assets/javascripts/vue_shared/components/gl_modal.vue
+6
-2
app/assets/javascripts/vue_shared/components/icon.vue
app/assets/javascripts/vue_shared/components/icon.vue
+0
-1
app/assets/javascripts/vue_shared/components/issue/issue_warning.vue
...javascripts/vue_shared/components/issue/issue_warning.vue
+25
-25
app/assets/javascripts/vue_shared/components/loading_button.vue
...sets/javascripts/vue_shared/components/loading_button.vue
+28
-28
app/assets/javascripts/vue_shared/components/markdown/field.vue
...sets/javascripts/vue_shared/components/markdown/field.vue
+118
-118
app/assets/javascripts/vue_shared/components/markdown/header.vue
...ets/javascripts/vue_shared/components/markdown/header.vue
+51
-50
app/assets/javascripts/vue_shared/components/markdown/toolbar.vue
...ts/javascripts/vue_shared/components/markdown/toolbar.vue
+24
-24
app/assets/javascripts/vue_shared/components/markdown/toolbar_button.vue
...scripts/vue_shared/components/markdown/toolbar_button.vue
+36
-36
app/assets/javascripts/vue_shared/components/memory_graph.vue
...assets/javascripts/vue_shared/components/memory_graph.vue
+2
-1
app/assets/javascripts/vue_shared/components/notes/placeholder_note.vue
...ascripts/vue_shared/components/notes/placeholder_note.vue
+33
-35
app/assets/javascripts/vue_shared/components/notes/placeholder_system_note.vue
...s/vue_shared/components/notes/placeholder_system_note.vue
+16
-16
app/assets/javascripts/vue_shared/components/panel_resizer.vue
...ssets/javascripts/vue_shared/components/panel_resizer.vue
+78
-78
app/assets/javascripts/vue_shared/components/pikaday.vue
app/assets/javascripts/vue_shared/components/pikaday.vue
+53
-53
app/assets/javascripts/vue_shared/components/project_avatar/image.vue
...avascripts/vue_shared/components/project_avatar/image.vue
+61
-62
app/assets/javascripts/vue_shared/components/recaptcha_modal.vue
...ets/javascripts/vue_shared/components/recaptcha_modal.vue
+47
-47
app/assets/javascripts/vue_shared/components/sidebar/date_picker.vue
...javascripts/vue_shared/components/sidebar/date_picker.vue
+91
-91
app/assets/javascripts/vue_shared/components/table_pagination.vue
...ts/javascripts/vue_shared/components/table_pagination.vue
+103
-103
app/assets/javascripts/vue_shared/components/time_ago_tooltip.vue
...ts/javascripts/vue_shared/components/time_ago_tooltip.vue
+1
-3
app/assets/javascripts/vue_shared/components/toggle_button.vue
...ssets/javascripts/vue_shared/components/toggle_button.vue
+47
-47
app/assets/javascripts/vue_shared/components/user_avatar/user_avatar_link.vue
...ts/vue_shared/components/user_avatar/user_avatar_link.vue
+0
-1
app/assets/javascripts/vue_shared/components/user_avatar/user_avatar_svg.vue
...pts/vue_shared/components/user_avatar/user_avatar_svg.vue
+0
-2
app/assets/javascripts/vue_shared/mixins/ci_pagination_api_mixin.js
.../javascripts/vue_shared/mixins/ci_pagination_api_mixin.js
+9
-10
app/assets/javascripts/vue_shared/models/label.js
app/assets/javascripts/vue_shared/models/label.js
+1
-1
app/assets/javascripts/vue_shared/translate.js
app/assets/javascripts/vue_shared/translate.js
+2
-7
app/assets/javascripts/vue_shared/vue_resource_interceptor.js
...assets/javascripts/vue_shared/vue_resource_interceptor.js
+1
-1
No files found.
app/assets/javascripts/vue_shared/components/bar_chart.vue
View file @
3271c5f0
...
@@ -118,7 +118,9 @@ export default {
...
@@ -118,7 +118,9 @@ export default {
this
.
rectYAxisLabelDims
.
height
!=
null
?
this
.
rectYAxisLabelDims
.
height
/
2
:
0
;
this
.
rectYAxisLabelDims
.
height
!=
null
?
this
.
rectYAxisLabelDims
.
height
/
2
:
0
;
const
yCoord
=
this
.
vbHeight
/
2
+
rectWidth
-
5
;
const
yCoord
=
this
.
vbHeight
/
2
+
rectWidth
-
5
;
return
`translate(
${
this
.
minX
+
this
.
yAxisTextTransformPadding
}
,
${
yCoord
}
) rotate(-
${
this
.
yAxisTextRotation
}
)`
;
return
`translate(
${
this
.
minX
+
this
.
yAxisTextTransformPadding
}
,
${
yCoord
}
) rotate(-
${
this
.
yAxisTextRotation
}
)`
;
},
},
},
},
mounted
()
{
mounted
()
{
...
@@ -207,8 +209,7 @@ export default {
...
@@ -207,8 +209,7 @@ export default {
renderedYAxis
.
selectAll
(
'
.tick
'
).
each
(
function
createTickLines
(
d
,
i
)
{
renderedYAxis
.
selectAll
(
'
.tick
'
).
each
(
function
createTickLines
(
d
,
i
)
{
if
(
i
>
0
)
{
if
(
i
>
0
)
{
d3
d3
.
select
(
this
)
.
select
(
this
)
.
select
(
'
line
'
)
.
select
(
'
line
'
)
.
attr
(
'
x2
'
,
width
)
.
attr
(
'
x2
'
,
width
)
.
attr
(
'
class
'
,
'
axis-tick
'
);
.
attr
(
'
class
'
,
'
axis-tick
'
);
...
@@ -217,8 +218,7 @@ export default {
...
@@ -217,8 +218,7 @@ export default {
// Add the panning capabilities
// Add the panning capabilities
if
(
this
.
isPanAvailable
)
{
if
(
this
.
isPanAvailable
)
{
d3
d3
.
select
(
this
.
$refs
.
baseSvg
)
.
select
(
this
.
$refs
.
baseSvg
)
.
call
(
this
.
zoom
)
.
call
(
this
.
zoom
)
.
on
(
'
wheel.zoom
'
,
null
);
// This disables the pan of the graph with the scroll of the mouse wheel
.
on
(
'
wheel.zoom
'
,
null
);
// This disables the pan of the graph with the scroll of the mouse wheel
}
}
...
...
app/assets/javascripts/vue_shared/components/deprecated_modal.vue
View file @
3271c5f0
<
script
>
<
script
>
/* eslint-disable vue/require-default-prop */
/* eslint-disable vue/require-default-prop */
export
default
{
export
default
{
name
:
'
DeprecatedModal
'
,
// use GlModal instead
name
:
'
DeprecatedModal
'
,
// use GlModal instead
props
:
{
props
:
{
id
:
{
id
:
{
type
:
String
,
type
:
String
,
required
:
false
,
required
:
false
,
},
title
:
{
type
:
String
,
required
:
false
,
},
text
:
{
type
:
String
,
required
:
false
,
},
hideFooter
:
{
type
:
Boolean
,
required
:
false
,
default
:
false
,
},
kind
:
{
type
:
String
,
required
:
false
,
default
:
'
primary
'
,
},
modalDialogClass
:
{
type
:
String
,
required
:
false
,
default
:
''
,
},
closeKind
:
{
type
:
String
,
required
:
false
,
default
:
'
default
'
,
},
closeButtonLabel
:
{
type
:
String
,
required
:
false
,
default
:
'
Cancel
'
,
},
primaryButtonLabel
:
{
type
:
String
,
required
:
false
,
default
:
''
,
},
secondaryButtonLabel
:
{
type
:
String
,
required
:
false
,
default
:
''
,
},
submitDisabled
:
{
type
:
Boolean
,
required
:
false
,
default
:
false
,
},
},
},
title
:
{
type
:
String
,
required
:
false
,
},
text
:
{
type
:
String
,
required
:
false
,
},
hideFooter
:
{
type
:
Boolean
,
required
:
false
,
default
:
false
,
},
kind
:
{
type
:
String
,
required
:
false
,
default
:
'
primary
'
,
},
modalDialogClass
:
{
type
:
String
,
required
:
false
,
default
:
''
,
},
closeKind
:
{
type
:
String
,
required
:
false
,
default
:
'
default
'
,
},
closeButtonLabel
:
{
type
:
String
,
required
:
false
,
default
:
'
Cancel
'
,
},
primaryButtonLabel
:
{
type
:
String
,
required
:
false
,
default
:
''
,
},
secondaryButtonLabel
:
{
type
:
String
,
required
:
false
,
default
:
''
,
},
submitDisabled
:
{
type
:
Boolean
,
required
:
false
,
default
:
false
,
},
},
computed
:
{
computed
:
{
btnKindClass
()
{
btnKindClass
()
{
return
{
return
{
[
`btn-
${
this
.
kind
}
`
]:
true
,
[
`btn-
${
this
.
kind
}
`
]:
true
,
};
};
},
},
btnCancelKindClass
()
{
btnCancelKindClass
()
{
return
{
return
{
[
`btn-
${
this
.
closeKind
}
`
]:
true
,
[
`btn-
${
this
.
closeKind
}
`
]:
true
,
};
};
},
},
},
},
methods
:
{
methods
:
{
emitCancel
(
event
)
{
emitCancel
(
event
)
{
this
.
$emit
(
'
cancel
'
,
event
);
this
.
$emit
(
'
cancel
'
,
event
);
},
},
emitSubmit
(
event
)
{
emitSubmit
(
event
)
{
this
.
$emit
(
'
submit
'
,
event
);
this
.
$emit
(
'
submit
'
,
event
);
},
},
},
};
},
};
</
script
>
</
script
>
<
template
>
<
template
>
...
...
app/assets/javascripts/vue_shared/components/file_icon/file_icon_map.js
View file @
3271c5f0
...
@@ -583,7 +583,5 @@ const fileNameIcons = {
...
@@ -583,7 +583,5 @@ const fileNameIcons = {
};
};
export
default
function
getIconForFile
(
name
)
{
export
default
function
getIconForFile
(
name
)
{
return
fileNameIcons
[
name
]
||
return
fileNameIcons
[
name
]
||
fileExtensionIcons
[
name
?
name
.
split
(
'
.
'
).
pop
()
:
''
]
||
''
;
fileExtensionIcons
[
name
?
name
.
split
(
'
.
'
).
pop
()
:
''
]
||
''
;
}
}
app/assets/javascripts/vue_shared/components/gl_modal.vue
View file @
3271c5f0
...
@@ -41,10 +41,14 @@ export default {
...
@@ -41,10 +41,14 @@ export default {
},
},
},
},
mounted
()
{
mounted
()
{
$
(
this
.
$el
).
on
(
'
shown.bs.modal
'
,
this
.
opened
).
on
(
'
hidden.bs.modal
'
,
this
.
closed
);
$
(
this
.
$el
)
.
on
(
'
shown.bs.modal
'
,
this
.
opened
)
.
on
(
'
hidden.bs.modal
'
,
this
.
closed
);
},
},
beforeDestroy
()
{
beforeDestroy
()
{
$
(
this
.
$el
).
off
(
'
shown.bs.modal
'
,
this
.
opened
).
off
(
'
hidden.bs.modal
'
,
this
.
closed
);
$
(
this
.
$el
)
.
off
(
'
shown.bs.modal
'
,
this
.
opened
)
.
off
(
'
hidden.bs.modal
'
,
this
.
closed
);
},
},
methods
:
{
methods
:
{
emitCancel
(
event
)
{
emitCancel
(
event
)
{
...
...
app/assets/javascripts/vue_shared/components/icon.vue
View file @
3271c5f0
<
script
>
<
script
>
// only allow classes in images.scss e.g. s12
// only allow classes in images.scss e.g. s12
const
validSizes
=
[
8
,
10
,
12
,
16
,
18
,
24
,
32
,
48
,
72
];
const
validSizes
=
[
8
,
10
,
12
,
16
,
18
,
24
,
32
,
48
,
72
];
let
iconValidator
=
()
=>
true
;
let
iconValidator
=
()
=>
true
;
...
...
app/assets/javascripts/vue_shared/components/issue/issue_warning.vue
View file @
3271c5f0
<
script
>
<
script
>
import
icon
from
'
../../../vue_shared/components/icon.vue
'
;
import
icon
from
'
../../../vue_shared/components/icon.vue
'
;
export
default
{
export
default
{
components
:
{
components
:
{
icon
,
icon
,
},
props
:
{
isLocked
:
{
type
:
Boolean
,
default
:
false
,
required
:
false
,
},
},
props
:
{
isConfidential
:
{
isLocked
:
{
type
:
Boolean
,
type
:
Boolean
,
default
:
false
,
default
:
false
,
required
:
false
,
required
:
false
,
},
isConfidential
:
{
type
:
Boolean
,
default
:
false
,
required
:
false
,
},
},
},
computed
:
{
},
warningIcon
()
{
computed
:
{
if
(
this
.
isConfidential
)
return
'
eye-slash
'
;
warningIcon
()
{
if
(
this
.
isLocked
)
return
'
lock
'
;
if
(
this
.
isConfidential
)
return
'
eye-slash
'
;
if
(
this
.
isLocked
)
return
'
lock
'
;
return
''
;
return
''
;
},
isLockedAndConfidential
()
{
return
this
.
isConfidential
&&
this
.
isLocked
;
},
},
},
};
isLockedAndConfidential
()
{
return
this
.
isConfidential
&&
this
.
isLocked
;
},
},
};
</
script
>
</
script
>
<
template
>
<
template
>
<div
class=
"issuable-note-warning"
>
<div
class=
"issuable-note-warning"
>
...
...
app/assets/javascripts/vue_shared/components/loading_button.vue
View file @
3271c5f0
<
script
>
<
script
>
/* eslint-disable vue/require-default-prop */
/* eslint-disable vue/require-default-prop */
/* This is a re-usable vue component for rendering a button
/* This is a re-usable vue component for rendering a button
that will probably be sending off ajax requests and need
that will probably be sending off ajax requests and need
to show the loading status by setting the `loading` option.
to show the loading status by setting the `loading` option.
This can also be used for initial page load when you don't
This can also be used for initial page load when you don't
...
@@ -17,34 +17,34 @@
...
@@ -17,34 +17,34 @@
*/
*/
export
default
{
export
default
{
props
:
{
props
:
{
loading
:
{
loading
:
{
type
:
Boolean
,
type
:
Boolean
,
required
:
false
,
required
:
false
,
default
:
false
,
default
:
false
,
},
disabled
:
{
type
:
Boolean
,
required
:
false
,
default
:
false
,
},
label
:
{
type
:
String
,
required
:
false
,
},
containerClass
:
{
type
:
[
String
,
Array
,
Object
],
required
:
false
,
default
:
'
btn btn-align-content
'
,
},
},
},
methods
:
{
disabled
:
{
onClick
(
e
)
{
type
:
Boolean
,
this
.
$emit
(
'
click
'
,
e
);
required
:
false
,
}
,
default
:
false
,
},
},
};
label
:
{
type
:
String
,
required
:
false
,
},
containerClass
:
{
type
:
[
String
,
Array
,
Object
],
required
:
false
,
default
:
'
btn btn-align-content
'
,
},
},
methods
:
{
onClick
(
e
)
{
this
.
$emit
(
'
click
'
,
e
);
},
},
};
</
script
>
</
script
>
<
template
>
<
template
>
...
...
app/assets/javascripts/vue_shared/components/markdown/field.vue
View file @
3271c5f0
<
script
>
<
script
>
import
$
from
'
jquery
'
;
import
$
from
'
jquery
'
;
import
{
s__
}
from
'
~/locale
'
;
import
{
s__
}
from
'
~/locale
'
;
import
Flash
from
'
../../../flash
'
;
import
Flash
from
'
../../../flash
'
;
import
GLForm
from
'
../../../gl_form
'
;
import
GLForm
from
'
../../../gl_form
'
;
import
markdownHeader
from
'
./header.vue
'
;
import
markdownHeader
from
'
./header.vue
'
;
import
markdownToolbar
from
'
./toolbar.vue
'
;
import
markdownToolbar
from
'
./toolbar.vue
'
;
import
icon
from
'
../icon.vue
'
;
import
icon
from
'
../icon.vue
'
;
export
default
{
export
default
{
components
:
{
components
:
{
markdownHeader
,
markdownHeader
,
markdownToolbar
,
markdownToolbar
,
icon
,
icon
,
},
props
:
{
markdownPreviewPath
:
{
type
:
String
,
required
:
false
,
default
:
''
,
},
},
props
:
{
markdownDocsPath
:
{
markdownPreviewPath
:
{
type
:
String
,
type
:
String
,
required
:
true
,
required
:
false
,
default
:
''
,
},
markdownDocsPath
:
{
type
:
String
,
required
:
true
,
},
markdownVersion
:
{
type
:
Number
,
required
:
false
,
default
:
0
,
},
addSpacingClasses
:
{
type
:
Boolean
,
required
:
false
,
default
:
true
,
},
quickActionsDocsPath
:
{
type
:
String
,
required
:
false
,
default
:
''
,
},
canAttachFile
:
{
type
:
Boolean
,
required
:
false
,
default
:
true
,
},
enableAutocomplete
:
{
type
:
Boolean
,
required
:
false
,
default
:
true
,
},
},
},
data
()
{
markdownVersion
:
{
return
{
type
:
Number
,
markdownPreview
:
''
,
required
:
false
,
referencedCommands
:
''
,
default
:
0
,
referencedUsers
:
''
,
markdownPreviewLoading
:
false
,
previewMarkdown
:
false
,
};
},
},
computed
:
{
addSpacingClasses
:
{
shouldShowReferencedUsers
()
{
type
:
Boolean
,
const
referencedUsersThreshold
=
10
;
required
:
false
,
return
this
.
referencedUsers
.
length
>=
referencedUsersThreshold
;
default
:
true
,
},
},
},
mounted
()
{
quickActionsDocsPath
:
{
/*
type
:
String
,
GLForm class handles all the toolbar buttons
required
:
false
,
*/
default
:
''
,
return
new
GLForm
(
$
(
this
.
$refs
[
'
gl-form
'
]),
{
emojis
:
this
.
enableAutocomplete
,
members
:
this
.
enableAutocomplete
,
issues
:
this
.
enableAutocomplete
,
mergeRequests
:
this
.
enableAutocomplete
,
epics
:
this
.
enableAutocomplete
,
milestones
:
this
.
enableAutocomplete
,
labels
:
this
.
enableAutocomplete
,
snippets
:
this
.
enableAutocomplete
,
});
},
},
beforeDestroy
()
{
canAttachFile
:
{
const
glForm
=
$
(
this
.
$refs
[
'
gl-form
'
]).
data
(
'
glForm
'
);
type
:
Boolean
,
if
(
glForm
)
{
required
:
false
,
glForm
.
destroy
();
default
:
true
,
}
},
enableAutocomplete
:
{
type
:
Boolean
,
required
:
false
,
default
:
true
,
},
},
methods
:
{
},
showPreviewTab
()
{
data
()
{
if
(
this
.
previewMarkdown
)
return
;
return
{
markdownPreview
:
''
,
referencedCommands
:
''
,
referencedUsers
:
''
,
markdownPreviewLoading
:
false
,
previewMarkdown
:
false
,
};
},
computed
:
{
shouldShowReferencedUsers
()
{
const
referencedUsersThreshold
=
10
;
return
this
.
referencedUsers
.
length
>=
referencedUsersThreshold
;
},
},
mounted
()
{
/*
GLForm class handles all the toolbar buttons
*/
return
new
GLForm
(
$
(
this
.
$refs
[
'
gl-form
'
]),
{
emojis
:
this
.
enableAutocomplete
,
members
:
this
.
enableAutocomplete
,
issues
:
this
.
enableAutocomplete
,
mergeRequests
:
this
.
enableAutocomplete
,
epics
:
this
.
enableAutocomplete
,
milestones
:
this
.
enableAutocomplete
,
labels
:
this
.
enableAutocomplete
,
snippets
:
this
.
enableAutocomplete
,
});
},
beforeDestroy
()
{
const
glForm
=
$
(
this
.
$refs
[
'
gl-form
'
]).
data
(
'
glForm
'
);
if
(
glForm
)
{
glForm
.
destroy
();
}
},
methods
:
{
showPreviewTab
()
{
if
(
this
.
previewMarkdown
)
return
;
this
.
previewMarkdown
=
true
;
this
.
previewMarkdown
=
true
;
/*
/*
Can't use `$refs` as the component is technically in the parent component
Can't use `$refs` as the component is technically in the parent component
so we access the VNode & then get the element
so we access the VNode & then get the element
*/
*/
const
text
=
this
.
$slots
.
textarea
[
0
].
elm
.
value
;
const
text
=
this
.
$slots
.
textarea
[
0
].
elm
.
value
;
if
(
text
)
{
if
(
text
)
{
this
.
markdownPreviewLoading
=
true
;
this
.
markdownPreviewLoading
=
true
;
this
.
$http
this
.
$http
.
post
(
this
.
versionedPreviewPath
(),
{
text
})
.
post
(
this
.
versionedPreviewPath
(),
{
text
})
.
then
(
resp
=>
resp
.
json
())
.
then
(
resp
=>
resp
.
json
())
.
then
(
data
=>
this
.
renderMarkdown
(
data
))
.
then
(
data
=>
this
.
renderMarkdown
(
data
))
.
catch
(()
=>
new
Flash
(
s__
(
'
Error loading markdown preview
'
)));
.
catch
(()
=>
new
Flash
(
s__
(
'
Error loading markdown preview
'
)));
}
else
{
}
else
{
this
.
renderMarkdown
();
this
.
renderMarkdown
();
}
}
},
},
showWriteTab
()
{
showWriteTab
()
{
this
.
markdownPreview
=
''
;
this
.
markdownPreview
=
''
;
this
.
previewMarkdown
=
false
;
this
.
previewMarkdown
=
false
;
},
},
renderMarkdown
(
data
=
{})
{
renderMarkdown
(
data
=
{})
{
this
.
markdownPreviewLoading
=
false
;
this
.
markdownPreviewLoading
=
false
;
this
.
markdownPreview
=
data
.
body
||
'
Nothing to preview.
'
;
this
.
markdownPreview
=
data
.
body
||
'
Nothing to preview.
'
;
if
(
data
.
references
)
{
if
(
data
.
references
)
{
this
.
referencedCommands
=
data
.
references
.
commands
;
this
.
referencedCommands
=
data
.
references
.
commands
;
this
.
referencedUsers
=
data
.
references
.
users
;
this
.
referencedUsers
=
data
.
references
.
users
;
}
}
this
.
$nextTick
(()
=>
{
this
.
$nextTick
(()
=>
{
$
(
this
.
$refs
[
'
markdown-preview
'
]).
renderGFM
();
$
(
this
.
$refs
[
'
markdown-preview
'
]).
renderGFM
();
});
});
},
},
versionedPreviewPath
()
{
versionedPreviewPath
()
{
const
{
markdownPreviewPath
,
markdownVersion
}
=
this
;
const
{
markdownPreviewPath
,
markdownVersion
}
=
this
;
return
`
${
markdownPreviewPath
}${
return
`
${
markdownPreviewPath
}${
markdownPreviewPath
.
indexOf
(
'
?
'
)
===
-
1
?
'
?
'
:
'
&
'
markdownPreviewPath
.
indexOf
(
'
?
'
)
===
-
1
?
'
?
'
:
'
&
'
}
markdown_version=
${
markdownVersion
}
`
;
}
markdown_version=
${
markdownVersion
}
`
;
},
},
},
};
},
};
</
script
>
</
script
>
<
template
>
<
template
>
...
...
app/assets/javascripts/vue_shared/components/markdown/header.vue
View file @
3271c5f0
<
script
>
<
script
>
import
$
from
'
jquery
'
;
import
$
from
'
jquery
'
;
import
tooltip
from
'
../../directives/tooltip
'
;
import
tooltip
from
'
../../directives/tooltip
'
;
import
toolbarButton
from
'
./toolbar_button.vue
'
;
import
toolbarButton
from
'
./toolbar_button.vue
'
;
import
icon
from
'
../icon.vue
'
;
import
icon
from
'
../icon.vue
'
;
export
default
{
export
default
{
directives
:
{
directives
:
{
tooltip
,
tooltip
,
},
components
:
{
toolbarButton
,
icon
,
},
props
:
{
previewMarkdown
:
{
type
:
Boolean
,
required
:
true
,
},
},
components
:
{
},
toolbarButton
,
computed
:
{
icon
,
mdTable
()
{
return
[
'
| header | header |
'
,
'
| ------ | ------ |
'
,
'
| cell | cell |
'
,
'
| cell | cell |
'
,
].
join
(
'
\n
'
);
},
},
props
:
{
},
previewMarkdown
:
{
mounted
()
{
type
:
Boolean
,
$
(
document
).
on
(
'
markdown-preview:show.vue
'
,
this
.
previewMarkdownTab
);
required
:
true
,
$
(
document
).
on
(
'
markdown-preview:hide.vue
'
,
this
.
writeMarkdownTab
);
},
},
beforeDestroy
()
{
$
(
document
).
off
(
'
markdown-preview:show.vue
'
,
this
.
previewMarkdownTab
);
$
(
document
).
off
(
'
markdown-preview:hide.vue
'
,
this
.
writeMarkdownTab
);
},
methods
:
{
isValid
(
form
)
{
return
(
!
form
||
(
form
.
find
(
'
.js-vue-markdown-field
'
).
length
&&
$
(
this
.
$el
).
closest
(
'
form
'
)[
0
]
===
form
[
0
])
);
},
},
computed
:
{
mdTable
()
{
return
[
'
| header | header |
'
,
'
| ------ | ------ |
'
,
'
| cell | cell |
'
,
'
| cell | cell |
'
,
].
join
(
'
\n
'
);
},
},
mounted
()
{
$
(
document
).
on
(
'
markdown-preview:show.vue
'
,
this
.
previewMarkdownTab
);
$
(
document
).
on
(
'
markdown-preview:hide.vue
'
,
this
.
writeMarkdownTab
);
},
beforeDestroy
()
{
$
(
document
).
off
(
'
markdown-preview:show.vue
'
,
this
.
previewMarkdownTab
);
$
(
document
).
off
(
'
markdown-preview:hide.vue
'
,
this
.
writeMarkdownTab
);
},
methods
:
{
isValid
(
form
)
{
return
!
form
||
form
.
find
(
'
.js-vue-markdown-field
'
).
length
&&
$
(
this
.
$el
).
closest
(
'
form
'
)[
0
]
===
form
[
0
];
},
previewMarkdownTab
(
event
,
form
)
{
previewMarkdownTab
(
event
,
form
)
{
if
(
event
.
target
.
blur
)
event
.
target
.
blur
();
if
(
event
.
target
.
blur
)
event
.
target
.
blur
();
if
(
!
this
.
isValid
(
form
))
return
;
if
(
!
this
.
isValid
(
form
))
return
;
this
.
$emit
(
'
preview-markdown
'
);
this
.
$emit
(
'
preview-markdown
'
);
},
},
writeMarkdownTab
(
event
,
form
)
{
writeMarkdownTab
(
event
,
form
)
{
if
(
event
.
target
.
blur
)
event
.
target
.
blur
();
if
(
event
.
target
.
blur
)
event
.
target
.
blur
();
if
(
!
this
.
isValid
(
form
))
return
;
if
(
!
this
.
isValid
(
form
))
return
;
this
.
$emit
(
'
write-markdown
'
);
this
.
$emit
(
'
write-markdown
'
);
},
},
},
};
},
};
</
script
>
</
script
>
<
template
>
<
template
>
...
...
app/assets/javascripts/vue_shared/components/markdown/toolbar.vue
View file @
3271c5f0
<
script
>
<
script
>
import
{
Link
}
from
'
@gitlab-org/gitlab-ui
'
;
import
{
Link
}
from
'
@gitlab-org/gitlab-ui
'
;
export
default
{
export
default
{
components
:
{
components
:
{
'
gl-link
'
:
Link
,
'
gl-link
'
:
Link
,
},
props
:
{
markdownDocsPath
:
{
type
:
String
,
required
:
true
,
},
},
props
:
{
quickActionsDocsPath
:
{
markdownDocsPath
:
{
type
:
String
,
type
:
String
,
required
:
false
,
required
:
true
,
default
:
''
,
},
quickActionsDocsPath
:
{
type
:
String
,
required
:
false
,
default
:
''
,
},
canAttachFile
:
{
type
:
Boolean
,
required
:
false
,
default
:
true
,
},
},
},
c
omputed
:
{
c
anAttachFile
:
{
hasQuickActionsDocsPath
()
{
type
:
Boolean
,
return
this
.
quickActionsDocsPath
!==
''
;
required
:
false
,
}
,
default
:
true
,
},
},
};
},
computed
:
{
hasQuickActionsDocsPath
()
{
return
this
.
quickActionsDocsPath
!==
''
;
},
},
};
</
script
>
</
script
>
<
template
>
<
template
>
...
...
app/assets/javascripts/vue_shared/components/markdown/toolbar_button.vue
View file @
3271c5f0
<
script
>
<
script
>
import
tooltip
from
'
../../directives/tooltip
'
;
import
tooltip
from
'
../../directives/tooltip
'
;
import
icon
from
'
../icon.vue
'
;
import
icon
from
'
../icon.vue
'
;
export
default
{
export
default
{
components
:
{
components
:
{
icon
,
icon
,
},
directives
:
{
tooltip
,
},
props
:
{
buttonTitle
:
{
type
:
String
,
required
:
true
,
},
},
directives
:
{
icon
:
{
tooltip
,
type
:
String
,
required
:
true
,
},
},
props
:
{
tag
:
{
buttonTitle
:
{
type
:
String
,
type
:
String
,
required
:
true
,
required
:
true
,
},
icon
:
{
type
:
String
,
required
:
true
,
},
tag
:
{
type
:
String
,
required
:
true
,
},
tagBlock
:
{
type
:
String
,
required
:
false
,
default
:
''
,
},
tagSelect
:
{
type
:
String
,
required
:
false
,
default
:
''
,
},
prepend
:
{
type
:
Boolean
,
required
:
false
,
default
:
false
,
},
},
},
};
tagBlock
:
{
type
:
String
,
required
:
false
,
default
:
''
,
},
tagSelect
:
{
type
:
String
,
required
:
false
,
default
:
''
,
},
prepend
:
{
type
:
Boolean
,
required
:
false
,
default
:
false
,
},
},
};
</
script
>
</
script
>
<
template
>
<
template
>
...
...
app/assets/javascripts/vue_shared/components/memory_graph.vue
View file @
3271c5f0
...
@@ -41,7 +41,8 @@ export default {
...
@@ -41,7 +41,8 @@ export default {
// Find metric timestamp which is closest to deploymentTime
// Find metric timestamp which is closest to deploymentTime
timestampDiff
=
Math
.
abs
(
metricTimestamps
[
0
]
-
median
);
timestampDiff
=
Math
.
abs
(
metricTimestamps
[
0
]
-
median
);
metricTimestamps
.
forEach
((
timestamp
,
index
)
=>
{
metricTimestamps
.
forEach
((
timestamp
,
index
)
=>
{
if
(
index
===
0
)
{
// Skip first element
if
(
index
===
0
)
{
// Skip first element
return
;
return
;
}
}
...
...
app/assets/javascripts/vue_shared/components/notes/placeholder_note.vue
View file @
3271c5f0
<
script
>
<
script
>
/**
/**
* Common component to render a placeholder note and user information.
* Common component to render a placeholder note and user information.
*
*
* This component needs to be used with a vuex store.
* This component needs to be used with a vuex store.
* That vuex store needs to have a `getUserData` getter that contains
* That vuex store needs to have a `getUserData` getter that contains
* {
* {
* path: String,
* path: String,
* avatar_url: String,
* avatar_url: String,
* name: String,
* name: String,
* username: String,
* username: String,
* }
* }
*
*
* @example
* @example
* <placeholder-note
* <placeholder-note
* :note="{body: 'This is a note'}"
* :note="{body: 'This is a note'}"
* />
* />
*/
*/
import
{
mapGetters
}
from
'
vuex
'
;
import
{
mapGetters
}
from
'
vuex
'
;
import
userAvatarLink
from
'
../user_avatar/user_avatar_link.vue
'
;
import
userAvatarLink
from
'
../user_avatar/user_avatar_link.vue
'
;
export
default
{
export
default
{
name
:
'
PlaceholderNote
'
,
name
:
'
PlaceholderNote
'
,
components
:
{
components
:
{
userAvatarLink
,
userAvatarLink
,
},
props
:
{
note
:
{
type
:
Object
,
required
:
true
,
},
},
props
:
{
},
note
:
{
computed
:
{
type
:
Object
,
...
mapGetters
([
'
getUserData
'
]),
required
:
true
,
},
},
};
},
computed
:
{
...
mapGetters
([
'
getUserData
'
,
]),
},
};
</
script
>
</
script
>
<
template
>
<
template
>
...
...
app/assets/javascripts/vue_shared/components/notes/placeholder_system_note.vue
View file @
3271c5f0
<
script
>
<
script
>
/**
/**
* Common component to render a placeholder system note.
* Common component to render a placeholder system note.
*
*
* @example
* @example
* <placeholder-system-note
* <placeholder-system-note
* :note="{ body: 'Commands are being applied'}"
* :note="{ body: 'Commands are being applied'}"
* />
* />
*/
*/
export
default
{
export
default
{
name
:
'
PlaceholderSystemNote
'
,
name
:
'
PlaceholderSystemNote
'
,
props
:
{
props
:
{
note
:
{
note
:
{
type
:
Object
,
type
:
Object
,
required
:
true
,
required
:
true
,
},
},
},
};
},
};
</
script
>
</
script
>
<
template
>
<
template
>
...
...
app/assets/javascripts/vue_shared/components/panel_resizer.vue
View file @
3271c5f0
<
script
>
<
script
>
export
default
{
export
default
{
props
:
{
props
:
{
startSize
:
{
startSize
:
{
type
:
Number
,
type
:
Number
,
required
:
true
,
required
:
true
,
},
side
:
{
type
:
String
,
required
:
true
,
},
minSize
:
{
type
:
Number
,
required
:
false
,
default
:
0
,
},
maxSize
:
{
type
:
Number
,
required
:
false
,
default
:
Number
.
MAX_VALUE
,
},
enabled
:
{
type
:
Boolean
,
required
:
false
,
default
:
true
,
},
},
},
data
()
{
side
:
{
return
{
type
:
String
,
size
:
this
.
startSize
,
required
:
true
,
};
},
},
computed
:
{
minSize
:
{
className
()
{
type
:
Number
,
return
`drag-
${
this
.
side
}
`
;
required
:
false
,
},
default
:
0
,
cursorStyle
()
{
if
(
this
.
enabled
)
{
return
{
cursor
:
'
ew-resize
'
};
}
return
{};
},
},
},
methods
:
{
maxSize
:
{
resetSize
(
e
)
{
type
:
Number
,
e
.
preventDefault
();
required
:
false
,
this
.
$emit
(
'
resize-start
'
,
this
.
size
);
default
:
Number
.
MAX_VALUE
,
},
enabled
:
{
type
:
Boolean
,
required
:
false
,
default
:
true
,
},
},
data
()
{
return
{
size
:
this
.
startSize
,
};
},
computed
:
{
className
()
{
return
`drag-
${
this
.
side
}
`
;
},
cursorStyle
()
{
if
(
this
.
enabled
)
{
return
{
cursor
:
'
ew-resize
'
};
}
return
{};
},
},
methods
:
{
resetSize
(
e
)
{
e
.
preventDefault
();
this
.
$emit
(
'
resize-start
'
,
this
.
size
);
this
.
size
=
this
.
startSize
;
this
.
size
=
this
.
startSize
;
this
.
$emit
(
'
update:size
'
,
this
.
size
);
this
.
$emit
(
'
update:size
'
,
this
.
size
);
// End resizing on next tick so that listeners can react to DOM changes
// End resizing on next tick so that listeners can react to DOM changes
this
.
$nextTick
(()
=>
{
this
.
$nextTick
(()
=>
{
this
.
$emit
(
'
resize-end
'
,
this
.
size
);
this
.
$emit
(
'
resize-end
'
,
this
.
size
);
});
});
},
},
startDrag
(
e
)
{
startDrag
(
e
)
{
if
(
this
.
enabled
)
{
if
(
this
.
enabled
)
{
e
.
preventDefault
();
this
.
startPos
=
e
.
clientX
;
this
.
currentStartSize
=
this
.
size
;
document
.
addEventListener
(
'
mousemove
'
,
this
.
drag
);
document
.
addEventListener
(
'
mouseup
'
,
this
.
endDrag
,
{
once
:
true
});
this
.
$emit
(
'
resize-start
'
,
this
.
size
);
}
},
drag
(
e
)
{
e
.
preventDefault
();
e
.
preventDefault
();
let
moved
=
e
.
clientX
-
this
.
startPos
;
this
.
startPos
=
e
.
clientX
;
if
(
this
.
side
===
'
left
'
)
moved
=
-
moved
;
this
.
currentStartSize
=
this
.
size
;
let
newSize
=
this
.
currentStartSize
+
moved
;
document
.
addEventListener
(
'
mousemove
'
,
this
.
drag
);
if
(
newSize
<
this
.
minSize
)
{
document
.
addEventListener
(
'
mouseup
'
,
this
.
endDrag
,
{
once
:
true
});
newSize
=
this
.
minSize
;
this
.
$emit
(
'
resize-start
'
,
this
.
size
);
}
else
if
(
newSize
>
this
.
maxSize
)
{
}
newSize
=
this
.
maxSize
;
},
}
drag
(
e
)
{
this
.
size
=
newSize
;
e
.
preventDefault
();
let
moved
=
e
.
clientX
-
this
.
startPos
;
if
(
this
.
side
===
'
left
'
)
moved
=
-
moved
;
let
newSize
=
this
.
currentStartSize
+
moved
;
if
(
newSize
<
this
.
minSize
)
{
newSize
=
this
.
minSize
;
}
else
if
(
newSize
>
this
.
maxSize
)
{
newSize
=
this
.
maxSize
;
}
this
.
size
=
newSize
;
this
.
$emit
(
'
update:size
'
,
newSize
);
this
.
$emit
(
'
update:size
'
,
newSize
);
},
},
endDrag
(
e
)
{
endDrag
(
e
)
{
e
.
preventDefault
();
e
.
preventDefault
();
document
.
removeEventListener
(
'
mousemove
'
,
this
.
drag
);
document
.
removeEventListener
(
'
mousemove
'
,
this
.
drag
);
this
.
$emit
(
'
resize-end
'
,
this
.
size
);
this
.
$emit
(
'
resize-end
'
,
this
.
size
);
},
},
},
};
},
};
</
script
>
</
script
>
<
template
>
<
template
>
...
...
app/assets/javascripts/vue_shared/components/pikaday.vue
View file @
3271c5f0
<
script
>
<
script
>
import
Pikaday
from
'
pikaday
'
;
import
Pikaday
from
'
pikaday
'
;
import
{
parsePikadayDate
,
pikadayToString
}
from
'
../../lib/utils/datefix
'
;
import
{
parsePikadayDate
,
pikadayToString
}
from
'
../../lib/utils/datefix
'
;
export
default
{
export
default
{
name
:
'
DatePicker
'
,
name
:
'
DatePicker
'
,
props
:
{
props
:
{
label
:
{
label
:
{
type
:
String
,
type
:
String
,
required
:
false
,
required
:
false
,
default
:
'
Date picker
'
,
default
:
'
Date picker
'
,
},
selectedDate
:
{
type
:
Date
,
required
:
false
,
default
:
null
,
},
minDate
:
{
type
:
Date
,
required
:
false
,
default
:
null
,
},
maxDate
:
{
type
:
Date
,
required
:
false
,
default
:
null
,
},
},
},
mounted
()
{
selectedDate
:
{
this
.
calendar
=
new
Pikaday
({
type
:
Date
,
field
:
this
.
$el
.
querySelector
(
'
.dropdown-menu-toggle
'
),
required
:
false
,
theme
:
'
gitlab-theme animate-picker
'
,
default
:
null
,
format
:
'
yyyy-mm-dd
'
,
},
container
:
this
.
$el
,
minDate
:
{
defaultDate
:
this
.
selectedDate
,
type
:
Date
,
setDefaultDate
:
!!
this
.
selectedDate
,
required
:
false
,
minDate
:
this
.
minDate
,
default
:
null
,
maxDate
:
this
.
maxDate
,
parse
:
dateString
=>
parsePikadayDate
(
dateString
),
toString
:
date
=>
pikadayToString
(
date
),
onSelect
:
this
.
selected
.
bind
(
this
),
onClose
:
this
.
toggled
.
bind
(
this
),
});
this
.
$el
.
append
(
this
.
calendar
.
el
);
this
.
calendar
.
show
();
},
},
beforeDestroy
()
{
maxDate
:
{
this
.
calendar
.
destroy
();
type
:
Date
,
required
:
false
,
default
:
null
,
},
},
mounted
()
{
this
.
calendar
=
new
Pikaday
({
field
:
this
.
$el
.
querySelector
(
'
.dropdown-menu-toggle
'
),
theme
:
'
gitlab-theme animate-picker
'
,
format
:
'
yyyy-mm-dd
'
,
container
:
this
.
$el
,
defaultDate
:
this
.
selectedDate
,
setDefaultDate
:
!!
this
.
selectedDate
,
minDate
:
this
.
minDate
,
maxDate
:
this
.
maxDate
,
parse
:
dateString
=>
parsePikadayDate
(
dateString
),
toString
:
date
=>
pikadayToString
(
date
),
onSelect
:
this
.
selected
.
bind
(
this
),
onClose
:
this
.
toggled
.
bind
(
this
),
});
this
.
$el
.
append
(
this
.
calendar
.
el
);
this
.
calendar
.
show
();
},
beforeDestroy
()
{
this
.
calendar
.
destroy
();
},
methods
:
{
selected
(
dateText
)
{
this
.
$emit
(
'
newDateSelected
'
,
this
.
calendar
.
toString
(
dateText
));
},
},
methods
:
{
toggled
()
{
selected
(
dateText
)
{
this
.
$emit
(
'
hidePicker
'
);
this
.
$emit
(
'
newDateSelected
'
,
this
.
calendar
.
toString
(
dateText
));
},
toggled
()
{
this
.
$emit
(
'
hidePicker
'
);
},
},
},
};
},
};
</
script
>
</
script
>
<
template
>
<
template
>
...
...
app/assets/javascripts/vue_shared/components/project_avatar/image.vue
View file @
3271c5f0
<
script
>
<
script
>
/* This is a re-usable vue component for rendering a project avatar that
/* This is a re-usable vue component for rendering a project avatar that
does not need to link to the project's profile. The image and an optional
does not need to link to the project's profile. The image and an optional
tooltip can be configured by props passed to this component.
tooltip can be configured by props passed to this component.
...
@@ -16,70 +15,70 @@
...
@@ -16,70 +15,70 @@
*/
*/
import
defaultAvatarUrl
from
'
images/no_avatar.png
'
;
import
defaultAvatarUrl
from
'
images/no_avatar.png
'
;
import
{
placeholderImage
}
from
'
../../../lazy_loader
'
;
import
{
placeholderImage
}
from
'
../../../lazy_loader
'
;
import
tooltip
from
'
../../directives/tooltip
'
;
import
tooltip
from
'
../../directives/tooltip
'
;
export
default
{
export
default
{
name
:
'
ProjectAvatarImage
'
,
name
:
'
ProjectAvatarImage
'
,
directives
:
{
directives
:
{
tooltip
,
tooltip
,
},
props
:
{
lazy
:
{
type
:
Boolean
,
required
:
false
,
default
:
false
,
},
imgSrc
:
{
type
:
String
,
required
:
false
,
default
:
defaultAvatarUrl
,
},
cssClasses
:
{
type
:
String
,
required
:
false
,
default
:
''
,
},
imgAlt
:
{
type
:
String
,
required
:
false
,
default
:
'
project avatar
'
,
},
size
:
{
type
:
Number
,
required
:
false
,
default
:
20
,
},
tooltipText
:
{
type
:
String
,
required
:
false
,
default
:
''
,
},
tooltipPlacement
:
{
type
:
String
,
required
:
false
,
default
:
'
top
'
,
},
},
computed
:
{
// API response sends null when gravatar is disabled and
// we provide an empty string when we use it inside project avatar link.
// In both cases we should render the defaultAvatarUrl
sanitizedSource
()
{
return
this
.
imgSrc
===
''
||
this
.
imgSrc
===
null
?
defaultAvatarUrl
:
this
.
imgSrc
;
},
resultantSrcAttribute
()
{
return
this
.
lazy
?
placeholderImage
:
this
.
sanitizedSource
;
},
},
props
:
{
tooltipContainer
()
{
lazy
:
{
return
this
.
tooltipText
?
'
body
'
:
null
;
type
:
Boolean
,
required
:
false
,
default
:
false
,
},
imgSrc
:
{
type
:
String
,
required
:
false
,
default
:
defaultAvatarUrl
,
},
cssClasses
:
{
type
:
String
,
required
:
false
,
default
:
''
,
},
imgAlt
:
{
type
:
String
,
required
:
false
,
default
:
'
project avatar
'
,
},
size
:
{
type
:
Number
,
required
:
false
,
default
:
20
,
},
tooltipText
:
{
type
:
String
,
required
:
false
,
default
:
''
,
},
tooltipPlacement
:
{
type
:
String
,
required
:
false
,
default
:
'
top
'
,
},
},
},
computed
:
{
avatarSizeClass
()
{
// API response sends null when gravatar is disabled and
return
`s
${
this
.
size
}
`
;
// we provide an empty string when we use it inside project avatar link.
// In both cases we should render the defaultAvatarUrl
sanitizedSource
()
{
return
this
.
imgSrc
===
''
||
this
.
imgSrc
===
null
?
defaultAvatarUrl
:
this
.
imgSrc
;
},
resultantSrcAttribute
()
{
return
this
.
lazy
?
placeholderImage
:
this
.
sanitizedSource
;
},
tooltipContainer
()
{
return
this
.
tooltipText
?
'
body
'
:
null
;
},
avatarSizeClass
()
{
return
`s
${
this
.
size
}
`
;
},
},
},
};
},
};
</
script
>
</
script
>
<
template
>
<
template
>
...
...
app/assets/javascripts/vue_shared/components/recaptcha_modal.vue
View file @
3271c5f0
<
script
>
<
script
>
import
DeprecatedModal
from
'
./deprecated_modal.vue
'
;
import
DeprecatedModal
from
'
./deprecated_modal.vue
'
;
export
default
{
export
default
{
name
:
'
RecaptchaModal
'
,
name
:
'
RecaptchaModal
'
,
components
:
{
components
:
{
DeprecatedModal
,
DeprecatedModal
,
},
},
props
:
{
props
:
{
html
:
{
html
:
{
type
:
String
,
type
:
String
,
required
:
false
,
required
:
false
,
default
:
''
,
default
:
''
,
},
},
},
},
data
()
{
data
()
{
return
{
return
{
script
:
{},
script
:
{},
scriptSrc
:
'
https://www.google.com/recaptcha/api.js
'
,
scriptSrc
:
'
https://www.google.com/recaptcha/api.js
'
,
};
};
},
},
watch
:
{
watch
:
{
html
()
{
html
()
{
this
.
appendRecaptchaScript
();
this
.
appendRecaptchaScript
();
},
},
},
},
mounted
()
{
mounted
()
{
window
.
recaptchaDialogCallback
=
this
.
submit
.
bind
(
this
);
window
.
recaptchaDialogCallback
=
this
.
submit
.
bind
(
this
);
},
},
methods
:
{
methods
:
{
appendRecaptchaScript
()
{
appendRecaptchaScript
()
{
this
.
removeRecaptchaScript
();
this
.
removeRecaptchaScript
();
const
script
=
document
.
createElement
(
'
script
'
);
const
script
=
document
.
createElement
(
'
script
'
);
script
.
src
=
this
.
scriptSrc
;
script
.
src
=
this
.
scriptSrc
;
script
.
classList
.
add
(
'
js-recaptcha-script
'
);
script
.
classList
.
add
(
'
js-recaptcha-script
'
);
script
.
async
=
true
;
script
.
async
=
true
;
script
.
defer
=
true
;
script
.
defer
=
true
;
this
.
script
=
script
;
this
.
script
=
script
;
document
.
body
.
appendChild
(
script
);
document
.
body
.
appendChild
(
script
);
},
},
removeRecaptchaScript
()
{
removeRecaptchaScript
()
{
if
(
this
.
script
instanceof
Element
)
this
.
script
.
remove
();
if
(
this
.
script
instanceof
Element
)
this
.
script
.
remove
();
},
},
close
()
{
close
()
{
this
.
removeRecaptchaScript
();
this
.
removeRecaptchaScript
();
this
.
$emit
(
'
close
'
);
this
.
$emit
(
'
close
'
);
},
},
submit
()
{
submit
()
{
this
.
$el
.
querySelector
(
'
form
'
).
submit
();
this
.
$el
.
querySelector
(
'
form
'
).
submit
();
},
},
},
};
},
};
</
script
>
</
script
>
<
template
>
<
template
>
...
...
app/assets/javascripts/vue_shared/components/sidebar/date_picker.vue
View file @
3271c5f0
<
script
>
<
script
>
import
datePicker
from
'
../pikaday.vue
'
;
import
datePicker
from
'
../pikaday.vue
'
;
import
toggleSidebar
from
'
./toggle_sidebar.vue
'
;
import
toggleSidebar
from
'
./toggle_sidebar.vue
'
;
import
collapsedCalendarIcon
from
'
./collapsed_calendar_icon.vue
'
;
import
collapsedCalendarIcon
from
'
./collapsed_calendar_icon.vue
'
;
import
{
dateInWords
}
from
'
../../../lib/utils/datetime_utility
'
;
import
{
dateInWords
}
from
'
../../../lib/utils/datetime_utility
'
;
export
default
{
export
default
{
name
:
'
SidebarDatePicker
'
,
name
:
'
SidebarDatePicker
'
,
components
:
{
components
:
{
datePicker
,
datePicker
,
toggleSidebar
,
toggleSidebar
,
collapsedCalendarIcon
,
collapsedCalendarIcon
,
},
},
props
:
{
props
:
{
blockClass
:
{
blockClass
:
{
type
:
String
,
type
:
String
,
required
:
false
,
required
:
false
,
default
:
''
,
default
:
''
,
},
},
collapsed
:
{
collapsed
:
{
type
:
Boolean
,
type
:
Boolean
,
required
:
false
,
required
:
false
,
default
:
true
,
default
:
true
,
},
},
showToggleSidebar
:
{
showToggleSidebar
:
{
type
:
Boolean
,
type
:
Boolean
,
required
:
false
,
required
:
false
,
default
:
false
,
default
:
false
,
},
},
isLoading
:
{
isLoading
:
{
type
:
Boolean
,
type
:
Boolean
,
required
:
false
,
required
:
false
,
default
:
false
,
default
:
false
,
},
},
editable
:
{
editable
:
{
type
:
Boolean
,
type
:
Boolean
,
required
:
false
,
required
:
false
,
default
:
false
,
default
:
false
,
},
},
label
:
{
label
:
{
type
:
String
,
type
:
String
,
required
:
false
,
required
:
false
,
default
:
'
Date picker
'
,
default
:
'
Date picker
'
,
},
},
selectedDate
:
{
selectedDate
:
{
type
:
Date
,
type
:
Date
,
required
:
false
,
required
:
false
,
default
:
null
,
default
:
null
,
},
},
minDate
:
{
minDate
:
{
type
:
Date
,
type
:
Date
,
required
:
false
,
required
:
false
,
default
:
null
,
default
:
null
,
},
},
maxDate
:
{
maxDate
:
{
type
:
Date
,
type
:
Date
,
required
:
false
,
required
:
false
,
default
:
null
,
default
:
null
,
},
},
},
},
data
()
{
data
()
{
return
{
return
{
editing
:
false
,
editing
:
false
,
};
};
},
},
computed
:
{
computed
:
{
selectedAndEditable
()
{
selectedAndEditable
()
{
return
this
.
selectedDate
&&
this
.
editable
;
return
this
.
selectedDate
&&
this
.
editable
;
},
},
selectedDateWords
()
{
selectedDateWords
()
{
return
dateInWords
(
this
.
selectedDate
,
true
);
return
dateInWords
(
this
.
selectedDate
,
true
);
},
},
collapsedText
()
{
collapsedText
()
{
return
this
.
selectedDateWords
?
this
.
selectedDateWords
:
'
None
'
;
return
this
.
selectedDateWords
?
this
.
selectedDateWords
:
'
None
'
;
},
},
},
},
methods
:
{
methods
:
{
stopEditing
()
{
stopEditing
()
{
this
.
editing
=
false
;
this
.
editing
=
false
;
},
},
toggleDatePicker
()
{
toggleDatePicker
()
{
this
.
editing
=
!
this
.
editing
;
this
.
editing
=
!
this
.
editing
;
},
},
newDateSelected
(
date
=
null
)
{
newDateSelected
(
date
=
null
)
{
this
.
date
=
date
;
this
.
date
=
date
;
this
.
editing
=
false
;
this
.
editing
=
false
;
this
.
$emit
(
'
saveDate
'
,
date
);
this
.
$emit
(
'
saveDate
'
,
date
);
},
},
toggleSidebar
()
{
toggleSidebar
()
{
this
.
$emit
(
'
toggleCollapse
'
);
this
.
$emit
(
'
toggleCollapse
'
);
},
},
},
},
};
};
</
script
>
</
script
>
<
template
>
<
template
>
...
...
app/assets/javascripts/vue_shared/components/table_pagination.vue
View file @
3271c5f0
<
script
>
<
script
>
import
{
s__
}
from
'
../../locale
'
;
import
{
s__
}
from
'
../../locale
'
;
const
PAGINATION_UI_BUTTON_LIMIT
=
4
;
const
PAGINATION_UI_BUTTON_LIMIT
=
4
;
const
UI_LIMIT
=
6
;
const
UI_LIMIT
=
6
;
const
SPREAD
=
'
...
'
;
const
SPREAD
=
'
...
'
;
const
PREV
=
s__
(
'
Pagination|Prev
'
);
const
PREV
=
s__
(
'
Pagination|Prev
'
);
const
NEXT
=
s__
(
'
Pagination|Next
'
);
const
NEXT
=
s__
(
'
Pagination|Next
'
);
const
FIRST
=
s__
(
'
Pagination|« First
'
);
const
FIRST
=
s__
(
'
Pagination|« First
'
);
const
LAST
=
s__
(
'
Pagination|Last »
'
);
const
LAST
=
s__
(
'
Pagination|Last »
'
);
export
default
{
export
default
{
props
:
{
props
:
{
/**
/**
This function will take the information given by the pagination component
This function will take the information given by the pagination component
Here is an example `change` method:
Here is an example `change` method:
...
@@ -20,12 +20,12 @@
...
@@ -20,12 +20,12 @@
gl.utils.visitUrl(`?page=${pagenum}`);
gl.utils.visitUrl(`?page=${pagenum}`);
},
},
*/
*/
change
:
{
change
:
{
type
:
Function
,
type
:
Function
,
required
:
true
,
required
:
true
,
},
},
/**
/**
pageInfo will come from the headers of the API call
pageInfo will come from the headers of the API call
in the `.then` clause of the VueResource API call
in the `.then` clause of the VueResource API call
there should be a function that contructs the pageInfo for this component
there should be a function that contructs the pageInfo for this component
...
@@ -41,94 +41,94 @@
...
@@ -41,94 +41,94 @@
previousPage: +headers['X-Prev-Page'],
previousPage: +headers['X-Prev-Page'],
});
});
*/
*/
pageInfo
:
{
pageInfo
:
{
type
:
Object
,
type
:
Object
,
required
:
true
,
required
:
true
,
},
},
},
computed
:
{
prev
()
{
return
this
.
pageInfo
.
previousPage
;
},
next
()
{
return
this
.
pageInfo
.
nextPage
;
},
getItems
()
{
const
total
=
this
.
pageInfo
.
totalPages
;
const
{
page
}
=
this
.
pageInfo
;
const
items
=
[];
if
(
page
>
1
)
{
items
.
push
({
title
:
FIRST
,
first
:
true
});
}
if
(
page
>
1
)
{
items
.
push
({
title
:
PREV
,
prev
:
true
});
}
else
{
items
.
push
({
title
:
PREV
,
disabled
:
true
,
prev
:
true
});
}
if
(
page
>
UI_LIMIT
)
items
.
push
({
title
:
SPREAD
,
separator
:
true
});
const
start
=
Math
.
max
(
page
-
PAGINATION_UI_BUTTON_LIMIT
,
1
);
const
end
=
Math
.
min
(
page
+
PAGINATION_UI_BUTTON_LIMIT
,
total
);
for
(
let
i
=
start
;
i
<=
end
;
i
+=
1
)
{
const
isActive
=
i
===
page
;
items
.
push
({
title
:
i
,
active
:
isActive
,
page
:
true
});
}
if
(
total
-
page
>
PAGINATION_UI_BUTTON_LIMIT
)
{
items
.
push
({
title
:
SPREAD
,
separator
:
true
,
page
:
true
});
}
if
(
page
===
total
)
{
items
.
push
({
title
:
NEXT
,
disabled
:
true
,
next
:
true
});
}
else
if
(
total
-
page
>=
1
)
{
items
.
push
({
title
:
NEXT
,
next
:
true
});
}
if
(
total
-
page
>=
1
)
{
items
.
push
({
title
:
LAST
,
last
:
true
});
}
return
items
;
},
showPagination
()
{
return
this
.
pageInfo
.
totalPages
>
1
;
},
},
computed
:
{
},
prev
()
{
methods
:
{
return
this
.
pageInfo
.
previousPage
;
changePage
(
text
,
isDisabled
)
{
},
if
(
isDisabled
)
return
;
next
()
{
return
this
.
pageInfo
.
nextPage
;
const
{
totalPages
,
nextPage
,
previousPage
}
=
this
.
pageInfo
;
},
getItems
()
{
switch
(
text
)
{
const
total
=
this
.
pageInfo
.
totalPages
;
case
SPREAD
:
const
{
page
}
=
this
.
pageInfo
;
break
;
const
items
=
[];
case
LAST
:
this
.
change
(
totalPages
);
if
(
page
>
1
)
{
break
;
items
.
push
({
title
:
FIRST
,
first
:
true
});
case
NEXT
:
}
this
.
change
(
nextPage
);
break
;
if
(
page
>
1
)
{
case
PREV
:
items
.
push
({
title
:
PREV
,
prev
:
true
});
this
.
change
(
previousPage
);
}
else
{
break
;
items
.
push
({
title
:
PREV
,
disabled
:
true
,
prev
:
true
});
case
FIRST
:
}
this
.
change
(
1
);
break
;
if
(
page
>
UI_LIMIT
)
items
.
push
({
title
:
SPREAD
,
separator
:
true
});
default
:
this
.
change
(
+
text
);
const
start
=
Math
.
max
(
page
-
PAGINATION_UI_BUTTON_LIMIT
,
1
);
break
;
const
end
=
Math
.
min
(
page
+
PAGINATION_UI_BUTTON_LIMIT
,
total
);
}
for
(
let
i
=
start
;
i
<=
end
;
i
+=
1
)
{
const
isActive
=
i
===
page
;
items
.
push
({
title
:
i
,
active
:
isActive
,
page
:
true
});
}
if
(
total
-
page
>
PAGINATION_UI_BUTTON_LIMIT
)
{
items
.
push
({
title
:
SPREAD
,
separator
:
true
,
page
:
true
});
}
if
(
page
===
total
)
{
items
.
push
({
title
:
NEXT
,
disabled
:
true
,
next
:
true
});
}
else
if
(
total
-
page
>=
1
)
{
items
.
push
({
title
:
NEXT
,
next
:
true
});
}
if
(
total
-
page
>=
1
)
{
items
.
push
({
title
:
LAST
,
last
:
true
});
}
return
items
;
},
showPagination
()
{
return
this
.
pageInfo
.
totalPages
>
1
;
},
},
},
methods
:
{
hideOnSmallScreen
(
item
)
{
changePage
(
text
,
isDisabled
)
{
return
!
item
.
first
&&
!
item
.
last
&&
!
item
.
next
&&
!
item
.
prev
&&
!
item
.
active
;
if
(
isDisabled
)
return
;
const
{
totalPages
,
nextPage
,
previousPage
}
=
this
.
pageInfo
;
switch
(
text
)
{
case
SPREAD
:
break
;
case
LAST
:
this
.
change
(
totalPages
);
break
;
case
NEXT
:
this
.
change
(
nextPage
);
break
;
case
PREV
:
this
.
change
(
previousPage
);
break
;
case
FIRST
:
this
.
change
(
1
);
break
;
default
:
this
.
change
(
+
text
);
break
;
}
},
hideOnSmallScreen
(
item
)
{
return
!
item
.
first
&&
!
item
.
last
&&
!
item
.
next
&&
!
item
.
prev
&&
!
item
.
active
;
},
},
},
};
},
};
</
script
>
</
script
>
<
template
>
<
template
>
<div
<div
...
...
app/assets/javascripts/vue_shared/components/time_ago_tooltip.vue
View file @
3271c5f0
...
@@ -11,9 +11,7 @@ export default {
...
@@ -11,9 +11,7 @@ export default {
directives
:
{
directives
:
{
tooltip
,
tooltip
,
},
},
mixins
:
[
mixins
:
[
timeagoMixin
],
timeagoMixin
,
],
props
:
{
props
:
{
time
:
{
time
:
{
type
:
String
,
type
:
String
,
...
...
app/assets/javascripts/vue_shared/components/toggle_button.vue
View file @
3271c5f0
<
script
>
<
script
>
import
{
s__
}
from
'
../../locale
'
;
import
{
s__
}
from
'
../../locale
'
;
import
icon
from
'
./icon.vue
'
;
import
icon
from
'
./icon.vue
'
;
const
ICON_ON
=
'
status_success_borderless
'
;
const
ICON_ON
=
'
status_success_borderless
'
;
const
ICON_OFF
=
'
status_failed_borderless
'
;
const
ICON_OFF
=
'
status_failed_borderless
'
;
const
LABEL_ON
=
s__
(
'
ToggleButton|Toggle Status: ON
'
);
const
LABEL_ON
=
s__
(
'
ToggleButton|Toggle Status: ON
'
);
const
LABEL_OFF
=
s__
(
'
ToggleButton|Toggle Status: OFF
'
);
const
LABEL_OFF
=
s__
(
'
ToggleButton|Toggle Status: OFF
'
);
export
default
{
export
default
{
components
:
{
components
:
{
icon
,
icon
,
},
},
model
:
{
model
:
{
prop
:
'
value
'
,
prop
:
'
value
'
,
event
:
'
change
'
,
event
:
'
change
'
,
},
},
props
:
{
props
:
{
name
:
{
name
:
{
type
:
String
,
type
:
String
,
required
:
false
,
required
:
false
,
default
:
null
,
default
:
null
,
},
},
value
:
{
value
:
{
type
:
Boolean
,
type
:
Boolean
,
required
:
false
,
required
:
false
,
default
:
null
,
default
:
null
,
},
disabledInput
:
{
type
:
Boolean
,
required
:
false
,
default
:
false
,
},
isLoading
:
{
type
:
Boolean
,
required
:
false
,
default
:
false
,
},
},
},
disabledInput
:
{
type
:
Boolean
,
required
:
false
,
default
:
false
,
},
isLoading
:
{
type
:
Boolean
,
required
:
false
,
default
:
false
,
},
},
computed
:
{
computed
:
{
toggleIcon
()
{
toggleIcon
()
{
return
this
.
value
?
ICON_ON
:
ICON_OFF
;
return
this
.
value
?
ICON_ON
:
ICON_OFF
;
},
},
ariaLabel
()
{
ariaLabel
()
{
return
this
.
value
?
LABEL_ON
:
LABEL_OFF
;
return
this
.
value
?
LABEL_ON
:
LABEL_OFF
;
},
},
},
},
methods
:
{
methods
:
{
toggleFeature
()
{
toggleFeature
()
{
if
(
!
this
.
disabledInput
)
this
.
$emit
(
'
change
'
,
!
this
.
value
);
if
(
!
this
.
disabledInput
)
this
.
$emit
(
'
change
'
,
!
this
.
value
);
},
},
},
};
},
};
</
script
>
</
script
>
<
template
>
<
template
>
...
...
app/assets/javascripts/vue_shared/components/user_avatar/user_avatar_link.vue
View file @
3271c5f0
<
script
>
<
script
>
/* This is a re-usable vue component for rendering a user avatar wrapped in
/* This is a re-usable vue component for rendering a user avatar wrapped in
a clickable link (likely to the user's profile). The link, image, and
a clickable link (likely to the user's profile). The link, image, and
tooltip can be configured by props passed to this component.
tooltip can be configured by props passed to this component.
...
...
app/assets/javascripts/vue_shared/components/user_avatar/user_avatar_svg.vue
View file @
3271c5f0
<
script
>
<
script
>
/* This is a re-usable vue component for rendering a user avatar svg (typically
/* This is a re-usable vue component for rendering a user avatar svg (typically
for a blank state). It will receive styles comparable to the user avatar,
for a blank state). It will receive styles comparable to the user avatar,
but no image is loaded, it isn't wrapped in a link, and tooltips aren't supported.
but no image is loaded, it isn't wrapped in a link, and tooltips aren't supported.
...
@@ -42,4 +41,3 @@ export default {
...
@@ -42,4 +41,3 @@ export default {
v-html=
"svg"
v-html=
"svg"
/>
/>
</
template
>
</
template
>
app/assets/javascripts/vue_shared/mixins/ci_pagination_api_mixin.js
View file @
3271c5f0
...
@@ -4,10 +4,7 @@
...
@@ -4,10 +4,7 @@
*
*
* Components need to have `scope`, `page` and `requestData`
* Components need to have `scope`, `page` and `requestData`
*/
*/
import
{
import
{
historyPushState
,
buildUrlWithCurrentLocation
}
from
'
../../lib/utils/common_utils
'
;
historyPushState
,
buildUrlWithCurrentLocation
,
}
from
'
../../lib/utils/common_utils
'
;
export
default
{
export
default
{
methods
:
{
methods
:
{
...
@@ -24,12 +21,14 @@ export default {
...
@@ -24,12 +21,14 @@ export default {
// stop polling
// stop polling
this
.
poll
.
stop
();
this
.
poll
.
stop
();
const
queryString
=
Object
.
keys
(
parameters
).
map
((
parameter
)
=>
{
const
queryString
=
Object
.
keys
(
parameters
)
const
value
=
parameters
[
parameter
];
.
map
(
parameter
=>
{
// update internal state for UI
const
value
=
parameters
[
parameter
];
this
[
parameter
]
=
value
;
// update internal state for UI
return
`
${
parameter
}
=
${
encodeURIComponent
(
value
)}
`
;
this
[
parameter
]
=
value
;
}).
join
(
'
&
'
);
return
`
${
parameter
}
=
${
encodeURIComponent
(
value
)}
`
;
})
.
join
(
'
&
'
);
// update polling parameters
// update polling parameters
this
.
requestData
=
parameters
;
this
.
requestData
=
parameters
;
...
...
app/assets/javascripts/vue_shared/models/label.js
View file @
3271c5f0
...
@@ -6,7 +6,7 @@ export default class ListLabel {
...
@@ -6,7 +6,7 @@ export default class ListLabel {
this
.
color
=
obj
.
color
;
this
.
color
=
obj
.
color
;
this
.
textColor
=
obj
.
text_color
;
this
.
textColor
=
obj
.
text_color
;
this
.
description
=
obj
.
description
;
this
.
description
=
obj
.
description
;
this
.
priority
=
(
obj
.
priority
!==
null
)
?
obj
.
priority
:
Infinity
;
this
.
priority
=
obj
.
priority
!==
null
?
obj
.
priority
:
Infinity
;
}
}
}
}
...
...
app/assets/javascripts/vue_shared/translate.js
View file @
3271c5f0
import
{
import
{
__
,
n__
,
s__
,
sprintf
}
from
'
../locale
'
;
__
,
n__
,
s__
,
sprintf
,
}
from
'
../locale
'
;
export
default
(
Vue
)
=>
{
export
default
Vue
=>
{
Vue
.
mixin
({
Vue
.
mixin
({
methods
:
{
methods
:
{
/**
/**
...
...
app/assets/javascripts/vue_shared/vue_resource_interceptor.js
View file @
3271c5f0
...
@@ -21,7 +21,7 @@ Vue.http.interceptors.push((request, next) => {
...
@@ -21,7 +21,7 @@ Vue.http.interceptors.push((request, next) => {
Vue
.
http
.
interceptors
.
push
((
request
,
next
)
=>
{
Vue
.
http
.
interceptors
.
push
((
request
,
next
)
=>
{
request
.
headers
.
set
(
csrf
.
headerKey
,
csrf
.
token
);
request
.
headers
.
set
(
csrf
.
headerKey
,
csrf
.
token
);
next
(
(
response
)
=>
{
next
(
response
=>
{
// Headers object has a `forEach` property that iterates through all values.
// Headers object has a `forEach` property that iterates through all values.
const
headers
=
{};
const
headers
=
{};
...
...
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