Skip to content
Open
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
8 changes: 4 additions & 4 deletions bower.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@
"name": "malhar-angular-dashboard",
"version": "1.0.1",
"dependencies": {
"bootstrap": "~3.3.1",
"angular-bootstrap": "0.12.x",
"foundation": "~5.5.1",
"angular-foundation": "~0.5.1",
"angular": "~1.3",
"angular-ui-sortable": "~0.13.3",
"lodash": "~3.1"
"lodash": "~3.1",
"angular-gridster": "~0.13.4"
},
"main": [
"dist/malhar-angular-dashboard.css",
Expand Down
56 changes: 40 additions & 16 deletions dist/malhar-angular-dashboard.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
*/
'use strict';

angular.module('ui.dashboard', ['ui.bootstrap', 'ui.sortable']);
angular.module('ui.dashboard', ['mm.foundation', 'gridster']);

angular.module('ui.dashboard')

Expand Down Expand Up @@ -67,15 +67,25 @@ angular.module('ui.dashboard')
scope.saveDashboard();
},
handle: '.widget-header',
distance: 5
distance: 5,
resizable: {
enabled: true,
handles: ['se'],
stop: function() { scope.saveDashboard(true) }
},
draggable: {
enabled: true, // whether dragging items is supported
handle: '.widget-header', // optional selector for resize handle
stop: function() { scope.saveDashboard(true) }
},
};
scope.sortableOptions = angular.extend({}, sortableDefaults, scope.options.sortableOptions || {});

scope.sortableOptions = angular.extend({}, sortableDefaults, scope.options.sortableOptions || {});
}],
link: function (scope) {

// Save default widget config for reset
scope.defaultWidgets = scope.options.defaultWidgets;
scope.defaultWidgets = scope.options.disableDefaultWidgets ? [] : scope.options.defaultWidgets;

scope.widgetDefs = new WidgetDefCollection(scope.options.widgetDefinitions);
var count = 1;
Expand Down Expand Up @@ -139,7 +149,7 @@ angular.module('ui.dashboard')
*/
scope.openWidgetSettings = function (widget) {

// Set up $modal options
// Set up $modal options
var options = _.defaults(
{ scope: scope },
widget.settingsModalOptions,
Expand All @@ -151,7 +161,7 @@ angular.module('ui.dashboard')
return widget;
}
};

// Create the modal
var modalInstance = $modal.open(options);
var onClose = widget.onSettingsClose || scope.options.onSettingsClose;
Expand All @@ -168,7 +178,7 @@ angular.module('ui.dashboard')
scope.$emit('widgetChanged', widget);
},
function (reason) {

// Call the dismiss callback
onDismiss(reason, scope);

Expand Down Expand Up @@ -211,7 +221,6 @@ angular.module('ui.dashboard')
if (force) {
scope.options.unsavedChangeCount = 0;
scope.dashboardState.save(scope.widgets);

} else {
++scope.options.unsavedChangeCount;
}
Expand Down Expand Up @@ -284,6 +293,10 @@ angular.module('ui.dashboard')
event.stopPropagation();
scope.saveDashboard();
});

