diff --git a/application/controllers/RedundancygroupController.php b/application/controllers/RedundancygroupController.php index 118a5c1cd..5e2bb4f62 100644 --- a/application/controllers/RedundancygroupController.php +++ b/application/controllers/RedundancygroupController.php @@ -15,6 +15,7 @@ use Icinga\Module\Icingadb\Web\Controller; use Icinga\Module\Icingadb\Widget\Detail\MultiselectQuickActions; use Icinga\Module\Icingadb\Widget\Detail\RedundancyGroupDetail; +use Icinga\Module\Icingadb\Widget\Detail\RedundancyGroupObjectHeader; use Icinga\Module\Icingadb\Widget\ItemList\DependencyNodeList; use ipl\Html\HtmlElement; use ipl\Html\Text; @@ -66,7 +67,7 @@ protected function loadGroup(): void $this->setTitleTab($this->getRequest()->getActionName()); $this->setTitle($this->group->display_name); - $this->addControl(new HtmlElement('div', null, Text::create($this->group->display_name))); + $this->addControl(new RedundancyGroupObjectHeader($this->group)); } public function indexAction(): void diff --git a/library/Icingadb/Widget/Detail/ObjectHeader.php b/library/Icingadb/Widget/Detail/ObjectHeader.php new file mode 100644 index 000000000..4ebec8459 --- /dev/null +++ b/library/Icingadb/Widget/Detail/ObjectHeader.php @@ -0,0 +1,142 @@ + */ + protected $baseAttributes = ['class' => 'object-header']; + + /** @var object The associated object */ + protected $object; + + protected $tag = 'div'; + + /** + * Create a new object header + * + * @param object $object + */ + public function __construct($object) + { + $this->object = $object; + + $this->addAttributes($this->baseAttributes); + + $this->init(); + } + + abstract protected function assembleHeader(BaseHtmlElement $header): void; + + abstract protected function assembleMain(BaseHtmlElement $main): void; + + protected function assembleCaption(BaseHtmlElement $caption): void + { + } + + protected function assembleTitle(BaseHtmlElement $title): void + { + } + + protected function assembleVisual(BaseHtmlElement $visual): void + { + } + + protected function getStateBallSize(): string + { + return StateBall::SIZE_BIG; + } + + protected function createCaption(): BaseHtmlElement + { + $caption = new HtmlElement('section', Attributes::create(['class' => 'caption'])); + + $this->assembleCaption($caption); + + return $caption; + } + + protected function createHeader(): BaseHtmlElement + { + $header = new HtmlElement('header'); + + $this->assembleHeader($header); + + return $header; + } + + protected function createMain(): BaseHtmlElement + { + $main = new HtmlElement('div', Attributes::create(['class' => 'main'])); + + $this->assembleMain($main); + + return $main; + } + + protected function createTimestamp(): ?BaseHtmlElement + { + //TODO: add support for host/service + return new TimeSince($this->object->state->last_state_change->getTimestamp()); + } + + protected function createSubject(): BaseHtmlElement + { + return new HtmlElement( + 'span', + Attributes::create(['class' => 'subject']), + Text::create($this->object->display_name) + ); + } + + protected function createTitle(): BaseHtmlElement + { + $title = new HtmlElement('div', Attributes::create(['class' => 'title'])); + + $this->assembleTitle($title); + + return $title; + } + + /** + * @return ?BaseHtmlElement + */ + protected function createVisual(): ?BaseHtmlElement + { + $visual = new HtmlElement('div', Attributes::create(['class' => 'visual'])); + + $this->assembleVisual($visual); + if ($visual->isEmpty()) { + return null; + } + + return $visual; + } + + /** + * Initialize the list item + * + * If you want to adjust the object header after construction, override this method. + */ + protected function init(): void + { + } + + protected function assemble(): void + { + $this->add([ + $this->createVisual(), + $this->createMain() + ]); + } +} \ No newline at end of file diff --git a/library/Icingadb/Widget/Detail/RedundancyGroupObjectHeader.php b/library/Icingadb/Widget/Detail/RedundancyGroupObjectHeader.php new file mode 100644 index 000000000..938e1b852 --- /dev/null +++ b/library/Icingadb/Widget/Detail/RedundancyGroupObjectHeader.php @@ -0,0 +1,42 @@ +addHtml(new StateBall($this->object->state->getStateText(), $this->getStateBallSize())); + } + + protected function assembleTitle(BaseHtmlElement $title): void + { + $title->addHtml($this->createSubject()); + if ($this->object->state->failed) { + $text = $this->translate('has no working objects'); + } else { + $text = $this->translate('has working objects'); + } + + $title->addHtml(HtmlElement::create('span', null, Text::create($text))); + } + + protected function assembleHeader(BaseHtmlElement $header): void + { + $header->add($this->createTitle()); + $header->add($this->createTimestamp()); + } + + protected function assembleMain(BaseHtmlElement $main): void + { + $main->add($this->createHeader()); + } +} \ No newline at end of file diff --git a/public/css/widget/object-header.less b/public/css/widget/object-header.less new file mode 100644 index 000000000..896fdf767 --- /dev/null +++ b/public/css/widget/object-header.less @@ -0,0 +1,50 @@ +// Layout +.object-header { + display: flex; + + .visual { + display: flex; + padding: 0.5em 0; + } + + .main { + flex: 1 1 auto; + padding: 0.5em 0; + width: 0; + margin-left: .5em; + + header { + display: flex; + justify-content: space-between; + + .title { + display: inline-flex; + align-items: baseline; + white-space: nowrap; + margin-right: 1em; + + & > * { + margin: 0 .28125em; // 0 calculated   width + } + + .subject { + .text-ellipsis(); + } + } + + time { + white-space: nowrap; + } + } + } +} + +.object-header { + color: @default-text-color-light; + + .title { + .subject { + color: @default-text-color; + } + } +}