diff options
Diffstat (limited to 'vendor/gipfl/icingaweb2/src/Widget')
-rw-r--r-- | vendor/gipfl/icingaweb2/src/Widget/ActionBar.php | 25 | ||||
-rw-r--r-- | vendor/gipfl/icingaweb2/src/Widget/Content.php | 14 | ||||
-rw-r--r-- | vendor/gipfl/icingaweb2/src/Widget/Controls.php | 163 | ||||
-rw-r--r-- | vendor/gipfl/icingaweb2/src/Widget/ControlsAndContent.php | 60 | ||||
-rw-r--r-- | vendor/gipfl/icingaweb2/src/Widget/ListItem.php | 26 | ||||
-rw-r--r-- | vendor/gipfl/icingaweb2/src/Widget/NameValueTable.php | 29 | ||||
-rw-r--r-- | vendor/gipfl/icingaweb2/src/Widget/Paginator.php | 463 | ||||
-rw-r--r-- | vendor/gipfl/icingaweb2/src/Widget/Tabs.php | 44 |
8 files changed, 824 insertions, 0 deletions
diff --git a/vendor/gipfl/icingaweb2/src/Widget/ActionBar.php b/vendor/gipfl/icingaweb2/src/Widget/ActionBar.php new file mode 100644 index 0000000..63e6c77 --- /dev/null +++ b/vendor/gipfl/icingaweb2/src/Widget/ActionBar.php @@ -0,0 +1,25 @@ +<?php + +namespace gipfl\IcingaWeb2\Widget; + +use ipl\Html\BaseHtmlElement; + +class ActionBar extends BaseHtmlElement +{ + protected $contentSeparator = ' '; + + /** @var string */ + protected $tag = 'div'; + + protected $defaultAttributes = ['class' => 'gipfl-action-bar']; + + /** + * @param string $target + * @return $this + */ + public function setBaseTarget($target) + { + $this->getAttributes()->set('data-base-target', $target); + return $this; + } +} diff --git a/vendor/gipfl/icingaweb2/src/Widget/Content.php b/vendor/gipfl/icingaweb2/src/Widget/Content.php new file mode 100644 index 0000000..92ea115 --- /dev/null +++ b/vendor/gipfl/icingaweb2/src/Widget/Content.php @@ -0,0 +1,14 @@ +<?php + +namespace gipfl\IcingaWeb2\Widget; + +use ipl\Html\BaseHtmlElement; + +class Content extends BaseHtmlElement +{ + protected $tag = 'div'; + + protected $contentSeparator = "\n"; + + protected $defaultAttributes = ['class' => 'content']; +} diff --git a/vendor/gipfl/icingaweb2/src/Widget/Controls.php b/vendor/gipfl/icingaweb2/src/Widget/Controls.php new file mode 100644 index 0000000..cb52013 --- /dev/null +++ b/vendor/gipfl/icingaweb2/src/Widget/Controls.php @@ -0,0 +1,163 @@ +<?php + +namespace gipfl\IcingaWeb2\Widget; + +use ipl\Html\BaseHtmlElement; +use ipl\Html\Html; +use ipl\Html\HtmlDocument; + +class Controls extends BaseHtmlElement +{ + protected $tag = 'div'; + + protected $contentSeparator = "\n"; + + protected $defaultAttributes = ['class' => 'controls']; + + /** @var Tabs */ + private $tabs; + + /** @var ActionBar */ + private $actions; + + /** @var string */ + private $title; + + /** @var string */ + private $subTitle; + + /** @var BaseHtmlElement */ + private $titleElement; + + /** + * @param $title + * @param null $subTitle + * @return $this + */ + public function addTitle($title, $subTitle = null) + { + $this->title = $title; + if ($subTitle !== null) { + $this->subTitle = $subTitle; + } + + return $this->setTitleElement($this->renderTitleElement()); + } + + /** + * @param BaseHtmlElement $element + * @return $this + */ + public function setTitleElement(BaseHtmlElement $element) + { + if ($this->titleElement !== null) { + $this->remove($this->titleElement); + } + + $this->titleElement = $element; + $this->prepend($element); + + return $this; + } + + public function getTitleElement() + { + return $this->titleElement; + } + + /** + * @return Tabs + */ + public function getTabs() + { + if ($this->tabs === null) { + $this->tabs = new Tabs(); + } + + return $this->tabs; + } + + /** + * @param Tabs $tabs + * @return $this + */ + public function setTabs(Tabs $tabs) + { + $this->tabs = $tabs; + return $this; + } + + /** + * @param Tabs $tabs + * @return $this + */ + public function prependTabs(Tabs $tabs) + { + if ($this->tabs === null) { + $this->tabs = $tabs; + } else { + $current = $this->tabs->getTabs(); + $this->tabs = $tabs; + foreach ($current as $name => $tab) { + $this->tabs->add($name, $tab); + } + } + + return $this; + } + + /** + * @return ActionBar + */ + public function getActionBar() + { + if ($this->actions === null) { + $this->setActionBar(new ActionBar()); + } + + return $this->actions; + } + + /** + * @param HtmlDocument $actionBar + * @return $this + */ + public function setActionBar(HtmlDocument $actionBar) + { + if ($this->actions !== null) { + $this->remove($this->actions); + } + + $this->actions = $actionBar; + $this->add($actionBar); + + return $this; + } + + /** + * @return BaseHtmlElement + */ + protected function renderTitleElement() + { + $h1 = Html::tag('h1', null, $this->title); + if ($this->subTitle) { + $h1->setSeparator(' ')->add( + Html::tag('small', null, $this->subTitle) + ); + } + + return $h1; + } + + /** + * @return string + */ + public function renderContent() + { + if (null !== $this->tabs) { + $this->prepend($this->tabs); + } + + return parent::renderContent(); + } +} diff --git a/vendor/gipfl/icingaweb2/src/Widget/ControlsAndContent.php b/vendor/gipfl/icingaweb2/src/Widget/ControlsAndContent.php new file mode 100644 index 0000000..8574ce7 --- /dev/null +++ b/vendor/gipfl/icingaweb2/src/Widget/ControlsAndContent.php @@ -0,0 +1,60 @@ +<?php + +namespace gipfl\IcingaWeb2\Widget; + +use ipl\Html\HtmlDocument; +use gipfl\IcingaWeb2\Url; + +interface ControlsAndContent +{ + /** + * @return Controls + */ + public function controls(); + + /** + * @return Tabs + */ + public function tabs(); + + /** + * @param HtmlDocument|null $actionBar + * @return HtmlDocument + */ + public function actions(HtmlDocument $actionBar = null); + + /** + * @return Content + */ + public function content(); + + /** + * @param $title + * @return $this + */ + public function setTitle($title); + + /** + * @param $title + * @return $this + */ + public function addTitle($title); + + /** + * @param $title + * @param null $url + * @param string $name + * @return $this + */ + public function addSingleTab($title, $url = null, $name = 'main'); + + /** + * @return Url + */ + public function url(); + + /** + * @return Url + */ + public function getOriginalUrl(); +} diff --git a/vendor/gipfl/icingaweb2/src/Widget/ListItem.php b/vendor/gipfl/icingaweb2/src/Widget/ListItem.php new file mode 100644 index 0000000..fa4b562 --- /dev/null +++ b/vendor/gipfl/icingaweb2/src/Widget/ListItem.php @@ -0,0 +1,26 @@ +<?php + +namespace gipfl\IcingaWeb2\Widget; + +use ipl\Html\Attributes; +use ipl\Html\BaseHtmlElement; +use ipl\Html\Html; +use ipl\Html\ValidHtml; + +class ListItem extends BaseHtmlElement +{ + protected $contentSeparator = "\n"; + + /** + * @param ValidHtml|array|string $content + * @param Attributes|array $attributes + * + * @return $this + */ + public function addItem($content, $attributes = null) + { + return $this->add( + Html::tag('li', $attributes, $content) + ); + } +} diff --git a/vendor/gipfl/icingaweb2/src/Widget/NameValueTable.php b/vendor/gipfl/icingaweb2/src/Widget/NameValueTable.php new file mode 100644 index 0000000..971a833 --- /dev/null +++ b/vendor/gipfl/icingaweb2/src/Widget/NameValueTable.php @@ -0,0 +1,29 @@ +<?php + +namespace gipfl\IcingaWeb2\Widget; + +use ipl\Html\Table; + +class NameValueTable extends Table +{ + protected $defaultAttributes = ['class' => 'name-value-table']; + + public function createNameValueRow($name, $value) + { + return $this::tr([$this::th($name), $this::td($value)]); + } + + public function addNameValueRow($name, $value) + { + return $this->add($this->createNameValueRow($name, $value)); + } + + public function addNameValuePairs($pairs) + { + foreach ($pairs as $name => $value) { + $this->addNameValueRow($name, $value); + } + + return $this; + } +} diff --git a/vendor/gipfl/icingaweb2/src/Widget/Paginator.php b/vendor/gipfl/icingaweb2/src/Widget/Paginator.php new file mode 100644 index 0000000..3c255a7 --- /dev/null +++ b/vendor/gipfl/icingaweb2/src/Widget/Paginator.php @@ -0,0 +1,463 @@ +<?php + +namespace gipfl\IcingaWeb2\Widget; + +use Icinga\Exception\ProgrammingError; +use gipfl\IcingaWeb2\Data\Paginatable; +use gipfl\IcingaWeb2\Icon; +use gipfl\IcingaWeb2\Link; +use gipfl\IcingaWeb2\Url; +use gipfl\Translation\TranslationHelper; +use ipl\Html\BaseHtmlElement; +use ipl\Html\Html; + +class Paginator extends BaseHtmlElement +{ + use TranslationHelper; + + protected $tag = 'div'; + + protected $defaultAttributes = [ + 'class' => 'pagination-control', + 'role' => 'navigation', + ]; + + /** @var Paginatable The query the paginator widget is created for */ + protected $query; + + /** @var int */ + protected $pageCount; + + /** @var int */ + protected $currentCount; + + /** @var Url */ + protected $url; + + /** @var string */ + protected $pageParam; + + /** @var string */ + protected $perPageParam; + + /** @var int */ + protected $totalCount; + + /** @var int */ + protected $defaultItemCountPerPage = 25; + + public function __construct( + Paginatable $query, + Url $url, + $pageParameter = 'page', + $perPageParameter = 'limit' + ) { + $this->query = $query; + $this->setPageParam($pageParameter); + $this->setPerPageParam($perPageParameter); + $this->setUrl($url); + } + + public function setItemsPerPage($count) + { + // TODO: this should become setOffset once available + $query = $this->getQuery(); + $query->setLimit($count); + + return $this; + } + + protected function setPageParam($pageParam) + { + $this->pageParam = $pageParam; + return $this; + } + + protected function setPerPageParam($perPageParam) + { + $this->perPageParam = $perPageParam; + return $this; + } + + public function getPageParam() + { + return $this->pageParam; + } + + public function getPerPageParam() + { + return $this->perPageParam; + } + + public function getCurrentPage() + { + $query = $this->getQuery(); + if ($query->hasOffset()) { + return ($query->getOffset() / $this->getItemsPerPage()) + 1; + } else { + return 1; + } + } + + protected function setCurrentPage($page) + { + $page = (int) $page; + $offset = $this->firstRowOnPage($page) - 1; + if ($page > 1) { + $query = $this->getQuery(); + $query->setOffset($offset); + } + } + + public function getPageCount() + { + if ($this->pageCount === null) { + $this->pageCount = (int) ceil($this->getTotalItemCount() / $this->getItemsPerPage()); + } + + return $this->pageCount; + } + + protected function getItemsPerPage() + { + $limit = $this->getQuery()->getLimit(); + if ($limit === null) { + throw new ProgrammingError('Something went wrong, got no limit when there should be one'); + } else { + return $limit; + } + } + + public function getTotalItemCount() + { + if ($this->totalCount === null) { + $this->totalCount = count($this->getQuery()); + } + + return $this->totalCount; + } + + public function getPrevious() + { + if ($this->hasPrevious()) { + return $this->getCurrentPage() - 1; + } else { + return null; + } + } + + public function hasPrevious() + { + return $this->getCurrentPage() > 1; + } + + public function getNext() + { + if ($this->hasNext()) { + return $this->getCurrentPage() + 1; + } else { + return null; + } + } + + public function hasNext() + { + return $this->getCurrentPage() < $this->getPageCount(); + } + + public function getQuery() + { + return $this->query; + } + + /** + * Returns an array of "local" pages given the page count and current page number + * + * @return array + */ + protected function getPages() + { + $page = $this->getPageCount(); + $current = $this->getCurrentPage(); + + $range = []; + + if ($page < 10) { + // Show all pages if we have less than 10 + for ($i = 1; $i < 10; $i++) { + if ($i > $page) { + break; + } + + $range[$i] = $i; + } + } else { + // More than 10 pages: + foreach ([1, 2] as $i) { + $range[$i] = $i; + } + + if ($current < 6) { + // We are on page 1-5 from + for ($i = 1; $i <= 7; $i++) { + $range[$i] = $i; + } + } else { + // Current page > 5 + $range[] = '…'; + + if (($page - $current) < 5) { + // Less than 5 pages left + $start = 5 - ($page - $current); + } else { + $start = 1; + } + + for ($i = $current - $start; $i < ($current + (4 - $start)); $i++) { + if ($i > $page) { + break; + } + + $range[$i] = $i; + } + } + + if ($current < ($page - 2)) { + $range[] = '…'; + } + + foreach ([$page - 1, $page] as $i) { + $range[$i] = $i; + } + } + + if (empty($range)) { + $range[] = 1; + } + + return $range; + } + + public function getDefaultItemCountPerPage() + { + return $this->defaultItemCountPerPage; + } + + public function setDefaultItemCountPerPage($count) + { + $this->defaultItemCountPerPage = (int) $count; + return $this; + } + + public function setUrl(Url $url) + { + $page = (int) $url->shift($this->getPageParam()); + $perPage = (int) $url->getParam($this->getPerPageParam()); + if ($perPage > 0) { + $this->setItemsPerPage($perPage); + } else { + if (! $this->getQuery()->hasLimit()) { + $this->setItemsPerPage($this->getDefaultItemCountPerPage()); + } + } + if ($page > 0) { + $this->setCurrentPage($page); + } + + $this->url = $url; + + return $this; + } + + public function getUrl() + { + if ($this->url === null) { + $this->setUrl(Url::fromRequest()); + } + + return $this->url; + } + + public function getPreviousLabel() + { + return $this->getLabel($this->getCurrentPage() - 1); + } + + protected function getNextLabel() + { + return $this->getLabel($this->getCurrentPage() + 1); + } + + protected function getLabel($page) + { + return sprintf( + $this->translate('Show rows %u to %u of %u'), + $this->firstRowOnPage($page), + $this->lastRowOnPage($page), + $this->getTotalItemCount() + ); + } + + protected function renderPrevious() + { + return Html::tag('li', [ + 'class' => 'nav-item' + ], Link::create( + Icon::create('angle-double-left'), + $this->makeUrl($this->getPrevious()), + null, + [ + 'title' => $this->getPreviousLabel(), + 'class' => 'previous-page' + ] + )); + } + + protected function renderNoPrevious() + { + return $this->renderDisabled(Html::tag('span', [ + 'class' => 'previous-page' + ], [ + $this->srOnly($this->translate('Previous page')), + Icon::create('angle-double-left') + ])); + } + + protected function renderNext() + { + return Html::tag('li', [ + 'class' => 'nav-item' + ], Link::create( + Icon::create('angle-double-right'), + $this->makeUrl($this->getNext()), + null, + [ + 'title' => $this->getNextLabel(), + 'class' => 'next-page' + ] + )); + } + + protected function renderNoNext() + { + return $this->renderDisabled(Html::tag('span', [ + 'class' => 'previous-page' + ], [ + $this->srOnly($this->translate('Next page')), + Icon::create('angle-double-right') + ])); + } + + protected function renderDots() + { + return $this->renderDisabled(Html::tag('span', null, '…')); + } + + protected function renderInnerPages() + { + $pages = []; + $current = $this->getCurrentPage(); + + foreach ($this->getPages() as $page) { + if ($page === '…') { + $pages[] = $this->renderDots(); + } else { + $pages[] = Html::tag( + 'li', + $page === $current ? ['class' => 'active'] : null, + $this->makeLink($page) + ); + } + } + + return $pages; + } + + protected function lastRowOnPage($page) + { + $perPage = $this->getItemsPerPage(); + $total = $this->getTotalItemCount(); + $last = $page * $perPage; + if ($last > $total) { + $last = $total; + } + + return $last; + } + + protected function firstRowOnPage($page) + { + return ($page - 1) * $this->getItemsPerPage() + 1; + } + + protected function makeLink($page) + { + return Link::create( + $page, + $this->makeUrl($page), + null, + ['title' => $this->getLabel($page)] + ); + } + + protected function makeUrl($page) + { + if ($page) { + return $this->getUrl()->with('page', $page); + } else { + return $this->getUrl(); + } + } + + protected function srOnly($content) + { + return Html::tag('span', ['class' => 'sr-only'], $content); + } + + protected function renderDisabled($content) + { + return Html::tag('li', [ + 'class' => ['nav-item', 'disabled'], + 'aria-hidden' => 'true' + ], $content); + } + + protected function renderList() + { + return Html::tag( + 'ul', + ['class' => ['nav', 'tab-nav']], + [ + $this->hasPrevious() ? $this->renderPrevious() : $this->renderNoPrevious(), + $this->renderInnerPages(), + $this->hasNext() ? $this->renderNext() : $this->renderNoNext() + ] + ); + } + + public function assemble() + { + $this->add([ + $this->renderScreenReaderHeader(), + $this->renderList() + ]); + } + + protected function renderScreenReaderHeader() + { + return Html::tag('h2', [ + // 'id' => $this->protectId('pagination') -> why? + 'class' => 'sr-only', + 'tab-index' => '-1' + ], $this->translate('Pagination')); + } + + public function render() + { + if ($this->getPageCount() < 2) { + return ''; + } else { + return parent::render(); + } + } +} diff --git a/vendor/gipfl/icingaweb2/src/Widget/Tabs.php b/vendor/gipfl/icingaweb2/src/Widget/Tabs.php new file mode 100644 index 0000000..38bf4cd --- /dev/null +++ b/vendor/gipfl/icingaweb2/src/Widget/Tabs.php @@ -0,0 +1,44 @@ +<?php + +namespace gipfl\IcingaWeb2\Widget; + +use Exception; +use Icinga\Web\Widget\Tabs as WebTabs; +use InvalidArgumentException; +use ipl\Html\ValidHtml; + +class Tabs extends WebTabs implements ValidHtml +{ + /** + * @param string $name + * @return $this + */ + public function activate($name) + { + try { + parent::activate($name); + } catch (Exception $e) { + throw new InvalidArgumentException( + "Can't activate '$name', there is no such tab" + ); + } + + return $this; + } + + /** + * @param string $name + * @param array|\Icinga\Web\Widget\Tab $tab + * @return $this + */ + public function add($name, $tab) + { + try { + parent::add($name, $tab); + } catch (Exception $e) { + throw new InvalidArgumentException($e->getMessage()); + } + + return $this; + } +} |