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  }