Skip to content

Custom Card "Media"

These are some custom-card for your plex, radarr and sonarr media libraries.

example-image-radarr example-image-sonarr
example-image-plex

Credits

  • Author: imswel - 2023
  • Version: 1.0.0

Changelog

1.0.0 Initial release

Requirements

This card needs the following to function correctly:

Component Required
Plex Recently Added Yes for Media Library Card
Radarr Upcoming Media Yes for Media Upcoming Card
Sonarr Upcoming Media Yes for Media Upcoming Card

Usage

Media Library Card for Plex Recently Added :

example-image-plex

Variable Default Required Notes
ulm_custom_card_imswel_medias_index 1 Yes The index of the item in your Plex library to show.
- type: custom:button-card
  template: "custom_card_imswel_medias_library"
  entity: sensor.plex_recently_added
  variables:
    ulm_custom_card_imswel_medias_index: 1


Media Upcoming Card for Radarr Upcoming Media & Sonarr Upcoming Media :

example-image-radarr example-image-sonarr

Variable Default Required Notes
ulm_custom_card_imswel_medias_index 1 Yes The index of the item in your Radarr/Sonarr library to show.
ulm_custom_card_imswel_medias_platform radarr Yes The platform to choose depending on the selected entity.
Can be: radarr or sonarr.
- type: custom:button-card
  template: "custom_card_imswel_medias_upcoming"
  entity: sensor.sonarr_upcoming_media
  variables:
    ulm_custom_card_imswel_medias_index: 1
    ulm_custom_card_imswel_medias_platform: "sonarr"

Template code

Template Code
custom_card_imswel_medias.yaml
---
custom_card_imswel_medias:
  show_icon: false
  show_label: true
  show_name: true
  show_state: false
  styles:
    label:
      - z-index: 2
      - color: "white"
      - font-weight: "bold"
      - font-size: "12px"
      - filter: "opacity(60%)"
    name:
      - z-index: 2
      - color: "white"
      - font-weight: "bold"
      - font-size: "14px"
    card:
      - z-index: 0
      - border-radius: "var(--border-radius)"
      - box-shadow: "var(--box-shadow)"
      - background-size: "cover"
      - background-position: "center center"
      - text-shadow: >
          [[[
            return entity == "undefined" ? "none" : "1px 1px 5px rgba(18, 22, 23, 0.9)";
          ]]]

custom_card_imswel_medias_library:
  template:
    - "custom_card_imswel_medias"
    - "ulm_translation_engine"
    - "custom_card_imswel_medias_language_variables"
  variables:
    ulm_custom_card_imswel_medias_index: 1
  triggers_update: "[[[ return entity.entity_id; ]]]"
  aspect_ratio: "5/2"
  label: >
    [[[
      if (entity.state == "unavailable" || entity.state == "undefined"){
        return variables.ulm_translation_unavailable;
      } else{
        var data = entity.attributes.data;
        if (data[variables.ulm_custom_card_imswel_medias_index].number == undefined){
          var number = '(' + data[variables.ulm_custom_card_imswel_medias_index].aired.split('-')[0] + ')';
        } else{
          var number = data[variables.ulm_custom_card_imswel_medias_index].number;
        }
        return `${data[variables.ulm_custom_card_imswel_medias_index].title} ${number}`;
      }
    ]]]
  name: "[[[ return variables.ulm_custom_card_imswel_recentlyadded ]]]"
  styles:
    label:
      - align-self: "start"
      - justify-self: "start"
      - margin-left: "12px"
    name:
      - align-self: "end"
      - justify-self: "start"
      - margin-left: "12px"
    grid:
      - grid-template-areas: "'icon .' 'n n' 'l l' '. .'"
      - grid-template-rows: "auto repeat(2, min-content) 12px"
    card:
      - padding: "0px"
      - background-image: >
          [[[
            return entity === undefined || `url(${states[entity.entity_id].attributes.data[variables.ulm_custom_card_imswel_medias_index].fanart})`;
          ]]]
      - border: "none"
    custom_fields:
      icon:
        - z-index: 2
        - align-self: "start"
        - justify-self: "start"
        - height: "24px"
        - width: "24px"
        - margin-left: "12px"
        - margin-top: "12px"
      blur:
        - z-index: 1
        - position: "absolute"
        - top: 0
        - left: 0
        - height: "100%"
        - width: "100%"
        - border-radius: "var(--border-radius)"
        - background: "linear-gradient(rgba(0,0,0,0) 40%, rgba(0,0,0,0.8) 100%)"
  custom_fields:
    icon: >
      <svg viewBox="0 0 50 50">
        <path d="M7.7.3h34.6c4.1 0 7.4 3.3 7.4 7.4v34.6c0 4.1-3.3 7.4-7.4 7.4H7.7c-4.1 0-7.4-3.3-7.4-7.4V7.7C.3 3.6 3.6.3 7.7.3z" fill="#282a2d"/>
        <path d="M25,7.1H14.6L25,25L14.6,42.9H25L35.4,25L25,7.1z" fill="#e5a00d"/>
      </svg>
    blur: >
      [[[ return entity === undefined ? null : "<div id='blur'></div>"; ]]]

