[FTUI3] weatherdetail.component.js

Begonnen von Jones, 12 Juli 2023, 02:08:52

Vorheriges Thema - Nächstes Thema

Jones

Update 2:
- inline svg icons für linke spalte der tagesansicht
- js / css cleanups

Du darfst diesen Dateianhang nicht ansehen.   Du darfst diesen Dateianhang nicht ansehen.
  [default]                                                                          [parameter test]

weatherdetail.component.js
/*
* Weatherdetail component for FTUI version 3
* Shows a weather forcast for 1-7 days with detailed info of the selected day.
*
* (c) 2023 by jones
*
* Under MIT License (http://www.opensource.org/licenses/mit-license.php)
*
* https://github.com/knowthelist/ftui
*/

import { FtuiElement } from '../element.component.js';
import { fhemService } from '../../modules/ftui/fhem.service.js';
import { dateFromString, dateFormat } from '../../modules/ftui/ftui.helper.js';

//////////////////////////////////////////////////////////////////////////////////////////////
// Weatherdetail class: Shows detailed weather forcast of the selected day
//////////////////////////////////////////////////////////////////////////////////////////////
export class FtuiWeatherdetail extends FtuiElement {
  constructor(properties) {
    super(Object.assign(FtuiWeatherdetail.properties, properties));
    this.fhemIconPath = '../images/default/weather/'; // path of kleinklima icons
    this.actDay = 0; // wich day-tab is selected (0:today, 1:tomorrow, ...)
    this.maxDay = 7; // proplanta device limit of detailed data
    this.minDay = 1;
    this.lastUpdate = 0; // used for ignoring startup spam from onChangeReading()
  }

  //////////////////////////////////////////////////////////////////////////////////////////////
  // Reading of the fhem device has changed
  //////////////////////////////////////////////////////////////////////////////////////////////
  onChangeReading(read) {
    if (!read) return;
    let time = new Date().getTime();
    if (time - this.lastUpdate > 4000) // MANY onChangeReading() events in first 4s after creating!?
    {
      this.lastUpdate = time;
      this.fetchData();
    }
  }

  //////////////////////////////////////////////////////////////////////////////////////////////
  // The html/css part of this component
  // A base part is defined here and will be extended later (access via id / class parameter)
  //////////////////////////////////////////////////////////////////////////////////////////////
  template() {
    return `
      <style> @import "components/weatherdetail/weatherdetail.component.css";</style>
      <ftui-column>
        <table><tr id="dayTabs"></tr></table>
        <ftui-row id="dayTable">please wait...</ftui-row>
      </ftui-column>
      `;
  }

  //////////////////////////////////////////////////////////////////////////////////////////////
  // Default properties
  // Will be overwritten by parameter in <ftui-weatherdetail> html element
  //////////////////////////////////////////////////////////////////////////////////////////////
  static get properties() {
    return {
    device: 'proplanta',
    forecast: '4',
    icondark: 'gray',
    iconlight: 'silver',
    bgactive: 'dark',
    bginactive: '#222222',
    bordercolor: 'gray',
    txtlight: 'white',
    };
  }

  //////////////////////////////////////////////////////////////////////////////////////////////
  // Convert properties to attributes
  //////////////////////////////////////////////////////////////////////////////////////////////
  static get observedAttributes() {
    return [...this.convertToAttributes(FtuiWeatherdetail.properties), ...super.observedAttributes];
  }

  //////////////////////////////////////////////////////////////////////////////////////////////
  // Component has connected to fhem
  //////////////////////////////////////////////////////////////////////////////////////////////
  onConnected() { // fires 2 times (?) on reload
  }