scope.$watch('widgets', function () {
scope.$root.$broadcast('dashboard.widgets.resized');
}, true);
}
};
}]);
Expand All @@ -292,7 +305,7 @@ angular.module("ui.dashboard").run(["$templateCache", function($templateCache) {
$templateCache.put("components/directives/dashboard/dashboard.html","<div>\n <div class=\"btn-toolbar\" ng-if=\"!options.hideToolbar\">\n <div class=\"btn-group\" ng-if=\"!options.widgetButtons\">\n <span class=\"dropdown\" on-toggle=\"toggled(open)\">\n <button type=\"button\" class=\"btn btn-primary dropdown-toggle\" data-toggle=\"dropdown\">\n Button dropdown <span class=\"caret\"></span>\n </button>\n <ul class=\"dropdown-menu\" role=\"menu\">\n <li ng-repeat=\"widget in widgetDefs\">\n <a href=\"#\" ng-click=\"addWidgetInternal($event, widget);\" class=\"dropdown-toggle\"><span class=\"label label-primary\">{{widget.name}}</span></a>\n </li>\n </ul>\n </span>\n </div>\n <div class=\"btn-group\" ng-if=\"options.widgetButtons\">\n <button ng-repeat=\"widget in widgetDefs\"\n ng-click=\"addWidgetInternal($event, widget);\" type=\"button\" class=\"btn btn-primary\">\n {{widget.name}}\n </button>\n </div>\n\n <button class=\"btn btn-warning\" ng-click=\"resetWidgetsToDefault()\">Default Widgets</button>\n\n <button ng-if=\"options.storage && options.explicitSave\" ng-click=\"options.saveDashboard()\" class=\"btn btn-success\" ng-disabled=\"!options.unsavedChangeCount\">{{ !options.unsavedChangeCount ? \"all saved\" : \"save changes (\" + options.unsavedChangeCount + \")\" }}</button>\n\n <button ng-click=\"clear();\" type=\"button\" class=\"btn btn-info\">Clear</button>\n </div>\n\n <div ui-sortable=\"sortableOptions\" ng-model=\"widgets\" class=\"dashboard-widget-area\">\n <div ng-repeat=\"widget in widgets\" ng-style=\"widget.containerStyle\" class=\"widget-container\" widget>\n <div class=\"widget panel panel-default\">\n <div class=\"widget-header panel-heading\">\n <h3 class=\"panel-title\">\n <span class=\"widget-title\" ng-dblclick=\"editTitle(widget)\" ng-hide=\"widget.editingTitle\">{{widget.title}}</span>\n <form action=\"\" class=\"widget-title\" ng-show=\"widget.editingTitle\" ng-submit=\"saveTitleEdit(widget)\">\n <input type=\"text\" ng-model=\"widget.title\" class=\"form-control\">\n </form>\n <span class=\"label label-primary\" ng-if=\"!options.hideWidgetName\">{{widget.name}}</span>\n <span ng-click=\"removeWidget(widget);\" class=\"glyphicon glyphicon-remove\" ng-if=\"!options.hideWidgetClose\"></span>\n <span ng-click=\"openWidgetSettings(widget);\" class=\"glyphicon glyphicon-cog\" ng-if=\"!options.hideWidgetSettings\"></span>\n <span ng-click=\"widget.contentStyle.display = widget.contentStyle.display === \'none\' ? \'block\' : \'none\'\" class=\"glyphicon\" ng-class=\"{\'glyphicon-plus\': widget.contentStyle.display === \'none\', \'glyphicon-minus\': widget.contentStyle.display !== \'none\' }\"></span>\n </h3>\n </div>\n <div class=\"panel-body widget-content\" ng-style=\"widget.contentStyle\"></div>\n <div class=\"widget-ew-resizer\" ng-mousedown=\"grabResizer($event)\"></div>\n <div ng-if=\"widget.enableVerticalResize\" class=\"widget-s-resizer\" ng-mousedown=\"grabSouthResizer($event)\"></div>\n </div>\n </div>\n </div>\n</div>");
$templateCache.put("components/directives/dashboard/widget-settings-template.html","<div class=\"modal-header\">\n <button type=\"button\" class=\"close\" data-dismiss=\"modal\" aria-hidden=\"true\" ng-click=\"cancel()\">&times;</button>\n <h3>Widget Options <small>{{widget.title}}</small></h3>\n</div>\n\n<div class=\"modal-body\">\n <form name=\"form\" novalidate class=\"form-horizontal\">\n <div class=\"form-group\">\n <label for=\"widgetTitle\" class=\"col-sm-2 control-label\">Title</label>\n <div class=\"col-sm-10\">\n <input type=\"text\" class=\"form-control\" name=\"widgetTitle\" ng-model=\"result.title\">\n </div>\n </div>\n <div ng-if=\"widget.settingsModalOptions.partialTemplateUrl\"\n ng-include=\"widget.settingsModalOptions.partialTemplateUrl\"></div>\n </form>\n</div>\n\n<div class=\"modal-footer\">\n <button type=\"button\" class=\"btn btn-default\" ng-click=\"cancel()\">Cancel</button>\n <button type=\"button\" class=\"btn btn-primary\" ng-click=\"ok()\">OK</button>\n</div>");
$templateCache.put("components/directives/dashboardLayouts/SaveChangesModal.html","<div class=\"modal-header\">\n <button type=\"button\" class=\"close\" data-dismiss=\"modal\" aria-hidden=\"true\" ng-click=\"cancel()\">&times;</button>\n <h3>Unsaved Changes to \"{{layout.title}}\"</h3>\n</div>\n\n<div class=\"modal-body\">\n <p>You have {{layout.dashboard.unsavedChangeCount}} unsaved changes on this dashboard. Would you like to save them?</p>\n</div>\n\n<div class=\"modal-footer\">\n <button type=\"button\" class=\"btn btn-default\" ng-click=\"cancel()\">Don\'t Save</button>\n <button type=\"button\" class=\"btn btn-primary\" ng-click=\"ok()\">Save</button>\n</div>");
$templateCache.put("components/directives/dashboardLayouts/dashboardLayouts.html","<ul ui-sortable=\"sortableOptions\" ng-model=\"layouts\" class=\"nav nav-tabs layout-tabs\">\n <li ng-repeat=\"layout in layouts\" ng-class=\"{ active: layout.active }\">\n <a ng-click=\"makeLayoutActive(layout)\">\n <span ng-dblclick=\"editTitle(layout)\" ng-show=\"!layout.editingTitle\">{{layout.title}}</span>\n <form action=\"\" class=\"layout-title\" ng-show=\"layout.editingTitle\" ng-submit=\"saveTitleEdit(layout)\">\n <input type=\"text\" ng-model=\"layout.title\" class=\"form-control\" data-layout=\"{{layout.id}}\">\n </form>\n <span ng-if=\"!layout.locked\" ng-click=\"removeLayout(layout)\" class=\"glyphicon glyphicon-remove remove-layout-icon\"></span>\n <!-- <span class=\"glyphicon glyphicon-pencil\"></span> -->\n <!-- <span class=\"glyphicon glyphicon-remove\"></span> -->\n </a>\n </li>\n <li>\n <a ng-click=\"createNewLayout()\">\n <span class=\"glyphicon glyphicon-plus\"></span>\n </a>\n </li>\n</ul>\n<div ng-repeat=\"layout in layouts | filter:isActive\" dashboard=\"layout.dashboard\" template-url=\"components/directives/dashboard/dashboard.html\"></div>");}]);
$templateCache.put("components/directives/dashboardLayouts/dashboardLayouts.html","<div gridster=\"sortableOptions\">\n <ul ng-model=\"layouts\" class=\"nav nav-tabs layout-tabs\">\n <li ng-repeat=\"layout in layouts\" ng-class=\"{ active: layout.active }\">\n <a ng-click=\"makeLayoutActive(layout)\">\n <span ng-dblclick=\"editTitle(layout)\" ng-show=\"!layout.editingTitle\">{{layout.title}}</span>\n <form action=\"\" class=\"layout-title\" ng-show=\"layout.editingTitle\" ng-submit=\"saveTitleEdit(layout)\">\n <input type=\"text\" ng-model=\"layout.title\" class=\"form-control\" data-layout=\"{{layout.id}}\">\n </form>\n <span ng-if=\"!layout.locked\" ng-click=\"removeLayout(layout)\" class=\"glyphicon glyphicon-remove remove-layout-icon\"></span>\n <!-- <span class=\"glyphicon glyphicon-pencil\"></span> -->\n <!-- <span class=\"glyphicon glyphicon-remove\"></span> -->\n </a>\n </li>\n <li>\n <a ng-click=\"createNewLayout()\">\n <span class=\"glyphicon glyphicon-plus\"></span>\n </a>\n </li>\n </ul>\n</div>\n<div ng-repeat=\"layout in layouts | filter:isActive\" dashboard=\"layout.dashboard\" template-url=\"components/directives/dashboard/dashboard.html\"></div>\n");}]);
/*
* Copyright (c) 2014 DataTorrent, Inc. ALL Rights Reserved.
*
Expand Down Expand Up @@ -353,6 +366,11 @@ angular.module('ui.dashboard')
scope.compileTemplate();
scope.$emit('widgetAdded', widget);

// emit widget resized event when gridster transition ends
scope.$on('gridster-item-transition-end', function(event, item) {
scope.$emit('dashboard.widget.resized', item);
});

}

};
Expand Down Expand Up @@ -968,10 +986,11 @@ angular.module('ui.dashboard')
def = convertToDefinition(def);
this.push(def);
this.map[def.name] = def;
}
};

return WidgetDefCollection;
});

/*
* Copyright (c) 2014 DataTorrent, Inc. ALL Rights Reserved.
*
Expand Down Expand Up @@ -1300,20 +1319,25 @@ angular.module('ui.dashboard')

DashboardState.prototype = {
/**
* Takes array of widget instance objects, serializes,
* Takes array of widget instance objects, serializes,
* and saves state.
*
*
* @param {Array} widgets scope.widgets from dashboard directive
* @return {Boolean} true on success, false on failure
*/
save: function (widgets) {

if (!this.storage) {
return true;
}

var serialized = _.map(widgets, function (widget) {
return widget.serialize();
var w = widget.serialize();
w.col = widget.col;
w.row = widget.row;
w.sizeX = widget.sizeX;
w.sizeY = widget.sizeY;
return w;
});

var item = { widgets: serialized, hash: this.hash };
Expand All @@ -1329,7 +1353,7 @@ angular.module('ui.dashboard')
/**
* Loads dashboard state from the storage object.
* Can handle a synchronous response or a promise.
*
*
* @return {Array|Promise} Array of widget definitions or a promise
*/
load: function () {
Expand Down Expand Up @@ -1449,4 +1473,4 @@ angular.module('ui.dashboard')

};
return DashboardState;
}]);
}]);
2 changes: 1 addition & 1 deletion src/app/index.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
'use strict';

