mirror of
https://github.com/fleetdm/fleet
synced 2026-05-23 08:58:41 +00:00
Update host side panel. New styles for labels. (#72)
The goal of this PR is to implement the new styles in the mockups and update the right-side panel on the hosts page. This right-side panel includes built-in labels, custom labels, and filtering for custom labels.
This commit is contained in:
parent
05b8e432e5
commit
57950a9645
10 changed files with 96 additions and 115 deletions
|
|
@ -38,7 +38,7 @@ $base-class: 'button';
|
|||
font-family: 'Nunito Sans', sans-serif;
|
||||
font-weight: $bold;
|
||||
display: inline-block;
|
||||
padding: 0 $pad-large;
|
||||
padding: 9px 15px;
|
||||
top: 0;
|
||||
border: 0;
|
||||
cursor: pointer;
|
||||
|
|
|
|||
|
|
@ -10,9 +10,9 @@ import { humanMemory, humanUptime, humanLastSeen } from './helpers';
|
|||
|
||||
const baseClass = 'host-details';
|
||||
|
||||
export const STATUSES = {
|
||||
online: 'ONLINE',
|
||||
offline: 'OFFLINE',
|
||||
export const statuses = {
|
||||
online: 'Online',
|
||||
offline: 'Offline',
|
||||
};
|
||||
|
||||
const ActionButton = ({ host, onDestroyHost, onQueryHost }) => {
|
||||
|
|
|
|||
|
|
@ -52,7 +52,13 @@ class HostSidePanel extends Component {
|
|||
});
|
||||
|
||||
return (
|
||||
<SecondarySidePanelContainer className={`${baseClass}__wrapper`}>
|
||||
<SecondarySidePanelContainer className={`${baseClass}`}>
|
||||
|
||||
<Button onClick={onAddHostClick} className={`${baseClass}__add-hosts button button--brand`}>
|
||||
<span>Add New Host</span>
|
||||
</Button>
|
||||
|
||||
<h3>Status</h3>
|
||||
<PanelGroup
|
||||
groupItems={allHostLabels}
|
||||
onLabelClick={onLabelClick}
|
||||
|
|
@ -60,12 +66,6 @@ class HostSidePanel extends Component {
|
|||
type="all-hosts"
|
||||
/>
|
||||
|
||||
<Button variant="unstyled" onClick={onAddHostClick} className={`${baseClass}__add-hosts`}>
|
||||
<Icon name="laptop-plus" className={`${baseClass}__add-hosts-icon`} />
|
||||
<span>Add New Host</span>
|
||||
</Button>
|
||||
|
||||
<hr className={`${baseClass}__hr`} />
|
||||
<PanelGroup
|
||||
groupItems={hostStatusLabels}
|
||||
onLabelClick={onLabelClick}
|
||||
|
|
@ -73,18 +73,16 @@ class HostSidePanel extends Component {
|
|||
selectedFilter={selectedFilter}
|
||||
type="status"
|
||||
/>
|
||||
<hr className={`${baseClass}__hr`} />
|
||||
|
||||
<h3>Operating Systems</h3>
|
||||
<PanelGroup
|
||||
groupItems={hostPlatformLabels}
|
||||
onLabelClick={onLabelClick}
|
||||
selectedFilter={selectedFilter}
|
||||
type="platform"
|
||||
/>
|
||||
{hostPlatformLabels.length > 0 && <hr className={`${baseClass}__hr`} />}
|
||||
<div className={`${baseClass}__panel-group-item`}>
|
||||
<Icon name="label" />
|
||||
<span className="title">LABELS</span>
|
||||
</div>
|
||||
|
||||
<h3 className="title">Labels</h3>
|
||||
<div className={`${baseClass}__panel-group-item ${baseClass}__panel-group-item--filter`}>
|
||||
<InputField
|
||||
name="tags-filter"
|
||||
|
|
@ -101,10 +99,9 @@ class HostSidePanel extends Component {
|
|||
selectedFilter={selectedFilter}
|
||||
type="label"
|
||||
/>
|
||||
<hr className={`${baseClass}__hr`} />
|
||||
|
||||
<Button variant="unstyled" onClick={onAddLabelClick} className={`${baseClass}__add-label-btn`}>
|
||||
ADD NEW LABEL
|
||||
<Icon name="label" className={`${baseClass}__add-label-icon`} />
|
||||
Add new label
|
||||
</Button>
|
||||
</SecondarySidePanelContainer>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -41,12 +41,12 @@ class PanelGroup extends Component {
|
|||
}
|
||||
|
||||
render () {
|
||||
const { groupItems } = this.props;
|
||||
const { groupItems, type } = this.props;
|
||||
const { renderGroupItem } = this;
|
||||
const baseClass = 'panel-group';
|
||||
|
||||
return (
|
||||
<div className={baseClass}>
|
||||
<div className={`${baseClass} ${baseClass}__${type}`}>
|
||||
{groupItems.map((item) => {
|
||||
return renderGroupItem(item);
|
||||
})}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,30 @@
|
|||
.panel-group {
|
||||
&__label {
|
||||
max-height: 280px;
|
||||
overflow-y: scroll;
|
||||
position: relative;
|
||||
|
||||
&:before {
|
||||
content: '';
|
||||
position: sticky;
|
||||
display: block;
|
||||
z-index: 1;
|
||||
top: -2px;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 17px;
|
||||
background-image: linear-gradient(to bottom, #f9fafc, transparent);
|
||||
}
|
||||
|
||||
&:after {
|
||||
content: '';
|
||||
position: sticky;
|
||||
display: block;
|
||||
bottom: -1px;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 17px;
|
||||
background-image: linear-gradient(to bottom, transparent, #f9fafc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -48,19 +48,8 @@ class PanelGroupItem extends Component {
|
|||
return <Icon name={iconClassForLabel(item)} className={`${baseClass}__icon`} />;
|
||||
}
|
||||
|
||||
renderDescription = () => {
|
||||
const { item } = this.props;
|
||||
const { title_description: titleDescription, type } = item;
|
||||
|
||||
if (!titleDescription || type === 'custom') {
|
||||
return false;
|
||||
}
|
||||
|
||||
return <span className={`${baseClass}__description`}>{titleDescription}</span>;
|
||||
}
|
||||
|
||||
render () {
|
||||
const { displayCount, renderDescription, renderIcon } = this;
|
||||
const { displayCount, renderIcon } = this;
|
||||
const { item, onLabelClick, isSelected } = this.props;
|
||||
const {
|
||||
display_text: displayText,
|
||||
|
|
@ -83,7 +72,6 @@ class PanelGroupItem extends Component {
|
|||
{renderIcon()}
|
||||
<span className={`${baseClass}__name`}>
|
||||
{displayText}
|
||||
{renderDescription()}
|
||||
</span>
|
||||
<span className={`${baseClass}__count`}>{displayCount()}</span>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -4,29 +4,29 @@ $base-class: 'panel-group-item';
|
|||
transition: color 75ms ease-in-out, background 75ms ease-in-out;
|
||||
width: 100%;
|
||||
font-size: $x-small;
|
||||
line-height: 2.25;
|
||||
letter-spacing: 0.5px;
|
||||
font-weight: $regular;
|
||||
color: $core-black;
|
||||
color: $black;
|
||||
text-align: left;
|
||||
padding: 0 $pad-large;
|
||||
padding: 10px 0;
|
||||
margin: 2px 0;
|
||||
border-radius: 8px;
|
||||
|
||||
&:hover {
|
||||
background-color: $core-blue-selected;
|
||||
|
||||
.#{$base-class}__icon {
|
||||
color: $core-black;
|
||||
}
|
||||
}
|
||||
|
||||
&.#{$base-class}--selected {
|
||||
color: $core-black;
|
||||
font-weight: $bold;
|
||||
background-color: $core-blue-selected;
|
||||
|
||||
.#{$base-class}__icon {
|
||||
color: $white;
|
||||
}
|
||||
|
||||
.#{$base-class}__count {
|
||||
font-weight: $bold;
|
||||
}
|
||||
}
|
||||
|
||||
&__flexy {
|
||||
|
|
@ -36,7 +36,7 @@ $base-class: 'panel-group-item';
|
|||
|
||||
&__icon {
|
||||
transition: color 75ms ease-in-out;
|
||||
margin-right: 23px;
|
||||
padding: 0 16px 0 8px;
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
|
|
@ -53,8 +53,9 @@ $base-class: 'panel-group-item';
|
|||
|
||||
&__count {
|
||||
transition: color 75ms ease-in-out;
|
||||
font-weight: $bold;
|
||||
font-weight: $regular;
|
||||
text-align: right;
|
||||
padding-right: 12px;
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,62 +1,53 @@
|
|||
.host-side-panel {
|
||||
color: $core-dark-blue-grey;
|
||||
padding: 14px 20px 22px;
|
||||
|
||||
.input-icon-field {
|
||||
margin-top: 0;
|
||||
|
||||
&__label {
|
||||
display: none;
|
||||
}
|
||||
|
||||
&__icon {
|
||||
top: 6px;
|
||||
}
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: $x-small;
|
||||
font-weight: $bold;
|
||||
color: $black;
|
||||
margin: 24px 0 10px 8px;
|
||||
}
|
||||
|
||||
&__add-label-btn {
|
||||
color: $white;
|
||||
font-size: $small;
|
||||
font-weight: $bold;
|
||||
background-color: $core-medium-blue-grey;
|
||||
font-weight: $regular;
|
||||
line-height: 2.25;
|
||||
letter-spacing: 0.5px;
|
||||
padding: 0 30px;
|
||||
padding: 9px 75px;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
margin-top: 24px;
|
||||
|
||||
&:hover {
|
||||
background-color: rgba($success, 0.1);
|
||||
background-color: darken($core-medium-blue-grey, 5%);
|
||||
}
|
||||
}
|
||||
|
||||
&__add-label-icon {
|
||||
margin: 0 0 0 $pad-small;
|
||||
}
|
||||
|
||||
&__wrapper {
|
||||
color: $core-dark-blue-grey;
|
||||
padding: 0;
|
||||
|
||||
.input-icon-field {
|
||||
margin-top: 0;
|
||||
|
||||
&__label {
|
||||
display: none;
|
||||
}
|
||||
|
||||
&__icon {
|
||||
top: 6px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&__hr {
|
||||
color: $core-dark-blue-grey;
|
||||
margin: $pad-base $pad-auto;
|
||||
width: 80%;
|
||||
height: 1px;
|
||||
background-color: #ececec;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
&__panel-group-item {
|
||||
background-color: $white;
|
||||
color: $core-dark-blue-grey;
|
||||
padding: $pad-half $pad-large;
|
||||
width: 100%;
|
||||
|
||||
&--filter {
|
||||
position: relative;
|
||||
|
||||
.kolidecon {
|
||||
position: absolute;
|
||||
top: calc(#{$pad-half} + 8px);
|
||||
left: calc(#{$pad-large} + 10px);
|
||||
font-size: 22px;
|
||||
top: 10px;
|
||||
left: 12px;
|
||||
font-size: 20px;
|
||||
color: $core-medium-blue-grey;
|
||||
}
|
||||
}
|
||||
|
|
@ -68,35 +59,11 @@
|
|||
}
|
||||
|
||||
&__filter-labels {
|
||||
margin: 0;
|
||||
margin-bottom: 16px;
|
||||
|
||||
.input-field {
|
||||
padding-left: 42px;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
&__add-hosts {
|
||||
padding: 0 $pad-large;
|
||||
width: 100%;
|
||||
line-height: 2.25;
|
||||
margin-top: 10px;
|
||||
text-align: left;
|
||||
|
||||
span {
|
||||
font-size: 16px;
|
||||
font-weight: $regular;
|
||||
line-height: normal;
|
||||
letter-spacing: -0.5px;
|
||||
color: $core-purple;
|
||||
text-transform: none;
|
||||
}
|
||||
|
||||
.kolidecon {
|
||||
margin-right: 20px;
|
||||
font-size: 26px;
|
||||
vertical-align: middle;
|
||||
margin-left: -3px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,8 +6,6 @@
|
|||
overflow: auto;
|
||||
width: $sidepanel-width;
|
||||
margin-left: $pad-base;
|
||||
padding-top: $pad-base;
|
||||
min-height: calc(100vh - #{$pad-base});
|
||||
|
||||
@include breakpoint(smalldesk) {
|
||||
width: $sidepanel-tablet-width;
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ const labelStubs = [
|
|||
{
|
||||
id: 'new',
|
||||
count: 0,
|
||||
display_text: 'NEW',
|
||||
display_text: 'New',
|
||||
slug: 'new',
|
||||
statusLabelKey: 'new_count',
|
||||
title_description: '(added in last 24hrs)',
|
||||
|
|
@ -40,7 +40,7 @@ const labelStubs = [
|
|||
id: 'online',
|
||||
count: 0,
|
||||
description: 'Hosts that have recently checked-in to kolide and are ready to run queries.',
|
||||
display_text: 'ONLINE',
|
||||
display_text: 'Online',
|
||||
slug: 'online',
|
||||
statusLabelKey: 'online_count',
|
||||
type: 'status',
|
||||
|
|
@ -49,7 +49,7 @@ const labelStubs = [
|
|||
id: 'offline',
|
||||
count: 0,
|
||||
description: 'Hosts that have not checked-in to kolide recently.',
|
||||
display_text: 'OFFLINE',
|
||||
display_text: 'Offline',
|
||||
slug: 'offline',
|
||||
statusLabelKey: 'offline_count',
|
||||
type: 'status',
|
||||
|
|
|
|||
Loading…
Reference in a new issue