  //////////////////////////////////////////////////////////////////////////////////////////////
  // Triggers on every attribute defined in <ftui-weatherdetail> html element
  //////////////////////////////////////////////////////////////////////////////////////////////
  onAttributeChanged(name) {
    let hStyle = this.shadowRoot.host.style;
    switch (name) {
      case 'device':
        fhemService.getReadingEvents(this.device).subscribe(read => this.onChangeReading(read));
      break;
      case 'forecast':
        if (this.forecast < this.minDay || this.forecast > this.maxDay)
          this.forecast = 4; // default: 4 days of weather forecast
      break;
    }
    // Setting all css default values (todo: run only once, not on every attribute)
    hStyle.setProperty('--icondark', this.icondark);
    hStyle.setProperty('--iconlight', this.iconlight);
    hStyle.setProperty('--bgactive', this.bgactive);
    hStyle.setProperty('--bginactive', this.bginactive);
    hStyle.setProperty('--bordercolor', this.bordercolor);
    hStyle.setProperty('--txtlight', this.txtlight);
  }

  //////////////////////////////////////////////////////////////////////////////////////////////
  // A day-tab was clicked -> update the detailed table
  //////////////////////////////////////////////////////////////////////////////////////////////
  onButtonClick(event, wDay)
  {
    this.actDay = wDay;
    this.fetchData();
  }

  //////////////////////////////////////////////////////////////////////////////////////////////
  // get kleinklima iconname
  //////////////////////////////////////////////////////////////////////////////////////////////
  getWeatherIcon(iconFilename) {
    const weatherIcon = [
    'sunny.png',                // t1
    'partly_cloudy.png',        // t2
    'partly_cloudy.png',        // t3
    'mostlycloudy.png',         // t4
    'cloudy.png',               // t5
    'chance_of_rain.png',       // t6
    'showers.png',              // t7
    'chance_of_storm.png',      // t8
  'chance_of_snow.png',       // t9
    'rainsnow.png',             // t10
    'snow.png',                 // t11
    'haze.png',                 // t12
    'haze.png',                 // t13
    'rain.png',                 // t14
    'sunny_night.png',          // n1
    'partlycloudy_night.png',   // n2
    'partlycloudy_night.png',   // n3
    'mostlycloudy_night.png',   // n4
    'overcast.png',             // n5 (Bedeckt)
    'chance_of_rain_night.png', // n6
    'showers_night.png',        // n7
    'chance_of_storm_night.png',// n8
    'sleet.png',                // n9 (Graupel)
    'rainsnow.png',             // n10
    'snow.png',                 // n11
    'haze_night.png',           // n12
    'haze_night.png',           // n13
  'rain.png']                 // n14
    let filename = iconFilename.substring(iconFilename.lastIndexOf("/")+1, iconFilename.length-4); // w/o path and extension
    let iconNr = filename.substring(1)-1;
    if (iconNr > 14)
    return "na.png"
    return filename[0]=="t"?this.fhemIconPath + weatherIcon[iconNr]:this.fhemIconPath + weatherIcon[iconNr+14];
  }

