Skip to content

Commit

Permalink
View edit mode
Browse files Browse the repository at this point in the history
clean up

show spy panel in embed mode
  • Loading branch information
stacey-gammon committed Dec 15, 2016
1 parent 8fe6204 commit c58984b
Show file tree
Hide file tree
Showing 10 changed files with 218 additions and 67 deletions.
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
<div class="panel panel-default" ng-switch on="panel.type" ng-if="savedObj || error">
<div class="panel panel-default" ng-class="{'panel--edit-mode': !isViewOnlyMode()}" ng-switch on="panel.type" ng-if="savedObj || error">
<div class="panel-heading">
<span class="panel-title" title="{{::savedObj.title}}">
{{::savedObj.title}}
</span>
<div class="btn-group">
<a aria-label="Edit" ng-show="!isFullScreenMode && editUrl" ng-href="{{::editUrl}}">
<a aria-label="Edit" ng-show="!isViewOnlyMode() && editUrl" ng-href="{{::editUrl}}">
<i aria-hidden="true" class="fa fa-pencil"></i>
</a>
<a aria-label="Move" ng-show="!isFullScreenMode" class="panel-move">
<a aria-label="Move" ng-show="!isViewOnlyMode()" class="panel-move">
<i aria-hidden="true" class="fa fa-arrows"></i>
</a>
<a aria-label="Remove" ng-show="!isFullScreenMode" ng-click="remove()">
<a aria-label="Remove" ng-show="!isViewOnlyMode()" ng-click="remove()">
<i aria-hidden="true" class="fa fa-times"></i>
</a>
</div>
Expand Down
13 changes: 13 additions & 0 deletions src/core_plugins/kibana/public/dashboard/dashboard_view_mode.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
/**
* A dashboard mode.
* @typedef {string} DashboardMode
*/

/**
* Dashboard view modes.
* @type {{EDIT: DashboardMode, VIEW: DashboardMode}}
*/
export const DashboardViewMode = {
EDIT: 'edit',
VIEW: 'view'
};
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { loadPanelProvider } from 'plugins/kibana/dashboard/components/panel/lib
import FilterManagerProvider from 'ui/filter_manager';
import uiModules from 'ui/modules';
import panelTemplate from 'plugins/kibana/dashboard/components/panel/panel.html';
import { DashboardViewMode } from 'plugins/kibana/dashboard/dashboard_view_mode';

uiModules
.get('app/dashboard')
Expand Down Expand Up @@ -33,6 +34,11 @@ uiModules
restrict: 'E',
template: panelTemplate,
scope: {
/**
* What view mode the dashboard is currently in - edit or view only.
* @type {DashboardViewMode}
*/
dashboardViewMode: '=',
/**
* Whether or not the dashboard this panel is contained on is in 'full screen mode'.
* @type {boolean}
Expand Down Expand Up @@ -99,6 +105,14 @@ uiModules

$scope.editUrl = '#management/kibana/objects/' + service.name + '/' + id + '?notFound=' + e.savedObjectType;
});

/**
* Determines whether or not to show edit controls.
* @returns {boolean}
*/
$scope.isViewOnlyMode = () => {
return $scope.dashboardViewMode === DashboardViewMode.VIEW || $scope.isFullScreenMode;
};
}
};
});
17 changes: 16 additions & 1 deletion src/core_plugins/kibana/public/dashboard/directives/grid.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import Binder from 'ui/binder';
import 'gridster';
import uiModules from 'ui/modules';
import { PanelUtils } from 'plugins/kibana/dashboard/components/panel/lib/panel_utils';
import { DashboardViewMode } from 'plugins/kibana/dashboard/dashboard_view_mode';

const app = uiModules.get('app/dashboard');

Expand Down Expand Up @@ -69,13 +70,26 @@ app.directive('dashboardGrid', function ($compile, Notifier) {
}
}).data('gridster');

function setResizeCapability() {
if ($scope.dashboardViewMode === DashboardViewMode.VIEW) {
gridster.disable_resize();
} else {
gridster.enable_resize();
}
}

// This is necessary to enable text selection within gridster elements
// http://stackoverflow.com/questions/21561027/text-not-selectable-from-editable-div-which-is-draggable
binder.jqOn($el, 'mousedown', function () {
gridster.disable().disable_resize();
});
binder.jqOn($el, 'mouseup', function enableResize() {
gridster.enable().enable_resize();
gridster.enable();
setResizeCapability();
});

$scope.$watch('dashboardViewMode', () => {
setResizeCapability();
});

