UI-Lovelace-Minimalist / UI

UI-Lovelace-Minimalist is a "theme" for HomeAssistant
https://ui-lovelace-minimalist.github.io/UI/
Other
1.63k stars 430 forks source link

ButtonCardJSTemplateError after upgrading HA to 2023.11 #1396

Closed nilsi closed 11 months ago

nilsi commented 11 months ago

All my cards in my dashboard report this after updating HA last night. I'm not sure what is wrong. I then tried updating everything in HACS but the issue still exists. Any idea what's wrong here?

ButtonCardJSTemplateError: TypeError: can't access property "match", number is undefined in 'var number = hass.resources[hass['language']]["ui.duration.hour"];
  var matches = number.match(/[...'

  tap_action:
  action: toggle
type: custom:button-card
group_expand: false
hold_action:
  action: none
double_tap_action:
  action: none
layout: vertical
size: 40%
color_type: icon
show_name: false
show_state: false
show_icon: false
show_units: true
show_label: true
show_entity_picture: false
show_live_stream: false
card_size: 3
variables:
  ulm_currency: $
  ulm_updates_available: Updates available!
  ulm_no_updates_available: No updates available
  ulm_ophaling: Garbage collection!
  ulm_geen_ophaling: No collections
  ulm_volgende_ophaling: Next collections
  ulm_morning: Good morning
  ulm_afternoon: Good afternoon
  ulm_evening: Good evening
  ulm_hello: Hello
  ulm_volume: Volume
  ulm_popups_color: Color
  ulm_radar: Radar
  ulm_popup_total: Total
  ulm_translation_back: '[[[ return hass.resources[hass[''language'']][''ui.common.back'']; ]]]'
  ulm_translation_brightness: '[[[ return hass.resources[hass[''language'']][''ui.card.light.brightness'']; ]]]'
  ulm_translation_color_temperature: >-
    [[[ return
    hass.resources[hass['language']]['ui.card.light.color_temperature']; ]]]
  ulm_translation_status: >-
    [[[ return
    hass.resources[hass['language']]['ui.dialogs.more_info_control.vacuum.status'];
    ]]]
  ulm_translation_scenes: >-
    [[[ return
    hass.resources[hass['language']]['ui.dialogs.quick-bar.commands.reload.scene'];
    ]]]
  ulm_translation_source: >-
    [[[ return hass.resources[hass['language']]['ui.card.media_player.source'];
    ]]]
  ulm_translation_history: >-
    [[[ return
    hass.resources[hass['language']]['ui.dialogs.more_info_control.history'];
    ]]]
  ulm_translation_close_cover: >-
    [[[ return
    hass.resources[hass['language']]['ui.dialogs.more_info_control.cover.close_cover'];
    ]]]
  ulm_translation_stop_cover: >-
    [[[ return
    hass.resources[hass['language']]['ui.dialogs.more_info_control.cover.stop_cover'];
    ]]]
  ulm_translation_open_cover: >-
    [[[ return
    hass.resources[hass['language']]['ui.dialogs.more_info_control.cover.open_cover'];
    ]]]
  ulm_translation_more_options: >-
    [[[ return
    hass.resources[hass['language']]['ui.panel.lovelace.editor.edit_card.options'];
    ]]]
  ulm_active_state: |
    [[[
      if (typeof(entity) !== 'undefined' && entity !== undefined){
        let not_active = ['disarmed','off','closed','not_home','standby','idle','docked','unknown','unavailable','paused']
        function containsNumbers(str) {
          return /\d/.test(str);
        }
        return (!not_active.includes(entity.state) && !containsNumbers(entity.state))
      }
    ]]]
  ulm_translation_hour: |
    [[[
      var number = hass.resources[hass['language']]["ui.duration.hour"];
      var matches = number.match(/[^{\}]+(?=})/g);
      var hour = "Hour";
      if (matches) {
        var hour = matches[1];
      }
      return(hour);
    ]]]
  ulm_translation_hours: |
    [[[
      var number = hass.resources[hass['language']]["ui.duration.hour"];
      var matches = number.match(/[^{\}]+(?=})/g);
      var hour = "Hours";
      if (matches) {
        var hour = matches[2];
      }
      return(hour);
    ]]]
  ulm_translation_hvac: |
    [[[
      if (typeof(entity) !== 'undefined' && entity !== undefined){
        let state = entity.state;
        let d_class = entity.attributes.device_class;
        let def = ["unknown", "unavailable"];
        let lang = hass["language"];
        let action = entity.attributes.hvac_action;
        let domain = entity.entity_id.substr(0, entity.entity_id.indexOf("."));
        var mode = hass.resources[lang]["state_attributes." + domain + ".hvac_action." + action];
        if (def.includes(state)) {
          var mode = hass.resources[lang]["state.default." + state ];
        }
        var label = hass.resources[lang]["component." + domain + ".state._." + state];
        var translation = label ? label : state;
        return (entity.attributes.current_temperature ) + '°' + ' • ' + translation + ((entity.state !='off' && mode !== undefined) ? ' (' + mode + ')' : '');
        }
    ]]]
  ulm_translation_off: '[[[ return hass.resources[hass[''language'']][''state.default.off'']; ]]]'
  ulm_translation_on: '[[[ return hass.resources[hass[''language'']][''state.default.on'']; ]]]'
  ulm_translation_state: |
    [[[
      if (typeof(entity) !== 'undefined' && entity !== undefined){
        let state = entity.state;
        let d_class = entity.attributes.device_class;
        let def = ["unknown", "unavailable"];
        let lang = hass["language"];
        let domain = entity.entity_id.substr(0, entity.entity_id.indexOf("."));
        var translation = hass.resources[lang]["component." + domain + ".entity_component._.state." + state]
        let display_precision = hass.entities[entity.entity_id]?.display_precision
        const now = new Date();
        const timestamp = (new Date(state)).getTime();
        const nowTimeStamp = now.getTime();
        const microSecondsDiff = Math.round(timestamp - nowTimeStamp);
        const daysDiff = Math.round(microSecondsDiff / (1000 * 60 * 60  * 24));
        const hoursDiff = Math.round(microSecondsDiff / (1000 * 60 * 60));
        const minutesDiff = Math.round(microSecondsDiff / (1000 * 60));
        const secondsDiff = Math.round(microSecondsDiff / (1000));
        const formatter = new Intl.RelativeTimeFormat(lang, { numeric: 'auto' });
        var scale = 'day'
        var diff = daysDiff
        if (Math.abs(secondsDiff) < 60){ scale = 'second'; diff = secondsDiff }
        else if (Math.abs(minutesDiff) < 60){ scale = 'minute'; diff = minutesDiff }
        else if (Math.abs(hoursDiff) < 24){ scale = 'hour'; diff = hoursDiff }

        if (def.includes(state)) {
          var translation = hass.resources[lang]["state.default." + state ];
        }
        else if (domain == "binary_sensor" && d_class != ''){
          var translation = hass.resources[lang]["component." + domain + ".entity_component." + d_class + ".state." + state]
        }
        else if (d_class == 'timestamp'){
          var translation = formatter.format(diff, scale)
        }
        else if (parseFloat(display_precision) >=0){
          var translation = parseFloat(entity.state).toFixed(display_precision?.toString())
        }
        return translation ? translation.charAt(0).toUpperCase() + translation.slice(1) : state;
      }
    ]]]
  ulm_translation_state_reverse: |
    [[[
      if (typeof(entity) !== 'undefined' && entity !== undefined){
        let state = entity.state;
        let def = ["unknown", "unavailable"];
        let lang = hass["language"];
        if (state === "on"){
          var translation = hass.resources[lang]["state.default.off"];
        } else if (state === "off"){
          var translation = hass.resources[lang]["state.default.on"];
        }
        if (def.includes(state)) {
          var translation = hass.resources[lang]["state.default." + state ];
        }
        return translation ? translation : state;
      }
    ]]]
  ulm_translation_state_unit: |
    [[[
      if (typeof(entity) !== 'undefined' && entity !== undefined){
        let state = entity.state;
        let d_class = entity.attributes.device_class;
        let def = ["unknown", "unavailable"];
        let lang = hass["language"];
        let domain = entity.entity_id.substr(0, entity.entity_id.indexOf("."));
        let unit = entity.attributes.unit_of_measurement != null ? " " + entity.attributes.unit_of_measurement : "";
        let display_precision = hass.entities[entity.entity_id]?.display_precision
        const now = new Date();
        const timestamp = (new Date(state)).getTime();
        const nowTimeStamp = now.getTime();
        const microSecondsDiff = Math.round(timestamp - nowTimeStamp);
        const daysDiff = Math.round(microSecondsDiff / (1000 * 60 * 60  * 24));
        const hoursDiff = Math.round(microSecondsDiff / (1000 * 60 * 60));
        const minutesDiff = Math.round(microSecondsDiff / (1000 * 60));
        const secondsDiff = Math.round(microSecondsDiff / (1000));
        const formatter = new Intl.RelativeTimeFormat(lang, { numeric: 'auto' });

        var scale = 'day'
        var diff = daysDiff
        if (Math.abs(secondsDiff) < 60){ scale = 'second'; diff = secondsDiff }
        else if (Math.abs(minutesDiff) < 60){ scale = 'minute'; diff = minutesDiff }
        else if (Math.abs(hoursDiff) < 24){ scale = 'hour'; diff = hoursDiff }

        if(hass.resources[lang]["component." + domain + ".entity_component._.state." + state]){
        var translation = hass.resources[lang]["component." + domain + ".entity_component._.state." + state] + unit
        } else {
        var translation =  state + unit;
        }
        if (def.includes(state)) {
          var translation = hass.resources[lang]["state.default." + state ];
        }
        else if (domain == "binary_sensor" && d_class != ''){
          var translation = hass.resources[lang]["component." + domain + ".entity_component." + d_class + ".state." + state]
        }
        else if (domain == "media_player" && d_class != ''){
          if (state == 'idle' || state == 'paused')
            var translation = hass.resources[lang]["component." + domain + ".entity_component._.state." + state];
          else {
            var translation = (entity.attributes.source) + ' • ' +  ( Math.round(entity.attributes.volume_level / 0.01)) + '%' ;
          }
        }
        else if (d_class == 'timestamp'){
          var translation = formatter.format(diff, scale);
        }
        else if (parseFloat(display_precision) >=0){
          var translation = parseFloat(entity.state).toFixed(display_precision?.toString()) + unit
        }
        return translation ? translation.charAt(0).toUpperCase() + translation.slice(1) : state;
      }
    ]]]
  ulm_translation_statistics: >-
    [[[ return
    hass.resources[hass['language']]['ui.components.statistic-picker.statistic'];
    ]]]
  ulm_translation_unavailable: >-
    [[[ return hass.resources[hass['language']]['state.default.unavailable'];
    ]]]
  ulm_translation_currency: |
    [[[
      var hasscurrency = hass.config["currency"];
      var currency =
      { "AFA": "؋",
        "ALL": "Lek",
        "DZD": "دج",
        "AOA": "Kz",
        "ARS": "$",
        "AMD": "֏",
        "AWG": "ƒ",
        "AUD": "$",
        "AZN": "m",
        "BSD": "B$",
        "BHD": ".د.ب",
        "BDT": "৳",
        "BBD": "Bds$",
        "BYR": "Br",
        "BEF": "fr",
        "BZD": "$",
        "BMD": "$",
        "BTN": "Nu.",
        "BTC": "฿",
        "BOB": "Bs.",
        "BAM": "KM",
        "BWP": "P",
        "BRL": "R$",
        "GBP": "£",
        "BND": "B$",
        "BGN": "Лв.",
        "BIF": "FBu",
        "KHR": "KHR",
        "CAD": "$",
        "CVE": "$",
        "KYD": "$",
        "XOF": "CFA",
        "XAF": "FCFA",
        "XPF": "₣",
        "CLP": "$",
        "CNY": "¥",
        "COP": "$",
        "KMF": "CF",
        "CDF": "FC",
        "CRC": "₡",
        "HRK": "kn",
        "CUC": "$, CUC",
        "CZK": "Kč",
        "DKK": "Kr.",
        "DJF": "Fdj",
        "DOP": "$",
        "XCD": "$",
        "EGP": "ج.م",
        "ERN": "Nfk",
        "EEK": "kr",
        "ETB": "Nkf",
        "EUR": "€",
        "FKP": "£",
        "FJD": "FJ$",
        "GMD": "D",
        "GEL": "ლ",
        "DEM": "DM",
        "GHS": "GH₵",
        "GIP": "£",
        "GRD": "₯, Δρχ, Δρ",
        "GTQ": "Q",
        "GNF": "FG",
        "GYD": "$",
        "HTG": "G",
        "HNL": "L",
        "HKD": "$",
        "HUF": "Ft",
        "ISK": "kr",
        "INR": "₹",
        "IDR": "Rp",
        "IRR": "﷼",
        "IQD": "د.ع",
        "ILS": "₪",
        "ITL": "L,£",
        "JMD": "J$",
        "JPY": "¥",
        "JOD": "ا.د",
        "KZT": "лв",
        "KES": "KSh",
        "KWD": "ك.د",
        "KGS": "лв",
        "LAK": "₭",
        "LVL": "Ls",
        "LBP": "£",
        "LSL": "L",
        "LRD": "$",
        "LYD": "د.ل",
        "LTL": "Lt",
        "MOP": "$",
        "MKD": "ден",
        "MGA": "Ar",
        "MWK": "MK",
        "MYR": "RM",
        "MVR": "Rf",
        "MRO": "MRU",
        "MUR": "₨",
        "MXN": "$",
        "MDL": "L",
        "MNT": "₮",
        "MAD": "MAD",
        "MZM": "MT",
        "MMK": "K",
        "NAD": "$",
        "NPR": "₨",
        "ANG": "ƒ",
        "TWD": "$",
        "NZD": "$",
        "NIO": "C$",
        "NGN": "₦",
        "KPW": "₩",
        "NOK": "kr",
        "OMR": ".ع.ر",
        "PKR": "₨",
        "PAB": "B/.",
        "PGK": "K",
        "PYG": "₲",
        "PEN": "S/.",
        "PHP": "₱",
        "PLN": "zł",
        "QAR": "ق.ر",
        "RON": "lei",
        "RUB": "₽",
        "RWF": "FRw",
        "SVC": "₡",
        "WST": "SAT",
        "SAR": "﷼",
        "RSD": "din",
        "SCR": "SRe",
        "SLL": "Le",
        "SGD": "$",
        "SKK": "Sk",
        "SBD": "Si$",
        "SOS": "Sh.so.",
        "ZAR": "R",
        "KRW": "₩",
        "XDR": "SDR",
        "LKR": "Rs",
        "SHP": "£",
        "SDG": ".س.ج",
        "SRD": "$",
        "SZL": "E",
        "SEK": "kr",
        "CHF": "CHf",
        "SYP": "LS",
        "STD": "Db",
        "TJS": "SM",
        "TZS": "TSh",
        "THB": "฿",
        "TOP": "$",
        "TTD": "$",
        "TND": "ت.د",
        "TRY": "₺",
        "TMT": "T",
        "UGX": "USh",
        "UAH": "₴",
        "AED": "إ.د",
        "UYU": "$",
        "USD": "$",
        "UZS": "лв",
        "VUV": "VT",
        "VEF": "Bs",
        "VND": "₫",
        "YER": "﷼",
        "ZMK": "ZK"
      }
      return currency[hasscurrency];
    ]]]
  ulm_weather: weather.metno
  ulm_language: '[[[ return hass[''language'']; ]]]'
  entity_1:
    entity_id: script.netflix_movie_time
    color: blue
    icon: mdi:netflix
    name: Movie Time
  entity_2:
    entity_id: script.youtube_tv_time
    color: red
    icon: mdi:youtube
    name: YouTube TV
  entity_3:
    entity_id: scene.plants_on
    color: green
    icon: mdi:leaf-circle
    name: Plants On
  entity_4:
    entity_id: scene.plants_off
    color: gray
    icon: mdi:leaf-circle-outline
    name: Plants Off
  entity_5:
    entity_id: ''
    color: |
      [[[
        var colors = ['yellow', 'blue', 'red', 'purple','green', 'pink'];
        var color = colors[Math.floor(Math.random() * colors.length)];
        return color;
      ]]]
  entity_6:
    entity_id: ''
    color: |
      [[[
        var colors = ['yellow', 'blue', 'red', 'purple','green', 'pink'];
        var color = colors[Math.floor(Math.random() * colors.length)];
        return color;
      ]]]
  entity_7:
    entity_id: ''
    color: |
      [[[
        var colors = ['yellow', 'blue', 'red', 'purple','green', 'pink'];
        var color = colors[Math.floor(Math.random() * colors.length)];
        return color;
      ]]]
  ulm_card_welcome_scenes_collapse: input_boolean.minimalist_dropdown