  //////////////////////////////////////////////////////////////////////////////////////////////
  // Get the whole data for this device from fhem
  //////////////////////////////////////////////////////////////////////////////////////////////
  fetchData(){
    fhemService.sendCommand('jsonlist2 ' + this.device)
      .then(response => response.json())
      .then((response) => {
      ////////////////////////////////////////////////////////////////////////////////////////
      // response-Object: Name, PossibleSets, PossibleAttrs, Internals, Readings, Attributes
      //                  Internals  -> of the fhem device (DEF, FUUID, ...)
      //                  Readings   -> of the fhem Device (fc0_cloud00, ...)
      //                  Attributes -> of the fhem Device (devStateIcon, ...)
      ////////////////////////////////////////////////////////////////////////////////////////
      if (response.Results[0])
      {
        const readings = response.Results[0].Readings;
        // -----------------------------------------------------------------------------------
        // Days overview (upper half of this html-object [displayed as tabs])
        // -----------------------------------------------------------------------------------
        this.elemDayTab = this.shadowRoot.getElementById('dayTabs');
        this.elemDayTab.textContent = ''; // delete all children
        for (let day = 0; day < this.forecast; day++) {
          let strDay = "fc"+day+"_";
          let elem = this.elemDayTab.insertCell(-1);
          (this.forecast < 6)?elem.classList.add("fontBig"):elem.classList.add("fontMedium");
          let date = readings[strDay+"date"].Value;
          let wDay = dateFormat(dateFromString(date), "ee");
          let content = '<td>'
          content+= '<ftui-column class='+(day==this.actDay?"tabActive":"tabInactive")+'>';
          content+= '<ftui-label class="date">'+ date +'</ftui-label>';
          content+= '<ftui-label class="weekday">'+(!day?"Heute":wDay)+'</ftui-label>';
          content+= '<img width="100%" src='+ this.getWeatherIcon(readings[strDay+"weatherDayIcon"].Value)+'>';
          content+= '<ftui-label class="tempMin tabUnit"><ftui-label class="'+(this.forecast < 6?"fontBig":"fontMedium")+'" text="'+readings[strDay+"tempMin"].Value+'"></ftui-label>°C&nbsp;';
          content+= '<ftui-label class="tempMax tabUnit"><ftui-label class="'+(this.forecast < 6?"fontBig":"fontMedium")+'" text="'+readings[strDay+"tempMax"].Value+'"></ftui-label>°C</ftui-label></ftui-label>';
          elem.innerHTML = content + '</ftui-column></td>';
          elem.addEventListener("click", event => this.onButtonClick(event, day));
        }
        // when forecast is < 4: create dummy tabs (else tabs would be extremely huge)
        for (let day = this.forecast; day < 4; day++) {
          let elem = this.elemDayTab.insertCell(-1);
        }
        // -----------------------------------------------------------------------------------
        // Day detailed (lower half of this html-object [displayed as table])
        // -----------------------------------------------------------------------------------
        const gfxSVG = [ // inline svg instructions: de.wikipedia.org/wiki/Scalable_Vector_Graphics
          '<svg><path class="svg3" d="m 4 13 a 7 7 0 1 1 0 1z" /><path class="svg1" d="M 10.5 8 l 0 6  l 5.5 0" /></svg>', // clock
          '<svg><path class="svg3" d="m 5 22 c -4.80 0.80, -4.80 7.20, 0  8 l 12, 0 c  3.20 -0.80,  3.2 -4.8, -0.4 -5.6 c 0 -3.6, -3.6 -3.6, -4 -2 c -0.4 -2.96, -5.84 -4.88, -7.76 -0.32"/></svg>', // cloud
          '<svg><path class="svg1" d="M 7.50 16 A 5 5 0 1 0 12.50 16 m 0.5 0.5 l 0 -12  m -6 0.5 l 0 12 M 13 5 A 3 3 0 0 0 7 5" /><path class="svg4" d="M 10 17.5 A 3 3 0 1 0 10.05 17.50 m -1 1 h 2 v -8 h -2 v 8 "/></svg>', // thermometer
          '<svg><path class="svg1" d="M 5 20 A 1 1 0 0 0 11 20 l 0 -18"/><path class="svg3" d="M 20 13 A 9 9 0 0 0 2 13"/><path class="svg5" d="M 7.5 13 A 2.5 2.5 0 0 0 2.5 13 M 14 13 A 3 3 0 0 0 8 13 M 19.5 13 A 2.5 2.5 0 0 0 14.5 13"/></svg>', // umbrella
          '<svg><path class="svg3" d="M 5 16 A 1 1 0 0 0 11 16 l -3 -6 l -3 6.3 M 14 11 A 1 1 0 0 0 18 11 l -2 -4 l -2 4.5"/></svg>', //waterdrops
          '<svg><path class="svg1" d="M 7 5 l 0 20" /><path class="svg3" d="M 9 5 l 10 5 -10 5 0 -10.1" />', // flag
        ];
        this.elemDayAll = this.shadowRoot.getElementById('dayTable');
        this.elemDayAll.textContent = ''; // delete all children
        let content = '<table style="pointer-events: none">';
        let strDay = "fc"+this.actDay+"_";
        const row = ["","","","","",""];
        const sumRows = row.length;
        for (let hour = 0; hour < 8; hour++) {
          let strHour = String("0" + hour*3).slice(-2);
          row[0]+= '<td><ftui-label class="unit"><ftui-label class="amount" text="' + strHour +'"></ftui-label>Uhr</ftui-label></td>';
          row[1]+= '<td><img height="50px" src='+ this.getWeatherIcon(readings[strDay+"weather"+strHour+"Icon"].Value) +'></td>';
          row[2]+= '<td><ftui-label class="unit"><ftui-label class="amount" text="' + readings[strDay+"temp"    +strHour].Value +'"></ftui-label>°C</ftui-label></td>';
          row[3]+= '<td><ftui-label class="unit"><ftui-label class="amount" text="' + readings[strDay+"chOfRain"+strHour].Value +'"></ftui-label>%</ftui-label></td>';
          row[4]+= '<td><ftui-label class="unit"><ftui-label class="amount" text="' + readings[strDay+"rain"    +strHour].Value +'"></ftui-label>mm</ftui-label></td>';
          row[5]+= '<td><ftui-label class="unit"><ftui-label class="amount" text="' + readings[strDay+"wind"    +strHour].Value +'"></ftui-label>km/h</ftui-label></td>';
        }
        for (let y = 0; y < sumRows; y++) {
          content+= '<tr><td style="width: 22px; vertical-align: top;">'+gfxSVG[y]+'</td>' +row[y] +'</tr>';
        }
        this.elemDayAll.innerHTML = content + '</table>';
      }
    })
  }
}

