Skip to content

Commit

Permalink
Merge pull request #49 from DataTorrent/layouts
Browse files Browse the repository at this point in the history
Added Layouts
  • Loading branch information
nickholub committed Jun 9, 2014
2 parents 552f7b4 + 9b13874 commit 156fdd8
Show file tree
Hide file tree
Showing 21 changed files with 2,242 additions and 38 deletions.
1 change: 1 addition & 0 deletions Gruntfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ module.exports = function (grunt) {
concat: {
dist: {
src: [
'src/directives/dashboard.js',
'src/directives/*.js',
'src/models/*.js',
'src/controllers/*.js',
Expand Down
30 changes: 29 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ Features:

- Widgets drag and drop (with jQuery UI Sortable)

- Fluid layout (widgets can have percentage width)
- Fluid layout (widgets can have percentage-based width, or have width set in any other unit)

- Any directive can be a widget (e.g. AngularUI directives)

Expand All @@ -25,6 +25,8 @@ Features:

- Saving widgets state to local storage

- Multiple Dashboard Layouts

Contributing
------------

Expand Down Expand Up @@ -73,6 +75,7 @@ See [simple demo](demo) (two widgets) for a quick start.
Running demo with Grunt.

``` bash
$ bower install
$ grunt demo
```

Expand Down Expand Up @@ -250,6 +253,31 @@ This string will be stored along with the dashboard state. Then later, when stat
### `stringifyStorage` (Boolean)
By default (`stringifyStorage=true`), the dashboard will convert its state (a JavaScript Object) to a string using `JSON.stringify` before passing it to `storage.setItem`. Additionally, the dashboard will assume that `storage.getItem` will return a JSON string and try to parse it with `JSON.parse`. This works with `window.localStorage` nicely, since objects cannot be used as `value` in `localStorage.setItem(key, value)`. However, if you are implementing your own `storage` and would not like this stringification business, set `stringifyStorage` to `false`.


Dashboard Layouts
-----------------
One common requirement for user-customizable dashboards is the ability to have multiple layouts consisting of the same set of widget definitions. This sounds more confusing than it is, so the best way to understand it is to take a look at the [layouts demo](http://datatorrent.github.io/malhar-angular-dashboard/#/layouts). You can also see this demo by running `grunt demo` and navigating to `/#/layouts` (or `/#/layouts/explicit-saving`, behavior when `options.explicitSave` is `true`). This is achieved by using the `dashboard-layouts` directive:

```HTML
<div dashboard-layouts="layoutOptions"></div>
```

### layoutOptions
The `layoutOptions` object passed to dashboard-layouts tries to mirror `dashboardOptions` as closely as possible:

key | type | default value | required | description
--- | ---- | ------------- | -------- | -----------
widgetDefinitions | Array | n/a | yes | Same as in `dashboardOptions`
defaultLayouts | Array | n/a | yes | List of objects where an object is `{ title: [STRING_LAYOUT_TITLE], active: [BOOLEAN_ACTIVE_STATE], defaultWidgets: [ARRAY_DEFAULT_WIDGETS] }`. Note that `defaultWidgets` is the same as in `dashboardOptions`.
widgetButtons | Boolean | true | no | Same as in `dashboardOptions`
storage | Object | null | no | Same as in `dashboardOptions`, only the saved objects look like: `{ layouts: [...], states: {...}, storageHash: '' }`
storageId | String | null | no (yes if `storage` is defined) | This is used as the first parameter passed to the three `storage` methods `setItem`, `getItem`, `removeItem`. See the **Persistence** section above.
storageHash | String | '' | no | Same as in `dashboardOptions`
stringifyStorage | Boolean | true | no | Same as in `dashboardOptions`
explicitSave | Boolean | false | no | Same as in `dashboardOptions`

As with `dashboardOptions`, `layoutOptions` gets endowed with the methods `addWidget`, `loadWidgets`, `saveDashboard` and `loadDashboard`. These will be applied to the currently active dashboard layout. Additionally, a method called `saveLayouts` is attached to the `layoutOptions` object. This method will save the state of the layouts explicitly.

Links
-----

Expand Down
6 changes: 6 additions & 0 deletions demo/demo.css
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
body {
margin: 15px;
}
a {
cursor: pointer;
}
.layout-tabs {
margin-bottom: 10px;
}
53 changes: 52 additions & 1 deletion demo/demo.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,14 @@ angular.module('app', [
templateUrl: 'view.html',
controller: 'ExplicitSaveDemoCtrl'
})
.when('/layouts', {
templateUrl: 'layouts.html',
controller: 'LayoutsDemoCtrl'
})
.when('/layouts/explicit-saving', {
templateUrl: 'layouts.html',
controller: 'LayoutsDemoExplicitSaveCtrl'
})
.otherwise({
redirectTo: '/'
});
Expand Down Expand Up @@ -81,7 +89,7 @@ angular.module('app', [
storage: $window.localStorage,
storageId: 'demo'
};

$scope.randomValue = Math.random();
$interval(function () {
$scope.randomValue = Math.random();
}, 500);
Expand All @@ -96,10 +104,50 @@ angular.module('app', [
storageId: 'explicitSave',
explicitSave: true
};
$scope.randomValue = Math.random();
$interval(function () {
$scope.randomValue = Math.random();
}, 500);
})
.controller('LayoutsDemoCtrl', function($scope, widgetDefinitions, defaultWidgets, LayoutStorage, $interval) {
$scope.layoutOptions = {
storageId: 'demo-layouts',
storage: localStorage,
storageHash: 'fs4df4d51',
widgetDefinitions: widgetDefinitions,
defaultWidgets: defaultWidgets,
defaultLayouts: [
{ title: 'Layout 1', active: true , defaultWidgets: defaultWidgets },
{ title: 'Layout 2', active: false, defaultWidgets: defaultWidgets },
{ title: 'Layout 3', active: false, defaultWidgets: defaultWidgets }
]
};
$scope.randomValue = Math.random();
$interval(function () {
$scope.randomValue = Math.random();
}, 500);

})
.controller('LayoutsDemoExplicitSaveCtrl', function($scope, widgetDefinitions, defaultWidgets, LayoutStorage, $interval) {

$scope.layoutOptions = {
storageId: 'demo-layouts',
storage: localStorage,
storageHash: 'fs4df4d51',
widgetDefinitions: widgetDefinitions,
defaultWidgets: defaultWidgets,
explicitSave: true,
defaultLayouts: [
{ title: 'Layout 1', active: true , defaultWidgets: defaultWidgets },
{ title: 'Layout 2', active: false, defaultWidgets: defaultWidgets },
{ title: 'Layout 3', active: false, defaultWidgets: defaultWidgets }
]
};
$scope.randomValue = Math.random();
$interval(function () {
$scope.randomValue = Math.random();
}, 500);

})
.directive('wtTime', function ($interval) {
return {
Expand All @@ -112,6 +160,8 @@ angular.module('app', [
scope.time = new Date().toLocaleTimeString();
}

update();

var promise = $interval(update, 500);

scope.$on('$destroy', function () {
Expand All @@ -137,6 +187,7 @@ angular.module('app', [
RandomDataModel.prototype = Object.create(WidgetDataModel.prototype);

RandomDataModel.prototype.init = function () {
this.updateScope('-');
this.intervalPromise = $interval(function () {
var value = Math.floor(Math.random() * 100);
this.updateScope(value);
Expand Down
1 change: 1 addition & 0 deletions demo/layouts.html
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<div dashboard-layouts="layoutOptions"></div>
12 changes: 12 additions & 0 deletions dist/angular-ui-dashboard.css
Original file line number Diff line number Diff line change
Expand Up @@ -64,4 +64,16 @@
top: 0;
left: 0;
z-index: 2;
}

.remove-layout-icon {
vertical-align: text-top;
cursor: pointer;
opacity: 0.3;
}
.remove-layout-icon:hover {
opacity: 1;
}
.layout-title {
display: inline-block;
}
Loading

0 comments on commit 156fdd8

Please sign in to comment.