$scope.$watchCollection('state.panels', function (panels) {
Expand Down Expand Up @@ -165,6 +179,7 @@ app.directive('dashboardGrid', function ($compile, Notifier) {
<dashboard-panel remove="removePanelFromState(${panel.panelId})"
panel="getPanelByPanelId(${panel.panelId})"
is-full-screen-mode="!chrome.getVisible()"
dashboard-view-mode="dashboardViewMode"
parent-ui-state="uiState">
</li>`;
panel.$el = $compile(panelHtml)($scope);
Expand Down
84 changes: 84 additions & 0 deletions src/core_plugins/kibana/public/dashboard/get_top_nav_config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import { DashboardViewMode } from './dashboard_view_mode';
import { createTopNavExecuteConfig, createTopNavTemplateConfig } from 'ui/kbn_top_nav/kbn_top_nav_config';

/**
* @param {DashboardMode} dashboardMode.
* @param kbnUrl - used to change the url.
* @param {(DashboardMode) => void} modeChange - a function to trigger a dashboard mode change.
* @return {Array} - Returns an array of objects for a top nav configuration, based on the
* mode.
*/
export function getTopNavConfig(dashboardMode, kbnUrl, modeChange) {
switch (dashboardMode) {
case DashboardViewMode.VIEW:
return [getNewConfig(kbnUrl), getOpenConfig(), getShareConfig(), getEditConfig(modeChange)];
case DashboardViewMode.EDIT:
return [getNewConfig(kbnUrl), getOpenConfig(), getAddConfig(), getSaveConfig(), getOptionsConfig(), getViewConfig(modeChange)];
default:
return [];
}
}

function getEditConfig(modeChange) {
return createTopNavExecuteConfig(
'edit',
'Switch to edit mode',
'dashboardEditMode',
() => { modeChange(DashboardViewMode.EDIT); });
}

function getViewConfig(modeChange) {
return createTopNavExecuteConfig(
'preview',
'Switch to preview mode',
'dashboardViewOnlyMode',
() => { modeChange(DashboardViewMode.VIEW); });
}

function getNewConfig(kbnUrl) {
return createTopNavExecuteConfig(
'new',
'New Dashboard',
'dashboardNewButton',
() => { kbnUrl.change('/dashboard', {}); });
}

function getAddConfig() {
return createTopNavTemplateConfig(
'add',
'Add a panel to the dashboard',
'dashboardAddPanelButton',
require('plugins/kibana/dashboard/partials/pick_visualization.html'));
}

function getSaveConfig() {
return createTopNavTemplateConfig(
'save',
'Save Dashboard',
'dashboardSaveButton',
require('plugins/kibana/dashboard/partials/save_dashboard.html'));
}

function getOpenConfig() {
return createTopNavTemplateConfig(
'open',
'Open Saved Dashboard',
'dashboardOpenButton',
require('plugins/kibana/dashboard/partials/load_dashboard.html'));
}

function getShareConfig() {
return createTopNavTemplateConfig(
'share',
'Share Dashboard',
'dashboardShareButton',
require('plugins/kibana/dashboard/partials/share.html'));
}

function getOptionsConfig() {
return createTopNavTemplateConfig(
'options',
'Options',
'dashboardOptionsButton',
require('plugins/kibana/dashboard/partials/options.html'));
}
4 changes: 2 additions & 2 deletions src/core_plugins/kibana/public/dashboard/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
>
<span
ng-show="dash.id"
ng-bind="dash.lastSavedTitle"
ng-bind="getDashTitle()"
></span>
</div>

Expand Down Expand Up @@ -54,7 +54,7 @@
<!-- Filters. -->
<filter-bar state="state"></filter-bar>

<div ng-show="!state.panels.length" class="text-center start-screen">
<div ng-show="showEditHelpText()" class="text-center start-screen">
<h2>Ready to get started?</h2>
<p>Click the <a class="btn btn-xs navbtn-inverse" ng-click="kbnTopNav.open('add'); toggleAddVisualization = !toggleAddVisualization" aria-label="Add visualization">Add</a> button in the menu bar above to add a visualization to the dashboard. <br/>If you haven't setup a visualization yet visit the <a href="#/visualize" title="Visualize">"Visualize"</a> tab to create your first visualization.</p>
</div>
Expand Down
49 changes: 18 additions & 31 deletions src/core_plugins/kibana/public/dashboard/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,10 @@ import uiRoutes from 'ui/routes';
import uiModules from 'ui/modules';
import indexTemplate from 'plugins/kibana/dashboard/index.html';
import { savedDashboardRegister } from 'plugins/kibana/dashboard/services/saved_dashboard_register';
import { DashboardViewMode } from './dashboard_view_mode';
import { getTopNavConfig } from './get_top_nav_config';
import { createPanelState } from 'plugins/kibana/dashboard/components/panel/lib/panel_state';

require('ui/saved_objects/saved_object_registry').register(savedDashboardRegister);

const app = uiModules.get('app/dashboard', [
Expand Down Expand Up @@ -104,37 +107,12 @@ app.directive('dashboardApp', function (Notifier, courier, AppState, timefilter,

$scope.$watch('state.options.darkTheme', setDarkTheme);

$scope.topNavMenu = [{
key: 'new',
description: 'New Dashboard',
run: function () { kbnUrl.change('/dashboard', {}); },
testId: 'dashboardNewButton',
}, {
key: 'add',
description: 'Add a panel to the dashboard',
template: require('plugins/kibana/dashboard/partials/pick_visualization.html'),
testId: 'dashboardAddPanelButton',
}, {
key: 'save',
description: 'Save Dashboard',
template: require('plugins/kibana/dashboard/partials/save_dashboard.html'),
testId: 'dashboardSaveButton',
}, {
key: 'open',
description: 'Open Saved Dashboard',
template: require('plugins/kibana/dashboard/partials/load_dashboard.html'),
testId: 'dashboardOpenButton',
}, {
key: 'share',
description: 'Share Dashboard',
template: require('plugins/kibana/dashboard/partials/share.html'),
testId: 'dashboardShareButton',
}, {
key: 'options',
description: 'Options',
template: require('plugins/kibana/dashboard/partials/options.html'),
testId: 'dashboardOptionsButton',
}];
const changeViewMode = (newMode) => {
$scope.dashboardViewMode = newMode;
$scope.topNavMenu = getTopNavConfig(newMode, kbnUrl, changeViewMode);
};
// Brand new dashboards are defaulted to edit mode, existing ones default to view mode.
changeViewMode(dash.id ? DashboardViewMode.VIEW : DashboardViewMode.EDIT);

$scope.refresh = _.bindKey(courier, 'fetch');

Expand Down Expand Up @@ -217,6 +195,11 @@ app.directive('dashboardApp', function (Notifier, courier, AppState, timefilter,
// update data when filters fire fetch event
$scope.$listen(queryFilter, 'fetch', $scope.refresh);

$scope.getDashTitle = function () {
const isEditMode = $scope.dashboardViewMode === DashboardViewMode.EDIT;
return isEditMode ? 'Editing ' + dash.lastSavedTitle : dash.lastSavedTitle;
};

$scope.newDashboard = function () {
kbnUrl.change('/dashboard', {});
};
Expand Down Expand Up @@ -291,6 +274,10 @@ app.directive('dashboardApp', function (Notifier, courier, AppState, timefilter,
};

init();

$scope.showEditHelpText = () => {
return !$scope.state.panels.length && $scope.dashboardViewMode === DashboardViewMode.EDIT;
};
}
};
});
9 changes: 7 additions & 2 deletions src/core_plugins/kibana/public/dashboard/styles/main.less
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,12 @@ dashboard-grid {
}

.gs-w {
border: 2px dashed transparent;

.panel {
border: 2px dashed transparent;
}

&:hover {
border-color: @kibanaGray4;

dashboard-panel {
.visualize-show-spy {
Expand All @@ -46,6 +48,9 @@ dashboard-grid {
.panel .panel-heading .btn-group {
display: block !important;
}
.panel--edit-mode {
border-color: @kibanaGray4;
}
}

}
Expand Down
47 changes: 20 additions & 27 deletions src/ui/public/kbn_top_nav/kbn_top_nav.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,27 +9,11 @@
*
* Menu items/templates are passed to the kbnTopNav via the config attribute
* and should be defined as an array of objects. Each object represents a menu
* item and should have the following properties:
* item and should be of type kbnTopNavConfig.
*
* @param {Array<Object>|KbnTopNavController} config
* @param {string} config[].key
* - the uniq key for this menu item.
* @param {string} [config[].label]
* - optional, string that will be displayed for the menu button.
* Defaults to the key
* @param {string} [config[].description]
* - optional, used for the screen-reader description of this menu
* item, defaults to "Toggle ${key} view" for templated menu items
* and just "${key}" for programatic menu items
* @param {boolean} [config[].hideButton]
* - optional, set to true to prevent a menu item from being created.
* This allow injecting templates into the navbar that don't have
* an associated template
* @param {function} [config[].run]
* - optional, function to call when the menu item is clicked, defaults
* to toggling the template
* @param {Array<kbnTopNavConfig>|KbnTopNavController} config
*
* Programatic control of the navbar can be acheived one of two ways
* Programmatic control of the navbar can be achieved one of two ways
*/

import _ from 'lodash';
Expand Down Expand Up @@ -98,15 +82,24 @@ module.directive('kbnTopNav', function (Private) {
});

const extensions = getNavbarExtensions($attrs.name);
let controls = _.get($scope, $attrs.config, []);
if (controls instanceof KbnTopNavController) {
controls.addItems(extensions);
} else {
controls = controls.concat(extensions);
}

$scope.kbnTopNav = new KbnTopNavController(controls);
$scope.kbnTopNav._link($scope, $element);
/**
* Dashboard makes some dynamic changes to the top nav so we need to watch this
* variable. Since the scope isn't isolate, I have to watch a variable that is defined on
* the parent scope. This is pretty ugly but without isolate scope, I don't see a better
* way to achieve dynamic updates.
*/
$scope.$watch('topNavMenu', function () {
let controls = _.get($scope, $attrs.config, []);
if (controls instanceof KbnTopNavController) {
controls.addItems(extensions);
} else {
controls = controls.concat(extensions);
}

$scope.kbnTopNav = new KbnTopNavController(controls);
$scope.kbnTopNav._link($scope, $element);
});

return $scope.kbnTopNav;
},
Expand Down
Loading

0 comments on commit c58984b

Please sign in to comment.