custom_card_imswel_medias_upcoming:
  template:
    - "custom_card_imswel_medias"
    - "ulm_translation_engine"
    - "custom_card_imswel_medias_language_variables"
  variables:
    ulm_custom_card_imswel_medias_index: 1
    ulm_custom_card_imswel_medias_platform: >
      [[[
        if (entity.entity_id.includes("sonarr")){
          return "sonarr";
        } else if(entity.entity_id.includes("plex")){
          return "plex";
        } else{
          return "radarr";
        }
      ]]]
  triggers_update: "all"
  aspect_ratio: "3/4"
  label: >
    [[[
      var data = entity.attributes?.data;
      var platform = variables.ulm_custom_card_imswel_medias_platform;
      var airdate = new Date(data[variables.ulm_custom_card_imswel_medias_index].airdate);

      Date.prototype.addDays = function (days) {
        const date = new Date(this.valueOf());
        date.setDate(date.getDate() + days);
        return date;
      }

      function formatRelease(release){
        if(release.includes("Available")){
          return ""
        } else if (release.includes("In Theaters")){
          return variables.ulm_custom_card_imswel_in_theaters;
        }
      }

      function formatDate(date){
        var weekday = variables.ulm_custom_card_imswel_weekday;
        var now = new Date();
        var tomorrow = now.addDays(1);

        var time = date - now;
        var secs = parseInt((time / 1000), 10);
        var days = Math.floor(secs / (3600*24));

        if (days < 6){
          if (weekday[date.getDay()] == weekday[now.getDay()]){
            return variables.ulm_custom_card_imswel_today;
          } else if (weekday[date.getDay()] == weekday[tomorrow.getDay()]){
            return variables.ulm_custom_card_imswel_tommorow;
          } else{
            return weekday[date.getDay()];
          }
        } else{
          return date.toLocaleDateString(variables.ulm_custom_card_imswel_locale);
        }
      }

      if(platform == "radarr"){
        var release = data[variables.ulm_custom_card_imswel_medias_index].release;
        return formatDate(airdate) + " " + formatRelease(release);
      } else if(platform == "sonarr"){
        return formatDate(airdate);
      }
    ]]]
  name: >
    [[[
      if (entity.state == "unavailable" || entity.state == "undefined"){
        return variables.ulm_translation_unavailable;
      } else{
        var data = entity.attributes?.data;
        var platform = variables.ulm_custom_card_imswel_medias_platform;

        if(platform == "radarr"){
          return `${data[variables.ulm_custom_card_imswel_medias_index].title}`;
        } else if(platform =="sonarr"){
          var number = data[variables.ulm_custom_card_imswel_medias_index].number;
          return `${data[variables.ulm_custom_card_imswel_medias_index].title} - ${number}`;
        }
      }
    ]]]
  styles:
    icon:
    label:
      - align-self: "start"
      - justify-self: "center"
    name:
      - align-self: "end"
      - justify-self: "center"
    state:
    img_cell:
    grid:
      - grid-template-areas: "'. . .' '. n .' '. l .' '. . .'"
      - grid-template-columns: "8px 1fr 8px"
      - grid-template-rows: "auto repeat(2, min-content) 8px"
    card:
      - background-image: >
          [[[
            return entity === undefined || `url(${states[entity.entity_id].attributes.data[variables.ulm_custom_card_imswel_medias_index].poster})`;
          ]]]
      - border: "none"
    custom_fields:
      overlay:
        - z-index: 1
        - position: "absolute"
        - top: 0
        - left: 0
        - height: "100%"
        - width: "100%"
        - border-radius: "var(--border-radius)"
        - background: "linear-gradient(rgba(0,0,0,0) 50%, rgba(0,0,0,0.8) 100%)"
  extra_styles: >
    .ellipsis:not(#overlay){
      white-space: normal !important;
      word-wrap: break-all;
      max-height: 2.4em;
      line-height: 1.2em;
    }
  custom_fields:
    overlay: >
      [[[ return entity === undefined ? null : "<div id='overlay'></div>"; ]]]