mirror of
https://github.com/Icinga/icingadb-web.git
synced 2026-06-09 00:32:05 -04:00
Merge BaseItemTable into StateItemTable
This commit is contained in:
parent
8e2791cb68
commit
389cc2ff57
7 changed files with 366 additions and 383 deletions
|
|
@ -22,7 +22,7 @@ use Icinga\Module\Icingadb\Common\SearchControls;
|
|||
use Icinga\Module\Icingadb\Data\CsvResultSet;
|
||||
use Icinga\Module\Icingadb\Data\JsonResultSet;
|
||||
use Icinga\Module\Icingadb\Web\Control\ViewModeSwitcher;
|
||||
use Icinga\Module\Icingadb\Widget\ItemTable\BaseItemTable;
|
||||
use Icinga\Module\Icingadb\Widget\ItemTable\StateItemTable;
|
||||
use Icinga\Module\Pdfexport\PrintableHtmlDocument;
|
||||
use Icinga\Module\Pdfexport\ProvidedHook\Pdfexport;
|
||||
use Icinga\Security\SecurityException;
|
||||
|
|
@ -513,7 +513,7 @@ class Controller extends CompatController
|
|||
{
|
||||
if ($content instanceof BaseItemList) {
|
||||
$this->content->getAttributes()->add('class', 'full-width');
|
||||
} elseif ($content instanceof BaseItemTable) {
|
||||
} elseif ($content instanceof StateItemTable) {
|
||||
$this->content->getAttributes()->add('class', 'full-height');
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,198 +0,0 @@
|
|||
<?php
|
||||
|
||||
/* Icinga DB Web | (c) 2022 Icinga GmbH | GPLv2 */
|
||||
|
||||
namespace Icinga\Module\Icingadb\Widget\ItemTable;
|
||||
|
||||
use Icinga\Module\Icingadb\Widget\EmptyState;
|
||||
use ipl\Html\Attributes;
|
||||
use ipl\Html\BaseHtmlElement;
|
||||
use ipl\Html\Form;
|
||||
use ipl\Html\Html;
|
||||
use ipl\Html\HtmlElement;
|
||||
use ipl\Html\HtmlString;
|
||||
use ipl\Orm\Common\SortUtil;
|
||||
use ipl\Orm\Query;
|
||||
use ipl\Web\Control\SortControl;
|
||||
use ipl\Web\Widget\Icon;
|
||||
|
||||
abstract class BaseItemTable extends BaseHtmlElement
|
||||
{
|
||||
protected $baseAttributes = [
|
||||
'class' => 'item-table'
|
||||
];
|
||||
|
||||
/** @var array<string, string> The columns to render */
|
||||
protected $columns;
|
||||
|
||||
/** @var iterable The datasource */
|
||||
protected $data;
|
||||
|
||||
/** @var string The sort rules */
|
||||
protected $sort;
|
||||
|
||||
protected $tag = 'table';
|
||||
|
||||
/**
|
||||
* Create a new item table
|
||||
*
|
||||
* @param iterable $data Datasource of the table
|
||||
* @param array<string, string> $columns The columns to render, keys are labels
|
||||
*/
|
||||
public function __construct(iterable $data, array $columns)
|
||||
{
|
||||
$this->data = $data;
|
||||
$this->columns = array_flip($columns);
|
||||
|
||||
$this->addAttributes($this->baseAttributes);
|
||||
|
||||
$this->init();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the item table
|
||||
*
|
||||
* If you want to adjust the item table after construction, override this method.
|
||||
*/
|
||||
protected function init()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the columns being rendered
|
||||
*
|
||||
* @return array<string, string>
|
||||
*/
|
||||
public function getColumns(): array
|
||||
{
|
||||
return $this->columns;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set sort rules (as returned by {@see SortControl::getSort()})
|
||||
*
|
||||
* @param ?string $sort
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setSort(?string $sort): self
|
||||
{
|
||||
$this->sort = $sort;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
abstract protected function getItemClass(): string;
|
||||
|
||||
abstract protected function getVisualColumn(): string;
|
||||
|
||||
abstract protected function getVisualLabel();
|
||||
|
||||
protected function assembleColumnHeader(BaseHtmlElement $header, string $name, $label): void
|
||||
{
|
||||
$sortRules = [];
|
||||
if ($this->sort !== null) {
|
||||
$sortRules = SortUtil::createOrderBy($this->sort);
|
||||
}
|
||||
|
||||
$active = false;
|
||||
$sortDirection = null;
|
||||
foreach ($sortRules as $rule) {
|
||||
if ($rule[0] === $name) {
|
||||
$sortDirection = $rule[1];
|
||||
$active = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ($sortDirection === 'desc') {
|
||||
$value = "$name asc";
|
||||
} else {
|
||||
$value = "$name desc";
|
||||
}
|
||||
|
||||
$icon = 'sort';
|
||||
if ($active) {
|
||||
$icon = $sortDirection === 'desc' ? 'sort-up' : 'sort-down';
|
||||
}
|
||||
|
||||
$form = new Form();
|
||||
$form->setAttribute('method', 'GET');
|
||||
|
||||
$button = $form->createElement('button', 'sort', [
|
||||
'value' => $value,
|
||||
'type' => 'submit',
|
||||
'title' => is_string($label) ? $label : null,
|
||||
'class' => $active ? 'active' : null
|
||||
]);
|
||||
$button->addHtml(
|
||||
Html::tag(
|
||||
'span',
|
||||
null,
|
||||
// With to have the height sized the same as the others
|
||||
$label ?? HtmlString::create(' ')
|
||||
),
|
||||
new Icon($icon)
|
||||
);
|
||||
$form->addElement($button);
|
||||
|
||||
$header->add($form);
|
||||
}
|
||||
|
||||
protected function assemble()
|
||||
{
|
||||
$itemClass = $this->getItemClass();
|
||||
|
||||
$headerRow = new HtmlElement('tr');
|
||||
|
||||
$visualCell = new HtmlElement('th', Attributes::create(['class' => 'has-visual']));
|
||||
$this->assembleColumnHeader($visualCell, $this->getVisualColumn(), $this->getVisualLabel());
|
||||
$headerRow->addHtml($visualCell);
|
||||
|
||||
foreach ($this->columns as $name => $label) {
|
||||
$headerCell = new HtmlElement('th');
|
||||
$this->assembleColumnHeader($headerCell, $name, is_int($label) ? $name : $label);
|
||||
$headerRow->addHtml($headerCell);
|
||||
}
|
||||
|
||||
$this->addHtml(new HtmlElement('thead', null, $headerRow));
|
||||
|
||||
$body = new HtmlElement('tbody', Attributes::create(['data-base-target' => '_next']));
|
||||
foreach ($this->data as $item) {
|
||||
$body->addHtml(new $itemClass($item, $this));
|
||||
}
|
||||
|
||||
if ($body->isEmpty()) {
|
||||
$body->addHtml(new HtmlElement(
|
||||
'tr',
|
||||
null,
|
||||
new HtmlElement(
|
||||
'td',
|
||||
Attributes::create(['colspan' => count($this->columns)]),
|
||||
new EmptyState(t('No items found.'))
|
||||
)
|
||||
));
|
||||
}
|
||||
|
||||
$this->addHtml($body);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enrich the given list of column names with appropriate labels
|
||||
*
|
||||
* @param Query $query
|
||||
* @param array $columns
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function applyColumnMetaData(Query $query, array $columns): array
|
||||
{
|
||||
$newColumns = [];
|
||||
foreach ($columns as $columnPath) {
|
||||
$label = $query->getResolver()->getColumnDefinition($columnPath)->getLabel();
|
||||
$newColumns[$label ?? $columnPath] = $columnPath;
|
||||
}
|
||||
|
||||
return $newColumns;
|
||||
}
|
||||
}
|
||||
|
|
@ -9,14 +9,15 @@ use ipl\Html\BaseHtmlElement;
|
|||
use ipl\Html\HtmlElement;
|
||||
use ipl\Orm\Model;
|
||||
|
||||
abstract class BaseRowItem extends BaseHtmlElement
|
||||
/** @todo Figure out what this might (should) have in common with the new BaseTableRowItem implementation */
|
||||
abstract class BaseStateRowItem extends BaseHtmlElement
|
||||
{
|
||||
protected $defaultAttributes = ['class' => 'row-item'];
|
||||
|
||||
/** @var Model */
|
||||
protected $item;
|
||||
|
||||
/** @var BaseItemTable */
|
||||
/** @var StateItemTable */
|
||||
protected $list;
|
||||
|
||||
protected $tag = 'tr';
|
||||
|
|
@ -25,9 +26,9 @@ abstract class BaseRowItem extends BaseHtmlElement
|
|||
* Create a new row item
|
||||
*
|
||||
* @param Model $item
|
||||
* @param BaseItemTable $list
|
||||
* @param StateItemTable $list
|
||||
*/
|
||||
public function __construct(Model $item, BaseItemTable $list)
|
||||
public function __construct(Model $item, StateItemTable $list)
|
||||
{
|
||||
$this->item = $item;
|
||||
$this->list = $list;
|
||||
|
|
@ -4,11 +4,89 @@
|
|||
|
||||
namespace Icinga\Module\Icingadb\Widget\ItemTable;
|
||||
|
||||
use Icinga\Module\Icingadb\Widget\EmptyState;
|
||||
use ipl\Html\Attributes;
|
||||
use ipl\Html\BaseHtmlElement;
|
||||
use ipl\Html\Form;
|
||||
use ipl\Html\Html;
|
||||
use ipl\Html\HtmlElement;
|
||||
use ipl\Html\HtmlString;
|
||||
use ipl\Orm\Common\SortUtil;
|
||||
use ipl\Orm\Query;
|
||||
use ipl\Web\Control\SortControl;
|
||||
use ipl\Web\Widget\Icon;
|
||||
|
||||
abstract class StateItemTable extends BaseItemTable
|
||||
/** @todo Figure out what this might (should) have in common with the new BaseItemTable implementation */
|
||||
abstract class StateItemTable extends BaseHtmlElement
|
||||
{
|
||||
protected $baseAttributes = [
|
||||
'class' => 'state-item-table'
|
||||
];
|
||||
|
||||
/** @var array<string, string> The columns to render */
|
||||
protected $columns;
|
||||
|
||||
/** @var iterable The datasource */
|
||||
protected $data;
|
||||
|
||||
/** @var string The sort rules */
|
||||
protected $sort;
|
||||
|
||||
protected $tag = 'table';
|
||||
|
||||
/**
|
||||
* Create a new item table
|
||||
*
|
||||
* @param iterable $data Datasource of the table
|
||||
* @param array<string, string> $columns The columns to render, keys are labels
|
||||
*/
|
||||
public function __construct(iterable $data, array $columns)
|
||||
{
|
||||
$this->data = $data;
|
||||
$this->columns = array_flip($columns);
|
||||
|
||||
$this->addAttributes($this->baseAttributes);
|
||||
|
||||
$this->init();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the item table
|
||||
*
|
||||
* If you want to adjust the item table after construction, override this method.
|
||||
*/
|
||||
protected function init()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the columns being rendered
|
||||
*
|
||||
* @return array<string, string>
|
||||
*/
|
||||
public function getColumns(): array
|
||||
{
|
||||
return $this->columns;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set sort rules (as returned by {@see SortControl::getSort()})
|
||||
*
|
||||
* @param ?string $sort
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setSort(?string $sort): self
|
||||
{
|
||||
$this->sort = $sort;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
abstract protected function getItemClass(): string;
|
||||
|
||||
abstract protected function getVisualColumn(): string;
|
||||
|
||||
protected function getVisualLabel()
|
||||
{
|
||||
return new Icon('heartbeat', ['title' => t('Severity')]);
|
||||
|
|
@ -16,7 +94,53 @@ abstract class StateItemTable extends BaseItemTable
|
|||
|
||||
protected function assembleColumnHeader(BaseHtmlElement $header, string $name, $label): void
|
||||
{
|
||||
parent::assembleColumnHeader($header, $name, $label);
|
||||
$sortRules = [];
|
||||
if ($this->sort !== null) {
|
||||
$sortRules = SortUtil::createOrderBy($this->sort);
|
||||
}
|
||||
|
||||
$active = false;
|
||||
$sortDirection = null;
|
||||
foreach ($sortRules as $rule) {
|
||||
if ($rule[0] === $name) {
|
||||
$sortDirection = $rule[1];
|
||||
$active = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ($sortDirection === 'desc') {
|
||||
$value = "$name asc";
|
||||
} else {
|
||||
$value = "$name desc";
|
||||
}
|
||||
|
||||
$icon = 'sort';
|
||||
if ($active) {
|
||||
$icon = $sortDirection === 'desc' ? 'sort-up' : 'sort-down';
|
||||
}
|
||||
|
||||
$form = new Form();
|
||||
$form->setAttribute('method', 'GET');
|
||||
|
||||
$button = $form->createElement('button', 'sort', [
|
||||
'value' => $value,
|
||||
'type' => 'submit',
|
||||
'title' => is_string($label) ? $label : null,
|
||||
'class' => $active ? 'active' : null
|
||||
]);
|
||||
$button->addHtml(
|
||||
Html::tag(
|
||||
'span',
|
||||
null,
|
||||
// With to have the height sized the same as the others
|
||||
$label ?? HtmlString::create(' ')
|
||||
),
|
||||
new Icon($icon)
|
||||
);
|
||||
$form->addElement($button);
|
||||
|
||||
$header->add($form);
|
||||
|
||||
switch (true) {
|
||||
case substr($name, -7) === '.output':
|
||||
|
|
@ -32,4 +156,61 @@ abstract class StateItemTable extends BaseItemTable
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
protected function assemble()
|
||||
{
|
||||
$itemClass = $this->getItemClass();
|
||||
|
||||
$headerRow = new HtmlElement('tr');
|
||||
|
||||
$visualCell = new HtmlElement('th', Attributes::create(['class' => 'has-visual']));
|
||||
$this->assembleColumnHeader($visualCell, $this->getVisualColumn(), $this->getVisualLabel());
|
||||
$headerRow->addHtml($visualCell);
|
||||
|
||||
foreach ($this->columns as $name => $label) {
|
||||
$headerCell = new HtmlElement('th');
|
||||
$this->assembleColumnHeader($headerCell, $name, is_int($label) ? $name : $label);
|
||||
$headerRow->addHtml($headerCell);
|
||||
}
|
||||
|
||||
$this->addHtml(new HtmlElement('thead', null, $headerRow));
|
||||
|
||||
$body = new HtmlElement('tbody', Attributes::create(['data-base-target' => '_next']));
|
||||
foreach ($this->data as $item) {
|
||||
$body->addHtml(new $itemClass($item, $this));
|
||||
}
|
||||
|
||||
if ($body->isEmpty()) {
|
||||
$body->addHtml(new HtmlElement(
|
||||
'tr',
|
||||
null,
|
||||
new HtmlElement(
|
||||
'td',
|
||||
Attributes::create(['colspan' => count($this->columns)]),
|
||||
new EmptyState(t('No items found.'))
|
||||
)
|
||||
));
|
||||
}
|
||||
|
||||
$this->addHtml($body);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enrich the given list of column names with appropriate labels
|
||||
*
|
||||
* @param Query $query
|
||||
* @param array $columns
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function applyColumnMetaData(Query $query, array $columns): array
|
||||
{
|
||||
$newColumns = [];
|
||||
foreach ($columns as $columnPath) {
|
||||
$label = $query->getResolver()->getColumnDefinition($columnPath)->getLabel();
|
||||
$newColumns[$label ?? $columnPath] = $columnPath;
|
||||
}
|
||||
|
||||
return $newColumns;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ use ipl\Web\Widget\StateBall;
|
|||
use ipl\Web\Widget\TimeSince;
|
||||
use ipl\Web\Widget\TimeUntil;
|
||||
|
||||
abstract class StateRowItem extends BaseRowItem
|
||||
abstract class StateRowItem extends BaseStateRowItem
|
||||
{
|
||||
/** @var StateItemTable */
|
||||
protected $list;
|
||||
|
|
|
|||
|
|
@ -1,176 +0,0 @@
|
|||
// Style
|
||||
|
||||
.item-table {
|
||||
padding: 0;
|
||||
|
||||
thead {
|
||||
th {
|
||||
font-weight: normal;
|
||||
|
||||
// Border styles start
|
||||
form {
|
||||
padding: 0 0 0 1px;
|
||||
border-bottom: 1px solid @gray-light;
|
||||
background: linear-gradient(to top, @gray-light, @body-bg-color);
|
||||
|
||||
button {
|
||||
background: @body-bg-color;
|
||||
}
|
||||
}
|
||||
&:first-child form {
|
||||
padding-left: 0;
|
||||
}
|
||||
// Border styles end
|
||||
}
|
||||
|
||||
button {
|
||||
.appearance(none);
|
||||
border: none;
|
||||
background: none;
|
||||
padding: .1em .5em;
|
||||
|
||||
text-align: left;
|
||||
color: @text-color-light;
|
||||
|
||||
> .icon {
|
||||
opacity: 0;
|
||||
width: 0;
|
||||
transition: opacity .25s linear, width .25s ease;
|
||||
}
|
||||
&:hover .icon,
|
||||
&:focus .icon,
|
||||
&.active .icon {
|
||||
opacity: 1;
|
||||
width: 1em;
|
||||
}
|
||||
|
||||
&.active {
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
> .empty-state,
|
||||
> tbody > tr:first-child .empty-state {
|
||||
.rounded-corners();
|
||||
background-color: @gray-lightest;
|
||||
}
|
||||
|
||||
.list-item:not(:last-child) > *:not(.visual),
|
||||
.row-item:not(:last-child) {
|
||||
border-bottom: 1px solid @gray-light;
|
||||
}
|
||||
}
|
||||
|
||||
@media print {
|
||||
.list-item.page-break-follows {
|
||||
&:not(:last-child) > *:not(.visual) {
|
||||
border-bottom: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Layout
|
||||
|
||||
table.item-table {
|
||||
table-layout: fixed;
|
||||
}
|
||||
|
||||
.item-table {
|
||||
display: table;
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
|
||||
thead {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
|
||||
th {
|
||||
// That's layout, yes, controls overflow when scrolling
|
||||
padding: 1em 0 0 0;
|
||||
background: @body-bg-color;
|
||||
}
|
||||
|
||||
th button {
|
||||
width: 100%;
|
||||
display: inline-flex;
|
||||
align-items: baseline;
|
||||
justify-content: space-between;
|
||||
|
||||
span {
|
||||
.text-ellipsis();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
th.has-visual {
|
||||
width: 3em;
|
||||
}
|
||||
|
||||
tbody td {
|
||||
.text-ellipsis();
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
.list-item {
|
||||
display: table-row;
|
||||
}
|
||||
|
||||
.list-item > .col {
|
||||
display: table-cell;
|
||||
vertical-align: middle;
|
||||
white-space: nowrap;
|
||||
|
||||
&:not(:last-child) {
|
||||
padding-right: 1em;
|
||||
}
|
||||
|
||||
&.title {
|
||||
.text-ellipsis();
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
> * {
|
||||
display: inline-block;
|
||||
|
||||
&:not(:last-child) {
|
||||
margin-right: .5em;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.list-item > *:not(.visual) {
|
||||
padding: .5em 0;
|
||||
}
|
||||
|
||||
.list-item > .visual {
|
||||
display: table-cell;
|
||||
padding: .5em 1em 0 0;
|
||||
}
|
||||
|
||||
> .empty-state,
|
||||
> tbody > tr:first-child .empty-state {
|
||||
margin: 0 1em;
|
||||
padding: 1em;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
.content.full-width .item-table .list-item {
|
||||
// The .list-item itself can't have padding because of `display:table-row`
|
||||
&:before, &:after {
|
||||
display: inline-block;
|
||||
content: '\00a0';
|
||||
width: 1em;
|
||||
}
|
||||
}
|
||||
|
||||
#layout.twocols table.item-table {
|
||||
> thead > tr > th,
|
||||
> tbody > tr > td {
|
||||
&:nth-child(n+6) {
|
||||
display: none;
|
||||
width: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,5 +1,180 @@
|
|||
// Style
|
||||
|
||||
.state-item-table {
|
||||
padding: 0;
|
||||
|
||||
thead {
|
||||
th {
|
||||
font-weight: normal;
|
||||
|
||||
// Border styles start
|
||||
form {
|
||||
padding: 0 0 0 1px;
|
||||
border-bottom: 1px solid @gray-light;
|
||||
background: linear-gradient(to top, @gray-light, @body-bg-color);
|
||||
|
||||
button {
|
||||
background: @body-bg-color;
|
||||
}
|
||||
}
|
||||
&:first-child form {
|
||||
padding-left: 0;
|
||||
}
|
||||
// Border styles end
|
||||
}
|
||||
|
||||
button {
|
||||
.appearance(none);
|
||||
border: none;
|
||||
background: none;
|
||||
padding: .1em .5em;
|
||||
|
||||
text-align: left;
|
||||
color: @text-color-light;
|
||||
|
||||
> .icon {
|
||||
opacity: 0;
|
||||
width: 0;
|
||||
transition: opacity .25s linear, width .25s ease;
|
||||
}
|
||||
&:hover .icon,
|
||||
&:focus .icon,
|
||||
&.active .icon {
|
||||
opacity: 1;
|
||||
width: 1em;
|
||||
}
|
||||
|
||||
&.active {
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
> .empty-state,
|
||||
> tbody > tr:first-child .empty-state {
|
||||
.rounded-corners();
|
||||
background-color: @gray-lightest;
|
||||
}
|
||||
|
||||
.list-item:not(:last-child) > *:not(.visual),
|
||||
.row-item:not(:last-child) {
|
||||
border-bottom: 1px solid @gray-light;
|
||||
}
|
||||
}
|
||||
|
||||
@media print {
|
||||
.list-item.page-break-follows {
|
||||
&:not(:last-child) > *:not(.visual) {
|
||||
border-bottom: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Layout
|
||||
|
||||
table.state-item-table {
|
||||
table-layout: fixed;
|
||||
}
|
||||
|
||||
.state-item-table {
|
||||
display: table;
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
|
||||
thead {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
|
||||
th {
|
||||
// That's layout, yes, controls overflow when scrolling
|
||||
padding: 1em 0 0 0;
|
||||
background: @body-bg-color;
|
||||
}
|
||||
|
||||
th button {
|
||||
width: 100%;
|
||||
display: inline-flex;
|
||||
align-items: baseline;
|
||||
justify-content: space-between;
|
||||
|
||||
span {
|
||||
.text-ellipsis();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
th.has-visual {
|
||||
width: 3em;
|
||||
}
|
||||
|
||||
tbody td {
|
||||
.text-ellipsis();
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
.list-item {
|
||||
display: table-row;
|
||||
}
|
||||
|
||||
.list-item > .col {
|
||||
display: table-cell;
|
||||
vertical-align: middle;
|
||||
white-space: nowrap;
|
||||
|
||||
&:not(:last-child) {
|
||||
padding-right: 1em;
|
||||
}
|
||||
|
||||
&.title {
|
||||
.text-ellipsis();
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
> * {
|
||||
display: inline-block;
|
||||
|
||||
&:not(:last-child) {
|
||||
margin-right: .5em;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.list-item > *:not(.visual) {
|
||||
padding: .5em 0;
|
||||
}
|
||||
|
||||
.list-item > .visual {
|
||||
display: table-cell;
|
||||
padding: .5em 1em 0 0;
|
||||
}
|
||||
|
||||
> .empty-state,
|
||||
> tbody > tr:first-child .empty-state {
|
||||
margin: 0 1em;
|
||||
padding: 1em;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
.content.full-width .state-item-table .list-item {
|
||||
// The .list-item itself can't have padding because of `display:table-row`
|
||||
&:before, &:after {
|
||||
display: inline-block;
|
||||
content: '\00a0';
|
||||
width: 1em;
|
||||
}
|
||||
}
|
||||
|
||||
#layout.twocols table.state-item-table {
|
||||
> thead > tr > th,
|
||||
> tbody > tr > td {
|
||||
&:nth-child(n+6) {
|
||||
display: none;
|
||||
width: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#layout.wide-layout .item-table th.has-plugin-output {
|
||||
width: 50em;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue