Skip to content
  • Home
  • Aktuell
  • Tags
  • 0 Ungelesen 0
  • Kategorien
  • Unreplied
  • Beliebt
  • GitHub
  • Docu
  • Hilfe
Skins
  • Light
  • Brite
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Standard: (Kein Skin)
  • Kein Skin
Einklappen
ioBroker Logo

Community Forum

  1. ioBroker Community Home
  2. Deutsch
  3. Visualisierung
  4. [Vorlage] MDCSS v2: ical Kalendar anzeigen

NEWS

  • UPDATE 31.10.: Amazon Alexa - ioBroker Skill läuft aus ?
    apollon77A
    apollon77
    48
    3
    8.4k

  • Monatsrückblick – September 2025
    BluefoxB
    Bluefox
    13
    1
    2.0k

  • Neues Video "KI im Smart Home" - ioBroker plus n8n
    BluefoxB
    Bluefox
    15
    1
    2.5k

[Vorlage] MDCSS v2: ical Kalendar anzeigen

Geplant Angeheftet Gesperrt Verschoben Visualisierung
vismaterial uimaterial css
56 Beiträge 15 Kommentatoren 8.3k Aufrufe 20 Watching
  • Älteste zuerst
  • Neuste zuerst
  • Meiste Stimmen
Antworten
  • In einem neuen Thema antworten
