2021-03-08 18:12:59 +05:30
< script >
/ * *
* Renders a deploy board .
*
* A deploy board is composed by :
* - Information area with percentage of completion .
* - Instances with status .
* - Button Actions .
* [ Mockup ] ( https : //gitlab.com/gitlab-org/gitlab-foss/uploads/2f655655c0eadf655d0ae7467b53002a/environments__deploy-graphic.png)
* /
2021-03-11 19:13:27 +05:30
import deployBoardSvg from '@gitlab/svgs/dist/illustrations/deploy-boards.svg' ;
2021-03-08 18:12:59 +05:30
import {
GlIcon ,
GlLoadingIcon ,
GlLink ,
GlTooltip ,
GlTooltipDirective ,
GlSafeHtmlDirective as SafeHtml ,
2022-04-04 11:22:00 +05:30
GlSprintf ,
2021-03-08 18:12:59 +05:30
} from '@gitlab/ui' ;
2021-03-11 19:13:27 +05:30
import { isEmpty } from 'lodash' ;
2022-04-04 11:22:00 +05:30
import { s _ _ , n _ _ } from '~/locale' ;
2021-03-11 19:13:27 +05:30
import instanceComponent from '~/vue_shared/components/deployment_instance.vue' ;
2021-03-08 18:12:59 +05:30
import { STATUS _MAP , CANARY _STATUS } from '../constants' ;
import CanaryIngress from './canary_ingress.vue' ;
export default {
components : {
instanceComponent ,
CanaryIngress ,
GlIcon ,
GlLoadingIcon ,
GlLink ,
2022-04-04 11:22:00 +05:30
GlSprintf ,
2021-03-08 18:12:59 +05:30
GlTooltip ,
} ,
directives : {
GlTooltip : GlTooltipDirective ,
SafeHtml ,
} ,
props : {
deployBoardData : {
type : Object ,
required : true ,
} ,
isLoading : {
type : Boolean ,
required : true ,
} ,
isEmpty : {
type : Boolean ,
required : true ,
} ,
logsPath : {
type : String ,
required : false ,
default : '' ,
} ,
2022-04-04 11:22:00 +05:30
graphql : {
type : Boolean ,
required : false ,
default : false ,
} ,
2021-03-08 18:12:59 +05:30
} ,
computed : {
canRenderDeployBoard ( ) {
return ! this . isEmpty && ! isEmpty ( this . deployBoardData ) ;
} ,
canRenderEmptyState ( ) {
return this . isEmpty ;
} ,
2022-04-04 11:22:00 +05:30
canaryIngress ( ) {
if ( this . graphql ) {
return this . deployBoardData . canaryIngress ;
}
return this . deployBoardData . canary _ingress ;
} ,
2021-03-08 18:12:59 +05:30
canRenderCanaryWeight ( ) {
2022-04-04 11:22:00 +05:30
return ! isEmpty ( this . canaryIngress ) ;
2021-03-08 18:12:59 +05:30
} ,
instanceCount ( ) {
const { instances } = this . deployBoardData ;
return Array . isArray ( instances ) ? instances . length : 0 ;
} ,
instanceIsCompletedCount ( ) {
const completionPercentage = this . deployBoardData . completion / 100 ;
const completionCount = Math . floor ( completionPercentage * this . instanceCount ) ;
return Number . isNaN ( completionCount ) ? 0 : completionCount ;
} ,
instanceIsCompletedText ( ) {
const title = n _ _ ( 'instance completed' , 'instances completed' , this . instanceIsCompletedCount ) ;
return ` ${ this . instanceIsCompletedCount } ${ title } ` ;
} ,
instanceTitle ( ) {
return n _ _ ( 'Instance' , 'Instances' , this . instanceCount ) ;
} ,
deployBoardSvg ( ) {
return deployBoardSvg ;
} ,
2022-04-04 11:22:00 +05:30
rollbackUrl ( ) {
if ( this . graphql ) {
return this . deployBoardData . rollbackUrl ;
}
return this . deployBoardData . rollback _url ;
} ,
abortUrl ( ) {
if ( this . graphql ) {
return this . deployBoardData . abortUrl ;
}
return this . deployBoardData . abort _url ;
} ,
2021-03-08 18:12:59 +05:30
deployBoardActions ( ) {
2022-04-04 11:22:00 +05:30
return this . rollbackUrl || this . abortUrl ;
2021-03-08 18:12:59 +05:30
} ,
statuses ( ) {
// Canary is not a pod status but it needs to be in the legend.
// Hence adding it here.
return {
... STATUS _MAP ,
CANARY _STATUS ,
} ;
} ,
} ,
methods : {
changeCanaryWeight ( weight ) {
this . $emit ( 'changeCanaryWeight' , weight ) ;
} ,
2022-04-04 11:22:00 +05:30
podName ( instance ) {
if ( this . graphql ) {
return instance . podName ;
}
return instance . pod _name ;
} ,
2021-03-08 18:12:59 +05:30
} ,
2022-04-04 11:22:00 +05:30
emptyStateText : s _ _ (
'DeployBoards|To see deployment progress for your environments, make sure you are deploying to %{codeStart}$KUBE_NAMESPACE%{codeEnd} and annotating with %{codeStart}app.gitlab.com/app=$CI_PROJECT_PATH_SLUG%{codeEnd} and %{codeStart}app.gitlab.com/env=$CI_ENVIRONMENT_SLUG%{codeEnd}.' ,
) ,
2021-03-08 18:12:59 +05:30
} ;
< / script >
< template >
< div class = "js-deploy-board deploy-board" >
2021-09-30 23:02:18 +05:30
< gl-loading-icon v-if = "isLoading" size="sm" class="loading-icon" / >
2021-03-08 18:12:59 +05:30
< template v-else >
< div v-if = "canRenderDeployBoard" class="deploy-board-information gl-p-5" >
< div class = "deploy-board-information gl-w-full" >
< section class = "deploy-board-status" >
< span v -gl -tooltip :title = "instanceIsCompletedText" >
< span ref = "percentage" class = "gl-text-center text-plain gl-font-lg"
> { { deployBoardData . completion } } % < / s p a n
>
< span class = "text text-center text-secondary" > { { _ _ ( 'Complete' ) } } < / span >
< / span >
< / section >
< section class = "deploy-board-instances" >
< div class = "gl-font-base text-secondary" >
< span class = "deploy-board-instances-text"
> { { instanceTitle } } ( { { instanceCount } } ) < / s p a n
>
< span ref = "legend-icon" data -testid = " legend -tooltip -target " >
< gl-icon class = "gl-text-blue-500 gl-ml-2" name = "question" / >
< / span >
< gl-tooltip : target = "() => $refs['legend-icon']" boundary = "#content-body" >
< div class = "deploy-board-legend gl-display-flex gl-flex-direction-column" >
< div
v - for = "status in statuses"
: key = "status.text"
class = "gl-display-flex gl-align-items-center"
>
< instance-component :status = "status.class" :stable = "status.stable" / >
< span class = "legend-text gl-ml-3" > { { status . text } } < / span >
< / div >
< / div >
< / gl-tooltip >
< / div >
< div class = "deploy-board-instances-container d-flex flex-wrap flex-row" >
< template v-for = "(instance, i) in deployBoardData.instances" >
< instance-component
: key = "i"
: status = "instance.status"
: tooltip - text = "instance.tooltip"
2022-04-04 11:22:00 +05:30
: pod - name = "podName(instance)"
2021-03-08 18:12:59 +05:30
: logs - path = "logsPath"
: stable = "instance.stable"
/ >
< / template >
< / div >
< / section >
< canary-ingress
v - if = "canRenderCanaryWeight"
class = "deploy-board-canary-ingress"
2022-04-04 11:22:00 +05:30
: canary - ingress = "canaryIngress"
: graphql = "graphql"
2021-03-08 18:12:59 +05:30
@ change = "changeCanaryWeight"
/ >
< section v-if = "deployBoardActions" class="deploy-board-actions" >
< gl-link
2022-04-04 11:22:00 +05:30
v - if = "rollbackUrl"
: href = "rollbackUrl"
2021-03-08 18:12:59 +05:30
class = "btn"
data - method = "post"
rel = "nofollow"
> { { _ _ ( 'Rollback' ) } } < / g l - l i n k
>
< gl-link
2022-04-04 11:22:00 +05:30
v - if = "abortUrl"
: href = "abortUrl"
2021-03-08 18:12:59 +05:30
class = "btn btn-danger btn-inverted"
data - method = "post"
rel = "nofollow"
> { { _ _ ( 'Abort' ) } } < / g l - l i n k
>
< / section >
< / div >
< / div >
< div v-if = "canRenderEmptyState" class="deploy-board-empty" >
< section v -safe -html = " deployBoardSvg " class = "deploy-board-empty-state-svg" > < / section >
< section class = "deploy-board-empty-state-text" >
< span class = "deploy-board-empty-state-title d-flex" > { {
_ _ ( 'Kubernetes deployment not found' )
} } < / span >
< span >
2022-04-04 11:22:00 +05:30
< gl-sprintf :message = "$options.emptyStateText" >
< template # code = "{ content }" >
< code > { { content } } < / code >
< / template >
< / gl-sprintf >
2021-03-08 18:12:59 +05:30
< / span >
< / section >
< / div >
< / template >
< / div >
< / template >