Modified: 
openmeetings/application/trunk/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/RoomPanel.java
URL: 
http://svn.apache.org/viewvc/openmeetings/application/trunk/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/RoomPanel.java?rev=1739141&r1=1739140&r2=1739141&view=diff
==============================================================================
--- 
openmeetings/application/trunk/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/RoomPanel.java
 (original)
+++ 
openmeetings/application/trunk/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/RoomPanel.java
 Thu Apr 14 17:08:51 2016
@@ -18,114 +18,77 @@
  */
 package org.apache.openmeetings.web.room;
 
-import static 
org.apache.openmeetings.util.OpenmeetingsVariables.CONFIG_APPLICATION_BASE_URL;
-import static 
org.apache.openmeetings.util.OpenmeetingsVariables.CONFIG_REDIRECT_URL_FOR_EXTERNAL_KEY;
 import static org.apache.openmeetings.util.OpenmeetingsVariables.webAppRootKey;
 import static org.apache.openmeetings.web.app.Application.addUserToRoom;
 import static org.apache.openmeetings.web.app.Application.getBean;
 import static org.apache.openmeetings.web.app.Application.getRoomUsers;
 import static org.apache.openmeetings.web.app.WebSession.getUserId;
-import static org.apache.openmeetings.web.util.OmUrlFragment.ROOMS_PUBLIC;
 
-import java.io.Serializable;
 import java.net.MalformedURLException;
 import java.net.URL;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Date;
-import java.util.Iterator;
-import java.util.List;
 
 import org.apache.openmeetings.db.dao.basic.ConfigurationDao;
 import org.apache.openmeetings.db.dao.calendar.AppointmentDao;
-import org.apache.openmeetings.db.dao.file.FileExplorerItemDao;
-import org.apache.openmeetings.db.dao.room.PollDao;
-import org.apache.openmeetings.db.dao.room.RoomDao;
 import org.apache.openmeetings.db.dao.user.UserDao;
 import org.apache.openmeetings.db.entity.calendar.Appointment;
 import org.apache.openmeetings.db.entity.calendar.MeetingMember;
-import org.apache.openmeetings.db.entity.file.FileExplorerItem;
-import org.apache.openmeetings.db.entity.file.FileItem;
-import org.apache.openmeetings.db.entity.file.FileItem.Type;
-import org.apache.openmeetings.db.entity.record.Recording;
 import org.apache.openmeetings.db.entity.room.Room;
 import org.apache.openmeetings.db.entity.room.RoomGroup;
 import org.apache.openmeetings.db.entity.room.RoomModerator;
-import org.apache.openmeetings.db.entity.user.Group;
 import org.apache.openmeetings.db.entity.user.GroupUser;
 import org.apache.openmeetings.db.entity.user.User;
-import org.apache.openmeetings.db.entity.user.User.Right;
 import org.apache.openmeetings.db.util.AuthLevelUtil;
 import org.apache.openmeetings.web.app.Application;
 import org.apache.openmeetings.web.app.Client;
 import org.apache.openmeetings.web.app.WebSession;
 import org.apache.openmeetings.web.common.BasePanel;
-import org.apache.openmeetings.web.common.menu.MenuPanel;
-import org.apache.openmeetings.web.common.menu.RoomMenuItem;
-import org.apache.openmeetings.web.common.tree.FileItemTree;
-import org.apache.openmeetings.web.common.tree.FileTreePanel;
-import org.apache.openmeetings.web.common.tree.MyRecordingTreeProvider;
-import org.apache.openmeetings.web.common.tree.PublicRecordingTreeProvider;
 import org.apache.openmeetings.web.room.activities.ActivitiesPanel;
 import org.apache.openmeetings.web.room.activities.Activity;
+import org.apache.openmeetings.web.room.menu.RoomMenuPanel;
 import org.apache.openmeetings.web.room.message.RoomMessage;
-import org.apache.openmeetings.web.room.poll.CreatePollDialog;
-import org.apache.openmeetings.web.room.poll.PollResultsDialog;
-import org.apache.openmeetings.web.room.poll.VoteDialog;
+import org.apache.openmeetings.web.room.sidebar.RoomSidebar;
 import org.apache.wicket.Component;
 import org.apache.wicket.ajax.AbstractDefaultAjaxBehavior;
-import org.apache.wicket.ajax.AjaxEventBehavior;
 import org.apache.wicket.ajax.AjaxRequestTarget;
 import org.apache.wicket.ajax.json.JSONArray;
 import org.apache.wicket.ajax.json.JSONException;
 import org.apache.wicket.ajax.json.JSONObject;
 import 
org.apache.wicket.authroles.authorization.strategies.role.annotations.AuthorizeInstantiation;
-import org.apache.wicket.behavior.AttributeAppender;
 import org.apache.wicket.core.request.handler.IPartialPageRequestHandler;
 import org.apache.wicket.event.IEvent;
-import org.apache.wicket.extensions.markup.html.repeater.tree.ITreeProvider;
 import org.apache.wicket.markup.head.IHeaderResponse;
 import org.apache.wicket.markup.head.JavaScriptHeaderItem;
 import org.apache.wicket.markup.head.OnDomReadyHeaderItem;
 import org.apache.wicket.markup.head.PriorityHeaderItem;
 import org.apache.wicket.markup.html.WebMarkupContainer;
-import org.apache.wicket.markup.html.basic.Label;
-import org.apache.wicket.markup.html.list.ListItem;
-import org.apache.wicket.markup.html.list.ListView;
-import org.apache.wicket.model.IModel;
-import org.apache.wicket.model.Model;
 import org.apache.wicket.protocol.ws.WebSocketSettings;
 import org.apache.wicket.protocol.ws.api.IWebSocketConnection;
-import org.apache.wicket.protocol.ws.api.WebSocketRequestHandler;
 import org.apache.wicket.protocol.ws.api.event.WebSocketPushPayload;
 import org.apache.wicket.protocol.ws.api.registry.IWebSocketConnectionRegistry;
 import org.apache.wicket.protocol.ws.api.registry.PageIdKey;
 import org.apache.wicket.protocol.ws.concurrent.Executor;
-import org.apache.wicket.request.flow.RedirectToUrlException;
 import org.apache.wicket.request.resource.JavaScriptResourceReference;
 import org.apache.wicket.request.resource.ResourceReference;
-import org.apache.wicket.util.string.Strings;
 import org.red5.logging.Red5LoggerFactory;
 import org.slf4j.Logger;
 import org.wicketstuff.whiteboard.WhiteboardBehavior;
 
 import com.googlecode.wicket.jquery.core.JQueryBehavior;
-import com.googlecode.wicket.jquery.core.Options;
-import com.googlecode.wicket.jquery.ui.form.button.Button;
 import com.googlecode.wicket.jquery.ui.widget.dialog.DialogButton;
 import com.googlecode.wicket.jquery.ui.widget.dialog.DialogButtons;
 import com.googlecode.wicket.jquery.ui.widget.dialog.DialogIcon;
 import com.googlecode.wicket.jquery.ui.widget.dialog.MessageDialog;
-import com.googlecode.wicket.jquery.ui.widget.menu.IMenuItem;
 
 @AuthorizeInstantiation("Room")
 public class RoomPanel extends BasePanel {
+       //TODO demoTime - demo timer
        private static final long serialVersionUID = 1L;
        private static final Logger log = 
Red5LoggerFactory.getLogger(RoomPanel.class, webAppRootKey);
-       private Long roomId;
-       private Client c;
+       private final Room r;
+       private final Client client;
+       private final RoomMenuPanel menu;
+       private final RoomSidebar sidebar;
        private final WebMarkupContainer room = new 
WebMarkupContainer("roomContainer");
-       private final StartSharingEventBehavior startSharing;
        private final AbstractDefaultAjaxBehavior aab = new 
AbstractDefaultAjaxBehavior() {
                private static final long serialVersionUID = 1L;
 
@@ -138,108 +101,35 @@ public class RoomPanel extends BasePanel
                                URL url = new URL(cfgDao.getBaseUrl());
                                String path = url.getPath();
                                path = path.substring(1, path.indexOf('/', 2) + 
1);
-                               Room r = getBean(RoomDao.class).get(roomId);
                                
target.appendJavaScript(String.format("initVideo(%s);", new JSONObject()
-                                               .put("uid", c.getUid())
+                                               .put("uid", client.getUid())
                                                .put("audioOnly", 
r.isAudioOnly())
                                                .put("SID", WebSession.getSid())
                                                .put("interview", 
Room.Type.interview == r.getType())
                                                //.put("protocol", 
cfgDao.getConfValue(CONFIG_FLASH_PROTOCOL, String.class, ""))
                                                .put("host", url.getHost())
                                                //.put("port", 
cfgDao.getConfValue(CONFIG_FLASH_PORT, String.class, ""))
-                                               .put("app", path + roomId)
+                                               .put("app", path + r.getId())
                                                .put("labels", 
getStringLabels(448, 449, 450, 451, 758, 447, 52, 53, 1429, 1430, 775, 452, 
767, 764, 765, 918, 54, 761, 762))
                                                .toString()
                                                ));
-                               broadcast(new RoomMessage(roomId, 
c.getUserId(), RoomMessage.Type.roomEnter));
+                               broadcast(new RoomMessage(r.getId(), 
RoomMessage.Type.roomEnter));
                                getMainPage().getChat().roomEnter(r, target);
                        } catch (MalformedURLException e) {
                                log.error("Error while constructing room 
parameters", e);
                        }
                }
        };
-       private final InvitationDialog invite;
-       private final CreatePollDialog createPoll;
-       private final VoteDialog vote;
-       private final PollResultsDialog pollResults;
-       private final MenuPanel menuPanel;
-       private final RoomMenuItem exitMenuItem = new 
RoomMenuItem(Application.getString(308), Application.getString(309), "room menu 
exit") {
-               private static final long serialVersionUID = 1L;
-
-               @Override
-               public void onClick(AjaxRequestTarget target) {
-                       exit(target);
-               }
-       };
-       private final RoomMenuItem filesMenu = new 
RoomMenuItem(Application.getString(245), null, false);
-       private final RoomMenuItem actionsMenu = new 
RoomMenuItem(Application.getString(635), null, false);
-       private final RoomMenuItem inviteMenuItem = new 
RoomMenuItem(Application.getString(213), Application.getString(1489), false) {
-               private static final long serialVersionUID = 1L;
-
-               @Override
-               public void onClick(AjaxRequestTarget target) {
-                       invite.updateModel(target);
-                       invite.open(target);
-               }
-       };
-       private final RoomMenuItem shareMenuItem = new 
RoomMenuItem(Application.getString(239), Application.getString(1480), false) {
-               private static final long serialVersionUID = 1L;
-
-               @Override
-               public void onClick(AjaxRequestTarget target) {
-                       startSharing.respond(target);
-               }
-       };
-       private final RoomMenuItem applyModerMenuItem = new 
RoomMenuItem(Application.getString(784), Application.getString(1481), false);
-       private final RoomMenuItem applyWbMenuItem = new 
RoomMenuItem(Application.getString(785), Application.getString(1492), false);
-       private final RoomMenuItem applyAvMenuItem = new 
RoomMenuItem(Application.getString(786), Application.getString(1482), false);
-       private final RoomMenuItem pollCreateMenuItem = new 
RoomMenuItem(Application.getString(24), Application.getString(1483), false) {
-               private static final long serialVersionUID = 1L;
-
-               @Override
-               public void onClick(AjaxRequestTarget target) {
-                       createPoll.updateModel(target);
-                       createPoll.open(target);
-               }
-       };
-       private final RoomMenuItem pollVoteMenuItem = new 
RoomMenuItem(Application.getString(42), Application.getString(1485), false) {
-               private static final long serialVersionUID = 1L;
-
-               @Override
-               public void onClick(AjaxRequestTarget target) {
-                       vote.updateModel(target);
-                       vote.open(target);
-               }
-       };
-       private final RoomMenuItem pollResultMenuItem = new 
RoomMenuItem(Application.getString(37), Application.getString(1484), false) {
-               private static final long serialVersionUID = 1L;
-
-               @Override
-               public void onClick(AjaxRequestTarget target) {
-                       pollResults.updateModel(target, 
c.hasRight(Client.Right.moderator));
-                       pollResults.open(target);
-               }
-       };
-       private final RoomMenuItem sipDialerMenuItem = new 
RoomMenuItem(Application.getString(1447), Application.getString(1488), false);
-       private final WebMarkupContainer userList = new 
WebMarkupContainer("userList");
-       private final ListView<RoomClient> users;
-       private final boolean showFiles;
-       private final Button shareBtn = new Button("share");
-       private final Button askBtn = new Button("ask");
        private final ActivitiesPanel activities;
        