template: card_welcome_scenes
styles:
  grid:
    - grid-template-areas: |
        [[[
          if(variables.ulm_card_welcome_scenes_collapse && states[variables.ulm_card_welcome_scenes_collapse].state == 'on'){
            return "\'item1\' \'item2\' ";
          } else {
            return "\'item1\' \'item2\' \'item3\' \'item4\'";
          }
        ]]]
    - grid-template-columns: 1fr
    - grid-template-rows: min-content min-content
    - row-gap: 0px
  card:
    - border-radius: var(--border-radius)
    - box-shadow: var(--box-shadow)
    - padding: 10px
  custom_fields:
    item3:
      - display: |
          [[[
            if(variables.ulm_card_welcome_scenes_collapse && states[variables.ulm_card_welcome_scenes_collapse].state == 'on'){
              return "none";
            } else {
              return "block";
            }
          ]]]
    item4:
      - display: |
          [[[
            if(variables.ulm_card_welcome_scenes_collapse && states[variables.ulm_card_welcome_scenes_collapse].state == 'on'){
              return "none";
            } else {
              return "block";
            }
          ]]]
custom_fields:
  item1:
    card:
      type: custom:button-card
      template: card_topbar_welcome
      variables:
        ulm_card_welcome_scenes_collapse: '[[[ return variables.ulm_card_welcome_scenes_collapse ]]]'
        ulm_weather: '[[[ return variables.ulm_weather]]]'
        ulm_language: '[[[ return variables.ulm_language ]]]'
      styles:
        card:
          - border-radius: none
          - box-shadow: none
          - padding: 4px
  item2:
    card:
      type: custom:button-card
      show_icon: false
      show_label: false
      show_name: true
      show_entity_picture: false
      name: |
        [[[
          var today = new Date();
          var time = today.getHours()
          let welcome = '';
          if (time >= '18'){
            welcome = variables.ulm_evening;
          } else if (time >= '12'){
            welcome = variables.ulm_afternoon;
          } else if (time >= '5'){
            welcome = variables.ulm_morning;
          } else {
            welcome = variables.ulm_hello;
          }
          return welcome + ', ' + '   <br>' + user.name + '!';
        ]]]
      styles:
        name:
          - align-self: start
          - justify-self: start
          - font-weight: bold
          - font-size: 24px
          - margin-left: 16px
        grid:
          - grid-template-areas: '''i n'' ''i l'''
          - grid-template-columns: min-content auto
          - grid-template-rows: min-content min-content
          - text-align: start
        card:
          - box-shadow: none
          - padding-bottom: 8px
  item3:
    card:
      type: custom:button-card
      show_icon: true
      show_label: true
      show_name: true
      show_entity_picture: false
      name: '[[[ return variables.ulm_translation_scenes ]]]'
      icon: mdi:dots-vertical
      styles:
        icon:
          - height: 20px
          - filter: opacity(50%)
        name:
          - align-self: start
          - justify-self: start
          - font-weight: bold
          - font-size: 18px
          - margin-left: 16px
        grid:
          - grid-template-areas: '''n i'''
          - grid-template-columns: 6fr 1fr
          - grid-template-rows: min-content min-content
          - text-align: start
        card:
          - box-shadow: none
          - padding-bottom: 0px
          - bottom: 10px
  item4:
    card:
      type: custom:button-card
      template: |
        [[[
          if(variables?.entity_1?.entity_id != ""){
            return 'card_scenes_welcome'
          } else {
            return 'card_scenes_welcome_auto'
          }
        ]]]
      styles:
        card:
          - border-radius: none
          - box-shadow: none
          - padding: 4px
      variables:
        entity_1: '[[[ return variables.entity_1]]]'
        entity_2: '[[[ return variables.entity_2]]]'
        entity_3: '[[[ return variables.entity_3]]]'
        entity_4: '[[[ return variables.entity_4]]]'
        entity_5: '[[[ return variables.entity_5]]]'
        entity_6: '[[[ return variables.entity_6]]]'
        entity_7: '[[[ return variables.entity_7]]]'
state: []
triggers_update: input_boolean.minimalist_dropdown
entity: input_boolean.minimalist_dropdown
lock:
  enabled: false
  duration: 5
  unlock: tap
nilsi commented 11 months ago

I found a closed issue already for this. It was solved by clicking into HACS and re-downloading the minimalist package again.