github.com/hernad/nomad@v1.6.112/ui/app/styles/components/job-status-panel.scss (about) 1 /** 2 * Copyright (c) HashiCorp, Inc. 3 * SPDX-License-Identifier: MPL-2.0 4 */ 5 @import '~@hashicorp/design-system-tokens/dist/products/css/helpers/colors.css'; 6 7 .job-status-panel { 8 // #region layout 9 &.steady-state.current-state .boxed-section-body { 10 display: grid; 11 grid-template-areas: 12 'title' 13 'allocation-status-row' 14 'legend-and-summary'; 15 gap: 1rem; 16 grid-auto-columns: 100%; 17 18 & > h3 { 19 grid-area: title; 20 margin: 0; 21 } 22 23 & > .allocation-status-row { 24 grid-area: allocation-status-row; 25 } 26 } 27 28 .boxed-section-head h2 .hds-badge { 29 margin-left: 5px; 30 margin-top: -2px; 31 } 32 33 &.active-deployment { 34 & > .boxed-section-head { 35 background: var(--token-color-surface-highlight); 36 37 h2 .hds-badge { 38 background-color: var(--token-color-border-highlight); 39 border-color: var(--token-color-border-highlight); 40 color: var(--token-color-foreground-highlight-high-contrast); 41 } 42 } 43 & > .boxed-section-head, 44 & > .boxed-section-body, 45 & > .boxed-section-foot { 46 border-color: var(--token-color-border-highlight); 47 } 48 } 49 50 &.active-deployment .boxed-section-body { 51 display: grid; 52 grid-template-areas: 53 'deployment-allocations' 54 'legend-and-summary' 55 'history-and-params'; 56 gap: 1rem; 57 grid-auto-columns: 100%; 58 59 &.requires-promotion { 60 grid-template-areas: 61 'promotion-alert' 62 'deployment-allocations' 63 'legend-and-summary' 64 'history-and-params'; 65 66 & > .canary-promotion-alert { 67 button { 68 background-color: $orange; 69 border-color: darken($orange, 5%); 70 &:hover { 71 background-color: darken($orange, 5%); 72 } 73 } 74 } 75 } 76 77 & > .promotion-alert { 78 grid-area: promotion-alert; 79 } 80 81 & > .deployment-allocations { 82 grid-area: deployment-allocations; 83 display: grid; 84 gap: 1rem; 85 grid-auto-columns: 100%; 86 87 & > h4 { 88 margin-bottom: -0.5rem; 89 display: grid; 90 grid-template-columns: auto 1fr; 91 gap: 0.5rem; 92 margin-top: 1rem; 93 94 & > .versions > ul { 95 grid-template-columns: unset; 96 grid-auto-columns: min-content; 97 grid-auto-flow: column; 98 } 99 } 100 } 101 102 & > .history-and-params { 103 grid-area: history-and-params; 104 } 105 } 106 107 .versions { 108 & > ul { 109 display: grid; 110 grid-template-columns: repeat(auto-fit, 65px); 111 gap: 0.5rem; 112 & > li { 113 white-space: nowrap; 114 &:has(.version-count) .version-label { 115 border-top-right-radius: 0; 116 border-bottom-right-radius: 0; 117 } 118 } 119 a { 120 text-decoration: none; 121 } 122 } 123 .version-label { 124 position: relative; 125 z-index: 2; 126 & > .hds-badge__text { 127 font-weight: 700; 128 } 129 } 130 .version-count { 131 color: $blue; 132 position: relative; 133 z-index: 1; 134 left: -1rem; 135 padding-left: 1rem; 136 } 137 } 138 139 .legend-and-summary { 140 // grid-area: legend-and-summary; 141 // TODO: may revisit this grid-area later, but is currently used in 2 competing ways 142 display: grid; 143 gap: 1rem; 144 grid-template-columns: 3fr 1fr 1fr; 145 &.has-latest-deployment { 146 grid-template-columns: 3fr 1fr 1fr 1fr; 147 } 148 149 & > section > h4, 150 & > legend > h4, 151 & > section > a > h4 { 152 margin-bottom: 0.5rem; 153 } 154 155 legend { 156 display: grid; 157 grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); 158 gap: 0.5rem; 159 grid-template-rows: min-content; 160 } 161 .latest-deployment { 162 h4 svg { 163 position: relative; 164 top: 3px; 165 } 166 } 167 168 .failed-or-lost > div { 169 display: grid; 170 gap: 3px; 171 & > span > button { 172 top: 3px; 173 } 174 } 175 } 176 177 // #endregion layout 178 179 .select-mode { 180 border: 1px solid $grey-blue; 181 background: rgba(0, 0, 0, 0.05); 182 border-radius: 2px; 183 display: grid; 184 gap: 0.5rem; 185 grid-template-columns: 1fr 1fr; 186 padding: 0.25rem 0.5rem; 187 margin-left: auto; 188 189 button { 190 height: auto; 191 padding: 0 0.5rem; 192 background: transparent; 193 transition: 0.1s; 194 195 &:hover { 196 background: rgba(255, 255, 255, 0.5); 197 } 198 199 &.is-active { 200 background: $white; 201 } 202 } 203 } 204 205 .running-allocs-title { 206 strong { 207 font-weight: 800; 208 } 209 } 210 211 .ungrouped-allocs { 212 display: grid; 213 gap: 10px; 214 grid-auto-flow: column; 215 grid-auto-columns: 32px; 216 217 & > .represented-allocation { 218 width: 32px; 219 } 220 } 221 222 .alloc-status-summaries { 223 display: flex; 224 height: 32px; 225 gap: 1.5rem; 226 227 .allocation-status-block { 228 display: grid; 229 grid-template-columns: auto 50px; 230 gap: 10px; 231 232 &.rest-only { 233 grid-template-columns: auto; 234 } 235 236 & > .ungrouped-allocs { 237 display: grid; 238 grid-auto-flow: column; 239 gap: 10px; 240 grid-auto-columns: unset; 241 & > .represented-allocation { 242 width: 32px; 243 } 244 } 245 246 .represented-allocation.rest { 247 // TODO: we eventually want to establish a minimum width here. However, we need to also include this in the allocation-status-block width computation. 248 font-size: 0.8rem; 249 font-weight: bold; 250 width: 100%; 251 252 & > .rest-count { 253 position: relative; 254 z-index: 2; 255 } 256 257 &.unplaced { 258 color: black; 259 } 260 } 261 } 262 } 263 264 .represented-allocation { 265 background: $green; 266 border-radius: 4px; 267 height: 32px; 268 width: 32px; 269 color: white; 270 position: relative; 271 display: grid; 272 align-content: center; 273 justify-content: center; 274 275 $queued: $grey; 276 $pending: $grey-lighter; 277 $running: $primary; 278 $complete: $nomad-green-pale; 279 $failed: $danger; 280 $lost: $dark; 281 282 // Client Statuses 283 &.running { 284 background: $running; 285 } 286 &.failed { 287 background: $failed; 288 } 289 &.unknown { 290 background: $unknown; 291 } 292 &.queued { 293 background: $queued; 294 } 295 &.complete { 296 background: $complete; 297 color: black; 298 } 299 &.pending { 300 background: $pending; 301 color: black; 302 position: relative; 303 overflow: hidden; 304 305 &:after { 306 content: ''; 307 position: absolute; 308 top: 0; 309 left: 0; 310 width: 100%; 311 height: 100%; 312 background: linear-gradient(-60deg, $pending, #eee, $pending); 313 animation: shimmer 2s ease-in-out infinite; 314 } 315 } 316 &.lost { 317 background: $lost; 318 } 319 320 &.unplaced { 321 background: $grey-lighter; 322 position: relative; 323 overflow: hidden; 324 325 &:before { 326 background: linear-gradient(-60deg, $pending, #eee, $pending); 327 animation: shimmer 2s ease-in-out infinite; 328 content: ''; 329 position: absolute; 330 top: 0; 331 left: 0; 332 width: 100%; 333 height: 100%; 334 } 335 &:after { 336 content: ''; 337 position: absolute; 338 top: 0; 339 left: 0; 340 width: calc(100% - 4px); 341 height: calc(100% - 4px); 342 margin: 2px; 343 background: white; 344 border-radius: 3px; 345 } 346 } 347 348 &.legend-example { 349 background: #eee; 350 } 351 352 // Health Statuses 353 354 .alloc-health-indicator { 355 width: 100%; 356 height: 100%; 357 position: absolute; 358 display: grid; 359 align-content: center; 360 justify-content: center; 361 } 362 363 &.running { 364 .alloc-health-indicator { 365 position: absolute; 366 width: 100%; 367 height: 100%; 368 display: grid; 369 align-content: center; 370 justify-content: center; 371 } 372 &.rest .alloc-health-indicator { 373 top: -7px; 374 right: -7px; 375 border-radius: 20px; 376 background: white; 377 box-shadow: 0px 0px 5px 0px rgba(0, 0, 0, 0.5); 378 width: 20px; 379 height: 20px; 380 box-sizing: border-box; 381 transform: scale(0.75); 382 } 383 } 384 385 // Canary Status 386 &.canary > .alloc-canary-indicator { 387 overflow: hidden; 388 width: 16px; 389 height: 16px; 390 position: absolute; 391 bottom: 0; 392 left: 0; 393 border-radius: 4px; 394 395 &:after { 396 content: ''; 397 position: absolute; 398 left: -8px; 399 bottom: -8px; 400 width: 16px; 401 height: 16px; 402 transform: rotate(45deg); 403 background-color: $orange; 404 } 405 } 406 } 407 408 .legend-item .represented-allocation .flight-icon { 409 animation: none; 410 } 411 412 .legend-item { 413 display: grid; 414 gap: 0.5rem; 415 grid-template-columns: auto 1fr; 416 white-space: nowrap; 417 flex: 1 0 auto; 418 419 &.faded .count { 420 opacity: 0.5; 421 } 422 423 .represented-allocation { 424 width: 20px; 425 height: 20px; 426 animation: none; 427 &:before, 428 &:after { 429 animation: none; 430 } 431 } 432 } 433 434 .history-and-params { 435 display: grid; 436 grid-template-columns: 70% auto; 437 gap: 1rem; 438 margin-top: 2rem; 439 & > .deployment-history, 440 & > .update-parameters { 441 display: grid; 442 grid-template-rows: 50px auto; 443 } 444 } 445 446 &.steady-state .history-and-params { 447 grid-template-columns: auto; 448 } 449 450 .deployment-history { 451 &.hidden > header { 452 margin-bottom: 0; 453 } 454 455 & > header { 456 display: grid; 457 grid-template-columns: 1fr 2fr; 458 gap: 1rem; 459 margin-bottom: 1rem; 460 align-items: end; 461 & > h4 { 462 margin-bottom: 0; 463 height: 100%; 464 & > button { 465 justify-content: left; 466 font-size: 1.25rem; 467 width: 100%; 468 color: $blue; 469 border: none; 470 box-shadow: none; 471 outline: none; 472 padding: 0; 473 font-weight: 600; 474 &:focus { 475 outline: none; 476 box-shadow: none; 477 } 478 479 &:hover, 480 &:focus { 481 text-decoration: underline; 482 } 483 & > svg { 484 padding-left: 0.5rem; 485 height: 2rem; 486 width: 2rem; 487 } 488 } 489 } 490 & > .search-box { 491 max-width: unset; 492 } 493 } 494 .timeline-container { 495 max-height: 300px; 496 overflow-y: auto; 497 & > ol > li { 498 @for $i from 1 through 50 { 499 &:nth-child(#{$i}) { 500 animation-name: historyItemSlide; 501 animation-duration: 0.2s; 502 animation-fill-mode: both; 503 animation-delay: 0.1s + (0.05 * $i); 504 } 505 506 &:nth-child(#{$i}) > div { 507 animation-name: historyItemShine; 508 animation-duration: 1s; 509 animation-fill-mode: both; 510 animation-delay: 0.1s + (0.05 * $i); 511 } 512 } 513 514 & > div { 515 gap: 0.5rem; 516 } 517 &.error > div { 518 border: 1px solid $danger; 519 background: lighten($danger, 45%); 520 } 521 } 522 } 523 } 524 525 .update-parameters { 526 & > code { 527 max-height: 300px; 528 overflow-y: auto; 529 display: block; 530 } 531 & > .title { 532 display: grid; 533 align-content: center; 534 } 535 ul, 536 span.notification { 537 display: block; 538 background: #1a2633; 539 padding: 1rem; 540 color: white; 541 .key { 542 color: #1caeff; 543 &:after { 544 content: '='; 545 color: white; 546 margin-left: 0.5rem; 547 } 548 } 549 .value { 550 color: #06d092; 551 } 552 } 553 } 554 } 555 556 @keyframes historyItemSlide { 557 from { 558 opacity: 0; 559 top: -40px; 560 } 561 to { 562 opacity: 1; 563 top: 0px; 564 } 565 } 566 567 @keyframes historyItemShine { 568 from { 569 box-shadow: inset 0 0 0 100px rgba(255, 200, 0, 0.2); 570 } 571 to { 572 box-shadow: inset 0 0 0 100px rgba(255, 200, 0, 0); 573 } 574 } 575 576 @keyframes shimmer { 577 0% { 578 transform: translate3d(-100%, 0, 0); 579 } 580 30% { 581 transform: translate3d(100%, 0, 0); 582 } 583 100% { 584 transform: translate3d(100%, 0, 0); 585 } 586 }