Skip to content

Commit

Permalink
Add landing page with table to Visualize app.
Browse files Browse the repository at this point in the history
- Update Visualize wizard UI.
- kbnTopNav directive supports no-menu-extensions attribute for excluding extensions, so you can hide the menu items entirely.
  • Loading branch information
cjcenizal committed Feb 4, 2017
1 parent 5778951 commit 5a5eecb
Show file tree
Hide file tree
Showing 9 changed files with 307 additions and 58 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
</a>
</div>

<!-- Allow searching if there is no linked Saved Searc. -->
<!-- Allow searching if there is no linked Saved Search. -->
<form
ng-if="vis.type.requiresSearch && !$state.linked"
name="queryInput"
Expand Down
3 changes: 2 additions & 1 deletion src/core_plugins/kibana/public/visualize/index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import 'plugins/kibana/visualize/styles/main.less';
import 'plugins/kibana/visualize/editor/editor';
import 'plugins/kibana/visualize/landing/landing';
import 'plugins/kibana/visualize/wizard/wizard';
import 'plugins/kibana/visualize/editor/add_bucket_agg';
import 'plugins/kibana/visualize/editor/agg';
Expand All @@ -24,7 +25,7 @@ uiRoutes
requireDefaultIndex: true
})
.when('/visualize', {
redirectTo: '/visualize/step/1'
redirectTo: '/visualize/landing'
});

// preloading
Expand Down
11 changes: 11 additions & 0 deletions src/core_plugins/kibana/public/visualize/landing/landing.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import routes from 'ui/routes';
import modules from 'ui/modules';
import visualizeLandingTemplate from './visualize_landing.html';
import { VisualizeLandingController } from './visualize_landing';

