< template >
< card class = "card-user" style = "max-height:100%" >
< div class = "author"
v - show = "hybridshowlog==false"
>
< img class = "avatar border-white" src = "@/assets/img/hybrid-1.png" alt = "..." >
< / div >
< v -wait for = "myRunInstancetutor" >
< template slot = "waiting" >
< div >
< img src = "@/assets/loading.gif" / >
Enter Lab_room ...
< / div >
< / template >
< / v - w a i t >
< b -container fluid >
< div class = "row text-center"
v - show = "hybridshowlog==false"
>
< div class = "col-12" >
< b > Manage your deployments < / b >
< / div >
< / div >
< br >
< div class = "row"
v - show = "hybridshowlog"
>
< div class = "col-12" >
< log -view >
< / l o g - v i e w >
< / div >
< / div >
< div class = "row" >
< div class = "col-3 text-info" >
< div class = "input-group-prepend" >
< button
class = "btn btn-outline-info"
round
type = "button"
@ click = "onActionLog(1)"
v - if = "hybridshowdata.bootstrapstackname&&hybridshowlog==false"
>
Show logs
< / button >
< button
class = "btn btn-outline-warning"
round
type = "button"
@ click = "onActionLog(2)"
v - if = "hybridshowdata.bootstrapstackname&&hybridshowlog==true"
>
Close logs
< / button >
< / div >
< / div >
< div class = "col-3 text-info" >
< div class = "input-group-prepend" >
< button
class = "btn btn-outline-danger"
round
type = "button"
@ click = "onActionHybrid('stack-stop')"
v - if = "hybridshowdata.bootstrapstackname"
>
Remove Stack
< / button >
< / div >
< / div >
< div class = "col-3 text-info" >
< div class = "input-group-prepend" >
< button
class = "btn btn-outline-danger"
round
type = "button"
@ click = "onActionHybrid('service-stop')"
v - if = "hybridshowdata.bootstrapnameid && hybridshowdata.status"
>
Remove Service
< / button >
< / div >
< / div >
< div class = "col-3 text-info" >
< div class = "input-group-prepend" >
< button
class = "btn btn-outline-warning"
round
type = "button"
@ click = "onActionHybrid('service-restart')"
v - if = "hybridshowdata.bootstrapnameid && hybridshowdata.status"
>
Restart Service
< / button >
< / div >
< / div >
< / div > <!-- row -- >
< div class = "row"
v - if = "hybridshowdata.bootstrapstackname"
>
< div class = "col-2 text-info"
>
Instances
< / div >
< div class = "col-3 text-secondary" >
{ { hybridshowdata . Replicas } }
< / div >
< div class = "col-2 text-info" >
Image
< / div >
< div class = "col-4 text-secondary" >
{ { hybridshowdata . bootstrapimage } }
< / div >
< / div > <!-- row -- >
< div class = "row"
v - if = "hybridshowdata.bootstrapstackname"
>
< div class = "col-2 text-info" >
Names
< / div >
< div class = "col-3 text-secondary" >
{ { hybridshowdata . bootstrapname } }
< / div >
< div class = "col-2 text-info" >
EndAt
< / div >
< div class = "col-4 text-secondary" >
{ { hybridshowdata . bootstrapdateend } }
< / div >
< / div > <!-- row -- >
< div class = "row"
v - if = "hybridshowdata.bootstrapstackname"
>
< div class = "col-2 text-info" >
Networks
< / div >
< div class = "col-3 text-secondary" >
{ { hybridshowdata . bootstrapnetwork } }
< / div >
< div class = "col-2 text-info" >
BeginAt
< / div >
< div class = "col-4 text-secondary" >
{ { hybridshowdata . bootstrapdatebegin } }
< / div >
< / div > <!-- row -- >
< div class = "row"
v - if = "hybridshowdata.bootstrapstackname"
>
< div class = "col-2 text-info" >
Status
< / div >
< div class = "col-3 text-secondary"
v - if = "hybridshowdata.status"
>
< span class = "ti-check text-success" > < / span >
< / div >
< div class = "col-3 text-secondary"
v - else
>
< span > < / span >
< / div >
< div class = "col-2 text-info" >
Ports
< / div >
< div class = "col-4 text-secondary"
v - if = "hybridshowdata.ports!=0"
>
{ { hybridshowdata . ports } }
< / div >
< div class = "col-4 text-secondary"
v - else
>
< / div >
< / div > <!-- row -- >
< / b - c o n t a i n e r >
< b -container fluid class = "bv-example-row" >
< div class = "input-group input-group-sm sm-3" >
< input type = "text"
class = "form-control"
aria - label = "Small" aria - describedby = "inputGroup-sizing-sm"
placeholder = "Search By StackName"
v - model = "searchFor"
@ keyup . enter = "setFilter"
>
< div class = "input-group-append" >
< button
class = "btn btn-outline-primary"
round
type = "button"
@ click = "setFilter" >
Go < / button >
< / div >
< div class = "input-group-append" >
< button class = "btn btn-outline-secondary"
round
type = "button"
@ click = "resetFilter" >
Reset < / button >
< / div >
< / div >
< div class = "white h-100 flex-fixed-width-item"
< vuetable
ref = "vuetable"
: key = "vuetablekeyd"
: api - url = 'apiurl'
: api - mode = "true"
: http - options = "httpOptions"
: fields = "fields"
: item - actions = "itemActions"
: sort - order = "sortOrder"
: show - sort - icons = "true"
: multi - sort = "multiSort"
: per - page = "perpage"
pagination - path = "links.pagination"
: pagination - component = "paginationComponent"
: append - params = "moreParams"
wrapper - class = "vuetable-wrapper"
loading - class = "loading"
detail - row - id = "id"
@ vuetable : pagination - data = "onPaginationData"
@ vuetable : load - success = "loadsuccess"
@ vuetable : load - error = "onLoadError"
: css = "css.table"
>
< div slot = "actions" slot -scope = " props " >
< button
v - if = "actionrowindex == props.rowIndex"
class = "ti-more-alt btn btn-secondary btn-sm"
round
@ click = "onAction('run-more', props.rowData, props.rowIndex)" >
< / button >
< button
v - else
class = "ti-more btn btn-outline-secondary btn-sm"
round
@ click = "onAction('run-more', props.rowData, props.rowIndex)" >
< / button >
< / div >
< / vuetable >
< div class = "vuetable-pagination ui basic segment grid" >
< vuetable -pagination -info
ref = "paginationInfo"
: css = "css.paginationInfo"
>
< / v u e t a b l e - p a g i n a t i o n - i n f o >
< vuetable -pagination
: css = "css.pagination"
ref = "pagination"
@ vuetable - pagination : change - page = "onChangePage"
>
< / v u e t a b l e - p a g i n a t i o n >
< / div >
< / div >
< / b - c o n t a i n e r >
< / card >
< / template >
< script >
import store from '@/store/index'
import { mapState , mapGetters , mapActions , dispatch } from 'vuex'
import Vue from 'vue'
import { Vuetable , VuetablePaginationDropdown } from 'vuetable-2'
import VuetablePaginationInfo from 'vuetable-2/src/components/VuetablePaginationInfo'
import VuetablePagination from 'vuetable-2/src/components/VuetablePagination'
import CssConfig from 'vuetable-2/src/components/VuetableCssConfig.js'
import card from '@/components/Card.vue'
import LogView from "./LogView.vue" ;
import { ApiConfig } from "@/config/index" ;
export default {
components : {
card ,
Vuetable ,
VuetablePagination ,
VuetablePaginationInfo ,
VuetablePaginationDropdown ,
LogView
} ,
props : {
} ,
data ( ) {
return {
hybridshowlog : false ,
actionrowindex : '' ,
playbookInfo : { } ,
hybridshowdata : { } ,
token : '' ,
playbook : {
'title' : '' ,
'name' : '' ,
'description' : ''
} ,
container : {
name : '' ,
view : 0
} ,
pipeline : { } ,
selected : 'hybrid' ,
options : [
{ text : 'Packages' , value : 'packages' } ,
{ text : 'Images' , value : 'images' } ,
{ text : 'Scripts' , value : 'scripts' }
] ,
showModal : false ,
visibility : [ ] ,
active : false ,
vuetablekeyd : 0 ,
fielddata : { } ,
fields : [
{
name : 'bootstrapname' ,
title : '<span class="orange"></span>Name' ,
sortField : 'bootstrapname' ,
visible : true ,
dataClass : 'text-left text-wrap text-break break-word' ,
width : '15%'
} ,
{
name : 'bootstrapstackname' ,
title : '<span class="orange"></span>StackName' ,
sortField : 'bootstrapstackname' ,
visible : true ,
dataClass : 'left aligned w-25' ,
width : '15%'
} ,
{
name : '_id' ,
title : '<span class="orange"></span>mongo' ,
visible : false
} ,
{
name : 'bootstrapdatebegin5' ,
title : '<span class="orange"></span>Begin' ,
sortField : 'bootstrapdatebegin5' ,
titleClass : 'center aligned' ,
visible : true ,
width : '10%'
} ,
{
name : 'bootstrapusersjoin' ,
title : '<span class="orange"></span>Public' ,
sortField : 'bootstrapusersjoin' ,
titleClass : 'center aligned' ,
visible : true ,
width : '5%' ,
callback : function ( value ) {
if ( value == true ) {
var v = '<span class="ti-check text-success"> </span>'
return v
} else {
var v = '<span> </span>'
return v
}
}
} ,
{
name : 'ID' ,
sortField : 'ID' ,
titleClass : 'center aligned' ,
dataClass : 'left aligned w-25' ,
visible : false ,
width : '15%'
} ,
{
name : '__slot:actions' , // <----
title : 'Actions' ,
titleClass : 'center aligned' ,
dataClass : 'center aligned' ,
width : '5%'
}
] ,
apiurl : ApiConfig . swarmlab_url_80 + "/swarmlabhybridbootstrapservices" ,
//apiurl:ApiConfig.swarmlab_url_80+"/swarmlabhybridservices",
css : CssConfig ,
perpage : 5 ,
searchFor : '' ,
sortOrder : [ {
field : 'pipelinename' ,
direction : 'asc'
} ] ,
multiSort : true ,
paginationComponent : 'vuetable-pagination' ,
itemActions : [
{ name : 'view-item' , label : '' , icon : 'glyphicon glyphicon-zoom-in' , class : 'btn btn-info' , extra : { 'title' : 'View' , 'data-toggle' : "tooltip" , 'data-placement' : "left" } } ,
{ name : 'edit-item' , label : '' , icon : 'glyphicon glyphicon-pencil' , class : 'btn btn-warning' , extra : { title : 'Edit' , 'data-toggle' : "tooltip" , 'data-placement' : "top" } } ,
{ name : 'delete-item' , label : '' , icon : 'glyphicon glyphicon-remove' , class : 'btn btn-danger' , extra : { title : 'Delete' , 'data-toggle' : "tooltip" , 'data-placement' : "right" } }
] ,
moreParams : {
'filter' : '' ,
'type' : 'scripts' ,
'tutor' : 'yes'
} ,
}
} ,
mounted ( ) {
this . $root . $on ( 'hybrid_refresh_bootstrap_view' , ( ) => {
Vue . nextTick ( ( ) => this . $refs . vuetable . refresh ( ) )
} )
/ *
//refresh from socket mytable
this . $root . $on ( 'hybrid_refresh_table' , ( v ) => {
this . $nextTick ( function ( ) {
Vue . nextTick ( ( ) => this . $refs . vuetable . refresh ( ) )
this . viewhybridoptions = false
} )
} )
* /
} ,
created ( ) {
var url_string = window . location . href
var url = new URL ( url_string ) ;
this . token = url . searchParams . get ( "token" ) ;
//console.log("token "+ this.token);
} ,
beforeDestroy ( ) {
this . $root . $off ( 'hybrid_refresh_bootstrap_view' )
//this.$root.$off('hybrid_refresh_table')
} ,
computed : {
httpOptions ( ) {
var token = this . token
var p = "headers: {Authorization: token}}" ; //table props -> :http-options="httpOptions"
return { headers : { Authorization : 'Bearer ' + token } } //table props -> :http-options="httpOptions"
} ,
} ,
methods : {
async onActionLog ( action ) {
if ( action == 1 ) {
var log = await store . dispatch ( "pipelineLLO/hybrid_servicelog" , {
token : this . token ,
bootstrapnameid : this . hybridshowdata . bootstrapnameid
} )
//console.log('logs1 '+JSON.stringify(log))
var data = log . data . data . data
if ( log . data . data . errorexec_msg == 'ok' && log . data . data . data ) {
this . hybridshowlog = true
this . $root . $emit ( 'hybrid_server_log_in' , data )
//console.log('logsdata '+JSON.stringify(log.data.data.data))
} else {
var info = 'No logs are available'
this . $swal ( {
type : 'Info' ,
title : 'LOG' ,
icon : 'info' ,
html : info ,
showCloseButton : true ,
showLoaderOnConfirm : false ,
allowOutsideClick : false ,
cancelButtonText : 'No, cancel!' ,
showCancelButton : false ,
showLoaderOnConfirm : false ,
reverseButtons : true ,
focusCancel : true ,
confirmButtonText : 'Ok!'
} )
}
} else if ( action == 2 ) {
this . hybridshowlog = false
}
} ,
async onActionHybrid ( action ) {
if ( action == 'stack-stop' ) {
var info = '<h5>This will remove the stack with the name<b> ' + this . hybridshowdata . bootstrapstackname + '</b> <br><br> Services, networks, and secrets associated with the stack will be removed. </h5>'
this . $swal ( {
type : 'Info' ,
title : 'Info!' ,
icon : 'warning' ,
html : info ,
showCloseButton : true ,
showLoaderOnConfirm : false ,
allowOutsideClick : false ,
cancelButtonText : 'No, cancel!' ,
showCancelButton : true ,
showLoaderOnConfirm : false ,
reverseButtons : true ,
focusCancel : true ,
confirmButtonText : 'Ok!'
} ) . then ( ( result ) => {
//console.log(JSON.stringify(result))
this . onActionHybrid_stackrm ( result ) ;
} )
} else if ( action == 'service-stop' ) {
var log = await store . dispatch ( "pipelineLLO/hybrid_servicerm" , {
token : this . token ,
bootstrapstackid : this . hybridshowdata . bootstrapstackid ,
bootstrapnameid : this . hybridshowdata . bootstrapnameid
} )
Vue . nextTick ( ( ) => this . $refs . vuetable . refresh ( ) )
} else if ( action == 'service-restart' ) {
var log = await store . dispatch ( "pipelineLLO/hybrid_servicerestart" , {
token : this . token ,
bootstrapnameid : this . hybridshowdata . bootstrapnameid
} )
Vue . nextTick ( ( ) => this . $refs . vuetable . refresh ( ) )
var info = ''
if ( log . data . data . errorexec_msg == 'ok' ) {
info = '<h5>Update existing service: ok!</h5>'
} else {
info = '<h5>Update existing service: error!</h5>'
}
this . $swal ( {
type : 'Info' ,
title : 'INFO' ,
icon : 'info' ,
html : info ,
showCloseButton : true ,
showLoaderOnConfirm : false ,
allowOutsideClick : false ,
cancelButtonText : 'No, cancel!' ,
showCancelButton : false ,
showLoaderOnConfirm : false ,
reverseButtons : true ,
focusCancel : true ,
confirmButtonText : 'Ok!'
} )
//console.log('stackid '+this.hybridshowdata.bootstrapnameid)
}
} ,
async onActionHybrid_stackrm ( action ) {
if ( action . isConfirmed ) {
var log = await store . dispatch ( "pipelineLLO/stackrm" , {
token : this . token ,
bootstrapstackid : this . hybridshowdata . bootstrapstackid
} )
Vue . nextTick ( ( ) => this . $refs . vuetable . refresh ( ) )
}
} ,
onError ( type , description ) {
var winfo = description
var info = '<h5>Bootstrap ' + type + '</h5>'
this . $swal ( {
type : type ,
html : info + winfo ,
showCloseButton : true ,
showLoaderOnConfirm : false ,
allowOutsideClick : false ,
cancelButtonText : 'No, cancel!' ,
showCancelButton : false ,
showLoaderOnConfirm : false ,
reverseButtons : true ,
focusCancel : true ,
confirmButtonText : 'Ok!'
} )
} ,
setFilter ( ) {
this . moreParams = {
'filter' : this . searchFor ,
'type' : this . selected
}
Vue . nextTick ( ( ) => this . $refs . vuetable . refresh ( ) )
} ,
resetFilter ( ) {
this . moreParams = { }
this . searchFor = ''
Vue . nextTick ( ( ) => this . $refs . vuetable . refresh ( ) )
} ,
onPaginationData ( paginationData ) {
this . $refs . pagination . setPaginationData ( paginationData )
this . $refs . paginationInfo . setPaginationData ( paginationData )
} ,
onChangePage ( page ) {
this . $refs . vuetable . changePage ( page )
} ,
editRow ( rowData ) {
alert ( "You clicked edit on" + JSON . stringify ( rowData ) ) ;
} ,
async onAction ( action , data , index ) {
this . actionrowindex = index
//this.$root.$emit('hybrid_show_info',data)
//console.log('index '+this.actionrowindex)
if ( action == 'view-item' ) {
} else if ( action == 'run-more' ) {
this . hybridshowdata = data
//console.log('hybrid '+JSON.stringify(data))
} else if ( action == 'delete-item' ) {
this . $swal ( {
type : 'info' ,
html : info + winfo ,
showCloseButton : true ,
showLoaderOnConfirm : false ,
allowOutsideClick : false ,
cancelButtonText : 'No, cancel!' ,
showCancelButton : true ,
showLoaderOnConfirm : false ,
reverseButtons : true ,
focusCancel : true ,
confirmButtonText : 'Yes, Delete it!'
} )
} else if ( action == 'run-item' ) {
}
} ,
refreshVuetable ( ) {
this . $nextTick ( ( ) => {
this . vuetablekeyd += 1
} )
} ,
playbookinfoShow ( value ) {
return this . visibility [ value ] = true
} ,
playbookinfo ( value ) {
return this . playbookInfo = value
} ,
rowClicked ( row , event ) {
return {
html : true ,
title : ( ) => { return 'Hello <b>Popover:</b> ' + ( ++ this . counter ) } ,
content : ( ) => { return 'The date is:<br><em>' + new Date ( ) + '</em>' }
}
} ,
loadsuccess ( response ) {
var data = response . data . data
this . fielddata = data
var n = data . length
n = n - 1
} ,
onLoadError ( payload ) {
/ *
//error2 "invalid_token" join-service.vue:684
//error2 "The access token provided has expired" join-service.vue:685
//error2 "Unauthorized" join-service.vue:686
//error2 401
* /
if ( payload . response . status == '401' ) {
window . location . href = 'https://api-login.swarmlab.io:8089' ;
Vue . nextTick ( ( ) => window . location . href = 'https://api-login.swarmlab.io:8089' )
}
}
} ,
actions : {
}
} ;
< / script >
< style >
. flex - fixed - width - item {
flex : 0 0 100 px ;
}
. modalinfo {
z - index : 10000000 ! important ;
position : fixed ;
}
/* a container with flex-direction column */
. vue - notifyjs . notifications {
. alert {
z - index : 100 ;
}
. list - move {
transition : transform 0.3 s , opacity 0.4 s ;
}
. list - item {
display : inline - block ;
margin - right : 10 px ;
}
. list - enter - active {
transition : transform 0.2 s ease - in , opacity 0.4 s ease - in ;
}
. list - leave - active {
transition : transform 1 s ease - out , opacity 0.4 s ease - out ;
}
. list - enter {
opacity : 0 ;
transform : scale ( 1.1 ) ;
}
. list - leave - to {
opacity : 0 ;
transform : scale ( 1.2 , 0.7 ) ;
}
}
pre {
//background-color: rgb(255, 247, 229);
background - color : # eff0f1 ;
border : 1 px solid blue ;
//white-space: pre-line;
}
< / style >