Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve dashboard editing flow #2219

Merged
merged 17 commits into from
Jan 28, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions client/app/assets/less/inc/schema-browser.less
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ div.table-name {
}

&:hover {
background: fade(@redash-gray, 10%);

.copy-to-editor {
display: flex;
}
Expand Down
2 changes: 1 addition & 1 deletion client/app/assets/less/redash/query.less
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ edit-in-place p.editable:hover {
}

.filter-container {
margin-bottom: 5px;
margin-bottom: 10px;
}

.editor__control--right {
Expand Down
72 changes: 72 additions & 0 deletions client/app/assets/less/redash/redash-newstyle.less
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,43 @@ body {
}
}

.add-widget-container {
background: #fff;
border-radius: @redash-radius;
padding: 15px;
position: fixed;
left: 15px;
bottom: 20px;
width: calc(~'100% - 30px');
z-index: 99;
box-shadow: fade(@redash-gray, 50%) 0px 7px 29px -3px;
display: flex;
justify-content: space-between;

h2 {
margin: 0;
font-size: 14px;
line-height: 2.1;
font-weight: 400;

.zmdi {
margin: 0;
margin-right: 5px;
font-size: 24px;
position: absolute;
bottom: 18px;
}

span {
padding-left: 30px;
}
}

.btn {
align-self: center;
}
}

body {
.ace-tm .ace_gutter {
background: #fff;
Expand Down Expand Up @@ -285,6 +322,11 @@ page-header, .page-header--new {
.label {
border-radius: 2px;
padding: 3px 6px 4px;
font-weight: 500;
}

.label-default {
background: fade(@redash-gray, 85%);
}

.tab-nav > li > a {
Expand All @@ -295,6 +337,21 @@ page-header, .page-header--new {
text-transform: none;
}

.dashboard-header {
position: -webkit-sticky; // required for Safari
position: sticky;
background: #f6f7f9;
z-index: 99;
width: 100%;
top: 0;
}

.widget-wrapper {
.parameter-container {
padding: 0 15px;
}
}

.dashboard__control {
margin: 8px 0;
}
Expand All @@ -310,6 +367,21 @@ page-header, .page-header--new {
}
}

.dashboard-header {
position: -webkit-sticky; // required for Safari
position: sticky;
background: #f6f7f9;
z-index: 99;
width: 100%;
top: 0;
}

.widget-wrapper {
.parameter-container {
padding: 0 15px;
}
}

.bg-ace {
background-color: fade(@redash-gray, 12%) !important;
}
Expand Down
7 changes: 0 additions & 7 deletions client/app/components/dashboards/edit-dashboard-dialog.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,6 @@ <h4 class="modal-title">Dashboard name: {{$ctrl.dashboard.name}}</h4>
<p>
<input type="text" class="form-control" placeholder="Dashboard Name" ng-model="$ctrl.dashboard.name" autofocus>
</p>

<p ng-if="$ctrl.dashboard.id">
<label>
<input name="input" type="checkbox" ng-model="$ctrl.dashboard.dashboard_filters_enabled">
Use Dashboard Level Filters
</label>
</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" ng-disabled="$ctrl.saveInProgress" ng-click="$ctrl.dismiss()">Close</button>
Expand Down
55 changes: 10 additions & 45 deletions client/app/components/dashboards/edit-dashboard-dialog.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,63 +8,28 @@ const EditDashboardDialog = {
dismiss: '&',
},
template,
controller($rootScope, $location, $http, toastr, Events, Dashboard) {
controller($rootScope, $location, $http, toastr, Events) {
'ngInject';

this.dashboard = this.resolve.dashboard;
this.gridsterOptions = {
margins: [5, 5],
rowHeight: 100,
colWidth: 260,
columns: 2,
mobileModeEnabled: false,
swapping: true,
minRows: 1,
draggable: {
enabled: true,
},
resizable: {
enabled: false,
},
};

this.isFormValid = () => !isEmpty(this.dashboard.name);

this.saveDashboard = () => {
this.saveInProgress = true;

if (this.dashboard.id) {
const request = {
slug: this.dashboard.id,
name: this.dashboard.name,
version: this.dashboard.version,
dashboard_filters_enabled: this.dashboard.dashboard_filters_enabled,
};

Dashboard.save(request, (dashboard) => {
this.dashboard = dashboard;
this.saveInProgress = false;
this.close({ $value: this.dashboard });
$rootScope.$broadcast('reloadDashboards');
}, (error) => {
this.saveInProgress = false;
if (error.status === 403) {
toastr.error('Unable to save dashboard: Permission denied.');
} else if (error.status === 409) {
toastr.error('It seems like the dashboard has been modified by another user. ' +
'Please copy/backup your changes and reload this page.', { autoDismiss: false });
}
});
Events.record('edit', 'dashboard', this.dashboard.id);
} else {
$http.post('api/dashboards', {
$http
.post('api/dashboards', {
name: this.dashboard.name,
}).success((response) => {
})
.success((response) => {
this.close();
$location.path(`/dashboard/${response.slug}`).replace();
$location
.path(`/dashboard/${response.slug}`)
.search('edit')
.replace();
});
Events.record('create', 'dashboard');
}
Events.record('create', 'dashboard');
};
},
};
Expand Down
7 changes: 2 additions & 5 deletions client/app/components/dashboards/widget.js
Original file line number Diff line number Diff line change
Expand Up @@ -82,11 +82,8 @@ function DashboardWidgetCtrl($location, $uibModal, $window, Events, currentUser)
Events.record('view', 'widget', this.widget.id);

this.reload = (force) => {
let maxAge = $location.search().maxAge;
if (force) {
maxAge = 0;
}
this.queryResult = this.query.getQueryResult(maxAge);
const maxAge = $location.search().maxAge;
this.queryResult = this.widget.getQueryResult(force, maxAge);
};

if (this.widget.visualization) {
Expand Down
2 changes: 1 addition & 1 deletion client/app/components/filters.html
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<div class="container bg-white p-b-15" ng-show="$ctrl.filters | notEmpty">
<div class="parameter-container container bg-white" ng-show="$ctrl.filters | notEmpty">
<div class="row">
<div class="col-sm-6 p-l-0 filter-container" ng-repeat="filter in $ctrl.filters">
<label>{{filter.friendlyName}}</label>
Expand Down
2 changes: 1 addition & 1 deletion client/app/components/parameters.html
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<div class="form-inline bg-white p-15"
<div class="parameter-container form-inline bg-white"
ng-if="parameters | notEmpty"
ui-sortable="{ 'ui-floating': true, 'disabled': !editable }"
ng-model="parameters">
Expand Down
58 changes: 37 additions & 21 deletions client/app/pages/dashboards/dashboard.html
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
<div class="container">

<div class="row p-l-15 p-r-15 m-b-10 m-l-0 m-r-0">
<div class="col-xs-12 col-sm-12 col-md-6 col-lg-7 page-header--new p-l-0">
<h3>{{$ctrl.dashboard.name}}
<div class="row p-l-15 p-r-15 m-b-10 m-l-0 m-r-0 dashboard-header">
<div class="col-xs-5 col-sm-5 col-lg-5 page-header--new p-l-0">
<h3>
<edit-in-place editable="$ctrl.layoutEditing" done="$ctrl.saveName" ignore-blanks="true" value="$ctrl.dashboard.name"></edit-in-place>
<span class="label label-default" ng-if="$ctrl.dashboard.is_draft && !$ctrl.dashboard.is_archived">Unpublished</span>
<span class="label label-warning" ng-if="$ctrl.dashboard.is_archived" uib-popover="This dashboard is archived and and won't appear in the dashboards list or search results." popover-placement="right" popover-trigger="'mouseenter'">Archived</span>
</h3>
</div>
<div class="col-xs-12 col-sm-12 col-md-6 col-lg-5 text-right dashboard__control p-r-0">
<div class="col-xs-7 col-sm-7 col-lg-7 text-right dashboard__control p-r-0">
<span ng-if="!$ctrl.dashboard.is_archived && !public" class="hidden-print">

<div class="btn-group">
<button type="button" class="btn btn-default btn-sm"
<button type="button" class="btn btn-primary btn-sm"
ng-disabled="$ctrl.isGridDisabled"
ng-click="$ctrl.editLayout(false, true)" ng-if="$ctrl.layoutEditing">
<i class="zmdi zmdi-check"></i> Apply Changes
Expand All @@ -20,11 +20,15 @@ <h3>{{$ctrl.dashboard.name}}
<button type="button" class="btn btn-default btn-sm"
ng-disabled="$ctrl.isGridDisabled"
ng-click="$ctrl.editLayout(false, false)" ng-if="$ctrl.layoutEditing">
Cancel
<i class="zmdi zmdi-close"></i> Cancel
</button>
</div>

<div class="btn-group" uib-dropdown>
<button type="button" class="btn btn-default btn-sm" ng-click="$ctrl.togglePublished()" tooltip="Publish Dashboard" ng-if="$ctrl.dashboard.is_draft && !$ctrl.layoutEditing">
<span class="fa fa-paper-plane"></span> Publish
</button>

<div class="btn-group" uib-dropdown ng-if="!$ctrl.layoutEditing">
<button id="split-button" type="button"
ng-class="{'btn-default btn-sm': $ctrl.refreshRate === null,'btn-primary btn-sm':$ctrl.refreshRate !== null}"
class="btn btn-sm" ng-click="$ctrl.loadDashboard(true)">
Expand All @@ -44,39 +48,43 @@ <h3>{{$ctrl.dashboard.name}}
</li>
</ul>
</div>
<button type="button" class="btn btn-sm" ng-class="{'btn-default': !$ctrl.isFullscreen, 'btn-primary': $ctrl.isFullscreen}" tooltip="Enable/Disable Fullscreen display" ng-click="$ctrl.toggleFullscreen()">
<button type="button" class="btn btn-sm" ng-class="{'btn-default': !$ctrl.isFullscreen, 'btn-primary': $ctrl.isFullscreen}" tooltip="Enable/Disable Fullscreen display" ng-click="$ctrl.toggleFullscreen()" ng-if="!$ctrl.dashboard.is_draft && !$ctrl.layoutEditing">
<span class="zmdi zmdi-fullscreen"></span>
</button>
<button type="button" class="btn btn-sm" ng-class="{'btn-default': !$ctrl.dashboard.publicAccessEnabled, 'btn-primary': $ctrl.dashboard.publicAccessEnabled}" tooltip="Enable/Disable Share URL" ng-click="$ctrl.openShareForm()" ng-if="$ctrl.dashboard.canEdit() || $ctrl.dashboard.publicAccessEnabled">
<button type="button" class="btn btn-sm" ng-class="{'btn-default': !$ctrl.dashboard.publicAccessEnabled, 'btn-primary': $ctrl.dashboard.publicAccessEnabled}" tooltip="Enable/Disable Share URL" ng-click="$ctrl.openShareForm()" ng-if="($ctrl.dashboard.canEdit() || $ctrl.dashboard.publicAccessEnabled) && !$ctrl.dashboard.is_draft && !$ctrl.layoutEditing">
<span class="zmdi zmdi-share"></span>
</button>
</span>
<div class="btn-group hidden-print" role="group" ng-show="$ctrl.dashboard.canEdit()" uib-dropdown ng-if="!$ctrl.dashboard.is_archived">
<div class="btn-group hidden-print" role="group" ng-show="$ctrl.dashboard.canEdit()" uib-dropdown ng-if="!$ctrl.dashboard.is_archived && !$ctrl.layoutEditing">
<button class="btn btn-default btn-sm dropdown-toggle" uib-dropdown-toggle>
<span class="zmdi zmdi-more"></span>
</button>
<ul class="dropdown-menu pull-right" uib-dropdown-menu>
<li ng-if="!$ctrl.dashboard.is_archived"><a ng-click="$ctrl.editDashboard()">Edit Dashboard</a></li>
<li ng-if="!$ctrl.dashboard.is_archived" ng-class="{hidden: $ctrl.isGridDisabled}"><a ng-click="$ctrl.editLayout(true)">Edit Layout</a></li>
<li ng-if="!$ctrl.dashboard.is_archived"><a ng-click="$ctrl.addWidget()">Add Widget</a></li>
<li ng-if="!$ctrl.dashboard.is_archived" ng-class="{hidden: $ctrl.isGridDisabled}"><a ng-click="$ctrl.editLayout(true)">Edit</a></li>
<li ng-if="$ctrl.showPermissionsControl"><a ng-click="$ctrl.showManagePermissionsModal()">Manage Permissions</a></li>
<li ng-if="!$ctrl.dashboard.is_draft"><a ng-click="$ctrl.togglePublished()">Unpublish Dashboard</a></li>
<li ng-if="$ctrl.dashboard.is_draft"><a ng-click="$ctrl.togglePublished()">Publish Dashboard</a></li>
<li ng-if="!$ctrl.dashboard.is_archived"><a ng-click="$ctrl.archiveDashboard()">Archive Dashboard</a></li>
<li ng-if="!$ctrl.dashboard.is_draft"><a ng-click="$ctrl.togglePublished()">Unpublish</a></li>
<li ng-if="!$ctrl.dashboard.is_archived"><a ng-click="$ctrl.archiveDashboard()">Archive</a></li>
</ul>
</div>
</div>
</div>

<div class="m-b-10 tiled">
<div class="m-b-10 p-15 bg-white tiled" ng-if="$ctrl.layoutEditing">
<label>
<input name="input" type="checkbox" ng-model="$ctrl.dashboard.dashboard_filters_enabled" ng-change="$ctrl.updateDashboardFiltersState()">
Use Dashboard Level Filters
</label>
</div>

<div class="m-b-10 p-15 bg-white tiled" ng-if="$ctrl.globalParameters.length > 0">
<parameters parameters="$ctrl.globalParameters" on-change="$ctrl.onGlobalParametersChange()"></parameters>
</div>

<div class="m-b-10 tiled">
<filters ng-if="$ctrl.dashboard.dashboard_filters_enabled" filters="$ctrl.filters" on-change="$ctrl.filtersOnChange(filter, $modal)"></filters>
<div class="m-b-10 p-15 bg-white tiled" ng-if="$ctrl.filters | notEmpty">
<filters filters="$ctrl.filters" on-change="$ctrl.filtersOnChange(filter, $modal)"></filters>
</div>

<div style="overflow: hidden">
<div style="overflow: hidden; padding-bottom: 5px;" ng-if="$ctrl.dashboard.widgets.length > 0">
<div gridster="$ctrl.dashboardGridOptions" class="dashboard-wrapper"
ng-class="{'preview-mode': !$ctrl.layoutEditing, 'editing-mode': $ctrl.layoutEditing}">
<div ng-repeat="widget in $ctrl.dashboard.widgets" gridster-item="widget.options.position"
Expand All @@ -85,4 +93,12 @@ <h3>{{$ctrl.dashboard.name}}
</div>
</div>
</div>

<div class="add-widget-container" ng-if="$ctrl.layoutEditing">
<h2>
<i class="zmdi zmdi-widgets"></i>
<span class="hidden-xs hidden-sm">Widgets are individual query visualizations or text boxes you can place on your dashboard in various arrangements.</span>
</h2>
<a class="btn btn-primary" ng-click="$ctrl.addWidget()">Add Widget</a>
</div>
</div>
Loading