openmeetings-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From solo...@apache.org
Subject svn commit: r1739141 [2/3] - in /openmeetings/application/trunk: ./ openmeetings-core/src/main/java/org/apache/openmeetings/core/converter/ openmeetings-core/src/main/java/org/apache/openmeetings/core/ldap/ openmeetings-core/src/main/java/org/apache/op...
Date Thu, 14 Apr 2016 17:08:52 GMT
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;




Mime
View raw message