angular.module('dashboard', ['ui.bootstrap']);
angular.module('dashboard', ['mm.foundation']);
4 changes: 1 addition & 3 deletions src/app/vendor.less
Original file line number Diff line number Diff line change
@@ -1,3 +1 @@
@import '../../bower_components/bootstrap/less/bootstrap.less';

@icon-font-path: '/fonts/';
@import '../../bower_components/foundation/css/foundation.css';
29 changes: 21 additions & 8 deletions src/components/directives/dashboard/dashboard.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
*/
'use strict';

angular.module('ui.dashboard', ['ui.bootstrap', 'ui.sortable']);
angular.module('ui.dashboard', ['mm.foundation', 'gridster']);

angular.module('ui.dashboard')

Expand Down Expand Up @@ -67,15 +67,25 @@ angular.module('ui.dashboard')
scope.saveDashboard();
},
handle: '.widget-header',
distance: 5
distance: 5,
resizable: {
enabled: true,
handles: ['se'],
stop: function() { scope.saveDashboard(true) }
},
draggable: {
enabled: true, // whether dragging items is supported
handle: '.widget-header', // optional selector for resize handle
stop: function() { scope.saveDashboard(true) }
},
};
scope.sortableOptions = angular.extend({}, sortableDefaults, scope.options.sortableOptions || {});

