28. 06. 2017 Valentina Da Rold NetEye

Erstellen eines neuen Themes für Icinga Web 2

Theming 1200x628

Icinga Web 2 ist ein leistungsstarkes PHP-Framework für Webapplikationen, das sich vor Allem durch sein übersichtliches, minimalistisches Design auszeichnet. Es ist schnell, responsive, benutzerfreundlich und einfach erweiterbar. Folgt man der auf dem offiziellen Repository beschriebenen Konfigurations-Prozedur ist auch die Installation ein Leichtes. (siehe Verlinkung am Ende des Artikels)

Neben der Systemkonfiguration, haben die Benutzer auch die Möglichkeit persönliche Einstellungen wie z.B. Sprache, Zeitzone und Theme vorzunehmen. Das Ziel dieses Artikels ist es aufzuzeigen wie ein komplett neues Theme für die Personalisierung der Icinga-Benutzeroberfläche, erstellt werden kann.

Beginnen wir also ganz am Anfang. Ein Style ist eine Sammlung von Attributen, welche das optische Erscheinungsbild einer Ansicht bzw. eines Fensters definiert. Ein Style kann Attribute wie Höhe, Padding, Farbe und Größe des Textes, Hintergrundfarbe und viele weitere festlegen. Ein Theme ist ein Style der innerhalb einer Software oder einer App zur Anwendung kommt. Wenn ein Style als Theme verwendet wird, werden die darin definierten Attribute für jede Bildschirmseite angewandt.

Icinga Web 2 basiert auf Less. Less ist ein CSS Pre-Processor, das bedeutet es erweitert CSS. Die Erweiterung erfolgt über das Hinzufügen von Features, welche die Integration von Variablen, Mixins (Snippets wiederverwendbaren Codes), Funktionen und vielen weiteren Techniken erlauben. Dadurch wird es einfacher CSS Code zu schreiben und zu erweitern, was wiederum die Nutzbarkeit in Hinblick auf das Erstellen von Themes enorm steigert. Icinga Web 2 kompiliert die Less Files automatisch, die dann vom Browser wie normale CSS Files verarbeitet werden.

Der Ordner /themes/

Alle Theme-Files von Icinga Web 2 sind im Ordner /public/ enthalten. Darin sind außerdem folgende Unterordner enthalten: css, js, font e images. Im Ordner /public/css/themes/ befindet sich das primäre Theme, das standardmäßig vom System geladen wird. Der einfachste Weg um die Benutzeroberfläche zu personalisieren ist das Erstellen eines neuen .less Files im Ordner themes. Diese Herangehensweise eignet sich besonders wenn man die Farbe und das Logo der Weboberfläche verändern möchte. Hierfür reicht es aus, die verwendeten Variablen zu kopieren und die gewünschten Werte einzufügen.

@icinga-blue: #4CAF50;
@gray-lighter: #BDBDBD;
@link-color: #388E3C; 

#icinga-logo {   
    background-image: url('../img/your_theme/your_logo.png');
}

Erstellen wir beispielsweise ein File mit dem Namen mein_theme.less und fügen dort den obenstehenden Code ein. Wie Sie sehen, erhalten wir eine grüne Version der Icinga Weboberfläche.

Von so:

Icinga blue

Auf so:

Icinga green

Ich empfehle Ihnen, ein einziges File zu verwenden um kleinere Personalisierungen vorzunehmen. Was aber, wenn wir die komplette Grafik verändern möchten?!

Erstellen mehrere Theme Files

In einem umfassenden CSS Projekt ist es wichtig den Code sehr übersichtlich zu strukturieren. Daher empfehle ich Ihnen in /public/css/ einen personalisierten Ordner zu erstellen und dort alle Style Files abzulegen. Zu beachten ist jedoch, dass diese Änderungen von Icinga nicht automatisch angewandt werden.

Anders als bei Less, wurde beim Icinga Web Projekt die Funktion @import deaktiviert. Das bedeutet, dass Sie die neuen Style Files manuell hochladen müssen. Dafür müssen Sie das File StyleSheet.php verändern, welches sich im Ordner /usr/share/php/Icinga/Web/ befindet und ein langes Array mit allen Theme Files enthält.

 /**
 * Array of core LESS files Web 2 sends to the client
 *
 * @var string[]
 */
 protected static $lessFiles = array(
 '../application/fonts/fontello-ifont/css/ifont-embedded.css',
 'css/vendor/normalize.css',
 'css/vendor/tipsy.css',
 'css/icinga/base.less',
 'css/icinga/badges.less',
 'css/icinga/mixins.less',
 'css/icinga/grid.less',
 'css/icinga/nav.less',
 'css/icinga/main.less',
 'css/icinga/animation.less',
 'css/icinga/layout.less',
 'css/icinga/layout-structure.less',
 'css/icinga/menu.less',
 'css/icinga/tabs.less',
 'css/icinga/forms.less',
 'css/icinga/setup.less',
 'css/icinga/widgets.less',
 'css/icinga/login.less',
 'css/icinga/about.less',
 'css/icinga/controls.less',
 'css/icinga/dev.less',
 'css/icinga/spinner.less',
 'css/icinga/compat.less',
 'css/icinga/print.less',
 'css/icinga/responsive.less',
 );

