Skip to content

Commit

Permalink
Grid layout (#693)
Browse files Browse the repository at this point in the history
* Grid layout

* Persist.

* Fix tests.

* Add event handler.
  • Loading branch information
adamdriscoll authored Mar 11, 2019
1 parent d53ba8c commit b87b21a
Show file tree
Hide file tree
Showing 7 changed files with 204 additions and 1 deletion.
3 changes: 2 additions & 1 deletion src/UniversalDashboard.UITest/Manifest.Tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -118,8 +118,9 @@ Describe "Manifest" {
Get-Command 'New-UDSideNavItem' -ErrorAction SilentlyContinue | Should not be $null
Get-Command 'New-UDTabContainer' -ErrorAction SilentlyContinue | Should not be $null
Get-Command 'New-UDTab' -ErrorAction SilentlyContinue | Should not be $null
Get-Command 'New-UDGridLayout' -ErrorAction SilentlyContinue | Should not be $null

(Get-Command -Module UniversalDashboard.Community | Measure-Object).Count | should be 103
(Get-Command -Module UniversalDashboard.Community | Measure-Object).Count | should be 104
}

It "should require .NET 4.7" -Skip {
Expand Down
80 changes: 80 additions & 0 deletions src/UniversalDashboard/Controls/src/grid-layout.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
function New-UDGridLayout {
param(
[Parameter()]
[string]$Id = (New-Guid).ToString(),
[Parameter()]
[int]$RowHeight = 30,
[Parameter()]
[scriptblock]$Content,
[Parameter()]
[Hashtable[]]$Layout,
[Parameter()]
[int]$LargeColumns = 12,
[Parameter()]
[int]$MediumColumns = 10,
[Parameter()]
[int]$SmallColumns = 6,
[Parameter()]
[int]$ExtraSmallColumns = 4,
[Parameter()]
[int]$ExtraExtraSmallColumns = 2,
[Parameter()]
[int]$LargeBreakpoint = 1200,
[Parameter()]
[int]$MediumBreakpoint = 996,
[Parameter()]
[int]$SmallBreakpoint = 768,
[Parameter()]
[int]$ExtraSmallBreakpoint = 480,
[Parameter()]
[int]$ExtraExtraSmallBreakpoint = 0,
[Parameter()]
[switch]$Draggable,
[Parameter()]
[switch]$Resizable,
[Parameter()]
[switch]$Persist,
[Parameter()]
[object]$OnLayoutChanged
)

End {
$Breakpoints = @{
lg = $LargeBreakpoint
md = $MediumBreakpoint
sm = $SmallBreakpoint
xs = $ExtraSmallBreakpoint
xxs = $ExtraExtraSmallBreakpoint
}

$Columns = @{
lg = $LargeColumns
md = $MediumColumns
sm = $SmallColumns
xs = $ExtraSmallColumns
xxs = $ExtraExtraSmallColumns
}

if ($OnLayoutChanged -is ([ScriptBlock])) {
$OnLayoutChanged = New-UDEndpoint -Endpoint $OnLayoutChanged
}
elseif ($OnLayoutChanged -isnot ([UniversalDashboard.Models.Endpoint])) {
throw "OnLayoutChanged must be a ScriptBlock of UDEndpoint"
}

@{
type = "grid-layout"
id = "grid-element-$Id"
className = "layout"
rowHeight = $RowHeight
content = $Content.Invoke()
layout = $Layout
cols = $Columns
breakpoints = $Breakpoints
isDraggable = $Draggable.IsPresent
isResizable = $Resizable.IsPresent
persist = $Persist.IsPresent
endpoint = $OnLayoutChanged.Name
}
}
}
2 changes: 2 additions & 0 deletions src/UniversalDashboard/New-UDModuleManifest.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,8 @@ $manifestParameters = @{
"New-UDFabButton"
"New-UDTab"
"New-UDTabContainer"
"New-UDGridLayout"
"New-UDGridLayoutElement"
)
CmdletsToExport = @("New-UDChart",
"New-UDDashboard",
Expand Down
30 changes: 30 additions & 0 deletions src/client/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions src/client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
"react-color": "2.13.8",
"react-debounce-input": "3.2.0",
"react-dom": "^16.6.0",
"react-grid-layout": "^0.16.6",
"react-interval": "^2.0.1",
"react-materialize": "1.1.0",
"react-redux": "5.0.7",
Expand Down
4 changes: 4 additions & 0 deletions src/client/src/app/services/render-service.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,16 @@ const UdGridComponent = React.lazy(() => import('./../ud-grid.jsx' /* webpackChu
const UdDateTimeComponent = React.lazy(() => import('./../basics/datetime.jsx' /* webpackChunkName: "ud-date-time" */))
const UdElementComponent = React.lazy(() => import('./../ud-element.jsx' /* webpackChunkName: "ud-element" */))
const UdTerminal = React.lazy(() => import( './../ud-terminal.jsx' /* webpackChunkName: "ud-terminal" */))
import UDGridLayout from './../ud-grid-layout';

export function internalRenderComponent(component, history) {
if (!component) return null;

switch(component.type) {

case "grid-layout":
return <UDGridLayout {...component} key={component.id}/>;

case "chart":
return <Suspense fallback={<div></div>}>
<UdChartComponent {...component} key={component.id}/>
Expand Down
85 changes: 85 additions & 0 deletions src/client/src/app/ud-grid-layout.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
import React from 'react';
import { WidthProvider, Responsive } from "react-grid-layout";
const ResponsiveReactGridLayout = WidthProvider(Responsive);

require('react-grid-layout/css/styles.css');
require('react-resizable/css/styles.css');

export default class UDGridLayout extends React.Component {

constructor(props) {
super(props);

var layouts = this.props.layout.map(x => {
x.i = "grid-element-" + x.i;
return x;
});
if (this.props.persist) {
var jsonLayouts = getFromLS("layouts");
if (jsonLayouts != null) {
layouts = JSON.parse(JSON.stringify(jsonLayouts))
}
};

this.state = {
layouts
};
}

onLayoutChange(layout, layouts) {

if (this.props.endpoint) {
UniversalDashboard.publish('element-event', {
type: "clientEvent",
eventId: this.props.endpoint,
eventName: 'onLayoutChanged',
eventData: JSON.stringify(layouts)
});
}

if (this.props.persist) {
saveToLS("layouts", layouts);
this.setState({ layouts });
}
}

render() {

var elements = this.props.content.map(x =>
<div key={"grid-element-" + x.id}>
{UniversalDashboard.renderComponent(x)}
</div>
);

return (
<ResponsiveReactGridLayout className={this.props.className} layouts={this.state.layouts} cols={this.props.cols} rowHeight={this.props.rowHeight} onLayoutChange={(layout, layouts) =>
this.onLayoutChange(layout, layouts)
}>
{elements}
</ResponsiveReactGridLayout>
)
}
}

function getFromLS(key) {
let ls = {};
if (global.localStorage) {
try {
ls = JSON.parse(global.localStorage.getItem("rgl-8")) || {};
} catch (e) {
/*Ignore*/
}
}
return ls[key];
}

function saveToLS(key, value) {
if (global.localStorage) {
global.localStorage.setItem(
"rgl-8",
JSON.stringify({
[key]: value
})
);
}
}

0 comments on commit b87b21a

Please sign in to comment.