diff --git a/assets/fonts/kolidecons/kolidecons.woff b/assets/fonts/kolidecons/kolidecons.woff index 9b256430a4..c1e936d2a5 100755 Binary files a/assets/fonts/kolidecons/kolidecons.woff and b/assets/fonts/kolidecons/kolidecons.woff differ diff --git a/assets/fonts/kolidecons/kolidecons.woff2 b/assets/fonts/kolidecons/kolidecons.woff2 index 0f7b2bdc61..68e8675260 100755 Binary files a/assets/fonts/kolidecons/kolidecons.woff2 and b/assets/fonts/kolidecons/kolidecons.woff2 differ diff --git a/assets/images/laptop-plus.svg b/assets/images/laptop-plus.svg new file mode 100644 index 0000000000..db1a850975 --- /dev/null +++ b/assets/images/laptop-plus.svg @@ -0,0 +1 @@ +Asset 1 \ No newline at end of file diff --git a/assets/images/swoop-arrow.svg b/assets/images/swoop-arrow.svg new file mode 100644 index 0000000000..ea56b8fd35 --- /dev/null +++ b/assets/images/swoop-arrow.svg @@ -0,0 +1,16 @@ + + + + Combined Shape + Created with Sketch. + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/components/hosts/LonelyHost/LonelyHost.jsx b/frontend/components/hosts/LonelyHost/LonelyHost.jsx new file mode 100644 index 0000000000..1fb326ac7f --- /dev/null +++ b/frontend/components/hosts/LonelyHost/LonelyHost.jsx @@ -0,0 +1,34 @@ +import React, { PropTypes } from 'react'; +import { noop } from 'lodash'; + +import Button from 'components/buttons/Button'; +import laptop from '../../../../assets/images/laptop-plus.svg'; +import swoop from '../../../../assets/images/swoop-arrow.svg'; + +const baseClass = 'lonely-host'; + +const LonelyHost = ({ onAddHostClick = noop }) => { + return ( +
+ + +
+

It's Kinda Lonely In Here...

+

Get started adding hosts to Kolide.

+

This can be done individually or across your entire fleet.

+ +
+
+ ); +}; + +LonelyHost.propTypes = { + onAddHostClick: PropTypes.func, +}; + +export default LonelyHost; diff --git a/frontend/components/hosts/LonelyHost/_styles.scss b/frontend/components/hosts/LonelyHost/_styles.scss new file mode 100644 index 0000000000..131d6e259e --- /dev/null +++ b/frontend/components/hosts/LonelyHost/_styles.scss @@ -0,0 +1,74 @@ +.lonely-host { + @include display(flex); + padding: 16px 8px; + + &__add-host-btn { + width: 244px; + height: 286px; + border-radius: 2px; + background-color: $white; + box-shadow: 0 3px 3px 0 rgba(0, 0, 0, 0.07); + border: solid 1px rgba(73, 143, 226, 0.22); + padding: 15px; + + &::before { + @include position(absolute, 0 null null -1px); + content: ''; + background-color: $link; + height: 6px; + width: calc(100% + 2px); + border-top-left-radius: 2px; + border-top-right-radius: 2px; + } + } + + &__title { + font-size: 16px; + font-weight: $bold; + letter-spacing: 1px; + text-align: center; + color: $link; + border-bottom: solid 1px #eaeefb; + padding-bottom: 15px; + margin-bottom: 15px; + display: block; + } + + &__icon { + display: block; + background-color: $bg-medium; + } + + &__laptop { + width: 82px; + margin: 60px 0; + fill: $alert; + } + + &__content { + margin-left: 30px; + + h1 { + font-size: 28px; + font-weight: $normal; + color: #48c586; + padding-left: 5px; + } + + h2 { + font-size: 16px; + font-weight: $bold; + line-height: 1.5; + letter-spacing: -0.5px; + color: rgba(32, 37, 50, 0.66); + padding-left: 5px; + } + + p { + font-size: 15px; + line-height: 1.6; + color: rgba(32, 37, 50, 0.66); + padding-left: 5px; + } + } +} diff --git a/frontend/components/hosts/LonelyHost/index.js b/frontend/components/hosts/LonelyHost/index.js new file mode 100644 index 0000000000..7d7d44686c --- /dev/null +++ b/frontend/components/hosts/LonelyHost/index.js @@ -0,0 +1 @@ +export default from './LonelyHost'; diff --git a/frontend/pages/hosts/ManageHostsPage/ManageHostsPage.jsx b/frontend/pages/hosts/ManageHostsPage/ManageHostsPage.jsx index 3e77b46920..6167e8dd52 100644 --- a/frontend/pages/hosts/ManageHostsPage/ManageHostsPage.jsx +++ b/frontend/pages/hosts/ManageHostsPage/ManageHostsPage.jsx @@ -15,6 +15,7 @@ import HostDetails from 'components/hosts/HostDetails'; import hostInterface from 'interfaces/host'; import HostSidePanel from 'components/side_panels/HostSidePanel'; import HostsTable from 'components/hosts/HostsTable'; +import LonelyHost from 'components/hosts/LonelyHost'; import Icon from 'components/icons/Icon'; import PlatformIcon from 'components/icons/PlatformIcon'; import osqueryTableInterface from 'interfaces/osquery_table'; @@ -326,7 +327,7 @@ export class ManageHostsPage extends Component { } renderHosts = () => { - const { display, isAddLabel } = this.props; + const { display, isAddLabel, selectedLabel } = this.props; const { onHostDetailActionClick, filterHosts, sortHosts, renderNoHosts } = this; if (isAddLabel) { @@ -337,6 +338,10 @@ export class ManageHostsPage extends Component { const sortedHosts = sortHosts(filteredHosts); if (sortedHosts.length === 0) { + if (selectedLabel && selectedLabel.type === 'all') { + return ; + } + return renderNoHosts(); } diff --git a/frontend/pages/hosts/ManageHostsPage/ManageHostsPage.tests.jsx b/frontend/pages/hosts/ManageHostsPage/ManageHostsPage.tests.jsx index 664223b642..f8b159d159 100644 --- a/frontend/pages/hosts/ManageHostsPage/ManageHostsPage.tests.jsx +++ b/frontend/pages/hosts/ManageHostsPage/ManageHostsPage.tests.jsx @@ -91,6 +91,18 @@ describe('ManageHostsPage - component', () => { }); describe('host rendering', () => { + it('render LonelyHost if no hosts available', () => { + const page = mount(); + + expect(page.find('LonelyHost').length).toEqual(1); + }); + + it('renders message if no hosts available and not on All Hosts', () => { + const page = mount(); + + expect(page.find('.manage-hosts__no-hosts').length).toEqual(1); + }); + it('renders hosts as HostDetails by default', () => { const page = mount(); diff --git a/frontend/styles/global/_icons.scss b/frontend/styles/global/_icons.scss index 4fad7e2544..47fe3b2c6a 100644 --- a/frontend/styles/global/_icons.scss +++ b/frontend/styles/global/_icons.scss @@ -14,342 +14,346 @@ } .kolidecon-lg { - font-size: 1.33333333em; - line-height: 0.75em; - vertical-align: -15%; + font-size: 1.33333333em; + line-height: 0.75em; + vertical-align: -15%; } .kolidecon-2x { - font-size: 2em; + font-size: 2em; } .kolidecon-3x { - font-size: 3em; + font-size: 3em; } .kolidecon-4x { - font-size: 4em; + font-size: 4em; } .kolidecon-5x { - font-size: 5em; + font-size: 5em; } .kolidecon-fw { - width: 1.28571429em; - text-align: center; + width: 1.28571429em; + text-align: center; } .kolidecon-kolide-logo-flat:before { - content: '\f000'; + content: '\f000'; } .kolidecon-chevrondown:before { - content: '\f004'; + content: '\f004'; } .kolidecon-chevronleft:before { - content: '\f006'; + content: '\f006'; } .kolidecon-chevronright:before { - content: '\f008'; + content: '\f008'; } .kolidecon-chevronup:before { - content: '\f00a'; + content: '\f00a'; } .kolidecon-cpu:before { - content: '\f00c'; + content: '\f00c'; } .kolidecon-downcarat:before { - content: '\f00d'; + content: '\f00d'; } .kolidecon-filter:before { - content: '\f00f'; + content: '\f00f'; } .kolidecon-mac:before { - content: '\f012'; + content: '\f012'; } .kolidecon-memory:before { - content: '\f013'; + content: '\f013'; } .kolidecon-storage:before { - content: '\f019'; + content: '\f019'; } .kolidecon-upcarat:before { - content: '\f01b'; + content: '\f01b'; } .kolidecon-uptime:before { - content: '\f01c'; + content: '\f01c'; } .kolidecon-world:before { - content: '\f01d'; + content: '\f01d'; } .kolidecon-osquery:before { - content: '\f021'; + content: '\f021'; } .kolidecon-join:before { - content: '\f022'; + content: '\f022'; } .kolidecon-add-button:before { - content: '\f029'; + content: '\f029'; } .kolidecon-packs:before { - content: '\f02f'; + content: '\f02f'; } .kolidecon-help:before { - content: '\f030'; + content: '\f030'; } .kolidecon-admin:before { - content: '\f031'; + content: '\f031'; } .kolidecon-config:before { - content: '\f032'; + content: '\f032'; } .kolidecon-mia:before { - content: '\f034'; + content: '\f034'; } .kolidecon-success-check:before { - content: '\f035'; + content: '\f035'; } .kolidecon-offline:before { - content: '\f036'; + content: '\f036'; } .kolidecon-windows:before { - content: '\f037'; + content: '\f037'; } .kolidecon-centos:before { - content: '\f038'; + content: '\f038'; } .kolidecon-ubuntu:before { - content: '\f039'; + content: '\f039'; } .kolidecon-apple:before { - content: '\f03a'; + content: '\f03a'; } .kolidecon-search:before { - content: '\f03b'; + content: '\f03b'; } .kolidecon-all-hosts:before { - content: '\f03c'; + content: '\f03c'; } .kolidecon-alerts:before { - content: '\f03e'; + content: '\f03e'; } .kolidecon-logout:before { - content: '\f03f'; + content: '\f03f'; } .kolidecon-user-settings:before { - content: '\f040'; + content: '\f040'; } .kolidecon-clipboard:before { - content: '\f043'; + content: '\f043'; } .kolidecon-list-select:before { - content: '\f044'; + content: '\f044'; } .kolidecon-grid-select:before { - content: '\f045'; + content: '\f045'; } .kolidecon-label:before { - content: '\f033'; + content: '\f033'; } .kolidecon-docker:before { - content: '\f046'; + content: '\f046'; } .kolidecon-cloud:before { - content: '\f047'; + content: '\f047'; } .kolidecon-self-hosted:before { - content: '\f048'; + content: '\f048'; } .kolidecon-help-solid:before { - content: '\f049'; + content: '\f049'; } .kolidecon-help-stroke:before { - content: '\f04a'; + content: '\f04a'; } .kolidecon-warning-filled:before { - content: '\f04b'; + content: '\f04b'; } .kolidecon-delete-cloud:before { - content: '\f04c'; + content: '\f04c'; } .kolidecon-pdf:before { - content: '\f04d'; + content: '\f04d'; } .kolidecon-credit-card-small:before { - content: '\f04e'; + content: '\f04e'; } .kolidecon-billing-card:before { - content: '\f04f'; + content: '\f04f'; } .kolidecon-lock-big:before { - content: '\f050'; + content: '\f050'; } .kolidecon-link-big:before { - content: '\f051'; + content: '\f051'; } .kolidecon-briefcase:before { - content: '\f052'; + content: '\f052'; } .kolidecon-name-card:before { - content: '\f053'; + content: '\f053'; } .kolidecon-kolide-logo:before { - content: '\f054'; + content: '\f054'; } .kolidecon-business:before { - content: '\f055'; + content: '\f055'; } .kolidecon-clock:before { - content: '\f056'; + content: '\f056'; } .kolidecon-host-large:before { - content: '\f057'; + content: '\f057'; } .kolidecon-single-host:before { - content: '\f03d'; + content: '\f03d'; } .kolidecon-username:before { - content: '\f02a'; + content: '\f02a'; } .kolidecon-password:before { - content: '\f02b'; + content: '\f02b'; } .kolidecon-email:before { - content: '\f02c'; + content: '\f02c'; } .kolidecon-hosts:before { - content: '\f02e'; + content: '\f02e'; } .kolidecon-query:before { - content: '\f02d'; + content: '\f02d'; } .kolidecon-import:before { - content: '\f058'; + content: '\f058'; } .kolidecon-pencil:before { - content: '\f059'; + content: '\f059'; } .kolidecon-add-plus:before { - content: '\f05a'; + content: '\f05a'; } .kolidecon-x:before { - content: '\f05b'; + content: '\f05b'; } .kolidecon-kill-kolide:before { - content: '\f05c'; + content: '\f05c'; } .kolidecon-right-arrow:before { - content: '\f05d'; + content: '\f05d'; } .kolidecon-camera:before { - content: '\f05e'; + content: '\f05e'; } .kolidecon-plus-minus:before { - content: '\f05f'; + content: '\f05f'; } .kolidecon-bold-plus:before { - content: '\f060'; + content: '\f060'; } .kolidecon-linux:before { - content: '\f061'; + content: '\f061'; } .kolidecon-clock2:before { - content: '\f063'; + content: '\f063'; } .kolidecon-trash:before { - content: '\f064'; + content: '\f064'; +} + +.kolidecon-laptop-plus:before { + content: '\f065'; } .sr-only { -position: absolute; -width: 1px; -height: 1px; -padding: 0; -margin: -1px; -overflow: hidden; -clip: rect(0, 0, 0, 0); -border: 0 + position: absolute; + width: 1px; + height: 1px; + padding: 0; + margin: -1px; + overflow: hidden; + clip: rect(0, 0, 0, 0); + border: 0 } .sr-only-focusable:active, .sr-only-focusable:focus { -position: static; -width: auto; -height: auto; -margin: 0; -overflow: visible; -clip: auto + position: static; + width: auto; + height: auto; + margin: 0; + overflow: visible; + clip: auto }