Es ist ausreichend, die Files des Custom-Themes hinzuzufügen.

/**
 * Array of core LESS files Web 2 sends to the client
 *
 * @var string[]
 */
 protected static $lessFiles = array(
 '../application/fonts/fontello-ifont/css/ifont-embedded.css',
 'css/vendor/normalize.css',
 'css/vendor/tipsy.css',
 'css/icinga/base.less',
 'css/icinga/badges.less',
 'css/icinga/mixins.less',
 'css/icinga/grid.less',
 'css/icinga/nav.less',
 'css/icinga/main.less',
 'css/icinga/animation.less',
 'css/icinga/layout.less',
 'css/icinga/layout-structure.less',
 'css/icinga/menu.less',
 'css/icinga/tabs.less',
 'css/icinga/forms.less',
 'css/icinga/setup.less',
 'css/icinga/widgets.less',
 'css/icinga/login.less',
 'css/icinga/about.less',
 'css/icinga/controls.less',
 'css/icinga/dev.less',
 'css/icinga/spinner.less',
 'css/icinga/compat.less',
 'css/icinga/print.less',
 'css/icinga/responsive.less',

 'css/your_theme/mixins.less',
 'css/your_theme/nav.less',
 'css/your_theme/base.less',
 'css/your_theme/menu.less',
 'css/your_theme/layout.less',
 'css/your_theme/tabs.less',
 'css/your_theme/main.less',
 'css/your_theme/forms.less',
 'css/your_theme/login.less',
 'css/your_theme/controls.less',
 );

Struktur eines Custom-Themes

Ich empfehle Ihnen die Struktur beizubehalten die im Icinga Web Theme genutzt wird. Mit anderen Worten: Erstellen Sie die Files mit denselben Namen wie im Icinga Theme und fügen Sie dort die Style-Regeln der Elemente ein.

Um dies zu tun, reicht es aus den vom System verwendeten HTML Tag auszulesen und herauszufinden wo der Style des Elements erstellt wird. Um die Elemente der Weboberfläche so einfach wie möglich zu analysieren, empfehle ich Ihnen den automatischen Reload der Seite zu deaktivieren: Gehen Sie zum Suchbalken, drücken Sie SHIFT + TAB bis der Text „Disable auto refresh“ erscheint. Drücken Sie nun ENTER um den Reload zu deaktivieren.

Auf diese Art und Weise ist es einfacher, herauszufinden wo der Style der verschiedenen Elemente erstellt wird, die Codestruktur geordnet zu halten und die Struktur des Themes zu verstehen.

In der Abbildung unten sehen Sie z.B. die Unterschiede zwischen dem Standard-Icinga-Theme (links) und dem Theme das ich für NetEye erstellt habe.

Icinga vs NetEye

Für diese Anpassung habe ich das File menu.less verwendet. Das Mockup des Designers sieht ein komplettes Restyling der Sektion „User“ vor: Die User-Settings sollen durch ein Zahnrad-Icon dargestellt werden und der Logout solle über das On/Off-Icon erfolgen. Beide Icons sollen direkt neben dem Namen des angemeldeten Users, im Footer der Sidebar dargestellt werden. Direkt darüber soll das NetEye Logo positioniert werden.

Sehen wir uns nun also den entsprechenden Code an.

// This first level part is used for styling the <ul class="nav nav-level-1"><li class="nav-item user-nav-item"> element
.first-level-item {
    position: fixed;
    bottom: 0;
    height: 3.5em;
    width: 16em;
    padding: 0 .5em;
    display: flex;
    align-items: center;
    justify-content: space-between;

    border-left: none; // remove border for the .active state
    border-right: 1px solid @menu-user-settings-border; // Custom color variables
    border-top: 1px solid @menu-user-settings-border;
    background-color: @menu-user-settings-background;
    &:before { // hide the triangle
        display: none;
    }
    > a {
        .ellipsis(); // used for cutting long username
        display: inline-block;
        padding: 0 .5em 0 0;
        font-size: 12px;
		// hiding icon and other images
        .icon-user {
            display: none;
        }
        &::before {
            display: none;
        }
    }
}

// The second level class attaches the settings and logout sub-menu
// <ul class="nav nav-level-2"><li class="nav-item no-icon">

.second-level {
    // resetting Icinga style
    position: static;
    width: auto;
    padding: 0;
    background-color: transparent;
    color: inherit;
    line-height: initial;

    display: inline-block;
    white-space: nowrap;
    a::before {
        display: none;
    }
}
.second-level-item {
    // resetting Icinga style
    display: inline-block;
    width: auto;
    margin: 0;
    background-color: transparent;
	// account & logout links
    > a {
        width: 27px;
        height: 24px;
        padding: 5px;

        // hiding item label
        text-indent: 200%;
        overflow: hidden;
        background-repeat: no-repeat;
        background-origin: content-box;
        &:before{
            display: none;
        }
    }
    &:nth-child(1) a {
		// setting the cog image (base 64) as background for the settings link
        background-image: url("data:image/svg xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 200 160'%3E%3Cpath d='...' fill='%23afafaf'%3E%3C/path%3E%3C/svg%3E");
    }
    &:nth-child(2) a {
		// setting the shutdown button as background for logout button
        background-image: url("data:image/svg xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 200 160'%3E%3Cpath d='...' fill='%23e65456'%3E%3C/path%3E%3C/svg%3E");
    }
}