scope.sortableOptions = angular.extend({}, sortableDefaults, scope.options.sortableOptions || {});
}],
link: function (scope) {

// Save default widget config for reset
scope.defaultWidgets = scope.options.defaultWidgets;
scope.defaultWidgets = scope.options.disableDefaultWidgets ? [] : scope.options.defaultWidgets;

scope.widgetDefs = new WidgetDefCollection(scope.options.widgetDefinitions);
var count = 1;
Expand Down Expand Up @@ -139,7 +149,7 @@ angular.module('ui.dashboard')
*/
scope.openWidgetSettings = function (widget) {

// Set up $modal options
// Set up $modal options
var options = _.defaults(
{ scope: scope },
widget.settingsModalOptions,
Expand All @@ -151,7 +161,7 @@ angular.module('ui.dashboard')
return widget;
}
};

// Create the modal
var modalInstance = $modal.open(options);
var onClose = widget.onSettingsClose || scope.options.onSettingsClose;
Expand All @@ -168,7 +178,7 @@ angular.module('ui.dashboard')
scope.$emit('widgetChanged', widget);
},
function (reason) {

// Call the dismiss callback
onDismiss(reason, scope);

Expand Down Expand Up @@ -211,7 +221,6 @@ angular.module('ui.dashboard')
if (force) {
scope.options.unsavedChangeCount = 0;
scope.dashboardState.save(scope.widgets);

} else {
++scope.options.unsavedChangeCount;
}
Expand Down Expand Up @@ -284,6 +293,10 @@ angular.module('ui.dashboard')
event.stopPropagation();
scope.saveDashboard();
});

