github.com/in4it/ecs-deploy@v0.0.42-0.20240508120354-ed77ff16df25/webapp/src/app/service-detail/service-detail.component.html (about) 1 <div class="service-detail-container"> 2 <div class="offset-md-2 col-md-8"> 3 <h1>{{service.serviceName}}</h1> 4 <ul class="nav nav-tabs"> 5 <li class="nav-item"> 6 <a class="nav-link" [class.active]="tab == 'service'" [routerLink]="" (click)="onClickService()">Service</a> 7 </li> 8 <li class="nav-item"> 9 <a class="nav-link" [class.active]="tab == 'versions'" [routerLink]="" (click)="onClickVersions()">Versions</a> 10 </li> 11 <li class="nav-item"> 12 <a class="nav-link" [class.active]="tab == 'events'" [routerLink]="" (click)="onClickEvents()">Event Logs</a> 13 </li> 14 <li class="nav-item"> 15 <a class="nav-link" [class.active]="tab == 'logs'" [routerLink]="" (click)="onClickLogs(true)">App Logs</a> 16 </li> 17 <li class="nav-item"> 18 <a class="nav-link" [class.active]="tab == 'parameters'" [routerLink]="" (click)="onClickParameters()">Parameters</a> 19 </li> 20 <li class="nav-item"> 21 <a class="nav-link" [class.active]="tab == 'scaling'" [routerLink]="" (click)="onClickScaling()">Scaling</a> 22 </li> 23 <li class="nav-item"> 24 <a class="nav-link" [class.active]="tab == 'runTask'" [routerLink]="" (click)="onClickRunTask()">Run Task</a> 25 </li> 26 </ul> 27 </div> 28 <div class="offset-md-2 col-md-8" *ngIf="tab == 'service'"> 29 <i *ngIf="loading" class="fa fa-refresh fa-spin fa-3x fa-fw"></i> 30 <span *ngIf="loading" class="sr-only">Loading...</span> 31 <div *ngIf="!loading"> 32 <div class="row"> 33 <div class="col-md-4 cluster-info"> 34 <ul class="list-group list-group-horizontal"> 35 <li class="list-group-item list-group-item-success" *ngIf="service.status == 'ACTIVE'">Service Status: {{service.status}}</li> 36 <li class="list-group-item list-group-item-warning" *ngIf="service.status != 'ACTIVE'">Service Status: {{service.status}}</li> 37 </ul> 38 </div> 39 <div class="col-md-8 cluster-info right-buttons"> 40 <ul class="list-inline"> 41 <li class="list-inline-item"><button [disabled]="loading" class="btn btn-primary" (click)="refresh()"><i class="fa fa-refresh" aria-hidden="true"></i> Refresh</button></li> 42 </ul> 43 </div> 44 </div> 45 <div *ngIf="service['deploymentMap']['ACTIVE']"> 46 <div class="alert alert-primary" role="alert" > 47 Deployment in progress... 48 </div> 49 <table class="table center-table"> 50 <thead class="thead-default"> 51 <tr> 52 <th class="w-40">Deployed at</th> 53 <th class="w-20">Services</th> 54 <th class="w-15"></th> 55 <th class="w-25"></th> 56 </tr> 57 </thead> 58 <tbody> 59 <tr> 60 <td>{{service["deploymentMap"]["ACTIVE"]["lastDeploy"]}}</td> 61 <td> 62 <strong>{{service["deploymentMap"]["ACTIVE"]["desiredCount"]}} / {{service["deploymentMap"]["ACTIVE"]["runningCount"]}}</strong> running 63 <span *ngIf="service['deploymentMap']['ACTIVE']['pendingCount'] > 0"> ({{service['deploymentMap']['ACTIVE']['pendingCount']}} pending)</span> 64 </td> 65 </tr> 66 </table> 67 <p class="deploy-arrow text-center"><i class="fa fa-arrow-down fa-3x" aria-hidden="true"></i></p> 68 </div> 69 <table class="table center-table"> 70 <thead class="thead-default"> 71 <tr> 72 <th>Deployed at</th> 73 <th>Services</th> 74 <th>Tasks</th> 75 <th>Containers</th> 76 </tr> 77 </thead> 78 <tbody> 79 <tr> 80 <td>{{service["deploymentMap"]["PRIMARY"]["lastDeploy"]}}</td> 81 <td> 82 <strong>{{service["deploymentMap"]["PRIMARY"]["desiredCount"]}} / {{service["deploymentMap"]["PRIMARY"]["runningCount"]}}</strong> running 83 <span *ngIf="service['deploymentMap']['PRIMARY']['pendingCount'] > 0"> ({{service['deploymentMap']['PRIMARY']['pendingCount']}} pending)</span> 84 </td> 85 <td> 86 <strong>{{service["taskStatus"]["RUNNING"] || 0 }} / {{service["taskTotal"]}}</strong> running 87 <span *ngIf="service['taskStatus']['STOPPED'] > 0"> ({{service['taskStatus']['STOPPED']}} stopped)</span> 88 <span *ngIf="service['taskStatus']['PENDING'] > 0"> ({{service['taskStatus']['PENDING']}} stopped)</span> 89 </td> 90 <td> 91 <strong>{{service["containerStatus"]["RUNNING"] || 0 }} / {{service["containerTotal"]}}</strong> running 92 <span *ngIf="service['containerStatus']['STOPPED'] > 0"> ({{service['containerStatus']['STOPPED']}} stopped)</span> 93 <span *ngIf="service['containerStatus']['PENDING'] > 0"> ({{service['containerStatus']['PENDING']}} stopped)</span> 94 </td> 95 </tr> 96 </table> 97 </div> 98 </div> 99 <div class="offset-md-2 col-md-8 cluster-info" *ngIf="tab == 'versions'"> 100 <i *ngIf="loading" class="fa fa-refresh fa-spin fa-3x fa-fw"></i> 101 <span *ngIf="loading" class="sr-only">Loading...</span> 102 <div class="right-buttons" *ngIf="!loading"> 103 <ul class="list-inline"> 104 <li class="list-inline-item"><a class="btn btn-primary" (click)="inspectChild.open(service.serviceName, selectedVersion)">Inspect</a></li> 105 <li class="list-inline-item"><a class="btn btn-primary" (click)="deployChild.open(service.serviceName, selectedVersion)">Deploy</a></li> 106 </ul> 107 </div> 108 <table class="table center-table" *ngIf="!loading"> 109 <thead class="thead-default"> 110 <tr> 111 <th> </th> 112 <th>image</th> 113 <th>tag</th> 114 <th>Last Deployed</th> 115 </tr> 116 </thead> 117 <tbody> 118 <tr *ngFor="let version of versions"> 119 <td class="text-center"><input type="radio" class="form-check-input" name="selectedVersion" [(ngModel)]="selectedVersion" [value]="version.lastDeploy" class="text-center" /></td> 120 <td>{{version.imageName}}</td> 121 <td>{{version.tag}}</td> 122 <td>{{version.lastDeployMoment}}</td> 123 </tr> 124 </table> 125 </div> 126 <div class="offset-md-2 col-md-8 cluster-info" *ngIf="tab == 'events'"> 127 <i *ngIf="loading" class="fa fa-refresh fa-spin fa-3x fa-fw"></i> 128 <span *ngIf="loading" class="sr-only">Loading...</span> 129 <div *ngIf="!loading"> 130 <div class="right-buttons"> 131 <ul class="list-inline"> 132 <li class="list-inline-item"><button [disabled]="loading" class="btn btn-primary" (click)="refresh()"><i class="fa fa-refresh" aria-hidden="true"></i> Refresh</button></li> 133 </ul> 134 </div> 135 <table class="table center-table"> 136 <thead class="thead-default"> 137 <tr> 138 <th class="w-25">Timestamp</th> 139 <th class="w-75">Message</th> 140 </tr> 141 </thead> 142 <tbody> 143 <tr *ngFor="let event of service.events"> 144 <td>{{event.createdAtFormatted}}</td> 145 <td>{{event.message}}</td> 146 </tr> 147 </table> 148 </div> 149 </div> 150 <div class="offset-md-2 col-md-8 cluster-info" *ngIf="tab == 'parameters'"> 151 <i *ngIf="loading" class="fa fa-refresh fa-spin fa-3x fa-fw"></i> 152 <span *ngIf="loading" class="sr-only">Loading...</span> 153 <div *ngIf="!loading"> 154 <div class="right-buttons"> 155 <ul class="list-inline"> 156 <li class="list-inline-item"><button [disabled]="loading" class="btn btn-primary" (click)="showNewParameter()"><i class="fa fa-file-text-o" aria-hidden="true"></i> New Parameter</button></li> 157 </ul> 158 </div> 159 <table class="table center-table"> 160 <thead class="thead-default"> 161 <tr> 162 <th class="w-25">Parameter Name</th> 163 <th class="w-75">Parameter Value</th> 164 </tr> 165 </thead> 166 <tbody> 167 <tr *ngIf="newParameter"> 168 <td class="align-middle"> 169 <input type="text" class="form-control" placeholder="Name..." name="parameterName" [(ngModel)]="newParameterInput.name" /> 170 </td> 171 <td class="align-middle"> 172 <div class="row align-middle"> 173 <div class="col-md-7 mx-auto h-100"> 174 <input type="text" class="form-control" placeholder="Value..." name="parameterValue" [(ngModel)]="newParameterInput.value" /> 175 </div> 176 <div class="col-md-2"> 177 <label class="checkbox-label"> 178 <input type="checkbox" [(ngModel)]="newParameterInput.encrypted" value="true" > Encrypt 179 </label> 180 </div> 181 <div class="col-md-2"> 182 <button [disabled]="saving" class="btn btn-primary" (click)="saveNewParameter()"><i class="fa fa-file-text-o" aria-hidden="true"></i> Save</button> 183 <i *ngIf="saving" class="fa fa-spinner" aria-hidden="true"></i> 184 </div> 185 </div> 186 </td> 187 </tr> 188 <tr *ngFor="let parameter of parameters.keys"> 189 <td class="align-middle">{{parameter}}</td> 190 <td class="align-middle" *ngIf="selectedParameter == parameter"> 191 <div class="row align-middle"> 192 <div class="col-9"> 193 <input type="text" class="form-control" *ngIf="parameters.map[parameter]['value'] != '***'" name="parameterValue" [(ngModel)]="parameterInput.value" /> 194 <input type="text" class="form-control" placeholder="new value..." *ngIf="parameters.map[parameter]['value'] == '***'" name="parameterValue" [(ngModel)]="parameterInput.value" /> 195 </div> 196 <div class="col-2"> 197 <button [disabled]="saving" class="btn btn-primary" (click)="saveParameter(parameter)"><i class="fa fa-file-text-o" aria-hidden="true"></i> Save</button> 198 <i *ngIf="saving" class="fa fa-spinner" aria-hidden="true"></i> 199 </div> 200 </div> 201 </td> 202 <td *ngIf="selectedParameter != parameter"> 203 {{parameters.map[parameter]["value"]}} <button class="btn" (click)="editParameter(parameter)"><i class="fa fa-pencil align-baseline" aria-hidden="true"></i></button> 204 <button class="btn float-right" (click)="confirmChild.open('deleteParameter', 'parameter', service.serviceName, parameter)"><i class="fa fa-trash" aria-hidden="true"></i></button> 205 </td> 206 </tr> 207 </table> 208 </div> 209 </div> 210 <div class="offset-md-2 col-md-8 cluster-info" *ngIf="tab == 'scaling'"> 211 <i *ngIf="loading" class="fa fa-refresh fa-spin fa-3x fa-fw"></i> 212 <span *ngIf="loading" class="sr-only">Loading...</span> 213 <div *ngIf="!loading"> 214 <div class="row"> 215 <div class="col-md-4"> 216 <h2>Manual Scaling</h2> 217 </div> 218 <div class="col-md-8 right-buttons"> 219 <ul class="list-inline"> 220 <li class="list-inline-item" *ngIf="scalingInput.autoscaling"><button [disabled]="loading" class="btn btn-primary" (click)="confirmChild.open('disableAutoscaling', 'autoscaling', service.serviceName, 'for '+service.serviceName)"><i class="fa fa-unlink" aria-hidden="true"></i> Disable Auto Scaling</button></li> 221 <li class="list-inline-item"><button [disabled]="loading" class="btn btn-primary" (click)="refresh()"><i class="fa fa-refresh" aria-hidden="true"></i> Refresh</button></li> 222 </ul> 223 </div> 224 </div> 225 <table class="table center-table"> 226 <thead class="thead-default"> 227 <tr> 228 <th class="w-25"><strong>Manual Scaling</strong></th> 229 <th class="w-25">Running Count</th> 230 <th class="w-25">Desired Count</th> 231 <th class="w-25"> </th> 232 </tr> 233 </thead> 234 <tbody> 235 <td>{{service["serviceName"]}}</td> 236 <td>{{service["runningCount"]}} ({{service["pendingCount"]}} pending)</td> 237 <td *ngIf="editManualScaling"> 238 <div class="row align-middle"> 239 <div class="col-6"> 240 <input type="text" class="form-control" name="desiredCount" [(ngModel)]="scalingInput.desiredCount" /> 241 </div> 242 <div class="col-2"> 243 <button [disabled]="saving" class="btn btn-primary" (click)="saveDesiredCount()"><i class="fa fa-file-text-o" aria-hidden="true"></i> Save</button> 244 <i *ngIf="saving" class="fa fa-spinner" aria-hidden="true"></i> 245 </div> 246 </div> 247 </td> 248 <td *ngIf="!editManualScaling"> 249 {{service["desiredCount"]}} <button class="btn" (click)="editDesiredCount()"><i class="fa fa-pencil align-baseline" aria-hidden="true"></i></button> 250 </td> 251 <tbody> 252 </table> 253 <h2>Auto Scaling</h2> 254 <div class="row" *ngIf="!scalingInput.autoscaling"> 255 <div class="col-6"> 256 <button [disabled]="saving" class="btn btn-primary" (click)="enableAutoscaling()"><i class="fa fa-balance-scale" aria-hidden="true"></i> Enable Auto Scaling</button> 257 </div> 258 </div> 259 <div *ngIf="scalingInput.autoscaling"> 260 <table class="table center-table"> 261 <tbody> 262 <tr> 263 <td class="w-25">Minimum number of tasks</td> 264 <td> 265 <div class="row"> 266 <div class="col-6"> 267 <input type="text" class="form-control" name="minimumCount" [(ngModel)]="scalingInput.minimumCount" /> 268 </div> 269 </div> 270 </td> 271 </tr> 272 <tr> 273 <td>Desired number of tasks</td> 274 <td> 275 <div class="row"> 276 <div class="col-6"> 277 <input type="text" class="form-control" name="desiredCount" [(ngModel)]="scalingInput.desiredCount" /> 278 </div> 279 </div> 280 </td> 281 </tr> 282 <tr> 283 <td>Maximum number of tasks</td> 284 <td> 285 <div class="row"> 286 <div class="col-6"> 287 <input type="text" class="form-control" name="maximumCount" [(ngModel)]="scalingInput.maximumCount" /> 288 </div> 289 </div> 290 </td> 291 </tr> 292 <td> </td> 293 <td> 294 <button [disabled]="saving" class="btn btn-primary" (click)="saveAutoscalingPolicy()"><i class="fa fa-file-text-o" aria-hidden="true"></i> Save</button> 295 </td> 296 <tr> 297 </tr> 298 </tbody> 299 </table> 300 <h2>Auto Scaling Policies</h2> 301 <table class="table center-table" *ngIf="scalingInput.policyCount > 0"> 302 <thead class="thead-default"> 303 <tr> 304 <th>Name</th> 305 <th>Policy</th> 306 <th>Action</th> 307 <th> </th> 308 </tr> 309 </thead> 310 <tbody> 311 <tr *ngFor="let policy of scalingInput.policies"> 312 <td>{{policy.policyName}}</td> 313 <td>{{policy.metric}} {{policy.comparisonOperator}} {{policy.threshold}}% for {{policy.evaluationPeriods}} times in {{policy.period/60}} minute(s) ({{policy.thresholdStatistic}})</td> 314 <td>{{policy.scalingAdjustment}}</td> 315 <td class="button"> 316 <button class="btn btn-middle" (click)="confirmChild.open('deleteAutoscalingPolicy', 'autoscaling policy', service.serviceName, policy.policyName)"><i class="fa fa-trash" aria-hidden="true"></i></button> 317 </td> 318 </tr> 319 </tbody> 320 </table> 321 <div *ngIf="!scalingInput.newAutoscalingPolicy"> 322 <div class="row"> 323 <div class="col-6"> 324 <button [disabled]="saving" class="btn btn-primary" (click)="newAutoscalingPolicy()"><i class="fa fa-balance-scale" aria-hidden="true"></i> New Scaling policy</button> 325 </div> 326 </div> 327 </div> 328 <div *ngIf="scalingInput.newAutoscalingPolicy"> 329 <h3>New Auto Scaling policy</h3> 330 <table class="table center-table"> 331 <tbody> 332 <tr> 333 <td class="w-25">Metric</td> 334 <td> 335 <div class="row"> 336 <div class="col-8"> 337 <select class="form-control" [(ngModel)]="scalingInputPolicy.metric"> 338 <option value="cpu">CPU in use (percentage)</option> 339 <option value="memory">Memory in use (percentage)</option> 340 </select> 341 </div> 342 </div> 343 </td> 344 </tr> 345 <tr> 346 <td>Threshold</td> 347 <td> 348 <div class="row"> 349 <div class="col-4"> 350 <select class="form-control" [(ngModel)]="scalingInputPolicy.thresholdStatistic"> 351 <option value="average">Average</option> 352 <option value="minimum">Minimum</option> 353 <option value="maximum">Maximum</option> 354 <option value="sum">Sum</option> 355 <option value="sampleCount">Data samples</option> 356 </select> 357 </div> 358 <div class="col-2"> 359 <select class="form-control" [(ngModel)]="scalingInputPolicy.comparisonOperator"> 360 <option value="greaterThanOrEqualToThreshold">>=</option> 361 <option value="lessThanOrEqualToThreshold"><=</option> 362 <option value="greaterThanThreshold">></option> 363 <option value="lessThanThreshold"><</option> 364 </select> 365 </div> 366 <div class="col-2"> 367 <input type="text" class="form-control" name="threshold" [(ngModel)]="scalingInputPolicy.threshold" /> 368 </div> 369 </div> 370 </td> 371 </tr> 372 <tr> 373 <td>Threshold period</td> 374 <td> 375 <div class="row"> 376 <div class="col-1"> 377 <span class="middle">for</span> 378 </div> 379 <div class="col-2"> 380 <input type="text" class="form-control" name="datapointsToAlarm" [(ngModel)]="scalingInputPolicy.datapointsToAlarm" /> 381 </div> 382 <div class="col-2"> 383 <span class="middle">periods of</span> 384 </div> 385 <div class="col-3"> 386 <select class="form-control" [(ngModel)]="scalingInputPolicy.period"> 387 <option value="60">1 minute</option> 388 <option value="300">5 minutes</option> 389 <option value="900">15 minutes</option> 390 <option value="1800">30 minutes</option> 391 <option value="3600">60 minutes</option> 392 </select> 393 </div> 394 </div> 395 </td> 396 </tr> 397 <tr> 398 <td>Scaling adjustment</td> 399 <td> 400 <div class="row"> 401 <div class="col-2"> 402 <select class="form-control" [(ngModel)]="scalingInputPolicy.scalingAdjustment"> 403 <option value="1">Up (+1)</option> 404 <option value="2">Up (+2)</option> 405 <option value="3">Up (+3)</option> 406 <option value="-1">Down (-1)</option> 407 <option value="-2">Down (-2)</option> 408 <option value="-3">Down (-3)</option> 409 </select> 410 </div> 411 </div> 412 </td> 413 </tr> 414 </tbody> 415 </table> 416 <div class="row"> 417 <div class="col-6"> 418 <button [disabled]="saving" class="btn btn-primary" (click)="addAutoscalingPolicy()"><i class="fa fa-balance-scale" aria-hidden="true"></i> Add policy</button> 419 </div> 420 </div> 421 </div> 422 </div> 423 </div> 424 </div> 425 <div class="offset-md-2 col-md-8 cluster-info" *ngIf="tab == 'runTask'"> 426 <i *ngIf="loading" class="fa fa-refresh fa-spin fa-3x fa-fw"></i> 427 <span *ngIf="loading" class="sr-only">Loading...</span> 428 <div *ngIf="!loading"> 429 <h3>General configuration</h3> 430 <table class="table center-table run-task"> 431 <thead class="thead-default"> 432 <tr> 433 <th class="w-25">Property</th> 434 <th class="w-75">Value</th> 435 </tr> 436 </thead> 437 <tbody> 438 <tr> 439 <td>Max. execution time (sec.)</td> 440 <td> 441 <div class="row"> 442 <div class="col-2"> 443 <input type="text" class="form-control" name="maxExecutionTime" [(ngModel)]="runTaskConfig.maxExecutionTime" /> 444 </div> 445 </div> 446 </td> 447 </tr> 448 </tbody> 449 </table> 450 <div *ngFor="let container of service['taskDefinition']['containerDefinitions']"> 451 <h3>{{container.name}}</h3> 452 <table class="table center-table run-task" *ngIf="runTaskInput[container.name].enabled"> 453 <thead class="thead-default"> 454 <tr> 455 <th class="w-25">Property</th> 456 <th class="w-75">Value</th> 457 </tr> 458 </thead> 459 <tbody> 460 <tr> 461 <td>Configuration</td> 462 <td> 463 <div class="row"> 464 <div class="col-6"> 465 <label class="checkbox-label"> 466 <input type="checkbox" [(ngModel)]="runTaskInput[container.name].enabled" value="true"/> Enabled 467 </label> 468 </div> 469 </div> 470 <div class="row"> 471 <div class="col-6"> 472 <label class="checkbox-label"> 473 <input type="checkbox" [(ngModel)]="runTaskInput[container.name].environmentVariables" value="true" checked="true"/> Load environment variables 474 </label> 475 </div> 476 </div> 477 </td> 478 </tr> 479 <tr> 480 <td>Command</td> 481 <td> 482 <div class="row"> 483 <div class="col-12"> 484 <input type="text" class="form-control" name="containerCommand" [(ngModel)]="runTaskInput[container.name].containerCommand" placeHolder="echo "this is a command"" /> 485 </div> 486 </div> 487 </td> 488 </tr> 489 <tbody> 490 </table> 491 <label class="checkbox-label" *ngIf="!runTaskInput[container.name].enabled"> 492 <input type="checkbox" [(ngModel)]="runTaskInput[container.name].enabled" value="true"/> Enable <br /> 493 </label> 494 </div> 495 <div class="bottom-buttons"> 496 <button [disabled]="saving" class="btn btn-primary" (click)="runTask()"><i class="fa fa-play" aria-hidden="true"></i> Run Task</button> 497 <i *ngIf="saving" class="fa fa-spinner" aria-hidden="true"></i> 498 </div> 499 </div> 500 </div> 501 <div class="offset-md-2 col-md-8 cluster-info" *ngIf="tab == 'logs'"> 502 <i *ngIf="loading" class="fa fa-refresh fa-spin fa-3x fa-fw"></i> 503 <span *ngIf="loading" class="sr-only">Loading...</span> 504 <div *ngIf="!loading"> 505 <div class="form-group row"> 506 <div class="col-md-8"> 507 <select class="form-control" [(ngModel)]="logsInput.selectedTaskArn" (ngModelChange)="updateLogs()" [compareWith]="compareByID"> 508 <option *ngFor="let t of logsInput['taskArns']" [ngValue]="t">{{t.name}}</option> 509 </select> 510 </div> 511 <div class="col-md-4"> 512 <select class="form-control" [(ngModel)]="logsInput.selectedContainer" (ngModelChange)="updateLogs()" [compareWith]="compareByID"> 513 <option *ngFor="let c of logsInput['containers']" [ngValue]="c">{{c.name}}</option> 514 </select> 515 </div> 516 </div> 517 <div class="form-group row"> 518 <div class="offset-md-8 col-md-4"> 519 <select class="form-control" [(ngModel)]="logsInput.selectedTimerange" (ngModelChange)="updateLogs()"> 520 <option *ngFor="let t of logsInput['timerange']" [ngValue]="t">{{t.name}}</option> 521 </select> 522 </div> 523 </div> 524 <div class="right-buttons"> 525 <ul class="list-inline"> 526 <li class="list-inline-item"><button [disabled]="loading" class="btn btn-primary" (click)="refreshLogs()"><i class="fa fa-refresh" aria-hidden="true"></i> Refresh</button></li> 527 </ul> 528 </div> 529 <i *ngIf="loadingLogs" class="fa fa-refresh fa-spin fa-3x fa-fw"></i> 530 <span *ngIf="loadingLogs" class="sr-only">Loading...</span> 531 <div class="table-responsive logs"> 532 <table class="table center-table" *ngIf="service['logs']"> 533 <thead class="thead-default"> 534 <tr> 535 <th class="w-30">Timestamp</th> 536 <th class="w-70">Message</th> 537 </tr> 538 </thead> 539 <tbody> 540 <tr *ngFor="let e of service.logs.logEvents"> 541 <td>{{e.timestamp}}</td> 542 <td>{{e.message}}</td> 543 </tr> 544 <tr *ngIf="service.logs.count == 0"> 545 <td> </td> 546 <td>No messages to show</td> 547 </tr> 548 </tbody> 549 </table> 550 </div> 551 <div class="right-buttons" *ngIf="service['logs'] && service.logs.count > 10"> 552 <ul class="list-inline"> 553 <li class="list-inline-item"><button [disabled]="loading" class="btn btn-primary" (click)="refreshLogs()"><i class="fa fa-refresh" aria-hidden="true"></i> Refresh</button></li> 554 </ul> 555 </div> 556 </div> 557 </div> 558 </div> 559 <app-service-detail-confirm (deletedItem)="deletedItem($event)" (deletingItem)="deletingItem($event)"></app-service-detail-confirm> 560 <app-service-detail-inspect></app-service-detail-inspect> 561 <app-service-detail-deploy (deployed)="deployed($event)" (deploying)="deploying($event)"></app-service-detail-deploy>