// applying the before define style to Icinga menu elements
body #menu .nav-level-1 > .user-nav-item {
    .first-level-item();
    &.hover, &.active, &:hover {
        .first-level-item();
        .nav-level-2 {
            .second-level();
            .nav-item {
                .second-level-item();
            }
        }
    }
    .nav-level-2 {
        .second-level();
        .nav-item {
            .second-level-item();
        }
    }
}

Über dieses Theming wird es möglich, der Benutzeroberfläche von Icinga das gewünschte Erscheinungsbild zu verleihen, ohne die PHP Files bearbeiten zu müssen. Das hat den großen Vorteil, dass bei Aktualisierungen und Änderungen am System-Core, auf die Layouts und Themes keine Rücksicht genommen werden muss.

Mehrere Versionen eines Custom-Themes

Und was wenn das Mockup mehrere Themes/Farbschemen vorsieht? In diesem Fall empfehle ich Ihnen spezielle Variablen für die Farben zu verwenden. Wie Sie im folgenden Code sehen, habe ich die Standard-Icinga-Variablen durch personalisierte Werte ersetzt.

menu.less
#header-logo-container {
 background-color: @customer-logo-background;
 border-bottom: 1px solid @customer-logo-border;
 border-right: 1px solid @customer-logo-border;
}
#header-logo {
 background-image: url( @customer-logo-url );
}
/* Customer logo end */

#menu {
 height: 100%;
 background-color: @menu-background;
 border-right: 1px solid @menu-border;
}

Auf diese Art und Weise können beliebig viele Themes im Ordner /public/css/themes/ hinzugefügt werden. Dementsprechend kann zwischen den Themes ganz einfach über die User-Settings hin und her gewechselt werden. Anbei als Beispiel das helle und das dunkle Theme, die ich kürzlich erstellt habe: Hier habe ich den verschiedenen Variablen einfach unterschiedliche Farbwerte zugewiesen. Gleichermaßen ist es auch möglich das Logo zu verändern.

light-theme.less
// Customer logo style
@customer-logo-url: "../img/your-theme/logo-light.svg";
@customer-logo-background: @white;
@customer-logo-border: @gray-lighter;

// Menu general style
@menu-background: @white;
@menu-border: @gray-lighter;
dark-theme.less
// Customer logo style
@customer-logo-url: "../img/your-theme/logo-dark.svg";
@customer-logo-background: @icinga-blue;
@customer-logo-border: @icinga-blue;

// Menu general style
@menu-background: @grey-dark;
@menu-border: @grey-dark;

Jetzt sind Sie dran!

Fassen wir die Vorgehensweise noch einmal kurz zusammen:

  1. Analysieren Sie das zu personalisierende Element
  2. Identifizieren Sie den entsprechenden Tag
  3. Identifizieren Sie den Style des Elements im Theme-File (.less) von Icinga
  4. Erstellen Sie den Ordner für Ihr Theme, der die Files mit derselben Namensgebung wie in Icinga enthält
  5. Fügen Sie die Files dem StyleSheet.php File hinzu
  6. Personalisieren Sie die Benutzeroberfläche

Wiederholen Sie dieses Vorgehen für jede Komponente die Sie ändern möchten.

Ich hoffe dieses kurze Tutorial hilft Ihnen bei Ihren zukünftigen Aktivitäten. Erinnern Sie sich einfach stets daran, dass der Personalisierungsprozess immer derselbe bleibt, egal wie kompliziert das Mockup anfangs scheinen mag.

Quellen

Icinga Web 2 Repository:

https://docs.icinga.com/icinga2/latest/doc/icingaweb/chapter/installationhttps://docs.icinga.com/icinga2/latest/doc/icingaweb/chapter/installation

Valentina Da Rold

Valentina Da Rold

Hi, I'm Valentina and I'm a Frontend Developer at Wuerth Phoenix. I started out my career applying my Cryptography skills to coding, but really quickly fell in love with the web. I have been making websites and applications since 2012 and I still can't get enough of it. Along the way I found a passion for front-end development, and I use this passion to create interfaces that solve problems. When I'm not creating beautiful solutions, I enjoy cooking or doing sport, while listening to beautiful music.

Author

Valentina Da Rold

Hi, I'm Valentina and I'm a Frontend Developer at Wuerth Phoenix. I started out my career applying my Cryptography skills to coding, but really quickly fell in love with the web. I have been making websites and applications since 2012 and I still can't get enough of it. Along the way I found a passion for front-end development, and I use this passion to create interfaces that solve problems. When I'm not creating beautiful solutions, I enjoy cooking or doing sport, while listening to beautiful music.

Leave a Reply

Your email address will not be published.

Archive