Anmelden zum Antworten
Dieses Thema wurde gelöscht. Nur Nutzer mit entsprechenden Rechten können es sehen.
  • E Ente

    @sigi234

    Hallo siggi234,

    danke für den Install-Screenshot. ;-)

    sigi234S Online
    sigi234S Online
    sigi234
    Forum Testing Most Active
    schrieb am zuletzt editiert von sigi234
    #43

    @Ente sagte in [Vorlage] MDCSS v2: ical Kalendar anzeigen:

    @sigi234

    Hallo siggi234,

    danke für den Install-Screenshot. ;-)

    Screenshot (674)_LI.jpg

    /*
    *** MduiShowIcal
    Dieses Script überwacht den ical-Adapter und erzeugt bei Änderungen an dessen States HTML-List States für die Anzeige als 
    Kalender in Listform mit
    * Tagesauflösung von "von/bis"-Terminen, inkl. Berücksichtigung der Uhrzeiten
    * Tagesdatum, Kalendarfarben aus ical oder optional aus dem Script
    * Termintext und -ort
    * optionalem Icon je Kalendar
    * optionalem "ignore", wenn ein Kalendar unberücksichtigt bleiben soll
    
    Es werden States für n-Logs erzeugt, jedem, Log kann ein Standardfilter mitgegeben werden. In jedem Log-Ordner 
    befindet sich ein list-HTML State, welcher direkt in der vis angezeigt werden kann (jeweils im basic-string (unescaped) Widget). 
    Über optionale Filter als string (Bsp:':Abfall:') oder als RegExp (Bsp:'/Feiertag|Geburtstag/') kann festgelegt werden, 
    welche Einträge beim Aufbau der list-HTML States berücksichtigt werden. 
    Bsp.: 
    log0 Filter: "abfall" oder ":Abfall:" (=Kalendarname) -> Zeigt nur Abfalltermine
    log0 Filter: "ferien" oder ":Ferien:" (=Kalendarname) -> Zeigt nur Ferientermine
    
    
    **** Installation
    Einfach als serverseitiges Script installieren und starten-5 Sek warten-stoppen-starten. Beim 1.Start werden 
    die notwendigen States unter STATE_PATH = '0_userdata.0.mdui.showIcal.' erzeugt. Erst beim 2.Start
    instanziiert das Script die Event-Handler und läuft dann.
    
    **** Konfiguration
    Eigentlich ist keine notwendig.
    Optional in der Funktion MduiShowIcal|doInit() eine Anpassung der KONFIGURATION vornehmen
    Optional Anpassung der tmpList.
      
    **** Dokumentation
    https://github.com/Uhula/ioBroker-Material-Design-Style/wiki/3.5-MduiShowIcal
    
    ###### Um ein Feedback zu erhalten wäre es schön, wenn jeder, der diese Vorlagen nutzt, den  1.Beitrag des Themas positiv bewertet (Pfeil nach oben oder unten ;-) ). Ich kann dann auch abschätzen, ob sich die weitere Pflege lohnt. Thx!
    
    ***** States
    Unter dem STATE_PATH werden die folgenden States erzeugt:
    version : Script-Version, wird verwendet um Script-Updates zu erkennen
    updatePressed : auf true setzen, wenn ein table/list update außerhalb des Intervals erfolgen soll
    
    Weiterhin werden MAX_LOG_FOLDER Unterordner im STATE_PATH erzeugt (N=0-9):
    
    * LogN.table        : enthält die table-HTML für ein basic-string (unescaped) Widget
    * LogN.list         : enthält die list-HTML für ein basic-string (unescaped) Widget
    * LogN.count        : Anzahl der Log-Zeilen (wenn das Log mit '/:error:|:warn:/' gefiltert ist, dann ist es die Anzahl der Fehler/Warnungen)
    * LogN.filter       : Filter, der auch die logCache angewendet wurde im .table/.list zu erzeugen (siehe Filter)
    * LogN.lastUpdate   : Timestamp des letzten Updates
    
    
    ***** Filter
    In den filter-States können sowohl strings (Bsp:'error') als auch RegExp-Strings (Bsp:'/warn|error/') 
    hinterlegt werden. RegExp-Strings werden an den einschließenden  '/' erkannt. Über den ':' kann der Anfang
    eines Feldes mit in den Filter einbezogen werden. 
    Beispiele: 
    '/Feiertag|Geburtstag/' (RegExp) zeigt alle Zeilen an, in denen 'Feiertag' oder 'Geburtstag' in irgendeinem Feld vorkommen
    ':Abfall:' (string) zeigt alle Zeilen an, welche derKalendar 'Abfall' lautet
    'Arzt' (string) zeigt alle Zeilen an, in denen 'Arzt' in irgendeinem Feld vorkommt
    
    **** Lizenz
    (c) 2020 by UH, MIT License, no warranty, use on your own risc
    
    *** Changelog
    2020.05.01 UH 
    * Anpassung an neues MduiBase (intern)
    * Anpassung an MDCSS 2.5
    * Serientermine vor dem aktuellem Datum werden nicht mehr angezeigt
    
    */
    
    // ------------------------------------------------------------------------------------- 
    // MduiBase
    // ------------------------------------------------------------------------------------- 
    
    class MduiBase {
    
        constructor() {
          this.init();
        }
        
        //
        init() {
            // const
            this.DEBUG      = false;
            this.VERSION    = '1.0/2020-01-01';
            this.NAME       = 'mduiBase';
            this.STATE_PATH = '0_userdata.0.mdui.base.';
            this.STATE_UNKNOWN    =  0;
            this.STATE_INSTALLING = 10;
            this.STATE_INSTALLED  = 11;
            this.STATE_STARTING   = 20;
            this.STATE_STARTED    = 21;
            this.STATE_STOPPING   = 30;
            this.STATE_STOPPED    = 31;
        
            // var
            this.state = this.STATE_UNKNOWN;
            this.states = [];
            this.subscribers = [];
            this.schedulers = [];
        
            this.doInit();
        
            // init der states
            this.states.push( { id:'version',     common:{name:'installed script-version', write:false, def:this.VERSION} } );
        }
        
        //
        // start the script/class
        //
        start() {
            // beim 1.Start nur die States erzeugen
            if ( !this.existState("version") || (this.getState('version').val!=this.VERSION) ) {
                for (let s=0; s<this.states.length; s++) { this.createState( this.states[s].id ); }
                this.logWarn('first script start, creating states for version '+this.VERSION+', automatic restarting script again in 10 sec ...');
                setStateDelayed(this.STATE_PATH + 'version', this.VERSION, 3000);
                setTimeout( this.start.bind(this), 10000 );
                this.state = this.STATE_INSTALLED; 
                return;
            }
            switch (this.state) {
                case this.STATE_UNKNOWN : ;
                case this.STATE_INSTALLING : ;
                case this.STATE_INSTALLED : ;
                case this.STATE_STOPPED : {
                    this.state = this.STATE_STARTING; 
                    if (this.doStart()) {
                        this.log('script started');
                        this.state = this.STATE_STARTED;
                    }
                    break;    
                }
                case this.STATE_STARTING : ;
                case this.STATE_STARTED : {
                    this.logWarn('script already starting/started');
                    break;    
                }
                case this.STATE_STOPPING : {
                    this.logWarn('script is stopping, pls start later again');
                    break;    
                }
          
            } 
        }
        
        //
        // stop the script/class
        //
        stop() {
            switch (this.state) {
                case this.STATE_STARTED : {
                    this.state = this.STATE_STOPPING; 
                    if (this.doStop()) {
                        for (let i=0; i<this.subscribers.length; i++) if (this.subscribers[i] !== undefined) unsubscribe( this.subscribers[i] );
                        this.subscribers = [];
                        for (let i=0; i<this.schedulers.length; i++) if (this.schedulers[i] !== undefined) clearSchedule( this.schedulers[i] );
                        this.schedulers = [];
                        this.state = this.STATE_STOPPED; 
                        this.log('script stopped');
                    }
                    break;    
                }
                default : {
                    this.log('cant stopp script, because not startet');
                }
            } 
        }
        
        //
        // virtual functions, overwrite it 
        //
        doInit() { return true; }
        doStart() { return true; }
        doStop() { return true; }
        
        // einen on-Handler registrieren
        subscribe( handler ) {
            this.subscribers.push( handler );
        }
        
        // einen timer registrieren
        schedule( handler ) {
            this.schedulers.push( handler );
        }
        
        //
        // tool functions 
        //
        logDebug(msg) { if (this.DEBUG) console.log('['+this.NAME+'] '+msg); }
        log(msg) { console.log('['+this.NAME+'] '+msg); }
        logWarn(msg) { console.warn('['+this.NAME+'] '+msg); }
        logError(msg) { console.error('['+this.NAME+'] '+msg); }
        
        // über den $-Operator nachsehen, ob der state bereits vorhanden ist
        // getState().notExists geht auch, erzeugt aber Warnmeldungen!
        existState(id) {
            return ( $(this.STATE_PATH+id).length==0?false:true);
        }
        
        // wrapper, adds statepath to state-ID
        getState(id) {
            return getState(this.STATE_PATH + id);
        }
        
        // like setState(), but adds statepath to state_ID and checks if state exists, when not, creates it
        setState(id,value) {
            if ( !this.existState(id) ) this.createState(id,value,undefined);
            else setState( this.STATE_PATH + id, value);
        }
        
        // like cresteState(), but adds statepath to state_ID and checks if state exists, when not, creates it
        createState(id,value,common) {
            if ( !this.existState(id) ) {
                if (common===undefined) {
                    // id im states-Array suchen
                    for (var i=0; i<this.states.length; i++) { 
                        if (this.states[i].id==id) {
                            if (this.states[i].hasOwnProperty('common'))
                                common = this.states[i].common;
                           break;
                        }   
                    }
                }
                if ( (typeof value === 'undefined') && (common.hasOwnProperty('def'))) value = common.def;
                // unter "0_userdata.0"
                let obj = {};
                obj.type = 'state';
                obj.native = {};
                obj.common = common;
                setObject(this.STATE_PATH + id, obj, (err) => {
                        if (err) {
                            this.log('cant write object for state "' + this.STATE_PATH + id + '": ' + err);
                        } else { 
                            this.log('state "' + this.STATE_PATH + id + '" created');
                        }
                });
        
                setTimeout( setState, 3000, this.STATE_PATH + id, value );
            }
        }
        
        // true, if str contains filter string or regexp 
        fitsFilter(str, filter) {
            if ( (filter===undefined) || !filter || (filter=='') )
                return true;
            if ( filter instanceof RegExp )  {
                if (str.match( filter ) != null) return true;
            } else if (typeof filter == 'string') {
                if(str.includes(filter)) return true;
            }
            return false;        
        }
        
        //
        escapeRegExp(str) {
            return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); 
        }
        
        // wandelt eine Farbe im hex-Format (#000000) in ein RGB-Array[2] um
        hexToRGB(hex) {
            var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
            return result 
                ? [parseInt(result[1],16),parseInt(result[2],16),parseInt(result[3],16)]
                : [0,0,0];
        };
        
        // Helligkeit berechnen
        getLuminance(r, g, b) {
            var a = [r, g, b].map(function (v) {
                v /= 255;
                return v <= 0.03928
                    ? v / 12.92
                    : Math.pow( (v + 0.055) / 1.055, 2.4 );
            });
            return a[0] * 0.2126 + a[1] * 0.7152 + a[2] * 0.0722;
        }
        
        // Kontrats berechnen
        getContrast(rgb1, rgb2) {
            var l1 = this.getLuminance(rgb1[0], rgb1[1], rgb1[2]) + 0.05;
            var l2 = this.getLuminance(rgb2[0], rgb2[1], rgb2[2]) + 0.05;
            if ( l1 > l2 ) return l1 / l2 
            else return l2 / l1;
        }
        
        // liefert die fontColor auf Basis der backgroundColor durch Berechnung
        // des Kontrasts
        getFontColor(backgroundColor) {
            if ( this.getContrast(this.hexToRGB(backgroundColor),this.hexToRGB("#000000")) < 6 ) 
                return "#ffffff";
            else
                return "#000000";
        }
        
        }
        
        // ------------------------------------------------------------------------------------- 
        // MduiLogHMDevices
        // ------------------------------------------------------------------------------------- 
        
        class MduiShowIcal extends MduiBase {
        
        constructor() {
            super();
        }
        
        doInit() {
          super.doInit();
        
          // const
          this.DEBUG = false;
          this.VERSION = '1.0/2020-03-22';
          this.NAME = 'mduiShowIcal';
          this.DAY_MILLISECONDS = 60 * 60 * 24 * 1000;
        
          // -----------------------  
          // optional: KONFIGURATION
          // -----------------------  
                               // state-Pfad unter dem die States angelegt werden  
          this.STATE_PATH      = '0_userdata.0.mdui.showIcal.'; 
                               // Anzahl der Table/List Ordner mit eigenem Filter/View
          this.MAX_LOG_FOLDER  = 3;   
                               // max.Anzahl der Zeilen für die Table/List Ausgabe
          this.MAX_TABLE_ROWS  = 200; 
                               // Objekt-Pfad zum ical.x.data.table
          this.ICAL_TABLE      = 'ical.0.data.table';
                               // siehe: https://github.com/ioBroker/ioBroker.javascript/blob/master/docs/en/javascript.md#formatdate
          this.DATE_FORMAT     = 'W DD.MM.YYYY hh:mm';
                               // optional können dem Kalendar noch Icons und abweichende
                               // Farben angegeben werden (diese überschreiben jene aus iCal)
                               // 'icon'     : 'Icon-Name' (MDCSS/Google WebFont)
                               // 'calColor' : *#rrggbb' abweichende Kalendarfarbe 
                               // 'ignore'   : true|false Kalendar komplett ignorieren
          this.CALENDAR        = {'mdui-Abfall'      : {'icon':'delete_outline', 'calcolor':'orange' },
                                  'mdui-Geburtstage' : {'icon':'cake'},
                                  'Familie'          : {'ignore':true}
                                   
                                 };
        
          // -----------------------  
          // ENDE KONFIGURATION
          // -----------------------  
        
          // var
          this.logs = [];
          for (let i=0; i<=this.MAX_LOG_FOLDER && i<10; i++) 
              this.logs.push({filter:'' });
          
        
          // init der states
          this.states.push( { id:'version',     common:{name:'installed script-version', write:false, def:this.VERSION} } );
          this.states.push( { id:'updatePressed',common:{name:'update button pressed', write:true, type:'boolean', def:'false', role:'button' }} );
          
          let defFilter;
          for (let i=0; i<=this.MAX_LOG_FOLDER && i<10; i++) {
              switch (i) {
                  case 1 : defFilter = ':Abfall:'; break;   
                  case 2 : defFilter = 'Geburtstag'; break;   
                  case 3 : defFilter = ''; break;   
                  default: defFilter = undefined;
              }
              this.states.push( { id:'log'+i+'.table',      common:{name:'ioBroker-log as table', write:false, role:'html' }} );
              this.states.push( { id:'log'+i+'.list',       common:{name:'ioBroker-log as list', write:false, role:'html' }} );
              this.states.push( { id:'log'+i+'.count',      common:{name:'ioBroker-log count', write:false, type:'number', def:'0' }} );
              this.states.push( { id:'log'+i+'.filter',     common:{name:'ioBroker-log filter', write:true, def:defFilter}} );
              this.states.push( { id:'log'+i+'.lastUpdate', common:{name:'ioBroker-log last update', write:false, def:'0' }} );
          }
        
          return true;  
        }
        
        // start the script/class
        doStart() {
            super.doStart();
            
            // subscriber erzeugen
            this.subscribe( on( this.STATE_PATH+'updatePressed', obj => { this.onUpdate(obj) } ));
            this.subscribe( on( new RegExp( this.STATE_PATH+'*.filter' ), obj => { this.onFilter(obj) } ));
            this.subscribe( on( this.ICAL_TABLE, obj => { this.onIcalTable(obj) } ));
        
            this.onBuildHTML();
            return true;
        }
        
        // stop the script/class
        doStop() {
            super.doStop();
            return true;
        }
        
        // 
        onUpdate(obj) {
            if (obj.state.val===true) {
                this.onBuildHTML();
            }
            this.setState('updatePressed', false);
        }
        
        // filter, sort events
        onFilter(obj) {
          this.onBuildHTML();
        }
        
        // Ical table hat sich geändert
        onIcalTable(obj) {
          this.onBuildHTML();
        }
        
        
        
        // creates the HTML states for every log
        /*
        'date' => "→ 16.10.2017" 
        'event' => "9.30 - 16.30 Uhr Stopka " 
        '_class' => "ical_Kerstin ical_today" 
        '_date' => "2017-10-16T07:30:00.000Z" 
        '_end' => "2017-10-16T14:30:00.000Z" 
        '_section' => "" 
        '_IDID' => "040000008200E00074C5B7101A82E008000000007645DC55A6DFC44FB2EC6FEA9EFEA33C100000007688316058136F42AD128D91103543C9" 
        '_allDay' => "false" 
        '_rule' => " " 
        '_calName' => "Kerstin" 
        
        Optionen der ical-Instanz:
            'daysPreview' => "7"
            'colorize' => "false"
            'defColor' => "white"
            'fulltime' => " 00:00"
            'dataPaddingWithZeros' => "true"
            'replaceDates' => "false"
            'language' => "de"
            'everyCalOneColor' => "true"
            'calendars' (array) 
                '0' (array) 
                    'name' => "Abfall"
                    'url' => "https://calendar.google.com/calendar/ical/ruo0ddgalu03qq2ehpm8imqnk4%40group.calendar.google.com/private-a30aac0367f8b50cfd7373f6222d29b4/basic.ics"
                    'user' => ""
                    'pass' => ""
                    'sslignore' => ""
                    'color' => ""
        */
        
        isSameDay(d1,d2) {
            return (d1.getDate()==d2.getDate()) && (d1.getMonth()==d2.getMonth()) && (d1.getFullYear()==d2.getFullYear());
        }
        
        getWeekNumber( date ) {
            let d = new Date(date);
            d.setHours(0,0,0);
            d.setDate(d.getDate()+4-(d.getDay()||7));
            return Math.ceil((((d-new Date(d.getFullYear(),0,1))/8.64e7)+1)/7);
        };            
        
        //
        buildEntry( entry ) {
            const WEEKDAY_NAMES = ["So", "Mo", "Di", "Mi", "Do", "Fr", "Sa"];
            const MONTH_NAMES = ["Jan", "Feb", "Mär", "Apr", "Mai", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Dez"];
        
            let beginDate = new Date( entry.beginDateISO );
            entry.beginTime = beginDate.getTime();
            entry.beginWeekDay = beginDate.getDay(); // 0=Sonntag 6=Samstag
            entry.beginWeekDayName = WEEKDAY_NAMES[entry.beginWeekDay]; 
            entry.beginDay = beginDate.getDate();
            entry.beginMonth = beginDate.getMonth();
            entry.beginMonthName = MONTH_NAMES[entry.beginMonth]; 
            entry.beginYear = beginDate.getFullYear();
            entry.beginHour = beginDate.getHours();
            entry.beginMinute = beginDate.getMinutes();
            entry.beginDate = formatDate(beginDate,  this.DATE_FORMAT);
        
            let currDate = new Date( entry.currDateISO );
            entry.currTime = currDate.getTime();
            entry.currWeekDay = currDate.getDay(); // 0=Sonntag 6=Samstag
            entry.currWeekDayName = WEEKDAY_NAMES[entry.currWeekDay]; 
            entry.currDay = currDate.getDate();
            entry.currMonth = currDate.getMonth();
            entry.currMonthName = MONTH_NAMES[entry.currMonth]; 
            entry.currYear = currDate.getFullYear();
            entry.currHour = currDate.getHours();
            entry.currMinute = currDate.getMinutes();
            entry.currDate = formatDate(currDate,  this.DATE_FORMAT);
            entry.currDateOnly = entry.currYear*10000+entry.currMonth*100+entry.currDay;
        
        
            let endDate = new Date( entry.endDateISO );
            //allDay Korrektur: liefert immer einen Tag zu viel
            if (entry.allDay && endDate.getHours()==0) endDate.setTime( endDate.getTime() - this.DAY_MILLISECONDS);
            entry.endTime = endDate.getTime();
            entry.endWeekDay = endDate.getDay(); // 0=Sonntag 6=Samstag
            entry.endDay = endDate.getDate();
            entry.endMonth = endDate.getMonth();
            entry.endYear = endDate.getFullYear();
            entry.endHour = endDate.getHours();
            entry.endMinute = endDate.getMinutes();
            entry.endDate = formatDate(endDate, this.DATE_FORMAT);
        
            // 
            if (entry.currWeekDay==0 || entry.currWeekDay==6) entry.dayColor = '#f44336'
            else entry.dayColor = 'inherited';
        
            // 
            if (entry.currWeekDay==1) entry.week = this.getWeekNumber(currDate)+'.W';
            else entry.week = '';
        
            // 
            if (entry.currTime < Date.now() ) entry.opacity = '.66'
            else entry.opacity = '1';
        
            // Zeitraumangabe berechnen
            entry.hint = '';
            if ( !this.isSameDay(beginDate, endDate) ) {
                    // mehrtägig
                    if (entry.allDay)
                        entry.timeSpan = 'ganztägig ';
                    else if ( this.isSameDay(beginDate, currDate) ) 
                            entry.timeSpan = 'ab ' + formatDate(beginDate,'hh:mm');
                         else if ( this.isSameDay(endDate, currDate) ) 
                                  entry.timeSpan = 'bis ' + formatDate(endDate,'hh:mm');
                              else 
                                   entry.timeSpan = 'ganztägig ';
                } else {
                    // an einem Tag
                    if (entry.allDay)
                        entry.timeSpan = 'ganztägig';
                    else if ( (entry.beginHour!=entry.endHour) || (entry.beginMinute!=entry.endMinute)  ) 
                             entry.timeSpan = formatDate(beginDate,'hh:mm') + '-' + formatDate(endDate,'hh:mm');
                         else   
                             entry.timeSpan = formatDate(beginDate,'hh:mm');
                }
            return entry;        
        };
        
        
        onBuildHTML() { try {
        
            let json = [];  
            let calTable = getState(this.ICAL_TABLE);
            let inst     = getObject("system.adapter."+this.ICAL_TABLE.substr(0,6));
            let instopt  = inst.native;
            let calendar = {};
            let cal      = {};
            let calOptions = {};
            let todayDate = new Date();
            let today = todayDate.getFullYear()*10000+todayDate.getMonth()*100+todayDate.getDate();
        
        
            for (var i = 0; i < calTable.val.length; i++) { 
              cal = calTable.val[i];
              let entry = {};
              if ( cal._calName != calendar.name ) {
                    calendar = {};
                    // color suchen
                    for (let c = 0; c < instopt.calendars.length; c++ ) {
                        if (cal._calName == instopt.calendars[c].name ) {
                            calendar = instopt.calendars[c];
                            break;
                        }
                    }
                    // options suchen
                    if (this.CALENDAR.hasOwnProperty(cal._calName)) calOptions = this.CALENDAR[cal._calName];
                    else calOptions={};
                }    
                if (calOptions.hasOwnProperty('ignore') && calOptions.ignore ) continue;
        
                if (calOptions.hasOwnProperty('calcolor')) entry.calColor = calOptions.calcolor;
                else if (calendar.color !== "") entry.calColor = calendar.color;
                     else entry.calColor = '#000000';
                entry.color = this.getFontColor( entry.calColor ); 
                if (calOptions.hasOwnProperty('icon')) entry.icon = calOptions.icon;
                else entry.icon='';
        
                entry.date = cal.date;
                entry.event = cal.event;
                entry.calName = cal._calName;
                entry.beginDateISO = cal._date;
                entry.currDateISO = cal._date;
                entry.endDateISO  = cal._end;
                entry.allDay  = cal._allDay; 
                entry.location = cal.location;
        
                entry = this.buildEntry( entry);
        
                if (entry.currDateOnly >= today)
                    json.push( entry );
        
                // Listenansicht
                // in calTable steht nur ein Eintrag für jeden Beginn, für die List-Darstellung
                // sind diese auch je Tag notwendig - hier jetzt bilden 
                if ( (entry.beginDay!=entry.endDay) || (entry.beginMonth!=entry.endMonth) || (entry.beginYear!=entry.endYear) ) {
                    let currTime = new Date(entry.beginDateISO).getTime() + this.DAY_MILLISECONDS;
                    let endTime = new Date(entry.endDateISO).getTime();
                    if (entry.allDay) endTime -= + this.DAY_MILLISECONDS;
                    let dayMax=Math.trunc( 2 + (endTime - currTime) /this. DAY_MILLISECONDS); 
                    entry.hint += ' (Tag 1/'+dayMax+')';
                    let dayCount=2; 
                    while (currTime <= endTime && dayCount<100) {
                        let newEntry = {};
                        Object.assign(newEntry, entry);
                        newEntry.currDateISO = new Date(currTime).toISOString();
                        newEntry = this.buildEntry( newEntry );
                        newEntry.hint += ' (Tag '+dayCount+'/'+dayMax+')';
                        if (newEntry.currDateOnly >= today)
                            json.push( newEntry );
                        currTime = currTime + this.DAY_MILLISECONDS;
                        dayCount++;
                    }
        
                }
            }
        
            // sortieren
            json.sort( (l,r) => {
                      let lv=l['currTime'],rv=r['currTime'];
                      return ((lv < rv) ? -1 : (lv > rv) ? 1 : 0);
                  } );
                
          // build table/list HTML
          for (let i=0; i<=this.MAX_LOG_FOLDER && i<10; i++) {
              let log = this.logs[i];
              log.filter = '';
              log.ts = 0;
              log.idState = 'log'+i;
              if (this.existState(log.idState+'.filter')) log.filter = this.getState(log.idState+'.filter').val;
              if (this.existState(log.idState+'.lastClear')) log.ts = this.getState(log.idState+'.lastClear').val;
        
              this.convertJSON2HTML(json, log);
          }
        } catch(err) { this.logError( 'onBuildHTML: '+err.message ); }  }
        
        
        // color date event calName beginDate endDate allDay
        convertJSON2HTML(json, log) {
        const tmpTable = {
        header : 
        `<tr>
        <th style="text-align:right;"></th>
        <th style="text-align:left;"></th>
        <th style="text-align:left;"></th>
        <th style="text-align:left;"></th>
        <th style="text-align:left;"></th>
        <th style="text-align:left; min-width:12em;">Betreff</th>
        <th style="text-align:left;">Zeit</th>
        <th style="text-align:left;">Ort</th>
        <th style="text-align:left;">Kalendar</th>
        <th style="text-align:left;"></th>
        </tr>`,
        row : 
        `<tr>
        <td style="text-align:right;">
           <span style="display:{showDay}; color:{dayColor}; font-size:1.5em; opacity:1; font-weight:bold;">{currDay}</span>
        </td>
        <td>
           <span style="display:{showDay}; font-size:0.8em; margin-top:0.3em; margin-left:4px; opacity:.8;">{currMonthName}</span>
        </td>
        <td>
           <span style="display:{showDay}; font-size:0.8em; margin-top:0.3em; opacity:.8;">{currWeekDayName}</span>
        </td>
        <td>
          <span style="display:inline-block; width:.8em; height:.8em; margin-top:0.3em; background:{calColor}; border-radius:50%;">&nbsp;</span>
        </td>
        <td>
          <i class='material-icons mdui-center {color}' style='font-size:1.2em;'>{icon}</i>
        </td>
        <td>{event}</td>
        <td><span style="font-size:1.0em; opacity:.8;">{timeSpan} {hint}</span></td>
        <td>{location}</td>
        <td><span style="font-size:0.8em; opacity:.8;color:{calColor};">{calName}</span></td>
        <td></td>
        </tr>`
        }
        
        const tmpList = {
        row : 
        `<div class="mdui-listitem" style="font-size:1em; width:100%; display:flex; opacity:{opacity};">
          <div style="min-width:3.5em;">
            <div style="display:{showDay}; color:{dayColor};">
              <span style="font-size:1.5em; opacity:1; font-weight:bold;">{currDay}</span>
              <span style="font-size:0.8em; margin:4px; opacity:.8;">{currMonthName}<br/>
              {currWeekDayName}</span>
            </div>
            <div style="display:{showDay}; text-align:right; font-size:0.6em; opacity:.6;">{week}</div>
          </div>
          <div style="min-width:1.2em;">
            <div style="width:.8em; height:.8em;  margin:.1em; text-align:center; background:{calColor}; border-radius:50%;">&nbsp;</div>
            <div class="mdui-icon" style="font-size:1.1em; text-align:center; margin-top:0.33em;">{icon}</div>
          </div>
          <div style="width:100%; margin-left:.25em;">
            <div style="">
              <div style="font-size:1.1em;">{event}</div>
            </div>
            <div style="width:100%; display:flex; flex-wrap:wrap; align-items:baseline; justify-content:space-between;">
              <div style="font-size:1.0em; opacity:.8;">
                {timeSpan}
                <span style="font-size:0.8em;">{hint} {location}</span>
              </div>
              <div style="font-size:0.8em; opacity:.8;color:{calColor};">{calName}</div>
            </div>
          </div>
        </div>`}
            // build htmlTable and htmlList
            let htmlTable  = "<table><thead>"+tmpTable.header+"</thead><tbody>";
            for (let [key, value] of Object.entries(log)) htmlTable = htmlTable.replace(new RegExp('{'+key+'}','g'),value);
           
            let htmlList  = "";
            let entry, tr;
            let count = 0;
            // filter as regex?
            if ( log.filter!==undefined && typeof log.filter == 'string' && log.filter.startsWith('/') && log.filter.endsWith('/') && (log.filter.length>=2) )  {
                log.filter = new RegExp(log.filter.substr(1,log.filter.length-2), 'i');
            }
        
            let lastEntry = {};
            for (var i = 0; i < json.length && count<this.MAX_TABLE_ROWS; i++) { 
                entry = json[i];
                if (this.fitsFilter(':' + entry.currDate + ':' + entry.event +':'+entry.calName + ':' + entry.location + ':',log.filter)) {
                    entry.showDay = (lastEntry=={}) || (entry.currDay!=lastEntry.currDay) || (entry.currMonth!=lastEntry.currMonth) || (entry.currYear!=lastEntry.currYear)?'flex':'none';
                    lastEntry = entry;
                    tr = tmpTable.row;    
                    for (let [key, value] of Object.entries(entry)) tr = tr.replace(new RegExp('{'+key+'}','g'),value);
                    htmlTable+=tr;
                    tr = tmpList.row;    
                    for (let [key, value] of Object.entries(entry)) tr = tr.replace(new RegExp('{'+key+'}','g'),value);
                    htmlList+=tr;
                    count++;
                }
            }
            htmlTable+="</body></table>";    
            this.setState(log.idState+'.table', htmlTable);  
            this.setState(log.idState+'.list', htmlList);  
            this.setState(log.idState+'.count', count);  
            this.setState(log.idState+'.lastUpdate', +new Date());  
        }
        
        }
        
        
        // create instance and start
        var mduiShowIcal = new MduiShowIcal( );
        mduiShowIcal.start();
        
        // on script stop, stop instance too
        onStop(function () { 
            mduiShowIcal.stop(); 
        }, 1000 );
    

    Bitte benutzt das Voting rechts unten im Beitrag wenn er euch geholfen hat.
    Immer Daten sichern!

    E 1 Antwort Letzte Antwort
    0
    • sigi234S sigi234

      @Ente sagte in [Vorlage] MDCSS v2: ical Kalendar anzeigen:

      @sigi234

      Hallo siggi234,

      danke für den Install-Screenshot. ;-)

      Screenshot (674)_LI.jpg

      /*
      *** MduiShowIcal
      Dieses Script überwacht den ical-Adapter und erzeugt bei Änderungen an dessen States HTML-List States für die Anzeige als 
      Kalender in Listform mit
      * Tagesauflösung von "von/bis"-Terminen, inkl. Berücksichtigung der Uhrzeiten
      * Tagesdatum, Kalendarfarben aus ical oder optional aus dem Script
      * Termintext und -ort
      * optionalem Icon je Kalendar
      * optionalem "ignore", wenn ein Kalendar unberücksichtigt bleiben soll
      
      Es werden States für n-Logs erzeugt, jedem, Log kann ein Standardfilter mitgegeben werden. In jedem Log-Ordner 
      befindet sich ein list-HTML State, welcher direkt in der vis angezeigt werden kann (jeweils im basic-string (unescaped) Widget). 
      Über optionale Filter als string (Bsp:':Abfall:') oder als RegExp (Bsp:'/Feiertag|Geburtstag/') kann festgelegt werden, 
      welche Einträge beim Aufbau der list-HTML States berücksichtigt werden. 
      Bsp.: 
      log0 Filter: "abfall" oder ":Abfall:" (=Kalendarname) -> Zeigt nur Abfalltermine
      log0 Filter: "ferien" oder ":Ferien:" (=Kalendarname) -> Zeigt nur Ferientermine
      
      
      **** Installation
      Einfach als serverseitiges Script installieren und starten-5 Sek warten-stoppen-starten. Beim 1.Start werden 
      die notwendigen States unter STATE_PATH = '0_userdata.0.mdui.showIcal.' erzeugt. Erst beim 2.Start
      instanziiert das Script die Event-Handler und läuft dann.
      
      **** Konfiguration
      Eigentlich ist keine notwendig.
      Optional in der Funktion MduiShowIcal|doInit() eine Anpassung der KONFIGURATION vornehmen
      Optional Anpassung der tmpList.
        
      **** Dokumentation
      https://github.com/Uhula/ioBroker-Material-Design-Style/wiki/3.5-MduiShowIcal
      
      ###### Um ein Feedback zu erhalten wäre es schön, wenn jeder, der diese Vorlagen nutzt, den  1.Beitrag des Themas positiv bewertet (Pfeil nach oben oder unten ;-) ). Ich kann dann auch abschätzen, ob sich die weitere Pflege lohnt. Thx!
      
      ***** States
      Unter dem STATE_PATH werden die folgenden States erzeugt:
      version : Script-Version, wird verwendet um Script-Updates zu erkennen
      updatePressed : auf true setzen, wenn ein table/list update außerhalb des Intervals erfolgen soll
      
      Weiterhin werden MAX_LOG_FOLDER Unterordner im STATE_PATH erzeugt (N=0-9):
      
      * LogN.table        : enthält die table-HTML für ein basic-string (unescaped) Widget
      * LogN.list         : enthält die list-HTML für ein basic-string (unescaped) Widget
      * LogN.count        : Anzahl der Log-Zeilen (wenn das Log mit '/:error:|:warn:/' gefiltert ist, dann ist es die Anzahl der Fehler/Warnungen)
      * LogN.filter       : Filter, der auch die logCache angewendet wurde im .table/.list zu erzeugen (siehe Filter)
      * LogN.lastUpdate   : Timestamp des letzten Updates
      
      
      ***** Filter
      In den filter-States können sowohl strings (Bsp:'error') als auch RegExp-Strings (Bsp:'/warn|error/') 
      hinterlegt werden. RegExp-Strings werden an den einschließenden  '/' erkannt. Über den ':' kann der Anfang
      eines Feldes mit in den Filter einbezogen werden. 
      Beispiele: 
      '/Feiertag|Geburtstag/' (RegExp) zeigt alle Zeilen an, in denen 'Feiertag' oder 'Geburtstag' in irgendeinem Feld vorkommen
      ':Abfall:' (string) zeigt alle Zeilen an, welche derKalendar 'Abfall' lautet
      'Arzt' (string) zeigt alle Zeilen an, in denen 'Arzt' in irgendeinem Feld vorkommt
      
      **** Lizenz
      (c) 2020 by UH, MIT License, no warranty, use on your own risc
      
      *** Changelog
      2020.05.01 UH 
      * Anpassung an neues MduiBase (intern)
      * Anpassung an MDCSS 2.5
      * Serientermine vor dem aktuellem Datum werden nicht mehr angezeigt
      
      */
      
      // ------------------------------------------------------------------------------------- 
      // MduiBase
      // ------------------------------------------------------------------------------------- 
      
      class MduiBase {
      
          constructor() {
            this.init();
          }
          
          //
          init() {
              // const
              this.DEBUG      = false;
              this.VERSION    = '1.0/2020-01-01';
              this.NAME       = 'mduiBase';
              this.STATE_PATH = '0_userdata.0.mdui.base.';
              this.STATE_UNKNOWN    =  0;
              this.STATE_INSTALLING = 10;
              this.STATE_INSTALLED  = 11;
              this.STATE_STARTING   = 20;
              this.STATE_STARTED    = 21;
              this.STATE_STOPPING   = 30;
              this.STATE_STOPPED    = 31;
          
              // var
              this.state = this.STATE_UNKNOWN;
              this.states = [];
              this.subscribers = [];
              this.schedulers = [];
          
              this.doInit();
          
              // init der states
              this.states.push( { id:'version',     common:{name:'installed script-version', write:false, def:this.VERSION} } );
          }
          
          //
          // start the script/class
          //
          start() {
              // beim 1.Start nur die States erzeugen
              if ( !this.existState("version") || (this.getState('version').val!=this.VERSION) ) {
                  for (let s=0; s<this.states.length; s++) { this.createState( this.states[s].id ); }
                  this.logWarn('first script start, creating states for version '+this.VERSION+', automatic restarting script again in 10 sec ...');
                  setStateDelayed(this.STATE_PATH + 'version', this.VERSION, 3000);
                  setTimeout( this.start.bind(this), 10000 );
                  this.state = this.STATE_INSTALLED; 
                  return;
              }
              switch (this.state) {
                  case this.STATE_UNKNOWN : ;
                  case this.STATE_INSTALLING : ;
                  case this.STATE_INSTALLED : ;
                  case this.STATE_STOPPED : {
                      this.state = this.STATE_STARTING; 
                      if (this.doStart()) {
                          this.log('script started');
                          this.state = this.STATE_STARTED;
                      }
                      break;    
                  }
                  case this.STATE_STARTING : ;
                  case this.STATE_STARTED : {
                      this.logWarn('script already starting/started');
                      break;    
                  }
                  case this.STATE_STOPPING : {
                      this.logWarn('script is stopping, pls start later again');
                      break;    
                  }
            
              } 
          }
          
          //
          // stop the script/class
          //
          stop() {
              switch (this.state) {
                  case this.STATE_STARTED : {
                      this.state = this.STATE_STOPPING; 
                      if (this.doStop()) {
                          for (let i=0; i<this.subscribers.length; i++) if (this.subscribers[i] !== undefined) unsubscribe( this.subscribers[i] );
                          this.subscribers = [];
                          for (let i=0; i<this.schedulers.length; i++) if (this.schedulers[i] !== undefined) clearSchedule( this.schedulers[i] );
                          this.schedulers = [];
                          this.state = this.STATE_STOPPED; 
                          this.log('script stopped');
                      }
                      break;    
                  }
                  default : {
                      this.log('cant stopp script, because not startet');
                  }
              } 
          }
          
          //
          // virtual functions, overwrite it 
          //
          doInit() { return true; }
          doStart() { return true; }
          doStop() { return true; }
          
          // einen on-Handler registrieren
          subscribe( handler ) {
              this.subscribers.push( handler );
          }
          
          // einen timer registrieren
          schedule( handler ) {
              this.schedulers.push( handler );
          }
          
          //
          // tool functions 
          //
          logDebug(msg) { if (this.DEBUG) console.log('['+this.NAME+'] '+msg); }
          log(msg) { console.log('['+this.NAME+'] '+msg); }
          logWarn(msg) { console.warn('['+this.NAME+'] '+msg); }
          logError(msg) { console.error('['+this.NAME+'] '+msg); }
          
          // über den $-Operator nachsehen, ob der state bereits vorhanden ist
          // getState().notExists geht auch, erzeugt aber Warnmeldungen!
          existState(id) {
              return ( $(this.STATE_PATH+id).length==0?false:true);
          }
          
          // wrapper, adds statepath to state-ID
          getState(id) {
              return getState(this.STATE_PATH + id);
          }
          
          // like setState(), but adds statepath to state_ID and checks if state exists, when not, creates it
          setState(id,value) {
              if ( !this.existState(id) ) this.createState(id,value,undefined);
              else setState( this.STATE_PATH + id, value);
          }
          
          // like cresteState(), but adds statepath to state_ID and checks if state exists, when not, creates it
          createState(id,value,common) {
              if ( !this.existState(id) ) {
                  if (common===undefined) {
                      // id im states-Array suchen
                      for (var i=0; i<this.states.length; i++) { 
                          if (this.states[i].id==id) {
                              if (this.states[i].hasOwnProperty('common'))
                                  common = this.states[i].common;
                             break;
                          }   
                      }
                  }
                  if ( (typeof value === 'undefined') && (common.hasOwnProperty('def'))) value = common.def;
                  // unter "0_userdata.0"
                  let obj = {};
                  obj.type = 'state';
                  obj.native = {};
                  obj.common = common;
                  setObject(this.STATE_PATH + id, obj, (err) => {
                          if (err) {
                              this.log('cant write object for state "' + this.STATE_PATH + id + '": ' + err);
                          } else { 
                              this.log('state "' + this.STATE_PATH + id + '" created');
                          }
                  });
          
                  setTimeout( setState, 3000, this.STATE_PATH + id, value );
              }
          }
          
          // true, if str contains filter string or regexp 
          fitsFilter(str, filter) {
              if ( (filter===undefined) || !filter || (filter=='') )
                  return true;
              if ( filter instanceof RegExp )  {
                  if (str.match( filter ) != null) return true;
              } else if (typeof filter == 'string') {
                  if(str.includes(filter)) return true;
              }
              return false;        
          }
          
          //
          escapeRegExp(str) {
              return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); 
          }
          
          // wandelt eine Farbe im hex-Format (#000000) in ein RGB-Array[2] um
          hexToRGB(hex) {
              var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
              return result 
                  ? [parseInt(result[1],16),parseInt(result[2],16),parseInt(result[3],16)]
                  : [0,0,0];
          };
          
          // Helligkeit berechnen
          getLuminance(r, g, b) {
              var a = [r, g, b].map(function (v) {
                  v /= 255;
                  return v <= 0.03928
                      ? v / 12.92
                      : Math.pow( (v + 0.055) / 1.055, 2.4 );
              });
              return a[0] * 0.2126 + a[1] * 0.7152 + a[2] * 0.0722;
          }
          
          // Kontrats berechnen
          getContrast(rgb1, rgb2) {
              var l1 = this.getLuminance(rgb1[0], rgb1[1], rgb1[2]) + 0.05;
              var l2 = this.getLuminance(rgb2[0], rgb2[1], rgb2[2]) + 0.05;
              if ( l1 > l2 ) return l1 / l2 
              else return l2 / l1;
          }
          
          // liefert die fontColor auf Basis der backgroundColor durch Berechnung
          // des Kontrasts
          getFontColor(backgroundColor) {
              if ( this.getContrast(this.hexToRGB(backgroundColor),this.hexToRGB("#000000")) < 6 ) 
                  return "#ffffff";
              else
                  return "#000000";
          }
          
          }
          
          // ------------------------------------------------------------------------------------- 
          // MduiLogHMDevices
          // ------------------------------------------------------------------------------------- 
          
          class MduiShowIcal extends MduiBase {
          
          constructor() {
              super();
          }
          
          doInit() {
            super.doInit();
          
            // const
            this.DEBUG = false;
            this.VERSION = '1.0/2020-03-22';
            this.NAME = 'mduiShowIcal';
            this.DAY_MILLISECONDS = 60 * 60 * 24 * 1000;
          
            // -----------------------  
            // optional: KONFIGURATION
            // -----------------------  
                                 // state-Pfad unter dem die States angelegt werden  
            this.STATE_PATH      = '0_userdata.0.mdui.showIcal.'; 
                                 // Anzahl der Table/List Ordner mit eigenem Filter/View
            this.MAX_LOG_FOLDER  = 3;   
                                 // max.Anzahl der Zeilen für die Table/List Ausgabe
            this.MAX_TABLE_ROWS  = 200; 
                                 // Objekt-Pfad zum ical.x.data.table
            this.ICAL_TABLE      = 'ical.0.data.table';
                                 // siehe: https://github.com/ioBroker/ioBroker.javascript/blob/master/docs/en/javascript.md#formatdate
            this.DATE_FORMAT     = 'W DD.MM.YYYY hh:mm';
                                 // optional können dem Kalendar noch Icons und abweichende
                                 // Farben angegeben werden (diese überschreiben jene aus iCal)
                                 // 'icon'     : 'Icon-Name' (MDCSS/Google WebFont)
                                 // 'calColor' : *#rrggbb' abweichende Kalendarfarbe 
                                 // 'ignore'   : true|false Kalendar komplett ignorieren
            this.CALENDAR        = {'mdui-Abfall'      : {'icon':'delete_outline', 'calcolor':'orange' },
                                    'mdui-Geburtstage' : {'icon':'cake'},
                                    'Familie'          : {'ignore':true}
                                     
                                   };
          
            // -----------------------  
            // ENDE KONFIGURATION
            // -----------------------  
          
            // var
            this.logs = [];
            for (let i=0; i<=this.MAX_LOG_FOLDER && i<10; i++) 
                this.logs.push({filter:'' });
            
          
            // init der states
            this.states.push( { id:'version',     common:{name:'installed script-version', write:false, def:this.VERSION} } );
            this.states.push( { id:'updatePressed',common:{name:'update button pressed', write:true, type:'boolean', def:'false', role:'button' }} );
            
            let defFilter;
            for (let i=0; i<=this.MAX_LOG_FOLDER && i<10; i++) {
                switch (i) {
                    case 1 : defFilter = ':Abfall:'; break;   
                    case 2 : defFilter = 'Geburtstag'; break;   
                    case 3 : defFilter = ''; break;   
                    default: defFilter = undefined;
                }
                this.states.push( { id:'log'+i+'.table',      common:{name:'ioBroker-log as table', write:false, role:'html' }} );
                this.states.push( { id:'log'+i+'.list',       common:{name:'ioBroker-log as list', write:false, role:'html' }} );
                this.states.push( { id:'log'+i+'.count',      common:{name:'ioBroker-log count', write:false, type:'number', def:'0' }} );
                this.states.push( { id:'log'+i+'.filter',     common:{name:'ioBroker-log filter', write:true, def:defFilter}} );
                this.states.push( { id:'log'+i+'.lastUpdate', common:{name:'ioBroker-log last update', write:false, def:'0' }} );
            }
          
            return true;  
          }
          
          // start the script/class
          doStart() {
              super.doStart();
              
              // subscriber erzeugen
              this.subscribe( on( this.STATE_PATH+'updatePressed', obj => { this.onUpdate(obj) } ));
              this.subscribe( on( new RegExp( this.STATE_PATH+'*.filter' ), obj => { this.onFilter(obj) } ));
              this.subscribe( on( this.ICAL_TABLE, obj => { this.onIcalTable(obj) } ));
          
              this.onBuildHTML();
              return true;
          }
          
          // stop the script/class
          doStop() {
              super.doStop();
              return true;
          }
          
          // 
          onUpdate(obj) {
              if (obj.state.val===true) {
                  this.onBuildHTML();
              }
              this.setState('updatePressed', false);
          }
          
          // filter, sort events
          onFilter(obj) {
            this.onBuildHTML();
          }
          
          // Ical table hat sich geändert
          onIcalTable(obj) {
            this.onBuildHTML();
          }
          
          
          
          // creates the HTML states for every log
          /*
          'date' => "→ 16.10.2017" 
          'event' => "9.30 - 16.30 Uhr Stopka " 
          '_class' => "ical_Kerstin ical_today" 
          '_date' => "2017-10-16T07:30:00.000Z" 
          '_end' => "2017-10-16T14:30:00.000Z" 
          '_section' => "" 
          '_IDID' => "040000008200E00074C5B7101A82E008000000007645DC55A6DFC44FB2EC6FEA9EFEA33C100000007688316058136F42AD128D91103543C9" 
          '_allDay' => "false" 
          '_rule' => " " 
          '_calName' => "Kerstin" 
          
          Optionen der ical-Instanz:
              'daysPreview' => "7"
              'colorize' => "false"
              'defColor' => "white"
              'fulltime' => " 00:00"
              'dataPaddingWithZeros' => "true"
              'replaceDates' => "false"
              'language' => "de"
              'everyCalOneColor' => "true"
              'calendars' (array) 
                  '0' (array) 
                      'name' => "Abfall"
                      'url' => "https://calendar.google.com/calendar/ical/ruo0ddgalu03qq2ehpm8imqnk4%40group.calendar.google.com/private-a30aac0367f8b50cfd7373f6222d29b4/basic.ics"
                      'user' => ""
                      'pass' => ""
                      'sslignore' => ""
                      'color' => ""
          */
          
          isSameDay(d1,d2) {
              return (d1.getDate()==d2.getDate()) && (d1.getMonth()==d2.getMonth()) && (d1.getFullYear()==d2.getFullYear());
          }
          
          getWeekNumber( date ) {
              let d = new Date(date);
              d.setHours(0,0,0);
              d.setDate(d.getDate()+4-(d.getDay()||7));
              return Math.ceil((((d-new Date(d.getFullYear(),0,1))/8.64e7)+1)/7);
          };            
          
          //
          buildEntry( entry ) {
              const WEEKDAY_NAMES = ["So", "Mo", "Di", "Mi", "Do", "Fr", "Sa"];
              const MONTH_NAMES = ["Jan", "Feb", "Mär", "Apr", "Mai", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Dez"];
          
              let beginDate = new Date( entry.beginDateISO );
              entry.beginTime = beginDate.getTime();
              entry.beginWeekDay = beginDate.getDay(); // 0=Sonntag 6=Samstag
              entry.beginWeekDayName = WEEKDAY_NAMES[entry.beginWeekDay]; 
              entry.beginDay = beginDate.getDate();
              entry.beginMonth = beginDate.getMonth();
              entry.beginMonthName = MONTH_NAMES[entry.beginMonth]; 
              entry.beginYear = beginDate.getFullYear();
              entry.beginHour = beginDate.getHours();
              entry.beginMinute = beginDate.getMinutes();
              entry.beginDate = formatDate(beginDate,  this.DATE_FORMAT);
          
              let currDate = new Date( entry.currDateISO );
              entry.currTime = currDate.getTime();
              entry.currWeekDay = currDate.getDay(); // 0=Sonntag 6=Samstag
              entry.currWeekDayName = WEEKDAY_NAMES[entry.currWeekDay]; 
              entry.currDay = currDate.getDate();
              entry.currMonth = currDate.getMonth();
              entry.currMonthName = MONTH_NAMES[entry.currMonth]; 
              entry.currYear = currDate.getFullYear();
              entry.currHour = currDate.getHours();
              entry.currMinute = currDate.getMinutes();
              entry.currDate = formatDate(currDate,  this.DATE_FORMAT);
              entry.currDateOnly = entry.currYear*10000+entry.currMonth*100+entry.currDay;
          
          
              let endDate = new Date( entry.endDateISO );
              //allDay Korrektur: liefert immer einen Tag zu viel
              if (entry.allDay && endDate.getHours()==0) endDate.setTime( endDate.getTime() - this.DAY_MILLISECONDS);
              entry.endTime = endDate.getTime();
              entry.endWeekDay = endDate.getDay(); // 0=Sonntag 6=Samstag
              entry.endDay = endDate.getDate();
              entry.endMonth = endDate.getMonth();
              entry.endYear = endDate.getFullYear();
              entry.endHour = endDate.getHours();
              entry.endMinute = endDate.getMinutes();
              entry.endDate = formatDate(endDate, this.DATE_FORMAT);
          
              // 
              if (entry.currWeekDay==0 || entry.currWeekDay==6) entry.dayColor = '#f44336'
              else entry.dayColor = 'inherited';
          
              // 
              if (entry.currWeekDay==1) entry.week = this.getWeekNumber(currDate)+'.W';
              else entry.week = '';
          
              // 
              if (entry.currTime < Date.now() ) entry.opacity = '.66'
              else entry.opacity = '1';
          
              // Zeitraumangabe berechnen
              entry.hint = '';
              if ( !this.isSameDay(beginDate, endDate) ) {
                      // mehrtägig
                      if (entry.allDay)
                          entry.timeSpan = 'ganztägig ';
                      else if ( this.isSameDay(beginDate, currDate) ) 
                              entry.timeSpan = 'ab ' + formatDate(beginDate,'hh:mm');
                           else if ( this.isSameDay(endDate, currDate) ) 
                                    entry.timeSpan = 'bis ' + formatDate(endDate,'hh:mm');
                                else 
                                     entry.timeSpan = 'ganztägig ';
                  } else {
                      // an einem Tag
                      if (entry.allDay)
                          entry.timeSpan = 'ganztägig';
                      else if ( (entry.beginHour!=entry.endHour) || (entry.beginMinute!=entry.endMinute)  ) 
                               entry.timeSpan = formatDate(beginDate,'hh:mm') + '-' + formatDate(endDate,'hh:mm');
                           else   
                               entry.timeSpan = formatDate(beginDate,'hh:mm');
                  }
              return entry;        
          };
          
          
          onBuildHTML() { try {
          
              let json = [];  
              let calTable = getState(this.ICAL_TABLE);
              let inst     = getObject("system.adapter."+this.ICAL_TABLE.substr(0,6));
              let instopt  = inst.native;
              let calendar = {};
              let cal      = {};
              let calOptions = {};
              let todayDate = new Date();
              let today = todayDate.getFullYear()*10000+todayDate.getMonth()*100+todayDate.getDate();
          
          
              for (var i = 0; i < calTable.val.length; i++) { 
                cal = calTable.val[i];
                let entry = {};
                if ( cal._calName != calendar.name ) {
                      calendar = {};
                      // color suchen
                      for (let c = 0; c < instopt.calendars.length; c++ ) {
                          if (cal._calName == instopt.calendars[c].name ) {
                              calendar = instopt.calendars[c];
                              break;
                          }
                      }
                      // options suchen
                      if (this.CALENDAR.hasOwnProperty(cal._calName)) calOptions = this.CALENDAR[cal._calName];
                      else calOptions={};
                  }    
                  if (calOptions.hasOwnProperty('ignore') && calOptions.ignore ) continue;
          
                  if (calOptions.hasOwnProperty('calcolor')) entry.calColor = calOptions.calcolor;
                  else if (calendar.color !== "") entry.calColor = calendar.color;
                       else entry.calColor = '#000000';
                  entry.color = this.getFontColor( entry.calColor ); 
                  if (calOptions.hasOwnProperty('icon')) entry.icon = calOptions.icon;
                  else entry.icon='';
          
                  entry.date = cal.date;
                  entry.event = cal.event;
                  entry.calName = cal._calName;
                  entry.beginDateISO = cal._date;
                  entry.currDateISO = cal._date;
                  entry.endDateISO  = cal._end;
                  entry.allDay  = cal._allDay; 
                  entry.location = cal.location;
          
                  entry = this.buildEntry( entry);
          
                  if (entry.currDateOnly >= today)
                      json.push( entry );
          
                  // Listenansicht
                  // in calTable steht nur ein Eintrag für jeden Beginn, für die List-Darstellung
                  // sind diese auch je Tag notwendig - hier jetzt bilden 
                  if ( (entry.beginDay!=entry.endDay) || (entry.beginMonth!=entry.endMonth) || (entry.beginYear!=entry.endYear) ) {
                      let currTime = new Date(entry.beginDateISO).getTime() + this.DAY_MILLISECONDS;
                      let endTime = new Date(entry.endDateISO).getTime();
                      if (entry.allDay) endTime -= + this.DAY_MILLISECONDS;
                      let dayMax=Math.trunc( 2 + (endTime - currTime) /this. DAY_MILLISECONDS); 
                      entry.hint += ' (Tag 1/'+dayMax+')';
                      let dayCount=2; 
                      while (currTime <= endTime && dayCount<100) {
                          let newEntry = {};
                          Object.assign(newEntry, entry);
                          newEntry.currDateISO = new Date(currTime).toISOString();
                          newEntry = this.buildEntry( newEntry );
                          newEntry.hint += ' (Tag '+dayCount+'/'+dayMax+')';
                          if (newEntry.currDateOnly >= today)
                              json.push( newEntry );
                          currTime = currTime + this.DAY_MILLISECONDS;
                          dayCount++;
                      }
          
                  }
              }
          
              // sortieren
              json.sort( (l,r) => {
                        let lv=l['currTime'],rv=r['currTime'];
                        return ((lv < rv) ? -1 : (lv > rv) ? 1 : 0);
                    } );
                  
            // build table/list HTML
            for (let i=0; i<=this.MAX_LOG_FOLDER && i<10; i++) {
                let log = this.logs[i];
                log.filter = '';
                log.ts = 0;
                log.idState = 'log'+i;
                if (this.existState(log.idState+'.filter')) log.filter = this.getState(log.idState+'.filter').val;
                if (this.existState(log.idState+'.lastClear')) log.ts = this.getState(log.idState+'.lastClear').val;
          
                this.convertJSON2HTML(json, log);
            }
          } catch(err) { this.logError( 'onBuildHTML: '+err.message ); }  }
          
          
          // color date event calName beginDate endDate allDay
          convertJSON2HTML(json, log) {
          const tmpTable = {
          header : 
          `<tr>
          <th style="text-align:right;"></th>
          <th style="text-align:left;"></th>
          <th style="text-align:left;"></th>
          <th style="text-align:left;"></th>
          <th style="text-align:left;"></th>
          <th style="text-align:left; min-width:12em;">Betreff</th>
          <th style="text-align:left;">Zeit</th>
          <th style="text-align:left;">Ort</th>
          <th style="text-align:left;">Kalendar</th>
          <th style="text-align:left;"></th>
          </tr>`,
          row : 
          `<tr>
          <td style="text-align:right;">
             <span style="display:{showDay}; color:{dayColor}; font-size:1.5em; opacity:1; font-weight:bold;">{currDay}</span>
          </td>
          <td>
             <span style="display:{showDay}; font-size:0.8em; margin-top:0.3em; margin-left:4px; opacity:.8;">{currMonthName}</span>
          </td>
          <td>
             <span style="display:{showDay}; font-size:0.8em; margin-top:0.3em; opacity:.8;">{currWeekDayName}</span>
          </td>
          <td>
            <span style="display:inline-block; width:.8em; height:.8em; margin-top:0.3em; background:{calColor}; border-radius:50%;">&nbsp;</span>
          </td>
          <td>
            <i class='material-icons mdui-center {color}' style='font-size:1.2em;'>{icon}</i>
          </td>
          <td>{event}</td>
          <td><span style="font-size:1.0em; opacity:.8;">{timeSpan} {hint}</span></td>
          <td>{location}</td>
          <td><span style="font-size:0.8em; opacity:.8;color:{calColor};">{calName}</span></td>
          <td></td>
          </tr>`
          }
          
          const tmpList = {
          row : 
          `<div class="mdui-listitem" style="font-size:1em; width:100%; display:flex; opacity:{opacity};">
            <div style="min-width:3.5em;">
              <div style="display:{showDay}; color:{dayColor};">
                <span style="font-size:1.5em; opacity:1; font-weight:bold;">{currDay}</span>
                <span style="font-size:0.8em; margin:4px; opacity:.8;">{currMonthName}<br/>
                {currWeekDayName}</span>
              </div>
              <div style="display:{showDay}; text-align:right; font-size:0.6em; opacity:.6;">{week}</div>
            </div>
            <div style="min-width:1.2em;">
              <div style="width:.8em; height:.8em;  margin:.1em; text-align:center; background:{calColor}; border-radius:50%;">&nbsp;</div>
              <div class="mdui-icon" style="font-size:1.1em; text-align:center; margin-top:0.33em;">{icon}</div>
            </div>
            <div style="width:100%; margin-left:.25em;">
              <div style="">
                <div style="font-size:1.1em;">{event}</div>
              </div>
              <div style="width:100%; display:flex; flex-wrap:wrap; align-items:baseline; justify-content:space-between;">
                <div style="font-size:1.0em; opacity:.8;">
                  {timeSpan}
                  <span style="font-size:0.8em;">{hint} {location}</span>
                </div>
                <div style="font-size:0.8em; opacity:.8;color:{calColor};">{calName}</div>
              </div>
            </div>
          </div>`}
              // build htmlTable and htmlList
              let htmlTable  = "<table><thead>"+tmpTable.header+"</thead><tbody>";
              for (let [key, value] of Object.entries(log)) htmlTable = htmlTable.replace(new RegExp('{'+key+'}','g'),value);
             
              let htmlList  = "";
              let entry, tr;
              let count = 0;
              // filter as regex?
              if ( log.filter!==undefined && typeof log.filter == 'string' && log.filter.startsWith('/') && log.filter.endsWith('/') && (log.filter.length>=2) )  {
                  log.filter = new RegExp(log.filter.substr(1,log.filter.length-2), 'i');
              }
          
              let lastEntry = {};
              for (var i = 0; i < json.length && count<this.MAX_TABLE_ROWS; i++) { 
                  entry = json[i];
                  if (this.fitsFilter(':' + entry.currDate + ':' + entry.event +':'+entry.calName + ':' + entry.location + ':',log.filter)) {
                      entry.showDay = (lastEntry=={}) || (entry.currDay!=lastEntry.currDay) || (entry.currMonth!=lastEntry.currMonth) || (entry.currYear!=lastEntry.currYear)?'flex':'none';
                      lastEntry = entry;
                      tr = tmpTable.row;    
                      for (let [key, value] of Object.entries(entry)) tr = tr.replace(new RegExp('{'+key+'}','g'),value);
                      htmlTable+=tr;
                      tr = tmpList.row;    
                      for (let [key, value] of Object.entries(entry)) tr = tr.replace(new RegExp('{'+key+'}','g'),value);
                      htmlList+=tr;
                      count++;
                  }
              }
              htmlTable+="</body></table>";    
              this.setState(log.idState+'.table', htmlTable);  
              this.setState(log.idState+'.list', htmlList);  
              this.setState(log.idState+'.count', count);  
              this.setState(log.idState+'.lastUpdate', +new Date());  
          }
          
          }
          
          
          // create instance and start
          var mduiShowIcal = new MduiShowIcal( );
          mduiShowIcal.start();
          
          // on script stop, stop instance too
          onStop(function () { 
              mduiShowIcal.stop(); 
          }, 1000 );
      
      E Offline
      E Offline
      Ente
      schrieb am zuletzt editiert von Ente
      #44

      @sigi234

      Skript läuft. Vielen Dank.

      Tut mir leid sigi. Wie bekomme ich das nun in meine vis integriert. Entschuldige bitte die Dummy-Frage.

      sigi234S 1 Antwort Letzte Antwort
      0
      • E Ente

        @sigi234

        Skript läuft. Vielen Dank.

        Tut mir leid sigi. Wie bekomme ich das nun in meine vis integriert. Entschuldige bitte die Dummy-Frage.

        sigi234S Online
        sigi234S Online
        sigi234
        Forum Testing Most Active
        schrieb am zuletzt editiert von
        #45

        @Ente sagte in [Vorlage] MDCSS v2: ical Kalendar anzeigen:

        @sigi234

        Skript läuft. Vielen Dank.

        Tut mir leid sigi. Wie bekomme ich das nun in meine vis integriert. Entschuldige bitte die Dummy-Frage.

        Es werden States für n-Logs erzeugt, jedem, Log kann ein Standardfilter mitgegeben werden. In jedem Log-Ordner
        befindet sich ein list-HTML State, welcher direkt in der vis angezeigt werden kann (jeweils im basic-string (unescaped) Widget).

        Bitte benutzt das Voting rechts unten im Beitrag wenn er euch geholfen hat.
        Immer Daten sichern!

        E 1 Antwort Letzte Antwort
        0
        • sigi234S sigi234

          @Ente sagte in [Vorlage] MDCSS v2: ical Kalendar anzeigen:

          @sigi234

          Skript läuft. Vielen Dank.

          Tut mir leid sigi. Wie bekomme ich das nun in meine vis integriert. Entschuldige bitte die Dummy-Frage.

          Es werden States für n-Logs erzeugt, jedem, Log kann ein Standardfilter mitgegeben werden. In jedem Log-Ordner
          befindet sich ein list-HTML State, welcher direkt in der vis angezeigt werden kann (jeweils im basic-string (unescaped) Widget).

          E Offline
          E Offline
          Ente
          schrieb am zuletzt editiert von Ente
          #46

          @sigi234 said in [Vorlage] MDCSS v2: ical Kalendar anzeigen:

          @Ente sagte in [Vorlage] MDCSS v2: ical Kalendar anzeigen:

          @sigi234

          Skript läuft. Vielen Dank.

          Tut mir leid sigi. Wie bekomme ich das nun in meine vis integriert. Entschuldige bitte die Dummy-Frage.

          Es werden States für n-Logs erzeugt, jedem, Log kann ein Standardfilter mitgegeben werden. In jedem Log-Ordner
          befindet sich ein list-HTML State, welcher direkt in der vis angezeigt werden kann (jeweils im basic-string (unescaped) Widget).

          Genau das habe ich gerade gefunden. Es zeigt auch die Termine an,

          feb6d00b-f448-415c-a618-733025c42ac5-image.png

          leider nicht so wie in dem Bild im 1. Post. bzw. wie hier:

          https://forum.iobroker.net/topic/31635/vorlage-mdcss-v2-ical-kalendar-anzeigen/15
          1ad94760-95e1-46fb-ac36-f89d3a9b77ad-image.png

          Ich vermute mal, dass ich das im Skript selbst ändern muss. Mal sehen.

          Edit: Das Datum erscheint schon einmal. Jetzt will ich noch die Farben ändern. Den Filter habe ich auch nicht.

          sigi234S 1 Antwort Letzte Antwort
          0
          • E Ente

            @sigi234 said in [Vorlage] MDCSS v2: ical Kalendar anzeigen:

            @Ente sagte in [Vorlage] MDCSS v2: ical Kalendar anzeigen:

            @sigi234

            Skript läuft. Vielen Dank.

            Tut mir leid sigi. Wie bekomme ich das nun in meine vis integriert. Entschuldige bitte die Dummy-Frage.

            Es werden States für n-Logs erzeugt, jedem, Log kann ein Standardfilter mitgegeben werden. In jedem Log-Ordner
            befindet sich ein list-HTML State, welcher direkt in der vis angezeigt werden kann (jeweils im basic-string (unescaped) Widget).

            Genau das habe ich gerade gefunden. Es zeigt auch die Termine an,

            feb6d00b-f448-415c-a618-733025c42ac5-image.png

            leider nicht so wie in dem Bild im 1. Post. bzw. wie hier:

            https://forum.iobroker.net/topic/31635/vorlage-mdcss-v2-ical-kalendar-anzeigen/15
            1ad94760-95e1-46fb-ac36-f89d3a9b77ad-image.png

            Ich vermute mal, dass ich das im Skript selbst ändern muss. Mal sehen.

            Edit: Das Datum erscheint schon einmal. Jetzt will ich noch die Farben ändern. Den Filter habe ich auch nicht.

            sigi234S Online
            sigi234S Online
            sigi234
            Forum Testing Most Active
            schrieb am zuletzt editiert von sigi234
            #47

            @Ente

            Hast du die Vorlage heruntergeladen und als View importiert?

            https://github.com/Uhula/ioBroker-Material-Design-Style/tree/master/templates/MduiShowIcal

            Bitte benutzt das Voting rechts unten im Beitrag wenn er euch geholfen hat.
            Immer Daten sichern!

            E 1 Antwort Letzte Antwort
            0
            • sigi234S sigi234

              @Ente

              Hast du die Vorlage heruntergeladen und als View importiert?

              https://github.com/Uhula/ioBroker-Material-Design-Style/tree/master/templates/MduiShowIcal

              E Offline
              E Offline
              Ente
              schrieb am zuletzt editiert von
              #48

              @sigi234 said in [Vorlage] MDCSS v2: ical Kalendar anzeigen:

              @Ente

              Hast du die Vorlage heruntergeladen und als View importiert?

              https://github.com/Uhula/ioBroker-Material-Design-Style/tree/master/templates/MduiShowIcal

              Ja, den JS von MduiShowIcal_Tableview.json und als View importiert. Das Ergebnis, naja:

              0ac27e47-3617-4816-886a-1fdd63e62982-image.png

              Das ganze verstehe ich nicht. Das Anzeigen der Termine reicht.

              sigi234S 1 Antwort Letzte Antwort
              0
              • E Ente

                @sigi234 said in [Vorlage] MDCSS v2: ical Kalendar anzeigen:

                @Ente

                Hast du die Vorlage heruntergeladen und als View importiert?

                https://github.com/Uhula/ioBroker-Material-Design-Style/tree/master/templates/MduiShowIcal

                Ja, den JS von MduiShowIcal_Tableview.json und als View importiert. Das Ergebnis, naja:

                0ac27e47-3617-4816-886a-1fdd63e62982-image.png

                Das ganze verstehe ich nicht. Das Anzeigen der Termine reicht.

                sigi234S Online
                sigi234S Online
                sigi234
                Forum Testing Most Active
                schrieb am zuletzt editiert von
                #49

                @Ente

                Welche Version hast du von MDCSS ?

                Bitte benutzt das Voting rechts unten im Beitrag wenn er euch geholfen hat.
                Immer Daten sichern!

                E 1 Antwort Letzte Antwort
                0
                • sigi234S sigi234

                  @Ente

                  Welche Version hast du von MDCSS ?

                  E Offline
                  E Offline
                  Ente
                  schrieb am zuletzt editiert von
                  #50

                  @sigi234 said in [Vorlage] MDCSS v2: ical Kalendar anzeigen:

                  @Ente

                  Welche Version hast du von MDCSS ?

                  Äh?? Wo finde ich das?

                  sigi234S 1 Antwort Letzte Antwort
                  0
                  • E Ente

                    @sigi234 said in [Vorlage] MDCSS v2: ical Kalendar anzeigen:

                    @Ente

                    Welche Version hast du von MDCSS ?

                    Äh?? Wo finde ich das?

                    sigi234S Online
                    sigi234S Online
                    sigi234
                    Forum Testing Most Active
                    schrieb am zuletzt editiert von
                    #51

                    @Ente sagte in [Vorlage] MDCSS v2: ical Kalendar anzeigen:

                    @sigi234 said in [Vorlage] MDCSS v2: ical Kalendar anzeigen:

                    @Ente

                    Welche Version hast du von MDCSS ?

                    Äh?? Wo finde ich das?

                    Screenshot (679)_LI.jpg

                    Bitte benutzt das Voting rechts unten im Beitrag wenn er euch geholfen hat.
                    Immer Daten sichern!

                    E 1 Antwort Letzte Antwort
                    0
                    • sigi234S sigi234

                      @Ente sagte in [Vorlage] MDCSS v2: ical Kalendar anzeigen:

                      @sigi234 said in [Vorlage] MDCSS v2: ical Kalendar anzeigen:

                      @Ente

                      Welche Version hast du von MDCSS ?

                      Äh?? Wo finde ich das?

                      Screenshot (679)_LI.jpg

                      E Offline
                      E Offline
                      Ente
                      schrieb am zuletzt editiert von Ente
                      #52

                      @sigi234 said in [Vorlage] MDCSS v2: ical Kalendar anzeigen:

                      @Ente sagte in [Vorlage] MDCSS v2: ical Kalendar anzeigen:

                      @sigi234 said in [Vorlage] MDCSS v2: ical Kalendar anzeigen:

                      @Ente

                      Welche Version hast du von MDCSS ?

                      Äh?? Wo finde ich das?

                      Screenshot (679)_LI.jpg

                      Hab das Skript jetzt eingefügt. > 2.5

                      Diese Objects habe allerdings ich nicht:

                      a95da2c1-9777-4562-b34b-90108d967337-image.png

                      Bei User.Datea habe ich nur das:

                      82a25b33-1595-4d31-886d-c10049998f3e-image.png

                      Irgendetwas habe ich grundsätzlich falsch gemacht.

                      E 1 Antwort Letzte Antwort
                      0
                      • E Ente

                        @sigi234 said in [Vorlage] MDCSS v2: ical Kalendar anzeigen:

                        @Ente sagte in [Vorlage] MDCSS v2: ical Kalendar anzeigen:

                        @sigi234 said in [Vorlage] MDCSS v2: ical Kalendar anzeigen:

                        @Ente

                        Welche Version hast du von MDCSS ?

                        Äh?? Wo finde ich das?

                        Screenshot (679)_LI.jpg

                        Hab das Skript jetzt eingefügt. > 2.5

                        Diese Objects habe allerdings ich nicht:

                        a95da2c1-9777-4562-b34b-90108d967337-image.png

                        Bei User.Datea habe ich nur das:

                        82a25b33-1595-4d31-886d-c10049998f3e-image.png

                        Irgendetwas habe ich grundsätzlich falsch gemacht.

                        E Offline
                        E Offline
                        Ente
                        schrieb am zuletzt editiert von Ente
                        #53

                        Hallo,

                        wie bekomme ich die Einträge in der view in weiß:

                        3605cf02-589f-4329-93c0-daefbe795cf3-image.png

                        Im Edit-Modus sind sie es.

                        Edit: Gefunden:

                        root.mdui-runtime {
                        --content-background: #f8f8f8;
                        --design-font-color: #000000;
                        --frame-color:#cfcfcf;

                        1 Antwort Letzte Antwort
                        0
                        • H Offline
                          H Offline
                          hendrik87
                          schrieb am zuletzt editiert von
                          #54

                          Hallo

                          Gibt es auch eine Möglichkeit sich die freien Tage anzeigen zu lassen?

                          ChaotC 1 Antwort Letzte Antwort
                          0
                          • H hendrik87

                            Hallo

                            Gibt es auch eine Möglichkeit sich die freien Tage anzeigen zu lassen?

                            ChaotC Offline
                            ChaotC Offline
                            Chaot
                            schrieb am zuletzt editiert von
                            #55

                            @hendrik87 Was meinst du? Die Tage ohne Eintrag?
                            Habe ich noch nicht probiert, aber versuche doch mal den Filter auf

                            " "
                            

                            zu setzen und schau was passiert.

                            ioBroker auf NUC unter Proxmox; VIS: 12" Touchscreen und 17" Touch; Lichtsteuerung, Thermometer und Sensoren: Tasmota (39); Ambiente Beleuchtung: WLED (9); Heizung: DECT Thermostate (9) an Fritz 6690; EMS-ESP; 1 Echo V2; 3 Echo DOT; 1 Echo Connect; 2 Echo Show 5; Unifi Ap-Ac Lite.

                            H 1 Antwort Letzte Antwort
                            0
                            • ChaotC Chaot

                              @hendrik87 Was meinst du? Die Tage ohne Eintrag?
                              Habe ich noch nicht probiert, aber versuche doch mal den Filter auf

                              " "
                              

                              zu setzen und schau was passiert.

                              H Offline
                              H Offline
                              hendrik87
                              schrieb am zuletzt editiert von
                              #56

                              @chaot

                              Die Tage wo es keinen Termin zu gibt sollen auch angezeigt werden. Also in meinem Fall der 28, 30, 31, ....
                              7997e083-d160-4a92-87e6-b6bf2b4b49b2-grafik.png

                              Eigentlich bin ich auf der Suche nach einem monatsweisen Zeilenkalender.
                              d82a5fed-789a-4e0b-a9d4-c0f19fb65e11-grafik.png

                              Da habe ich mit dem MDCSS bislang die beste Lösung gefunden.

                              1 Antwort Letzte Antwort
                              0
                              Antworten
                              • In einem neuen Thema antworten
                              Anmelden zum Antworten
                              • Älteste zuerst
                              • Neuste zuerst
                              • Meiste Stimmen


                              Support us

                              ioBroker
                              Community Adapters
                              Donate

                              829

                              Online

                              32.4k

                              Benutzer

                              81.4k

                              Themen

                              1.3m

                              Beiträge
                              Community
                              Impressum | Datenschutz-Bestimmungen | Nutzungsbedingungen | Einwilligungseinstellungen
                              ioBroker Community 2014-2025
                              logo
                              • Anmelden

                              • Du hast noch kein Konto? Registrieren

                              • Anmelden oder registrieren, um zu suchen
                              • Erster Beitrag
                                Letzter Beitrag
                              0
                              • Home
                              • Aktuell
                              • Tags
                              • Ungelesen 0
                              • Kategorien
                              • Unreplied
                              • Beliebt
                              • GitHub
                              • Docu
                              • Hilfe