-       public RoomPanel(String id, long _roomId) {
-               this(id, getBean(RoomDao.class).get(_roomId));
-       }
-       
-       public RoomPanel(String id, final Room r) {
+       public RoomPanel(String id, Room r) {
                super(id);
-               this.roomId = r.getId();
+               this.r = r;
                Component accessDenied = new 
WebMarkupContainer("accessDenied").setVisible(false);
                boolean allowed = false;
                String deniedMessage = null;
                if (r.isAppointment()) {
-                       Appointment a = 
getBean(AppointmentDao.class).getByRoom(roomId);
+                       Appointment a = 
getBean(AppointmentDao.class).getByRoom(r.getId());
                        if (a != null && !a.isDeleted()) {
                                allowed = 
a.getOwner().getId().equals(getUserId());
                                log.debug("appointed room, isOwner ? " + 
allowed);
@@ -287,102 +177,14 @@ public class RoomPanel extends BasePanel
                        accessDenied = new ExpiredMessageDialog("accessDenied", 
deniedMessage);
                        room.setVisible(false);
                }
-               room.add((menuPanel = new MenuPanel("roomMenu", 
getMenu())).setVisible(!r.getHideTopBar()));
+               client = new Client(r.getId());
+               room.add((menu = new RoomMenuPanel("roomMenu", 
this)).setVisible(!r.getHideTopBar()));
                WebMarkupContainer wb = new WebMarkupContainer("whiteboard");
                room.add(wb.setOutputMarkupId(true));
                room.add(new WhiteboardBehavior("1", wb.getMarkupId(), null, 
null, null));
                room.add(aab);
-               showFiles = !r.getHideFilesExplorer();
-               room.add(new WebMarkupContainer("flink").setVisible(showFiles));
-               room.add(new WebMarkupContainer("ftab").add(new 
FileTreePanel("tree") {
-                       private static final long serialVersionUID = 1L;
-
-                       @Override
-                       public void updateSizes() {
-                               // TODO Auto-generated method stub
-                               
-                       }
-                       
-                       @Override
-                       public void update(AjaxRequestTarget target, FileItem 
f) {
-                               // TODO Auto-generated method stub
-                               
-                       }
-                       
-                       @Override
-                       public void defineTrees() {
-                               FileExplorerItem f = new FileExplorerItem();
-                               f.setOwnerId(getUserId());
-                               selectedFile.setObject(f);
-                               treesView.add(selected = new 
FileItemTree<FileExplorerItem>(treesView.newChildId(), this, new 
FilesTreeProvider(null)));
-                               treesView.add(new 
FileItemTree<FileExplorerItem>(treesView.newChildId(), this, new 
FilesTreeProvider(roomId)));
-                               treesView.add(new 
FileItemTree<Recording>(treesView.newChildId(), this, new 
MyRecordingTreeProvider()));
-                               treesView.add(new 
FileItemTree<Recording>(treesView.newChildId(), this, new 
PublicRecordingTreeProvider(null, null)));
-                               for (GroupUser ou : 
getBean(UserDao.class).get(getUserId()).getGroupUsers()) {
-                                       Group o = ou.getGroup();
-                                       treesView.add(new 
FileItemTree<Recording>(treesView.newChildId(), this, new 
PublicRecordingTreeProvider(o.getId(), o.getName())));
-                               }
-                       }
-                       
-                       @Override
-                       public void createFolder(String name) {
-                               if (selectedFile.getObject() instanceof 
Recording) {
-                                       createRecordingFolder(name);
-                               } else {
-                                       FileExplorerItem f = new 
FileExplorerItem();
-                                       f.setName(name);
-                                       f.setInsertedBy(getUserId());
-                                       f.setInserted(new Date());
-                                       f.setType(Type.Folder);;
-                                       FileItem p = selectedFile.getObject();
-                                       long parentId = p.getId();
-                                       f.setParentId(Type.Folder == 
p.getType() && parentId > 0 ? parentId : null);
-                                       f.setOwnerId(p.getOwnerId());
-                                       f.setRoomId(p.getRoomId());
-                                       
getBean(FileExplorerItemDao.class).update(f);
-                               }
-                       }
-               }).setVisible(showFiles));
-               room.add(userList.add(users = new ListView<RoomClient>("user", 
getUsers()) {
-                       private static final long serialVersionUID = 1L;
-
-                       @Override
-                       protected void populateItem(ListItem<RoomClient> item) {
-                               RoomClient rc = item.getModelObject();
-                               item.setMarkupId(String.format("user%s", 
rc.c.getUid()));
-                               item.add(new Label("name", rc.u.getFirstname() 
+ " " + rc.u.getLastname()));
-                               
item.add(AttributeAppender.append("data-userid", rc.u.getId()));
-                               item.add(new 
WebMarkupContainer("privateChat").setVisible(!r.isChatHidden() && getUserId() 
!= rc.u.getId()));
-                               if (c != null && 
rc.c.getUid().equals(c.getUid())) {
-                                       
item.add(AttributeAppender.append("class", "current"));
-                               }
-                       }
-               }).setOutputMarkupId(true));
-               room.add(new JQueryBehavior(".room.sidebar.left .tabs", "tabs", 
new Options("active", showFiles && r.isFilesOpened() ? "ftab" : "utab")) {
-                       private static final long serialVersionUID = 1L;
-
-                       @Override
-                       protected void renderOnDomReadyScript(String script, 
IHeaderResponse response) {
-                               response.render(new 
PriorityHeaderItem(OnDomReadyHeaderItem.forScript(script)));
-                       }
-               });
-               room.add(new Label("roomName", r.getName()));
-               room.add(new Label("recording", "Recording 
started").setVisible(false)); //FIXME add/remove
-               
room.add(askBtn.setOutputMarkupPlaceholderTag(true).setVisible(false).add(new 
AttributeAppender("title", Application.getString(906))));
-               room.add(startSharing = new StartSharingEventBehavior(roomId));
-               room.add(shareBtn.add(new AjaxEventBehavior("click") {
-                       private static final long serialVersionUID = 1L;
-                       
-                       @Override
-                       protected void onEvent(AjaxRequestTarget target) {
-                               startSharing.respond(target);
-                       }
-               
}).setOutputMarkupPlaceholderTag(true).setVisible(false).add(new 
AttributeAppender("title", Application.getString(1480))));
-               room.add(invite = new InvitationDialog("invite", roomId));
-               room.add(createPoll = new CreatePollDialog("createPoll", 
roomId));
-               room.add(vote = new VoteDialog("vote", roomId));
-               room.add(pollResults = new PollResultsDialog("pollResults", 
roomId));
-               room.add((activities = new ActivitiesPanel("activitiesPanel", 
roomId)).setVisible(!r.isActivitiesHidden()));
+               room.add(sidebar = new RoomSidebar("sidebar", this));
+               room.add((activities = new ActivitiesPanel("activitiesPanel", 
r.getId())).setVisible(!r.isActivitiesHidden()));
                add(room, accessDenied);
        }
 
@@ -392,29 +194,32 @@ public class RoomPanel extends BasePanel
                        WebSocketPushPayload wsEvent = (WebSocketPushPayload) 
event.getPayload();
                        if (wsEvent.getMessage() instanceof RoomMessage) {
                                RoomMessage m = 
(RoomMessage)wsEvent.getMessage();
+                               IPartialPageRequestHandler handler = 
wsEvent.getHandler();
                                switch (m.getType()) {
                                        case pollCreated:
-                                               if (getUserId() != 
m.getSentUserId()) {
-                                                       
vote.updateModel(wsEvent.getHandler());
-                                                       
vote.open(wsEvent.getHandler());
+                                               if (getUserId() != 
m.getUserId()) {
+                                                       
menu.pollCreated(handler);
                                                }
                                        case pollClosed:
                                        case pollDeleted:
                                        case voted:
                                        case rightUpdated:
-                                               
updateUserMenuIcons(wsEvent.getHandler());
+                                               menu.update(handler);
                                                break;
                                        case roomEnter:
-                                               
updateUserMenuIcons(wsEvent.getHandler());
-                                               users.setList(getUsers());
-                                               
wsEvent.getHandler().add(userList);
-                                               
activities.addActivity(m.getSentUserId(), Activity.Type.roomEnter, 
wsEvent.getHandler());
+                                               menu.update(handler);
+                                               sidebar.updateUsers(handler);
+                                               
//activities.addActivity(m.getUid(), m.getSentUserId(), 
Activity.Type.roomEnter, handler);
                                                break;
                                        case roomExit:
                                                //TODO check user/remove tab
-                                               users.setList(getUsers());
-                                               
wsEvent.getHandler().add(userList);
-                                               
activities.addActivity(m.getSentUserId(), Activity.Type.roomExit, 
wsEvent.getHandler());
+                                               sidebar.updateUsers(handler);
+                                               
activities.addActivity(m.getUid(), m.getUserId(), Activity.Type.roomExit, 
handler);
+                                               break;
+                                       case requestRightModerator:
+                                               if (isModerator(getUserId(), 
r.getId())) {
+                                                       
activities.addActivity(m.getUid(), m.getUserId(), 
Activity.Type.requestRightModerator, handler);
+                                               }
                                                break;
                                        default:
                                                break;
@@ -435,25 +240,24 @@ public class RoomPanel extends BasePanel
                }
                return arr.toString();
        }
-       
+
        @Override
        protected void onBeforeRender() {
                super.onBeforeRender();
                if (room.isVisible()) {
-                       c = addUserToRoom(roomId, getPage().getPageId());
+                       addUserToRoom(client, getPage().getPageId());
                        User u = getBean(UserDao.class).get(getUserId());
                        //TODO do we need to check GroupModerationRights ????
                        if (AuthLevelUtil.hasAdminLevel(u.getRights())) {
-                               c.getRights().add(Client.Right.moderator);
+                               client.getRights().add(Client.Right.moderator);
                        } else {
-                               Room r = getBean(RoomDao.class).get(roomId);
-                               if (!r.isModerated() && 1 == 
getRoomUsers(roomId).size()) {
-                                       
c.getRights().add(Client.Right.moderator);
+                               if (!r.isModerated() && 1 == 
getRoomUsers(r.getId()).size()) {
+                                       
client.getRights().add(Client.Right.moderator);
                                } else if (r.isModerated()) {
                                        //TODO why do we need supermoderator 
????
                                        for (RoomModerator rm : 
r.getModerators()) {
                                                if (getUserId() == 
rm.getUser().getId()) {
-                                                       
c.getRights().add(Client.Right.moderator);
+                                                       
client.getRights().add(Client.Right.moderator);
                                                        break;
                                                }
                                        }
@@ -469,14 +273,14 @@ public class RoomPanel extends BasePanel
                for (Client c : getRoomUsers(m.getRoomId())) {
                        try {
                                final IWebSocketConnection wsConnection = 
reg.getConnection(Application.get(), c.getSessionId(), new 
PageIdKey(c.getPageId()));
-                               executor.run(new Runnable()
-                               {
-                                       @Override
-                                       public void run()
-                                       {
-                                               wsConnection.sendMessage(m);
-                                       }
-                               });
+                               if (wsConnection != null) {
+                                       executor.run(new Runnable() {
+                                               @Override
+                                               public void run() {
+                                                       
wsConnection.sendMessage(m);
+                                               }
+                                       });
+                               }
                        } catch (Exception e) {
                                log.error("Error while broadcasting message to 
room", e);
                        }
@@ -503,72 +307,27 @@ public class RoomPanel extends BasePanel
                }
        }
        
-       private void updateUserMenuIcons(WebSocketRequestHandler handler) {
-               boolean pollExists = getBean(PollDao.class).hasPoll(roomId);
-               User u = getBean(UserDao.class).get(getUserId());
-               boolean notExternalUser = u.getType() != User.Type.external && 
u.getType() != User.Type.contact;
-               exitMenuItem.setEnabled(notExternalUser);//TODO check this
-               filesMenu.setEnabled(showFiles);
-               Room r = getBean(RoomDao.class).get(roomId);
-               actionsMenu.setEnabled(!r.getHideActionsMenu());
-               boolean moder = c.hasRight(Client.Right.moderator);
-               inviteMenuItem.setEnabled(notExternalUser && moder);
-               //TODO add check "sharing started"
-               boolean shareVisible = Room.Type.interview != r.getType() && 
moder;
-               shareMenuItem.setEnabled(shareVisible);
-               shareBtn.setVisible(shareMenuItem.isEnabled());
-               applyModerMenuItem.setEnabled(!moder);
-               applyWbMenuItem.setEnabled(!moder);
-               applyAvMenuItem.setEnabled(!moder);
-               pollCreateMenuItem.setEnabled(moder);
-               pollVoteMenuItem.setEnabled(pollExists && notExternalUser && 
!getBean(PollDao.class).hasVoted(roomId, getUserId()));
-               pollResultMenuItem.setEnabled(pollExists || 
getBean(PollDao.class).getArchived(roomId).size() > 0);
-               //TODO sip menus
-               menuPanel.update(handler);
-               handler.add(askBtn.setVisible(!moder), 
shareBtn.setVisible(shareVisible));
-       }
-       
-       private List<IMenuItem> getMenu() {
-               List<IMenuItem> menu = new ArrayList<>();
-               exitMenuItem.setEnabled(false);
-               menu.add(exitMenuItem);
-               
-               filesMenu.getItems().add(new 
RoomMenuItem(Application.getString(15), Application.getString(1479)));
-               menu.add(filesMenu);
-               
-               actionsMenu.getItems().add(inviteMenuItem);
-               actionsMenu.getItems().add(shareMenuItem); //FIXME 
enable/disable
-               actionsMenu.getItems().add(applyModerMenuItem); //FIXME 
enable/disable
-               actionsMenu.getItems().add(applyWbMenuItem); //FIXME 
enable/disable
-               actionsMenu.getItems().add(applyAvMenuItem); //FIXME 
enable/disable
-               actionsMenu.getItems().add(pollCreateMenuItem);
-               actionsMenu.getItems().add(pollResultMenuItem); //FIXME 
enable/disable
-               actionsMenu.getItems().add(pollVoteMenuItem); //FIXME 
enable/disable
-               actionsMenu.getItems().add(sipDialerMenuItem);
-               actionsMenu.getItems().add(new 
RoomMenuItem(Application.getString(1126), Application.getString(1490)));
-               menu.add(actionsMenu);
-               return menu;
-       }
-       
        @Override
        public void onMenuPanelLoad(IPartialPageRequestHandler handler) {
-               handler.add(getMainPage().getHeader().setVisible(false), 
getMainPage().getMenu().setVisible(false)
-                               , 
getMainPage().getTopLinks().setVisible(false));
+               handler.add(getMainPage().getHeader().setVisible(false), 
getMainPage().getTopControls().setVisible(false));
+               if (r.isChatHidden()) {
+                       getMainPage().getChat().toggle(handler, false);
+               }
                handler.appendJavaScript("roomLoad();");
        }
        
        @Override
        public void cleanup(IPartialPageRequestHandler handler) {
-               handler.add(getMainPage().getHeader().setVisible(true), 
getMainPage().getMenu().setVisible(true)
-                               , getMainPage().getTopLinks().setVisible(true));
-               Room r = getBean(RoomDao.class).get(roomId);
+               handler.add(getMainPage().getHeader().setVisible(true), 
getMainPage().getTopControls().setVisible(true));
                if (r.isChatHidden()) {
-                       handler.add(getMainPage().getChat().setVisible(true)); 
//FIXME chat is broken on this step
+                       getMainPage().getChat().toggle(handler, true);
                }
-               handler.appendJavaScript("$(window).off('resize.openmeetings'); 
$('.room.video').dialog('destroy');");
+               
handler.appendJavaScript("$(window).off('resize.openmeetings');");
+               RoomMenuPanel.roomExit(this);
+               getMainPage().getChat().roomExit(r, handler);
        }
 
-       private ResourceReference newResourceReference() {
+       private static ResourceReference newResourceReference() {
                return new JavaScriptResourceReference(RoomPanel.class, 
"room.js");
        }
        
@@ -581,88 +340,6 @@ public class RoomPanel extends BasePanel
                }
        }
 
-       private List<RoomClient> getUsers() {
-               List<RoomClient> list = new ArrayList<RoomPanel.RoomClient>();
-               for (Client cl : getRoomUsers(roomId)) {
-                       list.add(new RoomClient(cl));
-               }
-               return list;
-       }
-       
-       private void exit(IPartialPageRequestHandler handler) {
-               if (WebSession.getRights().contains(Right.Dashboard)) {
-                       getMainPage().updateContents(ROOMS_PUBLIC, handler);
-               } else {
-                       String url = 
getBean(ConfigurationDao.class).getConfValue(CONFIG_REDIRECT_URL_FOR_EXTERNAL_KEY,
 String.class, "");
-                       if (Strings.isEmpty(url)) {
-                               url = 
getBean(ConfigurationDao.class).getConfValue(CONFIG_APPLICATION_BASE_URL, 
String.class, "");
-                       }
-                       throw new RedirectToUrlException(url);
-               }
-       }
-
-       static class RoomClient implements Serializable {
-               private static final long serialVersionUID = 1L;
-               private final Client c;
-               private final User u;
-               
-               RoomClient(Client c) {
-                       this.c = c;
-                       this.u = getBean(UserDao.class).get(c.getUserId());
-               }
-       }
-       
-       static class FilesTreeProvider implements 
ITreeProvider<FileExplorerItem> {
-               private static final long serialVersionUID = 1L;
-               Long roomId = null;
-
-               FilesTreeProvider(Long roomId) {
-                       this.roomId = roomId;
-               }
-               
-               public void detach() {
-                       // TODO LDM should be used
-               }
-
-               public boolean hasChildren(FileExplorerItem node) {
-                       return node.getId() <= 0 || Type.Folder == 
node.getType();
-               }
-
-               public Iterator<? extends FileExplorerItem> 
getChildren(FileExplorerItem node) {
-                       FileExplorerItemDao dao = 
getBean(FileExplorerItemDao.class);
-                       List<FileExplorerItem> list = null;
-                       if (node.getId() == 0) {
-                               list = dao.getByOwner(node.getOwnerId());
-                       } else if (node.getId() < 0) {
-                               list = dao.getByRoom(roomId);
-                       } else {
-                               list = dao.getByParent(node.getId());
-                       }
-                       return list.iterator();
-               }
-
-               public IModel<FileExplorerItem> model(FileExplorerItem object) {
-                       // TODO LDM should be used
-                       return Model.of(object);
-               }
-
-               @Override
-               public Iterator<? extends FileExplorerItem> getRoots() {
-                       FileExplorerItem f = new FileExplorerItem();
-                       f.setRoomId(roomId);
-                       f.setType(Type.Folder);
-                       if (roomId == null) {
-                               f.setId(0L);
-                               f.setOwnerId(getUserId());
-                               f.setName(Application.getString(706));
-                       } else {
-                               f.setId(-roomId);
-                               f.setName(Application.getString(707));
-                       }
-                       return Arrays.asList(f).iterator();
-               }
-       }
-       
        class ExpiredMessageDialog extends MessageDialog {
                private static final long serialVersionUID = 1L;
                public boolean autoOpen = false;
@@ -672,6 +349,7 @@ public class RoomPanel extends BasePanel
                        autoOpen = true;
                }
                
+               @Override
                public boolean isModal() {
                        return true;
                }
@@ -684,7 +362,23 @@ public class RoomPanel extends BasePanel
                
                @Override
                public void onClose(IPartialPageRequestHandler handler, 
DialogButton button) {
-                       RoomPanel.this.exit(handler);
+                       menu.exit(handler);
                }
        }
+       
+       public Room getRoom() {
+               return r;
+       }
+       
+       public Client getClient() {
+               return client;
+       }
+       
+       public RoomSidebar getSidebar() {
+               return sidebar;
+       }
+
+       public ActivitiesPanel getActivities() {
+               return activities;
+       }
 }

Modified: 
openmeetings/application/trunk/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/activities/ActivitiesPanel.html
URL: 
http://svn.apache.org/viewvc/openmeetings/application/trunk/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/activities/ActivitiesPanel.html?rev=1739141&r1=1739140&r2=1739141&view=diff
==============================================================================
--- 
openmeetings/application/trunk/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/activities/ActivitiesPanel.html
 (original)
+++ 
openmeetings/application/trunk/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/activities/ActivitiesPanel.html
 Thu Apr 14 17:08:51 2016
@@ -24,12 +24,9 @@
                <div onclick="toggleActivities();" class="clickable control 
block ui-widget-header ui-state-active"><div class="ui-icon ui-icon-carat-1-n 
sort-icon"></div><div class="label"><wicket:message key="1363"/></div></div>
        </div>
        <div wicket:id="container" class="area ui-widget-content">
-               <div wicket:id="activities" class="activity item">
+               <div wicket:id="activities" class="activity item 
ui-helper-clearfix ui-corner-all">
+                       <span wicket:id="close" class="ui-icon ui-icon-close 
ui-corner-all align-right clickable" wicket:message="title:85"></span>
                        <div wicket:id="text"></div>
-                       <button type="button" class="ui-button ui-widget 
ui-state-default ui-corner-all ui-button-icon-only ui-dialog-titlebar-close" 
role="button" title="Close">
-                               <span class="ui-button-icon-primary ui-icon 
ui-icon-closethick"></span>
-                               <span class="ui-button-text">Close</span>
-                       </button>
                </div>
        </div>
 </wicket:panel>

Modified: 
openmeetings/application/trunk/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/activities/ActivitiesPanel.java
URL: 
http://svn.apache.org/viewvc/openmeetings/application/trunk/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/activities/ActivitiesPanel.java?rev=1739141&r1=1739140&r2=1739141&view=diff
==============================================================================
--- 
openmeetings/application/trunk/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/activities/ActivitiesPanel.java
 (original)
+++ 
openmeetings/application/trunk/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/activities/ActivitiesPanel.java
 Thu Apr 14 17:08:51 2016
@@ -22,19 +22,23 @@ import static org.apache.openmeetings.ut
 import static org.apache.openmeetings.web.app.Application.getBean;
 import static org.apache.openmeetings.web.app.WebSession.getUserId;
 import static org.apache.openmeetings.web.room.RoomPanel.isModerator;
+import static 
org.apache.openmeetings.web.util.CallbackFunctionHelper.getNamedFunction;
+import static org.apache.wicket.ajax.attributes.CallbackParameter.explicit;
 
 import java.text.DateFormat;
 import java.text.SimpleDateFormat;
 import java.util.ArrayList;
-import java.util.List;
+import java.util.LinkedHashMap;
+import java.util.Map;
 
 import org.apache.openmeetings.db.dao.user.UserDao;
 import org.apache.openmeetings.db.entity.user.User;
-import org.apache.openmeetings.web.app.Application;
 import org.apache.openmeetings.web.common.BasePanel;
 import org.apache.openmeetings.web.room.activities.Activity.Type;
+import org.apache.wicket.Component;
 import org.apache.wicket.ajax.AbstractDefaultAjaxBehavior;
 import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.behavior.AttributeAppender;
 import org.apache.wicket.core.request.handler.IPartialPageRequestHandler;
 import org.apache.wicket.markup.head.CssHeaderItem;
 import org.apache.wicket.markup.head.IHeaderResponse;
@@ -58,25 +62,17 @@ public class ActivitiesPanel extends Bas
                accept, decline, close
        };
        private static ThreadLocal<DateFormat> df = new 
ThreadLocal<DateFormat>() {
+               @Override
                protected DateFormat initialValue() {
                        return new SimpleDateFormat("HH:mm:ss");
                };
        };
-       private final List<Activity> activities = new ArrayList<Activity>();
+       private final Map<String, Activity> activities = new LinkedHashMap<>();
        private final long roomId;
        private final WebMarkupContainer container = new 
WebMarkupContainer("container");
        private final AbstractDefaultAjaxBehavior action = new 
AbstractDefaultAjaxBehavior() {
                private static final long serialVersionUID = 1L;
 
-               private Activity get(String uid) {
-                       for (Activity a : activities) {
-                               if (a.getUid().equals(uid)) {
-                                       return a;
-                               }
-                       }
-                       return null;
-               }
-               
                @Override
                protected void respond(AjaxRequestTarget target) {
                        try {
@@ -84,13 +80,14 @@ public class ActivitiesPanel extends Bas
                                long roomId = 
getRequest().getRequestParameters().getParameterValue(PARAM_ROOM_ID).toLong();
                                assert(ActivitiesPanel.this.roomId == roomId);
                                Action action = 
Action.valueOf(getRequest().getRequestParameters().getParameterValue(ACTION).toString());
-                               Activity a = get(uid);
+                               Activity a = activities.get(uid);
                                if (a != null) {
                                        if (action == Action.close && 
(a.getType() == Type.roomEnter || a.getType() == Type.roomExit)) {
-                                               activities.remove(a);
+                                               activities.remove(uid);
+                                               update(target);
                                        } else if (isModerator(getUserId(), 
roomId)) {
                                                switch (a.getType()) {
-                                                       case askModeration:
+                                                       case 
requestRightModerator:
                                                                break;
                                                        default:
                                                                break;  
@@ -103,8 +100,14 @@ public class ActivitiesPanel extends Bas
                                log.error("Unexpected exception while 
processing activity action", e);
                        }
                }
+               
+               @Override
+               public void renderHead(Component component, IHeaderResponse 
response) {
+                       super.renderHead(component, response);
+                       response.render(new 
PriorityHeaderItem(JavaScriptHeaderItem.forScript(getNamedFunction("activityAction",
 this, explicit(PARAM_ROOM_ID), explicit(ACTION), explicit(PARAM_UID)), 
"activityAction")));
+               }
        };
-       private ListView<Activity> lv = new ListView<Activity>("activities", 
activities) {
+       private ListView<Activity> lv = new ListView<Activity>("activities", 
new ArrayList<Activity>()) {
                private static final long serialVersionUID = 1L;
 
                @Override
@@ -119,22 +122,45 @@ public class ActivitiesPanel extends Bas
                                case roomExit:
                                {
                                        User u = 
getBean(UserDao.class).get(a.getSender());
-                                       text = String.format("%s %s %s [%s]", 
u.getFirstname(), u.getLastname(), Application.getString(1367), 
df.get().format(a.getCreated()));
+                                       text = String.format("%s %s %s [%s]", 
u.getFirstname(), u.getLastname(), getString("1367"), 
df.get().format(a.getCreated()));
                                }
                                        break;
-                               case askModeration:
+                               case requestRightModerator:
+                               {
+                                       User u = 
getBean(UserDao.class).get(a.getSender());
+                                       text = String.format("%s %s %s [%s]", 
u.getFirstname(), u.getLastname(), 
getString("room.action.request.right.moderator"), 
df.get().format(a.getCreated()));
+                                       //FIXME TODO actions
+                               }
+                               //ask question 693
                                        break;
                        }
+                       item.add(new WebMarkupContainer("close").add(new 
AttributeAppender("onclick", String.format("activityAction(%s, '%s', '%s');", 
roomId, Action.close.name(), a.getUid()))));
                        item.add(new Label("text", text));
+                       item.add(AttributeAppender.append("class", 
getClass(a)));
+               }
+               
+               private String getClass(Activity a) {
+                       switch (a.getType()) {
+                               case requestRightModerator:
+                                       return "ui-state-highlight";
+                               case roomEnter:
+                               case roomExit:
+                       }
+                       return "ui-state-default";
                }
        };
 
-       public void addActivity(Long userId, Activity.Type type, 
IPartialPageRequestHandler target) {
+       public void addActivity(String uid, Long userId, Activity.Type type, 
IPartialPageRequestHandler handler) {
                //if (getUserId() != userId) {//FIXME should be replaced with 
client-id
-                       activities.add(new Activity(userId,  type));
-                       target.add(container);
+                       activities.put(uid, new Activity(uid, userId,  type));
+                       update(handler);
                //}
        }
+
+       public void update(IPartialPageRequestHandler handler) {
+               lv.setList(new ArrayList<>(activities.values()));
+               handler.add(container);
+       }
        
        public ActivitiesPanel(String id, long roomId) {
                super(id);

Modified: 
openmeetings/application/trunk/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/activities/Activity.java
URL: 
http://svn.apache.org/viewvc/openmeetings/application/trunk/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/activities/Activity.java?rev=1739141&r1=1739140&r2=1739141&view=diff
==============================================================================
--- 
openmeetings/application/trunk/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/activities/Activity.java
 (original)
+++ 
openmeetings/application/trunk/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/activities/Activity.java
 Thu Apr 14 17:08:51 2016
@@ -20,56 +20,39 @@ package org.apache.openmeetings.web.room
 
 import java.io.Serializable;
 import java.util.Date;
-import java.util.UUID;
 
 public class Activity implements Serializable {
        private static final long serialVersionUID = 1L;
-       public enum Type { //TODO maybe additional type is not necessary
+       public enum Type {
                roomEnter
                , roomExit
-               , askModeration //TODO check
+               , requestRightModerator
        }
-       private String uid;
-       private Long sender;
-       private Date created;
-       private Type type;
+       private final String uid;
+       private final Long sender;
+       private final Date created;
+       private final Type type;
        
-       public Activity(Long sender, Type type) {
-               this.uid = UUID.randomUUID().toString();
+       public Activity(String uid, Long sender, Type type) {
+               this.uid = uid;
                this.sender = sender;
                this.type = type;
-               this.created = new Date(); //TODO timezone
+               this.created = new Date();
        }
 
        public String getUid() {
                return uid;
        }
 
-       public void setUid(String uid) {
-               this.uid = uid;
-       }
-
        public Long getSender() {
                return sender;
        }
 
-       public void setSender(Long sender) {
-               this.sender = sender;
-       }
-
        public Type getType() {
                return type;
        }
 
-       public void setType(Type type) {
-               this.type = type;
-       }
-
        public Date getCreated() {
                return created;
        }
-
-       public void setCreated(Date created) {
-               this.created = created;
-       }
 }

Modified: 
openmeetings/application/trunk/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/activities/activities.js
URL: 
http://svn.apache.org/viewvc/openmeetings/application/trunk/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/activities/activities.js?rev=1739141&r1=1739140&r2=1739141&view=diff
==============================================================================
--- 
openmeetings/application/trunk/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/activities/activities.js
 (original)
+++ 
openmeetings/application/trunk/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/activities/activities.js
 Thu Apr 14 17:08:51 2016
@@ -16,18 +16,18 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-var closeBlock = "<span class='ui-icon ui-icon-close' 
role='presentation'></span>"
-       , closedHeight = "20px", openedHeight = "345px";
+var closedHeight = "20px", openedHeight = "345px";
 function openActivities() {
-       if ($('#activitiesPanel').height() < 24) {
-               $('#activitiesPanel .control.block 
.ui-icon').removeClass('ui-icon-carat-1-n').addClass('ui-icon-carat-1-s');
-               $('#activitiesPanel').animate({height: openedHeight}, 1000);
+       var activities = $('#activitiesPanel');
+       if (activities.height() < 24) {
+               $('.control.block .ui-icon', 
activities).removeClass('ui-icon-carat-1-n').addClass('ui-icon-carat-1-s');
+               activities.animate({height: openedHeight}, 1000);
        }
 }
 function closeActivities() {
        var activities = $('#activitiesPanel');
-       if ($('#activitiesPanel').height() > 24) {
-               $('#activitiesPanel .control.block 
.ui-icon').removeClass('ui-icon-carat-1-s').addClass('ui-icon-carat-1-n');
+       if (activities.height() > 24) {
+               $('.control.block .ui-icon', 
activities).removeClass('ui-icon-carat-1-s').addClass('ui-icon-carat-1-n');
                activities.animate({height: closedHeight}, 1000);
        }
 }

Copied: 
openmeetings/application/trunk/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/menu/InvitationDialog.java
 (from r1739126, 
openmeetings/application/trunk/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/InvitationDialog.java)
URL: 
http://svn.apache.org/viewvc/openmeetings/application/trunk/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/menu/InvitationDialog.java?p2=openmeetings/application/trunk/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/menu/InvitationDialog.java&p1=openmeetings/application/trunk/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/InvitationDialog.java&r1=1739126&r2=1739141&rev=1739141&view=diff
==============================================================================
--- 
openmeetings/application/trunk/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/InvitationDialog.java
 (original)
+++ 
openmeetings/application/trunk/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/menu/InvitationDialog.java
 Thu Apr 14 17:08:51 2016
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.openmeetings.web.room;
+package org.apache.openmeetings.web.room.menu;
 
 import static org.apache.openmeetings.util.OpenmeetingsVariables.webAppRootKey;
 import static org.apache.openmeetings.web.app.Application.getBean;

Added: 
openmeetings/application/trunk/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/menu/RoomMenuPanel.html
URL: 
http://svn.apache.org/viewvc/openmeetings/application/trunk/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/menu/RoomMenuPanel.html?rev=1739141&view=auto
==============================================================================
--- 
openmeetings/application/trunk/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/menu/RoomMenuPanel.html
 (added)
+++ 
openmeetings/application/trunk/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/menu/RoomMenuPanel.html
 Thu Apr 14 17:08:51 2016
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+  
+      http://www.apache.org/licenses/LICENSE-2.0
+         
+  Unless required by applicable law or agreed to in writing,
+  software distributed under the License is distributed on an
+  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  KIND, either express or implied.  See the License for the
+  specific language governing permissions and limitations
+  under the License.
+  
+-->
+<html xmlns:wicket="http://wicket.apache.org";>
+<wicket:panel>
+       <div wicket:id="roomMenu"></div>
+       <div class="room menu right">
+               <span wicket:id="ask" class="icon ask"></span>
+               <span wicket:id="share" class="icon share"></span>
+               <span wicket:id="recording" class="room recording"></span>
+               <span wicket:id="roomName" class="room name"></span>
+       </div>
+       <div wicket:id="invite"></div>
+       <div wicket:id="createPoll"></div>
+       <div wicket:id="vote"></div>
+       <div wicket:id="pollResults"></div>
+</wicket:panel>
+</html>

Added: 
openmeetings/application/trunk/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/menu/RoomMenuPanel.java
URL: 
http://svn.apache.org/viewvc/openmeetings/application/trunk/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/menu/RoomMenuPanel.java?rev=1739141&view=auto
==============================================================================
--- 
openmeetings/application/trunk/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/menu/RoomMenuPanel.java
 (added)
+++ 
openmeetings/application/trunk/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/menu/RoomMenuPanel.java
 Thu Apr 14 17:08:51 2016
@@ -0,0 +1,241 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License") +  you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.openmeetings.web.room.menu;
+
+import static 
org.apache.openmeetings.util.OpenmeetingsVariables.CONFIG_APPLICATION_BASE_URL;
+import static 
org.apache.openmeetings.util.OpenmeetingsVariables.CONFIG_REDIRECT_URL_FOR_EXTERNAL_KEY;
+import static org.apache.openmeetings.web.app.Application.getBean;
+import static org.apache.openmeetings.web.app.Application.removeUserFromRoom;
+import static org.apache.openmeetings.web.app.WebSession.getUserId;
+import static org.apache.openmeetings.web.util.OmUrlFragment.ROOMS_PUBLIC;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.openmeetings.db.dao.basic.ConfigurationDao;
+import org.apache.openmeetings.db.dao.room.PollDao;
+import org.apache.openmeetings.db.dao.user.UserDao;
+import org.apache.openmeetings.db.entity.room.Room;
+import org.apache.openmeetings.db.entity.user.User;
+import org.apache.openmeetings.db.entity.user.User.Right;
+import org.apache.openmeetings.web.app.Application;
+import org.apache.openmeetings.web.app.Client;
+import org.apache.openmeetings.web.app.WebSession;
+import org.apache.openmeetings.web.common.OmButton;
+import org.apache.openmeetings.web.common.menu.MenuPanel;
+import org.apache.openmeetings.web.common.menu.RoomMenuItem;
+import org.apache.openmeetings.web.room.RoomPanel;
+import org.apache.openmeetings.web.room.message.RoomMessage;
+import org.apache.openmeetings.web.room.poll.CreatePollDialog;
+import org.apache.openmeetings.web.room.poll.PollResultsDialog;
+import org.apache.openmeetings.web.room.poll.VoteDialog;
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.behavior.AttributeAppender;
+import org.apache.wicket.core.request.handler.IPartialPageRequestHandler;
+import org.apache.wicket.markup.html.basic.Label;
+import org.apache.wicket.markup.html.panel.Panel;
+import org.apache.wicket.request.flow.RedirectToUrlException;
+import org.apache.wicket.util.string.Strings;
+
+import com.googlecode.wicket.jquery.ui.widget.menu.IMenuItem;
+
+public class RoomMenuPanel extends Panel {
+       private static final long serialVersionUID = 1L;
+       private final InvitationDialog invite;
+       private final CreatePollDialog createPoll;
+       private final VoteDialog vote;
+       private final PollResultsDialog pollResults;
+       private final MenuPanel menuPanel;
+       private final StartSharingButton shareBtn;
+       private final OmButton askBtn = new OmButton("ask") {
+               private static final long serialVersionUID = 1L;
+               {
+                       setOutputMarkupPlaceholderTag(true);
+                       setVisible(false);
+               }
+               @Override
+               protected void onClick(AjaxRequestTarget target) {
+                       RoomPanel.broadcast(new 
RoomMessage(room.getRoom().getId(), RoomMessage.Type.requestRightModerator));
+               }
+       };
+       private final RoomPanel room;
+       private final RoomMenuItem exitMenuItem = new 
RoomMenuItem(Application.getString(308), Application.getString(309), "room menu 
exit") {
+               private static final long serialVersionUID = 1L;
+
+               @Override
+               public void onClick(AjaxRequestTarget target) {
+                       exit(target);
+               }
+       };
+       private final RoomMenuItem filesMenu = new 
RoomMenuItem(Application.getString(245), null, false);
+       private final RoomMenuItem actionsMenu = new 
RoomMenuItem(Application.getString(635), null, false);
+       private final RoomMenuItem inviteMenuItem = new 
RoomMenuItem(Application.getString(213), Application.getString(1489), false) {
+               private static final long serialVersionUID = 1L;
+
+               @Override
+               public void onClick(AjaxRequestTarget target) {
+                       invite.updateModel(target);
+                       invite.open(target);
+               }
+       };
+       private final RoomMenuItem shareMenuItem = new 
RoomMenuItem(Application.getString(239), Application.getString(1480), false) {
+               private static final long serialVersionUID = 1L;
+
+               @Override
+               public void onClick(AjaxRequestTarget target) {
+                       shareBtn.onClick(target);
+               }
+       };
+       private final RoomMenuItem applyModerMenuItem = new 
RoomMenuItem(Application.getString(784), Application.getString(1481), false);
+       private final RoomMenuItem applyWbMenuItem = new 
RoomMenuItem(Application.getString(785), Application.getString(1492), false);
+       private final RoomMenuItem applyAvMenuItem = new 
RoomMenuItem(Application.getString(786), Application.getString(1482), false);
+       private final RoomMenuItem pollCreateMenuItem = new 
RoomMenuItem(Application.getString(24), Application.getString(1483), false) {
+               private static final long serialVersionUID = 1L;
+
+               @Override
+               public void onClick(AjaxRequestTarget target) {
+                       createPoll.updateModel(target, null); //TODO FIXME
+                       createPoll.open(target);
+               }
+       };
+       private final RoomMenuItem pollVoteMenuItem = new 
RoomMenuItem(Application.getString(42), Application.getString(1485), false) {
+               private static final long serialVersionUID = 1L;
+
+               @Override
+               public void onClick(AjaxRequestTarget target) {
+                       vote.updateModel(target);
+                       vote.open(target);
+               }
+       };
+       private final RoomMenuItem pollResultMenuItem = new 
RoomMenuItem(Application.getString(37), Application.getString(1484), false) {
+               private static final long serialVersionUID = 1L;
+
+               @Override
+               public void onClick(AjaxRequestTarget target) {
+                       pollResults.updateModel(target, 
room.getClient().hasRight(Client.Right.moderator));
+                       pollResults.open(target);
+               }
+       };
+       private final RoomMenuItem sipDialerMenuItem = new 
RoomMenuItem(Application.getString(1447), Application.getString(1488), false);
+
+       public RoomMenuPanel(String id, final RoomPanel room) {
+               super(id);
+               this.room = room;
+               Room r = room.getRoom();
+               add((menuPanel = new MenuPanel("roomMenu", 
getMenu())).setVisible(!r.getHideTopBar()));
+               add(askBtn);
+               add(new Label("roomName", r.getName()));
+               add(new Label("recording", "Recording 
started").setVisible(false)); //FIXME add/remove
+               add(shareBtn = new StartSharingButton("share", 
room.getClient()));
+               add(invite = new InvitationDialog("invite", 
room.getRoom().getId()));
+               add(createPoll = new CreatePollDialog("createPoll", 
room.getRoom().getId()));
+               add(vote = new VoteDialog("vote", room.getRoom().getId()));
+               add(pollResults = new PollResultsDialog("pollResults", 
room.getRoom().getId()));
+       }
+       
+       @Override
+       protected void onInitialize() {
+               super.onInitialize();
+               askBtn.add(new AttributeAppender("title", getString("906")));
+       }
+       
+       private List<IMenuItem> getMenu() {
+               List<IMenuItem> menu = new ArrayList<>();
+               exitMenuItem.setEnabled(false);
+               exitMenuItem.setTop(true);
+               menu.add(exitMenuItem);
+               
+               filesMenu.getItems().add(new 
RoomMenuItem(Application.getString(15), Application.getString(1479)));
+               filesMenu.setTop(true);
+               menu.add(filesMenu);
+               
+               actionsMenu.setTop(true);
+               actionsMenu.getItems().add(inviteMenuItem);
+               actionsMenu.getItems().add(shareMenuItem); //FIXME 
enable/disable
+               actionsMenu.getItems().add(applyModerMenuItem); //FIXME 
enable/disable
+               actionsMenu.getItems().add(applyWbMenuItem); //FIXME 
enable/disable
+               actionsMenu.getItems().add(applyAvMenuItem); //FIXME 
enable/disable
+               actionsMenu.getItems().add(pollCreateMenuItem);
+               actionsMenu.getItems().add(pollResultMenuItem); //FIXME 
enable/disable
+               actionsMenu.getItems().add(pollVoteMenuItem); //FIXME 
enable/disable
+               actionsMenu.getItems().add(sipDialerMenuItem);
+               actionsMenu.getItems().add(new 
RoomMenuItem(Application.getString(1126), Application.getString(1490)));
+               menu.add(actionsMenu);
+               return menu;
+       }
+       
+       public void update(IPartialPageRequestHandler handler) {
+               boolean pollExists = 
getBean(PollDao.class).hasPoll(room.getRoom().getId());
+               User u = getBean(UserDao.class).get(getUserId());
+               boolean notExternalUser = u.getType() != User.Type.external && 
u.getType() != User.Type.contact;
+               exitMenuItem.setEnabled(notExternalUser);//TODO check this
+               filesMenu.setEnabled(room.getSidebar().isShowFiles());
+               actionsMenu.setEnabled(!room.getRoom().getHideActionsMenu());
+               boolean moder = 
room.getClient().hasRight(Client.Right.moderator);
+               inviteMenuItem.setEnabled(notExternalUser && moder);
+               //TODO add check "sharing started"
+               Room r = room.getRoom();
+               boolean shareVisible = Room.Type.interview != r.getType() && 
!r.getHideScreenSharing() && moder;
+               shareMenuItem.setEnabled(shareVisible);
+               shareBtn.setVisible(shareMenuItem.isEnabled());
+               //FIXME TODO apply* should be enabled if moder is in room
+               applyModerMenuItem.setEnabled(!moder);
+               applyWbMenuItem.setEnabled(!moder);
+               applyAvMenuItem.setEnabled(!moder);
+               pollCreateMenuItem.setEnabled(moder);
+               pollVoteMenuItem.setEnabled(pollExists && notExternalUser && 
!getBean(PollDao.class).hasVoted(r.getId(), getUserId()));
+               pollResultMenuItem.setEnabled(pollExists || 
getBean(PollDao.class).getArchived(r.getId()).size() > 0);
+               //TODO sip menus
+               menuPanel.update(handler);
+               //FIXME TODO add ask question button
+               //FIXME TODO askBtn should be visible if moder is in room
+               handler.add(askBtn.setVisible(!moder), 
shareBtn.setVisible(shareVisible));
+       }
+
+       public void pollCreated(IPartialPageRequestHandler handler) {
+               vote.updateModel(handler);
+               vote.open(handler);
+       }
+       
+       public void exit(IPartialPageRequestHandler handler) {
+               if (WebSession.getRights().contains(Right.Dashboard)) {
+                       room.getMainPage().updateContents(ROOMS_PUBLIC, 
handler);
+                       roomExit(room, false);
+               } else {
+                       String url = 
getBean(ConfigurationDao.class).getConfValue(CONFIG_REDIRECT_URL_FOR_EXTERNAL_KEY,
 String.class, "");
+                       if (Strings.isEmpty(url)) {
+                               url = 
getBean(ConfigurationDao.class).getConfValue(CONFIG_APPLICATION_BASE_URL, 
String.class, "");
+                       }
+                       throw new RedirectToUrlException(url);
+               }
+       }
+
+       public static void roomExit(RoomPanel room) {
+               roomExit(room, true);
+       }
+       
+       public static void roomExit(RoomPanel room, boolean broadcast) {
+               Client c = room.getClient();
+               removeUserFromRoom(c);
+               if (broadcast) {
+                       RoomMessage m = new RoomMessage(c.getRoomId(), 
c.getUserId(), RoomMessage.Type.roomExit);
+                       RoomPanel.broadcast(m);
+               }
+       }
+}

Copied: 
openmeetings/application/trunk/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/menu/StartSharingButton.java
 (from r1739126, 
openmeetings/application/trunk/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/StartSharingEventBehavior.java)
URL: 
http://svn.apache.org/viewvc/openmeetings/application/trunk/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/menu/StartSharingButton.java?p2=openmeetings/application/trunk/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/menu/StartSharingButton.java&p1=openmeetings/application/trunk/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/StartSharingEventBehavior.java&r1=1739126&r2=1739141&rev=1739141&view=diff
==============================================================================
--- 
openmeetings/application/trunk/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/StartSharingEventBehavior.java
 (original)
+++ 
openmeetings/application/trunk/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/menu/StartSharingButton.java
 Thu Apr 14 17:08:51 2016
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.openmeetings.web.room;
+package org.apache.openmeetings.web.room.menu;
 
 import static 
org.apache.openmeetings.util.OpenmeetingsVariables.CONFIG_SCREENSHARING_ALLOW_REMOTE;
 import static 
org.apache.openmeetings.util.OpenmeetingsVariables.CONFIG_SCREENSHARING_FPS;
@@ -25,7 +25,7 @@ import static org.apache.openmeetings.ut
 import static org.apache.openmeetings.util.OpenmeetingsVariables.webAppRootKey;
 import static org.apache.openmeetings.web.app.Application.getBean;
 import static org.apache.openmeetings.web.app.WebSession.getLanguage;
-import static org.apache.openmeetings.web.util.CallbackFunctionHelper.getParam;
+import static org.apache.openmeetings.web.room.RoomBroadcaster.getClient;
 
 import java.io.File;
 import java.io.FileInputStream;
@@ -43,23 +43,23 @@ import org.apache.openmeetings.db.dao.ro
 import org.apache.openmeetings.db.entity.room.Client;
 import org.apache.openmeetings.db.entity.room.Room;
 import org.apache.openmeetings.util.OmFileHelper;
+import org.apache.openmeetings.web.app.Application;
+import org.apache.openmeetings.web.common.OmButton;
 import org.apache.openmeetings.web.util.AjaxDownload;
-import org.apache.wicket.ajax.AbstractDefaultAjaxBehavior;
 import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.behavior.AttributeAppender;
 import org.apache.wicket.util.resource.StringResourceStream;
 import org.apache.wicket.util.string.Strings;
 import org.red5.logging.Red5LoggerFactory;
 import org.slf4j.Logger;
 
-public class StartSharingEventBehavior extends AbstractDefaultAjaxBehavior {
+public class StartSharingButton extends OmButton {
        private static final long serialVersionUID = 1L;
-       private static final Logger log = 
Red5LoggerFactory.getLogger(StartSharingEventBehavior.class, webAppRootKey);
+       private static final Logger log = 
Red5LoggerFactory.getLogger(StartSharingButton.class, webAppRootKey);
        private static final String CDATA_BEGIN = "<![CDATA[";
        private static final String CDATA_END = "]]>";
-       public static final String PARAM_PUBLIC_SID = "publicSid";
-       public static final String PARAM_URL = "url";
        private final AjaxDownload download;
-       private final Long roomId;
+       private final org.apache.openmeetings.web.app.Client c;
        private enum Protocol {
                rtmp
                , rtmpe
@@ -67,41 +67,40 @@ public class StartSharingEventBehavior e
                , rtmpt
        }
 
-       public StartSharingEventBehavior(Long _roomId) {
-               this.roomId = _roomId;
-               download = new AjaxDownload(true) {
+       public StartSharingButton(String id, 
org.apache.openmeetings.web.app.Client c) {
+               super(id);
+               this.c = c;
+               setOutputMarkupPlaceholderTag(true);
+               setVisible(false);
+               add(new AttributeAppender("title", 
Application.getString(1480)));
+               add(download = new AjaxDownload(true) {
                        private static final long serialVersionUID = 1L;
 
                        @Override
                        protected String getFileName() {
-                               return "public_" + roomId + ".jnlp";
+                               return String.format("public_%s.jnlp", 
StartSharingButton.this.c.getRoomId());
                        }
-               };
+               });
        }
        
        @Override
-       protected void onBind() {
-               super.onBind();
-               getComponent().add(download);
-       }
-       
-       @Override
-       protected void respond(AjaxRequestTarget target) {
+       protected void onClick(AjaxRequestTarget target) {
                //TODO deny download in case other screen sharing is in progress
                String app = "";
                try (InputStream jnlp = 
getClass().getClassLoader().getResourceAsStream("APPLICATION.jnlp")) {
                        ConfigurationDao cfgDao = 
getBean(ConfigurationDao.class);
                        app = IOUtils.toString(jnlp, StandardCharsets.UTF_8);
                        String baseUrl = cfgDao.getBaseUrl();
-                       String _url = getParam(getComponent(), 
PARAM_URL).toString();
-                       URI url = new URI(_url);
-                       Room room = getBean(RoomDao.class).get(roomId);
-                       String publicSid = getParam(getComponent(), 
PARAM_PUBLIC_SID).toString();
-                       SessionManager sessionManager = 
getBean(SessionManager.class);
-                       Client rc = 
sessionManager.getClientByPublicSID(publicSid, null);//TODO not necessary
+                       String publicSid = c.getUid();
+                       Client rc = getClient(publicSid);
                        if (rc == null) {
                                throw new 
RuntimeException(String.format("Unable to find client by publicSID '%s'", 
publicSid));
                        }
+                       String _url = rc.getTcUrl();
+                       URI url = new URI(_url);
+                       long roomId = c.getRoomId();
+                       Room room = getBean(RoomDao.class).get(roomId);
+                       SessionManager sessionManager = 
getBean(SessionManager.class);
                        String path = url.getPath();
                        path = path.substring(path.lastIndexOf('/') + 1);
                        if (Strings.isEmpty(path) || rc.getRoomId() == null || 
!path.equals(rc.getRoomId().toString()) || !rc.getRoomId().equals(roomId)) {

Modified: 
openmeetings/application/trunk/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/message/RoomMessage.java
URL: 
http://svn.apache.org/viewvc/openmeetings/application/trunk/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/message/RoomMessage.java?rev=1739141&r1=1739140&r2=1739141&view=diff
==============================================================================
--- 
openmeetings/application/trunk/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/message/RoomMessage.java
 (original)
+++ 
openmeetings/application/trunk/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/message/RoomMessage.java
 Thu Apr 14 17:08:51 2016
@@ -20,6 +20,7 @@ package org.apache.openmeetings.web.room
 
 import java.io.Serializable;
 import java.util.Date;
+import java.util.UUID;
 
 import org.apache.openmeetings.web.app.WebSession;
 import org.apache.wicket.protocol.ws.api.message.IWebSocketPushMessage;
@@ -34,29 +35,30 @@ public class RoomMessage implements IWeb
                , pollDeleted
                , voted
                , rightUpdated
+               , requestRightModerator
        }
        private final Date timestamp;
-       private final Long sentUserId;
+       private final String uid;
        private final Long roomId;
        private final Long userId;
        private final Type type;
 
+       public RoomMessage(Long roomId, Type type) {
+               this(roomId, WebSession.getUserId(), type);
+       }
+       
        public RoomMessage(Long roomId, Long userId, Type type) {
                this.timestamp = new Date();
-               this.sentUserId = WebSession.getUserId();
                this.roomId = roomId;
                this.userId = userId;
                this.type = type;
+               this.uid = UUID.randomUUID().toString();
        }
        
        public Date getTimestamp() {
                return timestamp;
        }
 
-       public Long getSentUserId() {
-               return sentUserId;
-       }
-
        public Long getRoomId() {
                return roomId;
        }
@@ -68,4 +70,8 @@ public class RoomMessage implements IWeb
        public Type getType() {
                return type;
        }
+
+       public String getUid() {
+               return uid;
+       }
 }

Modified: 
openmeetings/application/trunk/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/poll/CreatePollDialog.java
URL: 
http://svn.apache.org/viewvc/openmeetings/application/trunk/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/poll/CreatePollDialog.java?rev=1739141&r1=1739140&r2=1739141&view=diff
==============================================================================
--- 
openmeetings/application/trunk/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/poll/CreatePollDialog.java
 (original)
+++ 
openmeetings/application/trunk/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/poll/CreatePollDialog.java
 Thu Apr 14 17:08:51 2016
@@ -20,6 +20,7 @@ package org.apache.openmeetings.web.room
 
 import static org.apache.openmeetings.web.app.Application.getBean;
 import static org.apache.openmeetings.web.app.WebSession.getUserId;
+import static org.apache.openmeetings.web.room.RoomBroadcaster.broadcast;
 
 import java.util.Arrays;
 import java.util.List;
@@ -30,8 +31,6 @@ import org.apache.openmeetings.db.dao.us
 import org.apache.openmeetings.db.entity.room.RoomPoll;
 import org.apache.openmeetings.db.entity.user.User;
 import org.apache.openmeetings.web.app.Application;
-import org.apache.openmeetings.web.room.RoomPanel;
-import org.apache.openmeetings.web.room.message.RoomMessage;
 import org.apache.wicket.ajax.AjaxRequestTarget;
 import org.apache.wicket.markup.html.form.ChoiceRenderer;
 import org.apache.wicket.markup.html.form.DropDownChoice;
@@ -54,6 +53,7 @@ public class CreatePollDialog extends Ab
        private final Long roomId;
        private final PollForm form;
        private final KendoFeedbackPanel feedback = new 
KendoFeedbackPanel("feedback", new Options("button", true));
+       private String publicSid = null;
 
        public CreatePollDialog(String id, Long roomId) {
                super(id, Application.getString(18), new 
CompoundPropertyModel<RoomPoll>(new RoomPoll()));
@@ -61,7 +61,8 @@ public class CreatePollDialog extends Ab
                add(form = new PollForm("form", getModel()));
        }
 
-       public void updateModel(AjaxRequestTarget target) {
+       public void updateModel(AjaxRequestTarget target, String publicSid) {
+               this.publicSid = publicSid;
                RoomPoll p = new RoomPoll();
                User u = getBean(UserDao.class).get(getUserId());
                p.setCreator(u);
@@ -94,8 +95,8 @@ public class CreatePollDialog extends Ab
        @Override
        protected void onSubmit(AjaxRequestTarget target) {
                getBean(PollDao.class).close(roomId);
-               getBean(PollDao.class).update(form.getModelObject());
-               RoomPanel.broadcast(new RoomMessage(roomId, getUserId(), 
RoomMessage.Type.pollCreated));
+               RoomPoll p = 
getBean(PollDao.class).update(form.getModelObject());
+               broadcast(publicSid, "newPoll", p);
        }
 
        private class PollForm extends Form<RoomPoll> {

Modified: 
openmeetings/application/trunk/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/poll/PollResultsDialog.java
URL: 
http://svn.apache.org/viewvc/openmeetings/application/trunk/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/poll/PollResultsDialog.java?rev=1739141&r1=1739140&r2=1739141&view=diff
==============================================================================
--- 
openmeetings/application/trunk/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/poll/PollResultsDialog.java
 (original)
+++ 
openmeetings/application/trunk/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/poll/PollResultsDialog.java
 Thu Apr 14 17:08:51 2016
@@ -19,7 +19,6 @@
 package org.apache.openmeetings.web.room.poll;
 
 import static org.apache.openmeetings.web.app.Application.getBean;
-import static org.apache.openmeetings.web.app.WebSession.getUserId;
 
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -29,8 +28,6 @@ import org.apache.openmeetings.db.dao.ro
 import org.apache.openmeetings.db.entity.room.RoomPoll;
 import org.apache.openmeetings.db.entity.room.RoomPollAnswer;
 import org.apache.openmeetings.web.app.Application;
-import org.apache.openmeetings.web.room.RoomPanel;
-import org.apache.openmeetings.web.room.message.RoomMessage;
 import org.apache.wicket.ajax.AjaxRequestTarget;
 import org.apache.wicket.ajax.form.AjaxFormComponentUpdatingBehavior;
 import org.apache.wicket.core.request.handler.IPartialPageRequestHandler;
@@ -101,7 +98,6 @@ public class PollResultsDialog extends A
                                        RoomPoll p = 
getBean(PollDao.class).get(id);
                                        selForm.select.setModelObject(p);
                                        dispForm.updateModel(p, false, handler);
-                                       RoomPanel.broadcast(new 
RoomMessage(roomId, getUserId(), RoomMessage.Type.pollClosed));
                                        //TODO result dialogs of other users 
should also be updated
                                }
                        }
@@ -116,7 +112,6 @@ public class PollResultsDialog extends A
                                        
getBean(PollDao.class).delete(dispForm.getModelObject());
                                        selForm.updateModel(handler);
                                        
dispForm.updateModel(selForm.select.getModelObject(), true, handler);
-                                       RoomPanel.broadcast(new 
RoomMessage(roomId, getUserId(), RoomMessage.Type.pollDeleted));
                                        //TODO result dialogs of other users 
should also be updated
                                }
                        }

Modified: 
openmeetings/application/trunk/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/poll/VoteDialog.java
URL: 
http://svn.apache.org/viewvc/openmeetings/application/trunk/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/poll/VoteDialog.java?rev=1739141&r1=1739140&r2=1739141&view=diff
==============================================================================
--- 
openmeetings/application/trunk/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/poll/VoteDialog.java
 (original)
+++ 
openmeetings/application/trunk/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/poll/VoteDialog.java
 Thu Apr 14 17:08:51 2016
@@ -31,8 +31,6 @@ import org.apache.openmeetings.db.entity
 import org.apache.openmeetings.db.entity.room.RoomPollAnswer;
 import org.apache.openmeetings.db.entity.user.User;
 import org.apache.openmeetings.web.app.Application;
-import org.apache.openmeetings.web.room.RoomPanel;
-import org.apache.openmeetings.web.room.message.RoomMessage;
 import org.apache.wicket.ajax.AjaxRequestTarget;
 import org.apache.wicket.core.request.handler.IPartialPageRequestHandler;
 import org.apache.wicket.markup.html.WebMarkupContainer;
@@ -125,7 +123,6 @@ public class VoteDialog extends Abstract
                a.setVoteDate(new Date());
                a.getRoomPoll().getAnswers().add(a);
                getBean(PollDao.class).update(a.getRoomPoll());
-               RoomPanel.broadcast(new RoomMessage(roomId, getUserId(), 
RoomMessage.Type.voted));
        }
        
        @Override

Added: 
openmeetings/application/trunk/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/sidebar/RoomFilePanel.java
URL: 
http://svn.apache.org/viewvc/openmeetings/application/trunk/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/sidebar/RoomFilePanel.java?rev=1739141&view=auto
==============================================================================
--- 
openmeetings/application/trunk/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/sidebar/RoomFilePanel.java
 (added)
+++ 
openmeetings/application/trunk/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/sidebar/RoomFilePanel.java
 Thu Apr 14 17:08:51 2016
@@ -0,0 +1,164 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License") +  you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.openmeetings.web.room.sidebar;
+
+import static org.apache.openmeetings.web.app.Application.getBean;
+import static org.apache.openmeetings.web.app.WebSession.getUserId;
+
+import java.util.Arrays;
+import java.util.Date;
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.openmeetings.db.dao.file.FileExplorerItemDao;
+import org.apache.openmeetings.db.dao.user.UserDao;
+import org.apache.openmeetings.db.entity.file.FileExplorerItem;
+import org.apache.openmeetings.db.entity.file.FileItem;
+import org.apache.openmeetings.db.entity.file.FileItem.Type;
+import org.apache.openmeetings.db.entity.record.Recording;
+import org.apache.openmeetings.db.entity.user.Group;
+import org.apache.openmeetings.db.entity.user.GroupUser;
+import org.apache.openmeetings.web.app.Application;
+import org.apache.openmeetings.web.common.tree.FileItemTree;
+import org.apache.openmeetings.web.common.tree.FileTreePanel;
+import org.apache.openmeetings.web.common.tree.MyRecordingTreeProvider;
+import org.apache.openmeetings.web.common.tree.PublicRecordingTreeProvider;
+import org.apache.wicket.Component;
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.extensions.markup.html.repeater.tree.ITreeProvider;
+import org.apache.wicket.model.IModel;
+import org.apache.wicket.model.Model;
+
+public class RoomFilePanel extends FileTreePanel {
+       private static final long serialVersionUID = 1L;
+       private final long roomId;
+
+       public RoomFilePanel(String id, final long roomId) {
+               super(id);
+               this.roomId = roomId;
+       }
+       
+       @Override
+       public void updateSizes() {
+               // TODO Auto-generated method stub
+               
+       }
+       
+       @Override
+       public void update(AjaxRequestTarget target, FileItem f) {
+               // TODO Auto-generated method stub
+               
+       }
+       
+       @Override
+       protected Component getUpload(String id) {
+               Component u = super.getUpload(id);
+               u.setVisible(true);
+               return u;
+       }
+       
+       @Override
+       public void defineTrees() {
+               FileExplorerItem f = new FileExplorerItem();
+               f.setOwnerId(getUserId());
+               selectedFile.setObject(f);
+               treesView.add(selected = new 
FileItemTree<FileExplorerItem>(treesView.newChildId(), this, new 
FilesTreeProvider(null)));
+               treesView.add(new 
FileItemTree<FileExplorerItem>(treesView.newChildId(), this, new 
FilesTreeProvider(roomId)));
+               treesView.add(new 
FileItemTree<Recording>(treesView.newChildId(), this, new 
MyRecordingTreeProvider()));
+               treesView.add(new 
FileItemTree<Recording>(treesView.newChildId(), this, new 
PublicRecordingTreeProvider(null, null)));
+               for (GroupUser ou : 
getBean(UserDao.class).get(getUserId()).getGroupUsers()) {
+                       Group o = ou.getGroup();
+                       treesView.add(new 
FileItemTree<Recording>(treesView.newChildId(), this, new 
PublicRecordingTreeProvider(o.getId(), o.getName())));
+               }
+       }
+       
+       @Override
+       public void createFolder(String name) {
+               if (selectedFile.getObject() instanceof Recording) {
+                       createRecordingFolder(name);
+               } else {
+                       FileExplorerItem f = new FileExplorerItem();
+                       f.setName(name);
+                       f.setInsertedBy(getUserId());
+                       f.setInserted(new Date());
+                       f.setType(Type.Folder);;
+                       FileItem p = selectedFile.getObject();
+                       long parentId = p.getId();
+                       f.setParentId(Type.Folder == p.getType() && parentId > 
0 ? parentId : null);
+                       f.setOwnerId(p.getOwnerId());
+                       f.setRoomId(p.getRoomId());
+                       getBean(FileExplorerItemDao.class).update(f);
+               }
+       }
+
+       static class FilesTreeProvider implements 
ITreeProvider<FileExplorerItem> {
+               private static final long serialVersionUID = 1L;
+               Long roomId = null;
+
+               FilesTreeProvider(Long roomId) {
+                       this.roomId = roomId;
+               }
+               
+               @Override
+               public void detach() {
+                       // TODO LDM should be used
+               }
+
+               @Override
+               public boolean hasChildren(FileExplorerItem node) {
+                       return node.getId() <= 0 || Type.Folder == 
node.getType();
+               }
+
+               @Override
+               public Iterator<? extends FileExplorerItem> 
getChildren(FileExplorerItem node) {
+                       FileExplorerItemDao dao = 
getBean(FileExplorerItemDao.class);
+                       List<FileExplorerItem> list = null;
+                       if (node.getId() == 0) {
+                               list = dao.getByOwner(node.getOwnerId());
+                       } else if (node.getId() < 0) {
+                               list = dao.getByRoom(roomId);
+                       } else {
+                               list = dao.getByParent(node.getId());
+                       }
+                       return list.iterator();
+               }
+
+               @Override
+               public IModel<FileExplorerItem> model(FileExplorerItem object) {
+                       // TODO LDM should be used
+                       return Model.of(object);
+               }
+
+               @Override
+               public Iterator<? extends FileExplorerItem> getRoots() {
+                       FileExplorerItem f = new FileExplorerItem();
+                       f.setRoomId(roomId);
+                       f.setType(Type.Folder);
+                       if (roomId == null) {
+                               f.setId(0L);
+                               f.setOwnerId(getUserId());
+                               f.setName(Application.getString(706));
+                       } else {
+                               f.setId(-roomId);
+                               f.setName(Application.getString(707));
+                       }
+                       return Arrays.asList(f).iterator();
+               }
+       }
+}

Added: 
openmeetings/application/trunk/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/sidebar/RoomSidebar.html
URL: 
http://svn.apache.org/viewvc/openmeetings/application/trunk/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/sidebar/RoomSidebar.html?rev=1739141&view=auto
==============================================================================
--- 
openmeetings/application/trunk/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/sidebar/RoomSidebar.html
 (added)
+++ 
openmeetings/application/trunk/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/sidebar/RoomSidebar.html
 Thu Apr 14 17:08:51 2016
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+  
+      http://www.apache.org/licenses/LICENSE-2.0
+         
+  Unless required by applicable law or agreed to in writing,
+  software distributed under the License is distributed on an
+  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  KIND, either express or implied.  See the License for the
+  specific language governing permissions and limitations
+  under the License.
+  
+-->
+<html xmlns:wicket="http://wicket.apache.org";>
+<wicket:panel>
+       <div class="tabs" wicket:id="tabs"></div>
+       
+       <wicket:fragment wicket:id="user-panel">
+               <div class="user list">
+                       <div wicket:id="user" class="user ui-corner-all 
ui-widget-content">
+                               <div wicket:id="name" class="user name"></div>
+                               <div class="user actions">
+                                       <span wicket:id="privateChat" 
class="private-chat om-icon align-right clickable" wicket:message="title:1493" 
onclick="startPrivateChat($(this));"></span>
+                                       <div class="clear"></div>
+                               </div>
+                       </div>
+               </div>
+       </wicket:fragment>
+       
+       <wicket:fragment wicket:id="file-panel">
+               <div class="file list" wicket:id="tree"></div>
+       </wicket:fragment>
+</wicket:panel>
+</html>

Added: 
openmeetings/application/trunk/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/sidebar/RoomSidebar.java
URL: 
http://svn.apache.org/viewvc/openmeetings/application/trunk/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/sidebar/RoomSidebar.java?rev=1739141&view=auto
==============================================================================
--- 
openmeetings/application/trunk/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/sidebar/RoomSidebar.java
 (added)
+++ 
openmeetings/application/trunk/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/sidebar/RoomSidebar.java
 Thu Apr 14 17:08:51 2016
@@ -0,0 +1,162 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License") +  you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.openmeetings.web.room.sidebar;
+
+import static org.apache.openmeetings.web.app.Application.getBean;
+import static org.apache.openmeetings.web.app.Application.getRoomUsers;
+import static org.apache.openmeetings.web.app.WebSession.getUserId;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import org.apache.openmeetings.db.dao.user.UserDao;
+import org.apache.openmeetings.db.entity.room.Room;
+import org.apache.openmeetings.db.entity.user.User;
+import org.apache.openmeetings.web.app.Client;
+import org.apache.openmeetings.web.room.RoomPanel;
+import org.apache.wicket.behavior.AttributeAppender;
+import org.apache.wicket.core.request.handler.IPartialPageRequestHandler;
+import org.apache.wicket.extensions.markup.html.tabs.ITab;
+import org.apache.wicket.markup.html.WebMarkupContainer;
+import org.apache.wicket.markup.html.basic.Label;
+import org.apache.wicket.markup.html.list.ListItem;
+import org.apache.wicket.markup.html.list.ListView;
+import org.apache.wicket.markup.html.panel.Fragment;
+import org.apache.wicket.markup.html.panel.Panel;
+import org.apache.wicket.model.IModel;
+import org.apache.wicket.model.Model;
+
+import com.googlecode.wicket.jquery.ui.widget.tabs.TabbedPanel;
+
+public class RoomSidebar extends Panel {
+       private static final long serialVersionUID = 1L;
+       private final RoomPanel room;
+       private final TabbedPanel tabs;
+       private final ITab userTab;
+       private final ITab fileTab;
+       private boolean showFiles;
+       private final ListView<RoomClient> users = new 
ListView<RoomClient>("user", new ArrayList<RoomClient>()) {
+               private static final long serialVersionUID = 1L;
+
+               @Override
+               protected void populateItem(ListItem<RoomClient> item) {
+                       RoomClient rc = item.getModelObject();
+                       item.setMarkupId(String.format("user%s", 
rc.c.getUid()));
+                       item.add(new Label("name", rc.u.getFirstname() + " " + 
rc.u.getLastname()));
+                       item.add(AttributeAppender.append("data-userid", 
rc.u.getId()));
+                       item.add(new 
WebMarkupContainer("privateChat").setVisible(!room.getRoom().isChatHidden() && 
getUserId() != rc.u.getId()));
+                       if (room.getClient() != null && 
rc.c.getUid().equals(room.getClient().getUid())) {
+                               item.add(AttributeAppender.append("class", 
"current"));
+                       }
+               }
+       };
+       
+       public RoomSidebar(String id, final RoomPanel room) {
+               super(id);
+               this.room = room;
+               Room r = room.getRoom();
+               showFiles = !r.getHideFilesExplorer();//TODO add moderation 
check
+               
+               userTab = new ITab() {
+                       private static final long serialVersionUID = 1L;
+
+                       @Override
+                       public boolean isVisible() {
+                               return true;
+                       }
+                       
+                       @Override
+                       public IModel<String> getTitle() {
+                               return Model.of(getString("613"));
+                       }
+                       
+                       @Override
+                       public WebMarkupContainer getPanel(String containerId) {
+                               return new UserFragment(containerId, 
"user-panel");
+                       }
+               };
+               fileTab = new ITab() {
+                       private static final long serialVersionUID = 1L;
+
+                       @Override
+                       public boolean isVisible() {
+                               return showFiles;
+                       }
+                       
+                       @Override
+                       public IModel<String> getTitle() {
+                               return Model.of(getString("614"));
+                       }
+                       
+                       @Override
+                       public WebMarkupContainer getPanel(String containerId) {
+                               return new FileFragment(containerId, 
"file-panel");
+                       }
+               };
+               add(tabs = new TabbedPanel("tabs", Arrays.asList(userTab, 
fileTab)).setActiveTab(r.isFilesOpened() ? 1 : 0));
+       }
+       
+       public class UserFragment extends Fragment {
+               private static final long serialVersionUID = 1L;
+
+               public UserFragment(String id, String markupId) {
+            super(id, markupId, RoomSidebar.this);
+            add(users.setList(getUsers()));
+               }
+       }
+       
+       public class FileFragment extends Fragment {
+               private static final long serialVersionUID = 1L;
+
+               public FileFragment(String id, String markupId) {
+            super(id, markupId, RoomSidebar.this);
+            add(new RoomFilePanel("tree", room.getRoom().getId()));
+        }
+       }
+
+       private List<RoomClient> getUsers() {
+               List<RoomClient> list = new ArrayList<>();
+               for (Client cl : getRoomUsers(room.getRoom().getId())) {
+                       list.add(new RoomClient(cl));
+               }
+               return list;
+       }
+       
+       static class RoomClient implements Serializable {
+               private static final long serialVersionUID = 1L;
+               private final Client c;
+               private final User u;
+               
+               RoomClient(Client c) {
+                       this.c = c;
+                       this.u = getBean(UserDao.class).get(c.getUserId());
+               }
+       }
+       
+       public void updateUsers(IPartialPageRequestHandler handler) {
+               users.setList(getUsers());
+               handler.add(tabs);
+       }
+
+       public boolean isShowFiles() {
+               return showFiles;
+       }
+}

Modified: 
openmeetings/application/trunk/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/swf-functions.js
URL: 
http://svn.apache.org/viewvc/openmeetings/application/trunk/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/swf-functions.js?rev=1739141&r1=1739140&r2=1739141&view=diff
==============================================================================
--- 
openmeetings/application/trunk/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/swf-functions.js
 (original)
+++ 
openmeetings/application/trunk/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/swf-functions.js
 Thu Apr 14 17:08:51 2016
@@ -27,7 +27,6 @@ function initSwf(swfurl) {
                        __lzminimumversion : 8
                };
        var options = $.extend({}, general, {allowfullscreen : 'true'});
-       $('#header, #topControls, #chatPanel').hide();
        $('div[id="contents"], div[id="contents"] > div').css('height', '100%');
        var embed = $('<embed>').attr('quality', 'high').attr('bgcolor', 
options.bgcolor)
                .attr('src', "public/" + options.url)

Modified: 
openmeetings/application/trunk/openmeetings-web/src/main/java/org/apache/openmeetings/web/user/ChatPanel.java
URL: 
http://svn.apache.org/viewvc/openmeetings/application/trunk/openmeetings-web/src/main/java/org/apache/openmeetings/web/user/ChatPanel.java?rev=1739141&r1=1739140&r2=1739141&view=diff
==============================================================================
--- 
openmeetings/application/trunk/openmeetings-web/src/main/java/org/apache/openmeetings/web/user/ChatPanel.java
 (original)
+++ 
openmeetings/application/trunk/openmeetings-web/src/main/java/org/apache/openmeetings/web/user/ChatPanel.java
 Thu Apr 14 17:08:51 2016
@@ -55,6 +55,7 @@ import org.apache.wicket.ajax.json.JSONE
 import org.apache.wicket.ajax.json.JSONObject;
 import 
org.apache.wicket.authroles.authorization.strategies.role.annotations.AuthorizeInstantiation;
 import org.apache.wicket.behavior.Behavior;
+import org.apache.wicket.core.request.handler.IPartialPageRequestHandler;
 import org.apache.wicket.markup.head.CssHeaderItem;
 import org.apache.wicket.markup.head.IHeaderResponse;
 import org.apache.wicket.markup.head.JavaScriptHeaderItem;
@@ -189,7 +190,7 @@ public class ChatPanel extends BasePanel
 
        public void roomEnter(Room r, AjaxRequestTarget target) {
                if (r.isChatHidden()) {
-                       target.add(setVisible(false));
+                       toggle(target, false);
                        return;
                }
                StringBuilder sb = new StringBuilder();
@@ -204,6 +205,18 @@ public class ChatPanel extends BasePanel
                target.appendJavaScript(sb);
        }
        
+       public void roomExit(Room r, IPartialPageRequestHandler handler) {
+               if (r.isChatHidden()) {
+                       return;
+               }
+               
handler.appendJavaScript(String.format("removeChatTab('%1$s%2$d');", 
ID_ROOM_PREFIX, r.getId()));
+       }
+       
+       public void toggle(IPartialPageRequestHandler handler, boolean visible) 
{
+               handler.add(setVisible(visible));
+               handler.appendJavaScript("reinit();");
+       }
+       
        @Override
        public void renderHead(IHeaderResponse response) {
                super.renderHead(response);

Modified: 
openmeetings/application/trunk/openmeetings-web/src/main/java/org/apache/openmeetings/web/user/chat.js
URL: 
http://svn.apache.org/viewvc/openmeetings/application/trunk/openmeetings-web/src/main/java/org/apache/openmeetings/web/user/chat.js?rev=1739141&r1=1739140&r2=1739141&view=diff
==============================================================================
--- 
openmeetings/application/trunk/openmeetings-web/src/main/java/org/apache/openmeetings/web/user/chat.js
 (original)
+++ 
openmeetings/application/trunk/openmeetings-web/src/main/java/org/apache/openmeetings/web/user/chat.js
 Thu Apr 14 17:08:51 2016
@@ -37,6 +37,9 @@ $(function() {
                        }
                }
        });
+       reinit();
+});
+function reinit() {
        chatTabs = $("#chatTabs").tabs({
                activate: function(event, ui) {
                        $('#activeChatTab').val(ui.newPanel[0].id);
@@ -48,7 +51,7 @@ $(function() {
                $("#" + panelId).remove();
                chatTabs.tabs("refresh");
        });
-});
+}
 function openChat() {
        if ($('#chatPanel').height() < 24) {
                $('#chat .control.block 
.ui-icon').removeClass('ui-icon-carat-1-n').addClass('ui-icon-carat-1-s');
@@ -74,7 +77,10 @@ function activateTab(id) {
        chatTabs.tabs("option", "active", chatTabs.find('a[href="#' + id + 
'"]').parent().index());
 }
 function addChatTab(id, label) {
-       if ($('#chat').length < 1 || $('#' + id).length > 0) {
+       if (!$("#chatTabs").data("ui-tabs")) {
+               reinit();
+       }
+       if ($('#chat').length < 1 || $('#' + id).length) {
                return;
        }
        var li = $(tabTemplate.replace(/#\{href\}/g, "#" + 
id).replace(/#\{label\}/g, label));
@@ -86,6 +92,11 @@ function addChatTab(id, label) {
        chatTabs.tabs("refresh");
        activateTab(id);
 }
+function removeChatTab(id) {
+       $('li[aria-controls="' + id + '"]').remove();
+       $('#' + id).remove();
+       chatTabs.tabs("refresh");
+}
 function addChatMessage(m) {
        if ($('#chat').length > 0 && m && m.type == "chat") {
                var msg;



Reply via email to