PDA

View Full Version : Stateful portal panel



AnthonyViard
11 Dec 2013, 9:00 AM
Hi all,
I just started to use the portal example (http://docs.sencha.com/extjs/4.2.1/extjs-build/examples/portal/portal.html) in my app.

I wonder if it possible the panel to be stateful. I mean keep items and their ordering.

In my case i have 3 'portalpanel' in my homepage wich contains many portlet.

Portlets can be drag and drop inside a panel (change ordering) but also inside each other (portlet are shared by the three panels).

I would like my three panel, remember which portlet they contain and their order.

Actually i just gave to my portlet a statefulId and set stateful to true. The collapsed state is remember (done! ;)).

I add two PNG to show you the final result (ok my PNG are ugly...).

Grey blocks are portalpanel, white blocks are portlet.
First PNG my portlet are display by default config. Second one portlet have been moved by user, we need to remember this.
47192
47191

Below my view wich organize portal panels and portlet. PortalPanel, PortalColumn, Portlet and PortalDropZone are classes taken from 4.2.0 Extjs example folder.


Ext.define('myApp.view.home.HomePage', {
extend: 'Ext.container.Container',
alias: 'widget.cardHome',
requires: ['Ext.app.PortalPanel'],
padding: '10 0 0 0',
flex: 1,
layout: {
type: 'hbox'
},
initComponent: function () {
var me = this;
me.items = [
{
xtype: 'container',
flex: 1,
border: false,
items: [
{
xtype: 'portalpanel',
flex: 1,
itemId: 'centralPanel',
border: true,
defaults: {
flex: 1,
defaults: {
flex: 1
}
},
items: [
{
itemId: 'col1',
items: [
{
stateful: true,
stateId: 'portlet-1',
itemId: 'portlet-1'
},
{
itemId: 'portlet-2',
stateful: true,
stateId: 'portlet-2',
title: 'Portlet 2',
html: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum'
}
]
},
{
itemId: 'col2',
items: [
{
itemId: 'portlet-3',
title: 'Portlet 3',
stateful: true,
stateId: 'portlet-3',
html: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum'
},
{
itemId: 'portlet-4',
title: 'Portlet 4',
stateful: true,
stateId: 'portlet-4',
html: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum'
}
]
}
]
},
{
xtype: 'portalpanel',
itemId: 'bottomPanel',
border: true,
flex: 1,
defaults: {
flex: 1,
defaults: {
flex: 1
}
},
items: [
{
itemId: 'col3',
items: [
{
xtype: 'portlet',
stateful: true,
stateId: 'blocnote',
title: 'My tasks',
html: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum'
}
]
}
]
}
]
},
{
xtype: 'portalpanel',
itemId: 'rightPanel',
flex: 0.3,
border: true,
defaults: {
flex: 1,
defaults: {
flex: 1
}
},
items: [
{
itemId: 'col4',
items: [
{
xtype: 'portlet',
title: 'Bloc 1',
stateful: true,
stateId: 'bloc1',
html: 'Lorem ipsum dolor sit amet, fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum'
},
{
xtype: 'portlet',
title: 'Bloc 2',
stateful: true,
stateId: 'bloc2',
html: 'Lorem ipsum dolor sit amet. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum'
},
{
xtype: 'portlet',
title: 'Bloc 3',
stateful: true,
stateId: 'bloc3',
html: 'Lorem ipsum dolor sit amet Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum'
}
]
}
]
}
];
me.callParent(arguments);
}
});


If someone has a solution or something else I shall be grateful.

Thank you !

existdissolve
11 Dec 2013, 3:16 PM
The answer is "yes" - you could certainly make the panel stateful. The rub is that you'll have to implement the state management for it yourself (or find a plugin, if there is one, which I don't know :) ).

You might take a look at the Stateful Tree plugin by AlexTiTanium: https://github.com/AlexTiTanium/ExtJsStatefulTree

W (https://github.com/AlexTiTanium/ExtJsStatefulTree)hile it's obviously not for a portal, it does show how state management can implemented, so you could conceivably use this as a jumping off point for your portal version.

Hope that gives you a place to start!

AnthonyViard
11 Dec 2013, 11:31 PM
thanks for this link. i'm going to study this.Obviously it's not the a "plug and play" solution but a good way to start.I'll be back ;)

existdissolve
12 Dec 2013, 6:44 AM
It's not plug-n-play *yet*. Once you finish your implementation, you can hopefully share it with the community, and then it will be plug-n-play for others :)

In all seriousness, though, I do hope you are able to share it with everyone. I could see that being very useful to others.

Thanks!

AnthonyViard
12 Dec 2013, 7:16 AM
I'm very close the solution.
I add this to my mainContainer wich have all portalpanels/columns and portlet.



stateful: true,
stateId: 'myStateId',
stateEvents: ['drop'],
getState: function () {
var portlets = this.query('portlet'), result = []
for (var y = 0; y < portlets.length; y++) {
var portalColumn = portlets[y].up('portalcolumn');
result.push({
portletId: portlets[y].getItemId(),
porletColumnId: portalColumn.getItemId()
});
}
return {
portletsArray: result
};
},
saveState: function () {
var me = this, id = me.stateful && me.getStateId(), state;
if (id) {
state = me.getState() || [];
Ext.state.Manager.set(id, state);
}
},
applyState: function (state) {
var me = this;
for (var i = 0; i < state.portletsArray.length; i++) {
var porletStatedConfig = state.portletsArray[i]
, portalColumn = me.down('portalcolumn[itemId=' + porletStatedConfig.porletColumnId + ']')
, portlet = me.down('portlet[itemId=' + porletStatedConfig.portletId + ']');
portalColumn.add(portlet);
}
}


I have many things to do:
* maybe not use itemId because could have many items with same itemId
* At this time I couldn't restore the portlet position when the user drag it inside the same column (worked if the endDraged column is not the same that the strated one), in fact the drop event is not fire here.

Also i'm triying to disable the dragNdrop feature when the column has only one element, because it difficult to drop element in flex zone when it's empty. But i'll be thinking of this when all the statefull portal will work properly.

existdissolve
13 Dec 2013, 6:27 AM
Cool, glad you're on track. I would suggest wrapping this into a plugin, however. That will keep your component clean and allow the functionality to be quite a bit more portable.