window.customElements.define('ftui-weatherdetail', FtuiWeatherdetail);

weatherdetail.component.css
:host {
  --icondark:    setByJS;
  --iconlight:   setByJS;
  --bgactive:    setByJS;
  --bginactive:  setByJS;
  --bordercolor: setByJS;
  --txtlight:    setByJS;
}

.fontBig {
  font-size: 22px; 
}

.fontMedium {
  font-size: 18px; 
}

.tabActive {
  pointer-events: none;
  border: thin solid white;
  border-bottom: none;
  border-radius: 15px 15px 0 0;
  margin-left: -1px;
  border-color: var(--bordercolor);
  background-color: var(--bgactive);
}

.tabInactive {
  pointer-events: none;
  border-bottom: thin solid white;
  border-radius: 15px 15px 0 0;
  opacity: 0.55;
  border-color: var(--bordercolor);
  background-color: var(--bginactive);
}

.date {
  font-size: 95%;
  color: var(--txtlight);
}

.weekday {
  font-size: 70%;
  margin-top: -6px;
  color: var(--bordercolor);
}

.tempMin {
  font-size: 90%;
  color: deepSkyBlue;
}

.tempMax {
  font-size: 90%;
  color: orange;
}

.amount {
  font-size: 21px;
  font-weight: normal;
}

.unit {
  text-align: right;
  font-size: 11px;
}

.pic {
  margin-top: 4px;
  height: 18px;
}

table, tr, td {
  color: var(--txtlight);
  background-color: var(--bgactive);
/*  border: 1px solid white; */ /* Testing only */
  table-layout: fixed;
  padding: 0;
  margin: 0;
  text-align: center;
  width: 100%;
}

svg {
  position: absolute;
  display: block;
}

.svg1 {
  stroke: var(--icondark);
  stroke-width: 2;
  fill: transparent;
}

.svg2 {
  stroke: var(--iconlight);
  stroke-width: 1;
  fill: transparent;
}

.svg3 {
  stroke: var(--icondark);
  stroke-width: 0.5;
  fill: var(--iconlight);
}

.svg4 {
  fill: var(--iconlight);
}

.svg5 {
  stroke: var(--icondark);
  stroke-width: 1.4;
  fill: transparent;
}

demo farbenzauber
<ftui-grid base-width="128" base-height="113" margin="1" shape="square">
  <ftui-grid-tile row="1" col="2" height="4" width="5">
  <ftui-grid-header>Wettervorschau</ftui-grid-header>
  <ftui-weatherdetail device="Proplanta" forecast="4" ></ftui-weatherdetail>
  <!-- Color Demo
    <ftui-weatherdetail device="Proplanta" forecast="7" icondark="orange" iconlight="pink" txtlight="black" bgactive="blue" bginactive="red" bordercolor="green"></ftui-weatherdetail>
  -->
  </ftui-grid-tile>
