BigW Consortium Gitlab
Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
G
gitlab-ce
Project
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Commits
Issue Boards
Open sidebar
Forest Godfrey
gitlab-ce
Commits
7911f1c0
Commit
7911f1c0
authored
May 26, 2017
by
Phil Hughes
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'ci-build-pipeline-header-vue' into 'master'
Creates CI Header component to use in pipelines and job details pages See merge request !11726
parents
fe008c52
f4274ca1
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
352 additions
and
0 deletions
+352
-0
header_ci_component.vue
...javascripts/vue_shared/components/header_ci_component.vue
+122
-0
time_ago_tooltip.vue
...ts/javascripts/vue_shared/components/time_ago_tooltip.vue
+58
-0
timeago.js
app/assets/javascripts/vue_shared/mixins/timeago.js
+18
-0
ci-build-pipeline-header-vue.yml
changelogs/unreleased/ci-build-pipeline-header-vue.yml
+4
-0
header_ci_component_spec.js
...scripts/vue_shared/components/header_ci_component_spec.js
+82
-0
time_ago_tooltip_spec.js
...avascripts/vue_shared/components/time_ago_tooltip_spec.js
+68
-0
No files found.
app/assets/javascripts/vue_shared/components/header_ci_component.vue
0 → 100644
View file @
7911f1c0
<
script
>
import
ciIconBadge
from
'./ci_badge_link.vue'
;
import
timeagoTooltip
from
'./time_ago_tooltip.vue'
;
import
tooltipMixin
from
'../mixins/tooltip'
;
import
userAvatarLink
from
'./user_avatar/user_avatar_link.vue'
;
/**
* Renders header component for job and pipeline page based on UI mockups
*
* Used in:
* - job show page
* - pipeline show page
*/
export
default
{
props
:
{
status
:
{
type
:
Object
,
required
:
true
,
},
itemName
:
{
type
:
String
,
required
:
true
,
},
itemId
:
{
type
:
Number
,
required
:
true
,
},
time
:
{
type
:
String
,
required
:
true
,
},
user
:
{
type
:
Object
,
required
:
true
,
},
actions
:
{
type
:
Array
,
required
:
false
,
default
:
()
=>
[],
},
},
mixins
:
[
tooltipMixin
,
],
components
:
{
ciIconBadge
,
timeagoTooltip
,
userAvatarLink
,
},
computed
:
{
userAvatarAltText
()
{
return
`
${
this
.
user
.
name
}
's avatar`
;
},
},
methods
:
{
onClickAction
(
action
)
{
this
.
$emit
(
'postAction'
,
action
);
},
},
};
</
script
>
<
template
>
<header
class=
"page-content-header top-area"
>
<section
class=
"header-main-content"
>
<ci-icon-badge
:status=
"status"
/>
<strong>
{{
itemName
}}
#
{{
itemId
}}
</strong>
triggered
<timeago-tooltip
:time=
"time"
/>
by
<user-avatar-link
:link-href=
"user.web_url"
:img-src=
"user.avatar_url"
:img-alt=
"userAvatarAltText"
:tooltip-text=
"user.name"
:img-size=
"24"
/>
<a
:href=
"user.web_url"
:title=
"user.email"
class=
"js-user-link commit-committer-link"
ref=
"tooltip"
>
{{
user
.
name
}}
</a>
</section>
<section
class=
"header-action-button nav-controls"
v-if=
"actions.length"
>
<template
v-for=
"action in actions"
>
<a
v-if=
"action.type === 'link'"
:href=
"action.path"
:class=
"action.cssClass"
>
{{
action
.
label
}}
</a>
<button
v-else=
"action.type === 'button'"
@
click=
"onClickAction(action)"
:class=
"action.cssClass"
type=
"button"
>
{{
action
.
label
}}
</button>
</
template
>
</section>
</header>
</template>
app/assets/javascripts/vue_shared/components/time_ago_tooltip.vue
0 → 100644
View file @
7911f1c0
<
script
>
import
tooltipMixin
from
'../mixins/tooltip'
;
import
timeagoMixin
from
'../mixins/timeago'
;
import
'../../lib/utils/datetime_utility'
;
/**
* Port of ruby helper time_ago_with_tooltip
*/
export
default
{
props
:
{
time
:
{
type
:
String
,
required
:
true
,
},
tooltipPlacement
:
{
type
:
String
,
required
:
false
,
default
:
'top'
,
},
shortFormat
:
{
type
:
Boolean
,
required
:
false
,
default
:
false
,
},
cssClass
:
{
type
:
String
,
required
:
false
,
default
:
''
,
},
},
mixins
:
[
tooltipMixin
,
timeagoMixin
,
],
computed
:
{
timeagoCssClass
()
{
return
this
.
shortFormat
?
'js-short-timeago'
:
'js-timeago'
;
},
},
};
</
script
>
<
template
>
<time
:class=
"[timeagoCssClass, cssClass]"
class=
"js-timeago js-timeago-render"
:title=
"tooltipTitle(time)"
:data-placement=
"tooltipPlacement"
data-container=
"body"
ref=
"tooltip"
>
{{
timeFormated
(
time
)
}}
</time>
</
template
>
app/assets/javascripts/vue_shared/mixins/timeago.js
0 → 100644
View file @
7911f1c0
import
'../../lib/utils/datetime_utility'
;
/**
* Mixin with time ago methods used in some vue components
*/
export
default
{
methods
:
{
timeFormated
(
time
)
{
const
timeago
=
gl
.
utils
.
getTimeago
();
return
timeago
.
format
(
time
);
},
tooltipTitle
(
time
)
{
return
gl
.
utils
.
formatDate
(
time
);
},
},
};
changelogs/unreleased/ci-build-pipeline-header-vue.yml
0 → 100644
View file @
7911f1c0
---
title
:
Creates CI Header component for Pipelines and Jobs details pages
merge_request
:
author
:
spec/javascripts/vue_shared/components/header_ci_component_spec.js
0 → 100644
View file @
7911f1c0
import
Vue
from
'vue'
;
import
headerCi
from
'~/vue_shared/components/header_ci_component.vue'
;
describe
(
'Header CI Component'
,
()
=>
{
let
HeaderCi
;
let
vm
;
let
props
;
beforeEach
(()
=>
{
HeaderCi
=
Vue
.
extend
(
headerCi
);
props
=
{
status
:
{
group
:
'failed'
,
icon
:
'ci-status-failed'
,
label
:
'failed'
,
text
:
'failed'
,
details_path
:
'path'
,
},
itemName
:
'job'
,
itemId
:
123
,
time
:
'2017-05-08T14:57:39.781Z'
,
user
:
{
web_url
:
'path'
,
name
:
'Foo'
,
username
:
'foobar'
,
email
:
'foo@bar.com'
,
avatar_url
:
'link'
,
},
actions
:
[
{
label
:
'Retry'
,
path
:
'path'
,
type
:
'button'
,
cssClass
:
'btn'
,
},
{
label
:
'Go'
,
path
:
'path'
,
type
:
'link'
,
cssClass
:
'link'
,
},
],
};
vm
=
new
HeaderCi
({
propsData
:
props
,
}).
$mount
();
});
afterEach
(()
=>
{
vm
.
$destroy
();
});
it
(
'should render status badge'
,
()
=>
{
expect
(
vm
.
$el
.
querySelector
(
'.ci-failed'
)).
toBeDefined
();
expect
(
vm
.
$el
.
querySelector
(
'.ci-status-icon-failed svg'
)).
toBeDefined
();
expect
(
vm
.
$el
.
querySelector
(
'.ci-failed'
).
getAttribute
(
'href'
),
).
toEqual
(
props
.
status
.
details_path
);
});
it
(
'should render item name and id'
,
()
=>
{
expect
(
vm
.
$el
.
querySelector
(
'strong'
).
textContent
.
trim
()).
toEqual
(
'job #123'
);
});
it
(
'should render timeago date'
,
()
=>
{
expect
(
vm
.
$el
.
querySelector
(
'time'
)).
toBeDefined
();
});
it
(
'should render user icon and name'
,
()
=>
{
expect
(
vm
.
$el
.
querySelector
(
'.js-user-link'
).
textContent
.
trim
()).
toEqual
(
props
.
user
.
name
);
});
it
(
'should render provided actions'
,
()
=>
{
expect
(
vm
.
$el
.
querySelector
(
'.btn'
).
tagName
).
toEqual
(
'BUTTON'
);
expect
(
vm
.
$el
.
querySelector
(
'.btn'
).
textContent
.
trim
()).
toEqual
(
props
.
actions
[
0
].
label
);
expect
(
vm
.
$el
.
querySelector
(
'.link'
).
tagName
).
toEqual
(
'A'
);
expect
(
vm
.
$el
.
querySelector
(
'.link'
).
textContent
.
trim
()).
toEqual
(
props
.
actions
[
1
].
label
);
expect
(
vm
.
$el
.
querySelector
(
'.link'
).
getAttribute
(
'href'
)).
toEqual
(
props
.
actions
[
0
].
path
);
});
});
spec/javascripts/vue_shared/components/time_ago_tooltip_spec.js
0 → 100644
View file @
7911f1c0
import
Vue
from
'vue'
;
import
timeagoTooltip
from
'~/vue_shared/components/time_ago_tooltip.vue'
;
import
'~/lib/utils/datetime_utility'
;
describe
(
'Time ago with tooltip component'
,
()
=>
{
let
TimeagoTooltip
;
let
vm
;
beforeEach
(()
=>
{
TimeagoTooltip
=
Vue
.
extend
(
timeagoTooltip
);
});
afterEach
(()
=>
{
vm
.
$destroy
();
});
it
(
'should render timeago with a bootstrap tooltip'
,
()
=>
{
vm
=
new
TimeagoTooltip
({
propsData
:
{
time
:
'2017-05-08T14:57:39.781Z'
,
},
}).
$mount
();
expect
(
vm
.
$el
.
tagName
).
toEqual
(
'TIME'
);
expect
(
vm
.
$el
.
classList
.
contains
(
'js-timeago'
)).
toEqual
(
true
);
expect
(
vm
.
$el
.
getAttribute
(
'data-original-title'
),
).
toEqual
(
gl
.
utils
.
formatDate
(
'2017-05-08T14:57:39.781Z'
));
expect
(
vm
.
$el
.
getAttribute
(
'data-placement'
)).
toEqual
(
'top'
);
const
timeago
=
gl
.
utils
.
getTimeago
();
expect
(
vm
.
$el
.
textContent
.
trim
()).
toEqual
(
timeago
.
format
(
'2017-05-08T14:57:39.781Z'
));
});
it
(
'should render tooltip placed in bottom'
,
()
=>
{
vm
=
new
TimeagoTooltip
({
propsData
:
{
time
:
'2017-05-08T14:57:39.781Z'
,
tooltipPlacement
:
'bottom'
,
},
}).
$mount
();
expect
(
vm
.
$el
.
getAttribute
(
'data-placement'
)).
toEqual
(
'bottom'
);
});
it
(
'should render short format class'
,
()
=>
{
vm
=
new
TimeagoTooltip
({
propsData
:
{
time
:
'2017-05-08T14:57:39.781Z'
,
shortFormat
:
true
,
},
}).
$mount
();
expect
(
vm
.
$el
.
classList
.
contains
(
'js-short-timeago'
)).
toEqual
(
true
);
});
it
(
'should render provided html class'
,
()
=>
{
vm
=
new
TimeagoTooltip
({
propsData
:
{
time
:
'2017-05-08T14:57:39.781Z'
,
cssClass
:
'foo'
,
},
}).
$mount
();
expect
(
vm
.
$el
.
classList
.
contains
(
'foo'
)).
toEqual
(
true
);
});
});
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