Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 5 additions & 12 deletions .github/workflows/php.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,8 @@ jobs:
strategy:
fail-fast: false
matrix:
php: ['5.6', '7.0', '7.1', '7.2', '7.3', '7.4', '8.0']
php: ['7.0', '7.1', '7.2', '7.3', '7.4', '8.0', '8.1']
os: ['ubuntu-latest']
include:
- php: '5.6'
allow_failure: true
- php: '7.0'
allow_failure: true

steps:
- name: Checkout code base
Expand Down Expand Up @@ -51,20 +46,18 @@ jobs:
runs-on: ${{ matrix.os }}

env:
phpunit-version: 8.5.15
phpunit-version: 8.5

strategy:
fail-fast: false
matrix:
php: ['5.6', '7.0', '7.1', '7.2', '7.3', '7.4', '8.0']
php: ['7.0', '7.1', '7.2', '7.3', '7.4', '8.0', '8.1']
os: ['ubuntu-latest']
include:
- php: '5.6'
phpunit-version: 5.7.27
- php: '7.0'
phpunit-version: 6.5.14
phpunit-version: 6.5
- php: '7.1'
phpunit-version: 7.5.20
phpunit-version: 7.5

steps:
- name: Checkout code base
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Icinga PHP Library - Web Components

[![PHP Support](https://img.shields.io/badge/php-%3E%3D%205.6-777BB4?logo=PHP)](https://php.net/)
[![PHP Support](https://img.shields.io/badge/php-%3E%3D%207.0-777BB4?logo=PHP)](https://php.net/)
![Build Status](https://github.com/Icinga/ipl-web/workflows/PHP%20Tests/badge.svg?branch=master)

`ipl/web` provides common web components.
Expand Down
31 changes: 31 additions & 0 deletions asset/css/mixin/state-badges.less
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
.state-badges() {
&.state-badges {
padding: 0;

ul {
padding: 0;
}

li {
display: inline-block;
}

li > ul > li:first-child:not(:last-child) .state-badge {
border-bottom-right-radius: 0;
border-top-right-radius: 0;
}

li > ul > li:last-child:not(:first-child) .state-badge {
border-bottom-left-radius: 0;
border-top-left-radius: 0;
}

> li:not(:last-child) {
margin-right: .25em;
}

li > ul > li:last-child {
margin-left: 1px;
}
}
}
47 changes: 47 additions & 0 deletions asset/css/state-badge.less
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
.state-badge {
.rounded-corners();
color: var(--default-text-color-inverted, @default-text-color-inverted);
display: inline-block;
font-size: 1em;
min-width: 2em;
padding: .25em;
text-align: center;

&.handled {
opacity: .8;
}

&.state-critical {
background-color: var(--state-critical, @state-critical);
}

&.state-down {
background-color: var(--state-down, @state-down);
}

&.state-ok {
background-color: var(--state-ok, @state-ok);
}

&.state-pending {
background-color: var(--state-pending, @state-pending);
}

&.state-unknown {
background-color: var(--state-unknown, @state-unknown);
}

&.state-up {
background-color: var(--state-up, @state-up);
}

&.state-warning {
background-color: var(--state-warning, @state-warning);
}
}

a .state-badge {
&:not(.disabled):hover {
filter: brightness(80%);
}
}
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
}
},
"require": {
"php": ">=5.6.0",
"php": ">=7.0",
"ext-json": "*",
"ipl/html": ">=0.4.0",
"ipl/stdlib": ">=0.9.0",
Expand Down
184 changes: 184 additions & 0 deletions src/Common/StateBadges.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
<?php

namespace ipl\Web\Common;

use Icinga\Data\Filter\Filter;
use ipl\Html\BaseHtmlElement;
use ipl\Html\Html;
use ipl\Stdlib\BaseFilter;
use ipl\Web\Filter\QueryString;
use ipl\Web\Url;
use ipl\Web\Widget\Link;
use ipl\Web\Widget\StateBadge;

abstract class StateBadges extends BaseHtmlElement
{
use BaseFilter;

/** @var object $item */
protected $item;

/** @var string */
protected $type;

/** @var string Prefix */
protected $prefix;

/** @var Url Badge link */
protected $url;

protected $tag = 'ul';

protected $defaultAttributes = ['class' => 'state-badges'];

/**
* Create a new widget for state badges
*
* @param object $item
*/
public function __construct($item)
{
$this->item = $item;
$this->type = $this->getType();
$this->prefix = $this->getPrefix();
$this->url = $this->getBaseUrl();
}

/**
* Get the badge base URL
*
* @return Url
*/
abstract protected function getBaseUrl(): Url;

/**
* Get the type of the items
*
* @return string
*/
abstract protected function getType(): string;

/**
* Get the prefix for accessing state information
*
* @return string
*/
abstract protected function getPrefix(): string;

/**
* Get the integer of the given state text
*
* @param string $state
*
* @return int
*/
abstract protected function getStateInt(string $state): int;

/**
* Get the badge URL
*
* @return Url
*/
public function getUrl(): Url
{
return $this->url;
}

/**
* Set the badge URL
*
* @param Url $url
*
* @return $this
*/
public function setUrl(Url $url): self
{
$this->url = $url;

return $this;
}

/**
* Create a badge link
*
* @param $content
* @param array $params
*
* @return Link
*/
public function createLink($content, array $params = null): Link
{
$url = clone $this->getUrl();

if (! empty($params)) {
$url->getParams()->mergeValues($params);
}

if ($this->hasBaseFilter()) {
$url->addFilter(Filter::fromQueryString(QueryString::render($this->getBaseFilter())));
}

return new Link($content, $url);
}

/**
* Create a state bade
*
* @param string $state
*
* @return ?BaseHtmlElement
*/
protected function createBadge(string $state)
{
$key = $this->prefix . "_{$state}";

if (isset($this->item->$key) && $this->item->$key) {
return Html::tag('li', $this->createLink(
new StateBadge($this->item->$key, $state),
[$this->type . '.state.soft_state' => $this->getStateInt($state)]
));
}

return null;
}

/**
* Create a state group
*
* @param string $state
*
* @return ?BaseHtmlElement
*/
protected function createGroup(string $state)
{
$content = [];
$handledKey = $this->prefix . "_{$state}_handled";
$unhandledKey = $this->prefix . "_{$state}_unhandled";

if (isset($this->item->$unhandledKey) && $this->item->$unhandledKey) {
$content[] = Html::tag('li', $this->createLink(
new StateBadge($this->item->$unhandledKey, $state),
[
$this->type . '.state.soft_state' => $this->getStateInt($state),
$this->type . '.state.is_handled' => 'n'
]
));
}

if (isset($this->item->$handledKey) && $this->item->$handledKey) {
$content[] = Html::tag('li', $this->createLink(
new StateBadge($this->item->$handledKey, $state, true),
[
$this->type . '.state.soft_state' => $this->getStateInt($state),
$this->type . '.state.is_handled' => 'y'
]
));
}

if (empty($content)) {
return null;
}

return Html::tag('li', Html::tag('ul', $content));
}
}
47 changes: 47 additions & 0 deletions src/Widget/StateBadge.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
<?php

namespace ipl\Web\Widget;

use ipl\Html\BaseHtmlElement;

class StateBadge extends BaseHtmlElement
{
protected $defaultAttributes = ['class' => 'state-badge'];

/** @var mixed Badge content */
protected $content;

/** @var bool Whether the state is handled */
protected $isHandled;

/** @var string Textual representation of a state */
protected $state;

/**
* Create a new state badge
*
* @param mixed $content Content of the badge
* @param string $state Textual representation of a state
* @param bool $isHandled True if state is handled
*/
public function __construct($content, string $state, bool $isHandled = false)
{
$this->content = $content;
$this->isHandled = $isHandled;
$this->state = $state;
}

protected function assemble()
{
$this->setTag('span');

$class = "state-{$this->state}";
if ($this->isHandled) {
$class .= ' handled';
}

$this->addAttributes(['class' => $class]);

$this->add($this->content);
}
}