<ftui-grid>
[FTUI3] Addons: https://github.com/mr-petz/ftui/tree/addons
Manchmal habe ich Angst, dass ich euch nerve, aber dann fällt mir ein: Ihr seid ja freiwillig hier!

Jones

#1
[12.07.23]
moin,
bräuchte mal eure hilfe. möchte gerne ein weatherdetail.component.js erstellen aber verzweifel gerade an der fehlenden doku.
mein vorbild ist das teil von bruchbude aus ftui2. habe die ente gequält, aber die suche hat mir nicht weitergeholfen.
mein problem:
ich verstehe nicht wie die component funktioniert. zum testen habe ich folgende zeilen in weather.component.js in onAttributeChanged() eingefügt:
alert(fhemService.getReadingItem(getReadingID("Proplanta","fc0_weatherDayIcon")).data.value)
alert(fhemService.getReadingItem(getReadingID("Proplanta","fc1_weatherDayIcon")).data.value)
der erste alert zeigt mir das reading aus fhem korrekt an, der 2. alert gibt nur ein undefined aus.
habe versucht mir die infos aus den vorhandenen components zusammenzusuchen, aber mein javascript-hintergrund reicht dafür einfach nicht.
habe zuerst versucht das ganze ohne component zu erstellen, aber das ist einfach viel zu langsam. ich möchte mindestens die geschwindigkeit von ftui2 haben.

[13.07.23]
sind wohl alle gerade im sommerurlaub, oder ich muss erklären warum ich die o.g. funktion nutzen möchte:
die "einfache" version geht für text, aber nicht für icons <ftui-label size="3" color="white" [text]="Proplanta:fc0_date"></ftui-label>weil ich das reading zum kleinklima iconname konvertieren muss:
  // kleinklima icons
  getWeatherIcon(iconFilename) {
    const weatherIcon = ['CLOUDLESS', 'PARTLY_CLOUDY', 'MOSTLY_CLOUDY', 'CLOUDY', 'OVERCAST', 'LIGHT_SHOWERS', 'SHOWERS',
                 'SCATTERED_THUNDERSTORM', 'SNOW_SHOWER', 'SNOW', 'RAIN_SNOW', 'HAZE', 'FOGGY', 'DRIZZLE']
    let filename = iconFilename.substring(iconFilename.lastIndexOf("/")+1, iconFilename.length-4); // w/o path and extension
    let iconNr = filename.substring(1)-1;
    if (iconNr > 14) {
return "na.png"
    }
    return filename[0]=="t"?weatherIcon[iconNr]:weatherIcon[iconNr] + "_NIGHT"
  }
Wäre echt froh über eine hilfestellung von euch.
[FTUI3] Addons: https://github.com/mr-petz/ftui/tree/addons
Manchmal habe ich Angst, dass ich euch nerve, aber dann fällt mir ein: Ihr seid ja freiwillig hier!

yersinia

Ich hab den Thread jetzt drei mal gelesen und verstehe immer noch nicht, was du vor hast.
Was stimmt mit dem Mapping nicht?
Proplanta-Icons werden doch erst interne Status und dann in kleinklima-icons übersetzt.
Was funktioniert jetzt genau nicht für dich?
viele Grüße, yersinia
----
FHEM 6.4 (SVN) on RPi 4B with RasPi OS Bookworm (perl 5.36.0) | FTUI
nanoCUL->2x868(1x ser2net)@tsculfw, 1x433@Sduino | MQTT2 | Tasmota | ESPEasy
VCCU->14xSEC-SCo, 7xCC-RT-DN, 5xLC-Bl1PBU-FM, 3xTC-IT-WM-W-EU, 1xPB-2-WM55, 1xLC-Sw1PBU-FM, 1xES-PMSw1-Pl

Jones

@yersinia
du meinst die weather.component.js.
ja, die funzt aber nur kriechend langsam weil ich mindestens 12 kleinklima icons brauche.
beim init siehst du wie jedes icon nach einander aufploppt und machmal erst nach einem reload.