routes
.when('/visualize/landing', {
template: visualizeLandingTemplate,
controller: VisualizeLandingController,
controllerAs: 'landingController',
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
<!-- Local nav. -->
<kbn-top-nav name="visualize" no-menu-extensions>
<!-- Transcluded elements. -->
<div data-transclude-slots>
<!-- Title. -->
<div
data-transclude-slot="topLeftCorner"
class="kuiLocalTitle"
>
Visualize
</div>
</div>
</kbn-top-nav>

<div class="kuiViewContent kuiViewContent--constrainedWidth">
<!-- ControlledTable -->
<div class="kuiViewContentItem kuiControlledTable kuiVerticalRhythm">
<!-- ToolBar -->
<div class="kuiToolBar">
<div class="kuiToolBarSearch">
<div class="kuiToolBarSearchBox">
<div class="kuiToolBarSearchBox__icon kuiIcon fa-search"></div>
<input
class="kuiToolBarSearchBox__input"
type="text"
placeholder="Search..."
aria-label="Filter"
ng-model="landingController.filter"
>
</div>
</div>

<div class="kuiToolBarSection">
<!-- Bulk delete button -->
<button
class="kuiButton kuiButton--danger kuiButton--iconText"
confirm-click="landingController.deleteSelectedItems()"
confirmation="Are you sure you want to delete the selected visualizations? This action is irreversible!"
aria-label="Delete selected objects"
ng-hide="landingController.getSelectedItemsCount() === 0"
>
<span aria-hidden="true" class="kuiButton__icon kuiIcon fa-trash"></span>
Delete
</button>

<!-- Create visualization button -->
<a
class="kuiButton kuiButton--primary kuiButton--iconText"
href="#/visualize/step/1"
aria-label="Create new visualization"
ng-hide="landingController.getSelectedItemsCount() > 0"
>
<span aria-hidden="true" class="kuiButton__icon kuiIcon fa-plus"></span>
Create visualization
</a>
</div>

<div class="kuiToolBarSection">
<!-- We need an empty section for the buttons to be positioned consistently. -->
</div>
</div>

<!-- NoResults -->
<div class="kuiPanel kuiPanel--centered" ng-if="!landingController.items.length">
<div class="kuiNoResults">
No visualizations matched your search.
</div>
</div>

<!-- Table -->
<table class="kuiTable" ng-if="landingController.items.length">
<thead>
<tr>
<th class="kuiTableHeaderCell kuiTableHeaderCell--checkBox">
<input
type="checkbox"
class="kuiCheckBox"
ng-checked="landingController.areAllItemsChecked()"
ng-click="landingController.toggleAll()"
>
</th>
<th class="kuiTableHeaderCell">
Visualization
</th>
<th class="kuiTableHeaderCell">
Type
</th>
</tr>
</thead>

<tbody>
<tr
ng-repeat="item in landingController.items track by item.id | orderBy:'title'"
class="kuiTableRow"
>
<td class="kuiTableRowCell kuiTableRowCell--checkBox">
<input
type="checkbox"
class="kuiCheckBox"
ng-click="landingController.toggleItem(item)"
ng-checked="landingController.isItemChecked(item)"
>
</td>

<td class="kuiTableRowCell">
<div class="kuiTableRowCell__liner">
<a class="kuiLink" ng-href="{{ item.url }}">
{{ item.title }}
</a>

<button
class="kuiMicroButton kuiTableRowHoverReveal"
ng-click="landingController.edit(item)"
aria-label="Edit"
tooltip="Edit object"
>
<span
aria-hidden="true"
class="kuiIcon fa-code"
></span>
</button>
</div>
</td>

<td class="kuiTableRowCell">
<div class="kuiTableRowCell__liner">
{{ item.type.title }}
</div>
</td>
</tr>

</tbody>
</table>

<!-- ToolBarFooter -->
<div class="kuiToolBarFooter">
<div class="kuiToolBarFooterSection">
<div class="kuiToolBarText" ng-hide="landingController.getSelectedItemsCount() === 0">
{{ landingController.getSelectedItemsCount() }} selected
</div>
</div>
<div class="kuiToolBarFooterSection">
<!-- We need an empty section for the buttons to be positioned consistently. -->
</div>
</div>
</div>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import SavedObjectRegistryProvider from 'ui/saved_objects/saved_object_registry';

export function VisualizeLandingController(
$scope,
kbnUrl,
Notifier,
Private
) {
// TODO: Extract this into an external service.
const services = Private(SavedObjectRegistryProvider).byLoaderPropertiesName;
const visualizationService = services.visualizations;
const notify = new Notifier({ location: 'Visualize' });

let selectedItems = [];

const fetchObjects = () => {
visualizationService.find(this.filter)
.then(result => {
this.items = result.hits;
});
};

this.items = [];
this.filter = '';

this.toggleAll = function toggleAll() {
if (this.areAllItemsChecked()) {
selectedItems = [];
} else {
selectedItems = this.items.slice(0);
}
};

this.toggleItem = function toggleItem(item) {
if (this.isItemChecked(item)) {
const index = selectedItems.indexOf(item);
selectedItems.splice(index, 1);
} else {
selectedItems.push(item);
}
};

this.isItemChecked = function isItemChecked(item) {
return selectedItems.indexOf(item) !== -1;
};

this.areAllItemsChecked = function areAllItemsChecked() {
return this.getSelectedItemsCount() === this.items.length;
};

this.getSelectedItemsCount = function getSelectedItemsCount() {
return selectedItems.length;
};

this.deleteSelectedItems = function deleteSelectedItems() {
const selectedIds = selectedItems.map(item => item.id);

visualizationService.delete(selectedIds)
.then(fetchObjects)
.then(() => {
selectedItems = [];
})
.catch(error => notify.error(error));
};

this.open = function open(item) {
kbnUrl.change(item.url.substr(1));
};

this.edit = function edit(item) {
const params = {
// TODO: Get this value from somewhere instead of hardcodign it.
service: 'savedVisualizations',
id: item.id
};

kbnUrl.change('/management/kibana/objects/{{ service }}/{{ id }}', params);
};

$scope.$watch(() => this.filter, () => {
fetchObjects();
});
}
70 changes: 31 additions & 39 deletions src/core_plugins/kibana/public/visualize/styles/main.less
Original file line number Diff line number Diff line change
Expand Up @@ -2,56 +2,48 @@
@import (reference) "~ui/styles/bootstrap/list-group";
@import (reference) "~ui/styles/list-group-menu";

/**
* 1. Push down the breadcrumbs a bit.
*/
.vis-wizard {
margin: 0;
padding: 12px 0 0; // 1
.wizard-sub-title {
margin-top: 0px;
margin-bottom: 8px;
padding: 0px 5px;
}

.wizard-sub-title {
margin-top: 0px;
margin-bottom: 8px;
padding: 0px 5px;
}
.wizard-type {
flex: 1;

.wizard-type {
flex: 1;
// TODO: When we migrate off Bootstrap, we can eliminate these "mixins".
.list-group-item();
.list-group-menu .list-group-menu-item();

// TODO: When we migrate off Bootstrap, we can eliminate these "mixins".
.list-group-item();
.list-group-menu .list-group-menu-item();
border: none;
border-radius: 0;
background-color: @kibanaGray6;
}

border: none;
border-radius: 0;
background-color: @kibanaGray6;
.wizard-type-heading {
flex: 0 0 200px;
display: flex;
align-items: center;
font-size: 1.2em;
}

.wizard-type-heading {
flex: 0 0 200px;
display: flex;
align-items: center;
font-size: 1.2em;
.wizard-type-heading-icon {
flex: 0 0 auto;
margin-right: @padding-base-horizontal;
font-size: 1.5em;
text-align: center;
color: @saved-object-finder-icon-color;
}

.wizard-type-heading-icon {
flex: 0 0 auto;
margin-right: @padding-base-horizontal;
font-size: 1.5em;
text-align: center;
color: @saved-object-finder-icon-color;
}

.wizard-type-heading-text {
flex: 1 0 auto;
}

.wizard-type-description {
flex: 1 1 auto;
color: @wizard-vis-type-description-color;
.wizard-type-heading-text {
flex: 1 0 auto;
}

.wizard-type-description {
flex: 1 1 auto;
color: @wizard-vis-type-description-color;
}

@media (min-width: @screen-lg) {
.wizard {
padding: 0;
Expand Down
30 changes: 18 additions & 12 deletions src/core_plugins/kibana/public/visualize/wizard/step_1.html
Original file line number Diff line number Diff line change
@@ -1,10 +1,24 @@
<div class="container-fluid vis-wizard">
<div class="visualizeWizardBreadcrumbs">
<bread-crumbs></bread-crumbs>
<!-- Local nav. -->
<kbn-top-nav name="visualize" no-menu-extensions>
<!-- Transcluded elements. -->
<div data-transclude-slots>
<!-- Breadcrumbs. -->
<bread-crumbs
data-transclude-slot="topLeftCorner"
></bread-crumbs>
</div>
</kbn-top-nav>

<div class="kuiViewContent kuiViewContent--constrainedWidth">
<!-- Header -->
<div class="kuiViewContentItem kuiSubHeader">
<h1 class="kuiTitle">
Select visualization type
</h1>
</div>

<div class="wizard">
<div class="wizard-column">
<h3 class="wizard-sub-title">Create New Visualization</h3>
<div class="wizard-row">
<a
class="wizard-type"
Expand All @@ -23,13 +37,5 @@ <h4 class="wizard-type-heading-text">{{type.title}}</h4>
</a>
</div>
</div>
<div class="wizard-column">
<h3 class="wizard-sub-title">Or, Open a Saved Visualization</h3>
<saved-object-finder
title="Saved Visualizations"
type="visualizations"
class="wizard-row"
></saved-object-finder>
</div>
</div>
</div>
Loading

0 comments on commit 5a5eecb

Please sign in to comment.