scope.$watch('widgets', function () {
scope.$root.$broadcast('dashboard.widgets.resized');
}, true);
}
};
}]);
40 changes: 21 additions & 19 deletions src/components/directives/dashboardLayouts/dashboardLayouts.html
Original file line number Diff line number Diff line change
@@ -1,19 +1,21 @@
<ul ui-sortable="sortableOptions" ng-model="layouts" class="nav nav-tabs layout-tabs">
<li ng-repeat="layout in layouts" ng-class="{ active: layout.active }">
<a ng-click="makeLayoutActive(layout)">
<span ng-dblclick="editTitle(layout)" ng-show="!layout.editingTitle">{{layout.title}}</span>
<form action="" class="layout-title" ng-show="layout.editingTitle" ng-submit="saveTitleEdit(layout)">
<input type="text" ng-model="layout.title" class="form-control" data-layout="{{layout.id}}">
</form>
<span ng-if="!layout.locked" ng-click="removeLayout(layout)" class="glyphicon glyphicon-remove remove-layout-icon"></span>
<!-- <span class="glyphicon glyphicon-pencil"></span> -->
<!-- <span class="glyphicon glyphicon-remove"></span> -->
</a>
</li>
<li>
<a ng-click="createNewLayout()">
<span class="glyphicon glyphicon-plus"></span>
</a>
</li>
</ul>
<div ng-repeat="layout in layouts | filter:isActive" dashboard="layout.dashboard" template-url="components/directives/dashboard/dashboard.html"></div>
<div gridster="sortableOptions">
<ul ng-model="layouts" class="nav nav-tabs layout-tabs">
<li ng-repeat="layout in layouts" ng-class="{ active: layout.active }">
<a ng-click="makeLayoutActive(layout)">
<span ng-dblclick="editTitle(layout)" ng-show="!layout.editingTitle">{{layout.title}}</span>
<form action="" class="layout-title" ng-show="layout.editingTitle" ng-submit="saveTitleEdit(layout)">
<input type="text" ng-model="layout.title" class="form-control" data-layout="{{layout.id}}">
</form>
<span ng-if="!layout.locked" ng-click="removeLayout(layout)" class="glyphicon glyphicon-remove remove-layout-icon"></span>
<!-- <span class="glyphicon glyphicon-pencil"></span> -->
<!-- <span class="glyphicon glyphicon-remove"></span> -->
</a>
</li>
<li>
<a ng-click="createNewLayout()">
<span class="glyphicon glyphicon-plus"></span>
</a>
</li>
</ul>
</div>
<div ng-repeat="layout in layouts | filter:isActive" dashboard="layout.dashboard" template-url="components/directives/dashboard/dashboard.html"></div>
5 changes: 5 additions & 0 deletions src/components/directives/widget/widget.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,11 @@ angular.module('ui.dashboard')
scope.compileTemplate();
scope.$emit('widgetAdded', widget);

// emit widget resized event when gridster transition ends
scope.$on('gridster-item-transition-end', function(event, item) {
scope.$emit('dashboard.widget.resized', item);
});

}

};
Expand Down
Loading