war das gleich damals bei ftui2 bis zum modul von bruchbude was sich seither bei mir bewährt hat.
deshalb wollte ich sowas auch für ftui3 und scheitere an der fehlenden doku für die component
hatte im quellcode was mit fhemService (siehe oben) gefunden, was bei mir aber nur für ein reading funzt.
das muss man wohl irgendwie initialisieren!?
[FTUI3] Addons: https://github.com/mr-petz/ftui/tree/addons
Manchmal habe ich Angst, dass ich euch nerve, aber dann fällt mir ein: Ihr seid ja freiwillig hier!

yersinia

Neee, ich mein schon die map, weil genau hier von Proplanta nach internal states nach kleinklima icons gemapt wird und du dies eigtl nicht (nochmals) tun müsstest.

12 icons zu laden sollte eigtl kein Thema sein - ich lade 20 icons (icon-set=basline; provider=proplanteICON_LONG) über templates und da merk ich keine (wesentlich unangenehme) Verzögerung. Hast du die Probleme mit anderen icon-sets auch?

Wenn du unbedingt eine eigene component bauen willst, schau dir mal das repo von mr_petz an, vlt die Thermostat-Komponente. Wie du genau fhem.service.js einbindest und über Bindings die readings abfragst kann ich dir leider nicht sagen. Ggf kannst du im repo von setstate stöbern und dir input holen.
viele Grüße, yersinia
----
FHEM 6.4 (SVN) on RPi 4B with RasPi OS Bookworm (perl 5.36.0) | FTUI
nanoCUL->2x868(1x ser2net)@tsculfw, 1x433@Sduino | MQTT2 | Tasmota | ESPEasy
VCCU->14xSEC-SCo, 7xCC-RT-DN, 5xLC-Bl1PBU-FM, 3xTC-IT-WM-W-EU, 1xPB-2-WM55, 1xLC-Sw1PBU-FM, 1xES-PMSw1-Pl

Jones

ZitatNeee, ich mein schon die map, weil genau hier von Proplanta nach internal states nach kleinklima icons gemapt wird und du dies eigtl nicht (nochmals) tun müsstest.
würde ich ja nicht nochmal tun. ich rufe ja weather.component.js gar nicht auf.
Zitat12 icons zu laden sollte eigtl kein Thema sein - ich lade 20 icons (icon-set=basline; provider=proplanteICON_LONG) über templates und da merk ich keine (wesentlich unangenehme) Verzögerung. Hast du die Probleme mit anderen icon-sets auch?
andere icon-sets habe ich nicht versucht. ein normales icon ist kein problem.
Zitatschau dir mal das repo von mr_petz an, vlt die Thermostat-Komponente. Ggf kannst du im repo von setstate stöbern und dir input holen.
da waren sie wieder, seine 3 probleme: ich verstehe nicht wie genau die daten von fhem geholt werden (s.o.)
ich dachte fhemService.getReadingItem(...) wäre die lösung, aber mir fehlt da ein wenig gehirnschmalz um mehr als 1 reading zu bekommen  :'(
ZitatWie du genau fhem.service.js einbindest und über Bindings die readings abfragst kann ich dir leider nicht sagen.
danke für deine zeit und für das gefühl nicht ignoriert zu werden  ;)
ich will das unbedingt in ein component packen damit es flüssig läuft. falls ich hier den richtigen "schubs" bekomme würde ich meine component auf jeden fall gut dokumentieren um anderen einen leichteren einstieg in das thema zu ermöglichen.
[FTUI3] Addons: https://github.com/mr-petz/ftui/tree/addons
Manchmal habe ich Angst, dass ich euch nerve, aber dann fällt mir ein: Ihr seid ja freiwillig hier!


Jones

@mr_petz
die fetchData() funktion sieht genau nach dem aus was ich brauche.
damit ist die nachtschicht zum testen eingeleutet.

sobald ich was gescheites hinbekomme, kommentiere ich die einzelnen schritte und poste die component hier.

thx

[FTUI3] Addons: https://github.com/mr-petz/ftui/tree/addons
Manchmal habe ich Angst, dass ich euch nerve, aber dann fällt mir ein: Ihr seid ja freiwillig hier!

Jones

@mr_petz
habe es zwar nicht geschafft es auf die geschwindigkeit von ftui2 zu bekommen, aber als component ist es schon deutlich schneller als ohne.
ohne die anregung mit deinem weekdaytime hätte ich es nicht geschafft.
falls dir ein paar grobe schnitzer im code auffallen würde ich mich sehr über weitere anregungen freuen...
[FTUI3] Addons: https://github.com/mr-petz/ftui/tree/addons
Manchmal habe ich Angst, dass ich euch nerve, aber dann fällt mir ein: Ihr seid ja freiwillig hier!

yersinia

Nice! Das wäre was fürs addons repo.
viele Grüße, yersinia
----
FHEM 6.4 (SVN) on RPi 4B with RasPi OS Bookworm (perl 5.36.0) | FTUI
nanoCUL->2x868(1x ser2net)@tsculfw, 1x433@Sduino | MQTT2 | Tasmota | ESPEasy
VCCU->14xSEC-SCo, 7xCC-RT-DN, 5xLC-Bl1PBU-FM, 3xTC-IT-WM-W-EU, 1xPB-2-WM55, 1xLC-Sw1PBU-FM, 1xES-PMSw1-Pl

Jones

@yersinia
wenn du zugriff hast würde ich mich über eine einstellung ins repo freuen.
[FTUI3] Addons: https://github.com/mr-petz/ftui/tree/addons
Manchmal habe ich Angst, dass ich euch nerve, aber dann fällt mir ein: Ihr seid ja freiwillig hier!

yersinia

#11
Ich kann ein pr stellen; lass uns erst mal mr_petz Antwort abwarten.

Edit: was mir noch einfällt: ich würde einen eigenen Namensraum für die CSS Klassen bilden; so unterbindest von vornherein, dass es Komplikationen mit anderen, zufällig gleichen, Klassen gibt.
viele Grüße, yersinia
----
FHEM 6.4 (SVN) on RPi 4B with RasPi OS Bookworm (perl 5.36.0) | FTUI
nanoCUL->2x868(1x ser2net)@tsculfw, 1x433@Sduino | MQTT2 | Tasmota | ESPEasy
VCCU->14xSEC-SCo, 7xCC-RT-DN, 5xLC-Bl1PBU-FM, 3xTC-IT-WM-W-EU, 1xPB-2-WM55, 1xLC-Sw1PBU-FM, 1xES-PMSw1-Pl

mr_petz

Ok ich fange mal an.
(Bin aber auch kein Programmierer!)

Hinweise zum JS:
- die Schleifen würde ich immer mit geschweiften Klammern setzen (ich weis es gibt auch Einzeilerschleifen ohne Klammer)
- this.dayTab mit den getElementById und addEventListener würde ich mit in die Schleife vom this.arrDaySummary reinpacken weil du da eh this.sumDays = 4 Tage gesetzt hast
- was passiert wenn ich nur 3 Tage Anzeigen möchte?
- this.* als Variable/Attribute brauchst du nur bei einer globalen Verwendung
- var nimmt man nicht mehr bei ES2020, dafür const oder let nehmen, let ist wie var (veränderbar), const für eine nicht im Nachgang veränderbare bzw. feste Variable
- du setzt rein auf kleinklima-Iconset, damit grenzt du das stark ein und musst den User sagen er soll umswitchen oder selber mappen. Da kommen bestimmt noch Anfragen wegen anderen Icons?

zum css:
- Hintergrund/Schriftfarben würde ich anpassbar machen
- die fa_* Icons müssen bereitstehen und im richtigen Verzeichnis sein (Hinweis darauf fehlt)

Das ist alles meine subjektive Sichtweise und soll keine Kritik sein!
Es ist auch immer schwierig sich in vorhandene Codes reinzudenken (kostet Zeit) was der Ersteller wie erreicht...

ps. Alles ungetestet von mir. Habe noch keine Zeit gefunden...

LG

Jones

@mr_petz
vielen dank für deine zeit

Zitat(Bin aber auch kein Programmierer!)
aber du hast deutlich mehr erfahrung und kennst daher etliche stolpersteine

Zitatdie Schleifen würde ich immer mit geschweiften Klammern setzen (ich weis es gibt auch Einzeilerschleifen ohne Klammer)
ist wahrscheinlich besser, da ich ein kandidat für flüchtigkeitsfehler bin und so schnell mal ne 2. zeite einfüge die dann ausserhalb des loops ist.
die if/else dann wohl auch? code optik leidet dann aber...

Zitatthis.dayTab mit den getElementById und addEventListener würde ich mit in die Schleife vom this.arrDaySummary reinpacken weil du da eh this.sumDays = 4 Tage gesetzt hast
stimmt, werde nochmal was an der code optik ändern. da muss ich eh durchfegen wegen der variablen anzahl der tabs.

Zitatwas passiert wenn ich nur 3 Tage Anzeigen möchte?
dann sieht das scheiße aus, weil da ungenutzter raum ist. tag 4 stört doch niemanden, wer tag 4 nicht wissen will - klickt einfach nicht drauf.
aber egal, ich wollte ja deine anregungen... also habe ich damit schonmal angefangen.
wollte eigentlich auch nur 4 tage weil die experten sagen: "mehr aus 3 tage ist kristallkugel"
aber habe jetzt auch ne erweiterung auf mehr als 4 tage auf der todo.

Zitatthis.* als Variable/Attribute brauchst du nur bei einer globalen Verwendung
jo, ist so eine copy und paste geschichte. genau wie bei diesem einen var.
btw, wie setze ich this.myValue auf const? einfach const davor schreiben klappt nicht.

Zitatdu setzt rein auf kleinklima-Iconset, damit grenzt du das stark ein und musst den User sagen er soll umswitchen oder selber mappen. Da kommen bestimmt noch Anfragen wegen anderen Icons?
weil ich finde das die mit abstand am besten aussehen... da möchte ich eigentlich nix anderes.
aber wenn da jetzt ein shitstorm kommt von wegen monopol werde ich mich beugen ;D

Zitatdie fa_* Icons müssen bereitstehen und im richtigen Verzeichnis sein (Hinweis darauf fehlt)
hm, ich habe ftui3 komplett gelöscht und neu installiert, aber fhem nicht. bei mir waren die da drin und ich dachte das gehört zur standard installation.
gehören die nicht zu den standard icons? dann muss ich mal gucken ob ich da was aus dem ftui3 folder nehme. hatte ich zuerst, aber die haben problem gemacht (rumgezappel beim resizing - bei den icons aus dem fhem folder dagegen keine probleme)

ZitatHintergrund/Schriftfarben würde ich anpassbar machen
mit css habe ich 0 erfahrung, das kommt dann erst mit version 2.0


[FTUI3] Addons: https://github.com/mr-petz/ftui/tree/addons
Manchmal habe ich Angst, dass ich euch nerve, aber dann fällt mir ein: Ihr seid ja freiwillig hier!

mr_petz

Zitat von: Jones am 21 Juli 2023, 22:38:23@mr_petz
vielen dank für deine zeit

Gerne.


Zitatjo, ist so eine copy und paste geschichte. genau wie bei diesem einen var.
btw, wie setze ich this.myValue auf const? einfach const davor schreiben klappt nicht.

Wo hast du denn this.myValue?
Wenn dann const myValue = XYZ;
oder wenn es im Nachgang nochmal geändert wird let myValue = XYZ;
Wenn du es in jeder Funktion brauchst, dann lass es this.myValue


Zitatmit css habe ich 0 erfahrung, das kommt dann erst mit version 2.0

mit z.Bsp.:
background: var(--weatherdetail-bg-color, var(--dark-color));
würdest du es mit dem ersten Eintrag vom var() ansprechbar machen und wenn es niemand in anspruch nimmt dann wird --dark-color vom ftui3 genommen.
es würde auch sowas gehen:
background: var(--weatherdetail-bg-color, #424949);
man kann das var() auch kombinieren.

LG mr_petz