You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openmeetings.apache.org by so...@apache.org on 2017/07/02 16:03:44 UTC

openmeetings git commit: [OPENMEETINGS-1639] seems to be implemented

Repository: openmeetings
Updated Branches:
  refs/heads/master 568c47ac6 -> dd043e069


[OPENMEETINGS-1639] seems to be implemented


Project: http://git-wip-us.apache.org/repos/asf/openmeetings/repo
Commit: http://git-wip-us.apache.org/repos/asf/openmeetings/commit/dd043e06
Tree: http://git-wip-us.apache.org/repos/asf/openmeetings/tree/dd043e06
Diff: http://git-wip-us.apache.org/repos/asf/openmeetings/diff/dd043e06

Branch: refs/heads/master
Commit: dd043e06962a4d3f57290f6bc6414b06b14ed1c2
Parents: 568c47a
Author: Maxim Solodovnik <so...@gmail.com>
Authored: Sun Jul 2 23:03:34 2017 +0700
Committer: Maxim Solodovnik <so...@gmail.com>
Committed: Sun Jul 2 23:03:34 2017 +0700

----------------------------------------------------------------------
 .../openmeetings/db/dto/room/Whiteboard.java    |   8 +-
 .../openmeetings/web/common/MainPanel.java      |  10 +-
 .../openmeetings/web/room/wb/UndoObject.java    |  61 +++++++++
 .../openmeetings/web/room/wb/WbPanel.java       | 129 ++++++++++++++++---
 .../org/apache/openmeetings/web/room/wb/wb.js   | 117 ++++++++++-------
 5 files changed, 249 insertions(+), 76 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/openmeetings/blob/dd043e06/openmeetings-db/src/main/java/org/apache/openmeetings/db/dto/room/Whiteboard.java
----------------------------------------------------------------------
diff --git a/openmeetings-db/src/main/java/org/apache/openmeetings/db/dto/room/Whiteboard.java b/openmeetings-db/src/main/java/org/apache/openmeetings/db/dto/room/Whiteboard.java
index be67d0e..393f608 100644
--- a/openmeetings-db/src/main/java/org/apache/openmeetings/db/dto/room/Whiteboard.java
+++ b/openmeetings-db/src/main/java/org/apache/openmeetings/db/dto/room/Whiteboard.java
@@ -102,8 +102,8 @@ public class Whiteboard {
 		return roomItems;
 	}
 
-	public void put(String uid, JSONObject obj) {
-		roomItems.put(uid, obj);
+	public JSONObject put(String uid, JSONObject obj) {
+		return roomItems.put(uid, obj);
 	}
 
 	public JSONObject get(String uid) {
@@ -114,8 +114,8 @@ public class Whiteboard {
 		return roomItems.entrySet();
 	}
 
-	public void remove(Object oid) {
-		roomItems.remove(oid);
+	public JSONObject remove(Object oid) {
+		return roomItems.remove(oid);
 	}
 
 	public String getName() {

http://git-wip-us.apache.org/repos/asf/openmeetings/blob/dd043e06/openmeetings-web/src/main/java/org/apache/openmeetings/web/common/MainPanel.java
----------------------------------------------------------------------
diff --git a/openmeetings-web/src/main/java/org/apache/openmeetings/web/common/MainPanel.java b/openmeetings-web/src/main/java/org/apache/openmeetings/web/common/MainPanel.java
index 50afb36..edd8c9f 100644
--- a/openmeetings-web/src/main/java/org/apache/openmeetings/web/common/MainPanel.java
+++ b/openmeetings-web/src/main/java/org/apache/openmeetings/web/common/MainPanel.java
@@ -102,11 +102,11 @@ public class MainPanel extends Panel {
 	private static final WebMarkupContainer EMPTY = new WebMarkupContainer(CHILD_ID);
 	public static final String PARAM_USER_ID = "userId";
 	private String uid = null;
-	private final MenuPanel menu;
+	private final MenuPanel menu = new MenuPanel("menu", getMainMenu());
 	private final WebMarkupContainer topControls = new WebMarkupContainer("topControls");
 	private final WebMarkupContainer topLinks = new WebMarkupContainer("topLinks");
-	private final MarkupContainer contents;
-	private final ChatPanel chat;
+	private final MarkupContainer contents = new WebMarkupContainer("contents");
+	private final ChatPanel chat = new ChatPanel("chatPanel");
 	private final MessageDialog newMessage;
 	private final UserInfoDialog userInfo;
 	private BasePanel panel;
@@ -128,9 +128,7 @@ public class MainPanel extends Panel {
 		super(id);
 		this.panel = _panel;
 		setOutputMarkupId(true);
-		menu = new MenuPanel("menu", getMainMenu());
-		contents = new WebMarkupContainer("contents");
-		add(chat = new ChatPanel("chatPanel"));
+		add(chat);
 		add(newMessage = new MessageDialog("newMessageDialog", new CompoundPropertyModel<>(new PrivateMessage())) {
 			private static final long serialVersionUID = 1L;
 

http://git-wip-us.apache.org/repos/asf/openmeetings/blob/dd043e06/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/wb/UndoObject.java
----------------------------------------------------------------------
diff --git a/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/wb/UndoObject.java b/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/wb/UndoObject.java
new file mode 100644
index 0000000..08b9134
--- /dev/null
+++ b/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/wb/UndoObject.java
@@ -0,0 +1,61 @@
+/*
+ * 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.wb;
+
+import java.io.Serializable;
+
+import org.apache.openmeetings.util.NullStringer;
+
+import com.github.openjson.JSONArray;
+import com.github.openjson.JSONObject;
+
+public class UndoObject implements Serializable {
+	private static final long serialVersionUID = 1L;
+
+	public enum Type {
+		add
+		, remove
+		, modify
+	}
+	private final Type type;
+	private final String object;
+
+	public UndoObject(Type type, JSONObject obj) {
+		this.type = type;
+		this.object = obj.toString(new NullStringer());
+	}
+
+	public UndoObject(Type type, JSONArray arr) {
+		this.type = type;
+		this.object = arr.toString(new NullStringer());
+	}
+
+	public Type getType() {
+		return type;
+	}
+
+	public String getObject() {
+		return object;
+	}
+
+	@Override
+	public String toString() {
+		return "UndoObject [type=" + type + "]";
+	}
+}

http://git-wip-us.apache.org/repos/asf/openmeetings/blob/dd043e06/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/wb/WbPanel.java
----------------------------------------------------------------------
diff --git a/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/wb/WbPanel.java b/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/wb/WbPanel.java
index e70e410..3bd23a9 100644
--- a/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/wb/WbPanel.java
+++ b/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/wb/WbPanel.java
@@ -30,8 +30,13 @@ import java.io.File;
 import java.io.IOException;
 import java.nio.file.Files;
 import java.util.Arrays;
+import java.util.Deque;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.Map;
 import java.util.Map.Entry;
 import java.util.UUID;
+import java.util.function.Function;
 import java.util.function.Predicate;
 
 import org.apache.openmeetings.core.data.whiteboard.WhiteboardCache;
@@ -86,6 +91,7 @@ public class WbPanel extends Panel {
 	private static final int UPLOAD_WB_TOP = 0;
 	private static final int DEFAULT_WIDTH = 640;
 	private static final int DEFAULT_HEIGHT = 480;
+	private static final int UNDO_SIZE = 20;
 	public static final String FUNC_ACTION = "wbAction";
 	public static final String PARAM_ACTION = "action";
 	public static final String PARAM_OBJ = "obj";
@@ -106,7 +112,9 @@ public class WbPanel extends Panel {
 		, clearSlide
 		, save
 		, load
+		, undo
 	}
+	private final Map<Long, Deque<UndoObject>> undoList = new HashMap<>();
 	private final AbstractDefaultAjaxBehavior wbAction = new AbstractDefaultAjaxBehavior() {
 		private static final long serialVersionUID = 1L;
 
@@ -122,7 +130,8 @@ public class WbPanel extends Panel {
 				StringValue sv = getRequest().getRequestParameters().getParameterValue(PARAM_OBJ);
 				JSONObject obj = sv.isEmpty() ? new JSONObject() : new JSONObject(sv.toString());
 				if (Action.createObj == a || Action.modifyObj == a) {
-					if ("pointer".equals(obj.getJSONObject("obj").getString("type"))) {
+					JSONObject o = obj.optJSONObject("obj");
+					if (o != null && "pointer".equals(o.getString("type"))) {
 						sendWbOthers(a, obj);
 						return;
 					}
@@ -181,31 +190,41 @@ public class WbPanel extends Panel {
 							Whiteboard wb = getBean(WhiteboardCache.class).get(roomId).get(obj.getLong("wbId"));
 							JSONObject o = obj.getJSONObject("obj");
 							wb.put(o.getString("uid"), o);
+							addUndo(wb.getId(), new UndoObject(UndoObject.Type.add, o));
 							sendWbOthers(Action.createObj, obj);
 						}
 							break;
 						case modifyObj:
 						{
 							Whiteboard wb = getBean(WhiteboardCache.class).get(roomId).get(obj.getLong("wbId"));
-							JSONObject o = obj.getJSONObject("obj");
-							JSONArray arr = o.optJSONArray("objects");
-							if (arr == null) {
-								wb.put(o.getString("uid"), o);
-							} else {
-								for (int i = 0; i < arr.length(); ++i) {
-									JSONObject _o = arr.getJSONObject(i);
-									wb.put(_o.getString("uid"), _o);
-								}
+							JSONArray arr = obj.getJSONArray("obj");
+							JSONArray undo = new JSONArray();
+							for (int i = 0; i < arr.length(); ++i) {
+								JSONObject _o = arr.getJSONObject(i);
+								String uid = _o.getString("uid");
+								undo.put(wb.get(uid));
+								wb.put(uid, _o);
+							}
+							if (arr.length() != 0) {
+								addUndo(wb.getId(), new UndoObject(UndoObject.Type.modify, undo));
 							}
 							sendWbOthers(Action.modifyObj, obj);
 						}
+							break;
 						case deleteObj:
 						{
 							Whiteboard wb = getBean(WhiteboardCache.class).get(roomId).get(obj.getLong("wbId"));
 							JSONArray arr = obj.getJSONArray("obj");
+							JSONArray undo = new JSONArray();
 							for (int i = 0; i < arr.length(); ++i) {
 								JSONObject _o = arr.getJSONObject(i);
-								wb.remove(_o.getString("uid"));
+								JSONObject u = wb.remove(_o.getString("uid"));
+								if (u != null) {
+									undo.put(u);
+								}
+							}
+							if (undo.length() != 0) {
+								addUndo(wb.getId(), new UndoObject(UndoObject.Type.remove, undo));
 							}
 							sendWbAll(Action.deleteObj, obj);
 						}
@@ -213,7 +232,17 @@ public class WbPanel extends Panel {
 						case clearSlide:
 						{
 							Whiteboard wb = getBean(WhiteboardCache.class).get(roomId).get(obj.getLong("wbId"));
-							wb.entrySet().removeIf(e -> e.getValue().optInt("slide", -1) == obj.getInt("slide"));
+							JSONArray arr = new JSONArray();
+							wb.entrySet().removeIf(e -> {
+									boolean match = e.getValue().optInt("slide", -1) == obj.getInt("slide");
+									if (match) {
+										arr.put(e);
+									}
+									return match;
+								});
+							if (arr.length() != 0) {
+								addUndo(wb.getId(), new UndoObject(UndoObject.Type.remove, arr));
+							}
 							sendWbAll(Action.clearSlide, obj);
 						}
 							break;
@@ -221,6 +250,25 @@ public class WbPanel extends Panel {
 							wb2save = obj.getLong("wbId");
 							fileName.open(target);
 							break;
+						case undo:
+						{
+							Long wbId = obj.getLong("wbId");
+							UndoObject uo = getUndo(wbId);
+							if (uo != null) {
+								switch (uo.getType()) {
+									case add:
+										sendWbAll(Action.deleteObj, obj.put("obj", new JSONArray().put(new JSONObject(uo.getObject()))));
+										break;
+									case remove:
+										sendWbAll(Action.createObj, obj.put("obj", new JSONArray(uo.getObject())));
+										break;
+									case modify:
+										sendWbAll(Action.modifyObj, obj.put("obj", new JSONArray(uo.getObject())));
+										break;
+								}
+							}
+						}
+							break;
 						default:
 							break;
 					}
@@ -367,8 +415,9 @@ public class WbPanel extends Panel {
 		}
 		return _file;
 	}
+
 	private JSONObject addFileUrl(String ruid, JSONObject _file, FileItem fi, Client c) {
-		JSONObject file = new JSONObject(_file, JSONObject.getNames(_file)); //FIXME TODO openjson 1.0.2
+		JSONObject file = new JSONObject(_file.toString(new NullStringer()));
 		final FileSystemResourceReference ref;
 		final PageParameters pp = new PageParameters()
 				.add("id", fi.getId()).add("uid", c.getUid())
@@ -397,7 +446,24 @@ public class WbPanel extends Panel {
 		return file;
 	}
 
+	private static JSONArray getArray(JSONObject wb, Function<JSONObject, JSONObject> postprocess) {
+		JSONObject items = wb.getJSONObject("roomItems");
+		JSONArray arr = new JSONArray();
+		for (String uid : items.keySet()) {
+			JSONObject o = items.getJSONObject(uid);
+			if (postprocess != null) {
+				o = postprocess.apply(o);
+			}
+			arr.put(o);
+		}
+		return arr;
+	}
+
 	private void clearAll(Whiteboard wb) {
+		JSONArray arr = getArray(wb.toJson(), null);
+		if (arr.length() != 0) {
+			addUndo(wb.getId(), new UndoObject(UndoObject.Type.remove, arr));
+		}
 		wb.clear();
 		sendWbAll(Action.clearAll, new JSONObject().put("wbId", wb.getId()));
 	}
@@ -416,12 +482,7 @@ public class WbPanel extends Panel {
 					File f = fi.getFile();
 					if (f.exists() && f.isFile()) {
 						try (BufferedReader br = Files.newBufferedReader(f.toPath())) {
-							JSONObject items = new JSONObject(new JSONTokener(br)).getJSONObject("roomItems");
-							JSONArray arr = new JSONArray();
-							for (String uid : items.keySet()) {
-								JSONObject o = items.getJSONObject(uid);
-								arr.put(addFileUrl(wbs.getUid(), o));
-							}
+							JSONArray arr = getArray(new JSONObject(new JSONTokener(br)), (o) -> addFileUrl(wbs.getUid(), o));
 							sendWbAll(Action.load, getObjWbJson(wb.getId(), arr));
 						} catch (Exception e) {
 							log.error("Unexpected error while loading WB", e);
@@ -466,4 +527,34 @@ public class WbPanel extends Panel {
 			}
 		}
 	}
+
+	private void addUndo(Long wbId, UndoObject u) {
+		if (wbId == null) {
+			return;
+		}
+		if (!undoList.containsKey(wbId)) {
+			undoList.put(wbId, new LimitedLinkedList<>());
+		}
+		undoList.get(wbId).push(u);
+	}
+
+	private UndoObject getUndo(Long wbId) {
+		if (wbId == null || !undoList.containsKey(wbId)) {
+			return null;
+		}
+		Deque<UndoObject> deq = undoList.get(wbId);
+		return deq.isEmpty() ? null : deq.pop();
+	}
+
+	private static class LimitedLinkedList<T> extends LinkedList<T> {
+		private static final long serialVersionUID = 1L;
+
+		@Override
+		public void push(T e) {
+			super.push(e);
+			while (size() > UNDO_SIZE) {
+				removeLast();
+			}
+		}
+	}
 }

http://git-wip-us.apache.org/repos/asf/openmeetings/blob/dd043e06/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/wb/wb.js
----------------------------------------------------------------------
diff --git a/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/wb/wb.js b/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/wb/wb.js
index 6c8a7be..bf0074d 100644
--- a/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/wb/wb.js
+++ b/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/wb/wb.js
@@ -513,7 +513,7 @@ var Wb = function() {
 	const ACTIVE = 'active';
 	const BUMPER = 100;
 	var wb = {id: -1}, a, t, s, canvases = [], mode, slide = 0, width = 0, height = 0
-			, minWidth = 0, minHeight = 0, role = null;
+			, minWidth = 0, minHeight = 0, role = null, extraProps = ['uid', 'fileId', 'fileType', 'count', 'slide'];
 
 	function getBtn(m) {
 		return !!t ? t.find(".om-icon." + (m || mode)) : null;
@@ -625,6 +625,9 @@ var Wb = function() {
 				t.find('.om-icon.save').click(function() {
 					wbAction('save', JSON.stringify({wbId: wb.id}));
 				});
+				t.find('.om-icon.undo').click(function() {
+					wbAction('undo', JSON.stringify({wbId: wb.id}));
+				});
 				s.find('.wb-prop-b, .wb-prop-i')
 					.button()
 					.click(function() {
@@ -721,14 +724,16 @@ var Wb = function() {
 	function _removeHandler(o) {
 		var __o = _findObject(o);
 		if (!!__o) {
-			canvases[o.slide].remove(__o);
+			var cnvs = canvases[o.slide];
+			if (!!cnvs) {
+				cnvs.discardActiveGroup();
+				cnvs.remove(__o);
+			}
 		}
 	}
 	function _modifyHandler(_o) {
 		_removeHandler(_o);
-		var canvas = canvases[_o.slide];
-		_o.selectable = canvas.selection;
-		canvas.add(_o);
+		_createHandler(_o);
 	}
 	function _createHandler(_o) {
 		switch (_o.fileType) {
@@ -803,7 +808,7 @@ var Wb = function() {
 	};
 
 	function toOmJson(o) {
-		return o.toJSON(['uid', 'fileId', 'fileType', 'count', 'slide']);
+		return o.toJSON(extraProps);
 	}
 	//events
 	function wbObjCreatedHandler(o) {
@@ -843,9 +848,22 @@ var Wb = function() {
 		if (role === NONE && o.type != 'pointer') return;
 
 		o.includeDefaultValues = false;
+		var items = [];
+		if ("group" === o.type) {
+			o.clone(function(_o) {
+				// ungrouping
+				_o.includeDefaultValues = false;
+				var _items = _o.destroy().getObjects();
+				for (var i = 0; i < _items.length; ++i) {
+					items.push(toOmJson(_items[i]));
+				}
+			}, extraProps);
+		} else {
+			items.push(toOmJson(o));
+		}
 		wbAction('modifyObj', JSON.stringify({
 			wbId: wb.id
-			, obj: toOmJson(o)
+			, obj: items
 		}));
 	};
 	function objSelectedHandler(e) {
@@ -898,19 +916,21 @@ var Wb = function() {
 		console.log('Text Changed', obj);
 	};*/
 	function setHandlers(canvas) {
+		// off everything first to prevent duplicates
+		canvas.off({
+			'wb:object:created': wbObjCreatedHandler
+			, 'object:modified': objModifiedHandler
+			, 'object:added': objAddedHandler
+			, 'object:selected': objSelectedHandler
+			, 'path:created': pathCreatedHandler
+			//, 'text:editing:exited': textEditedHandler
+			//, 'text:changed': textChangedHandler
+		});
 		canvas.on({
 			'wb:object:created': wbObjCreatedHandler
 			, 'object:modified': objModifiedHandler
 		});
-		if (role === NONE) {
-			canvas.off({
-				'object:added': objAddedHandler
-				, 'object:selected': objSelectedHandler
-				, 'path:created': pathCreatedHandler
-				//, 'text:editing:exited': textEditedHandler
-				//, 'text:changed': textChangedHandler
-			});
-		} else {
+		if (role !== NONE) {
 			canvas.on({
 				'object:added': objAddedHandler
 				, 'object:selected': objSelectedHandler
@@ -1002,26 +1022,38 @@ var Wb = function() {
 		}
 	};
 	wb.createObj = function(o) {
-		switch(o.type) {
-			case 'pointer':
+		var arr = [];
+		if (!Array.isArray(o)) {
+			if ('pointer' === o.type) {
 				APointer().create(canvases[o.slide], o);
-				break;
-			default:
-				var __o = _findObject(o);
-				if (!__o) {
-					_createObject([o], _createHandler);
-				}
-				/*
-				 * https://jsfiddle.net/l2aelba/kro7h6rv/2/
-				if ('Video' === o.fileType || 'Recording' === o.fileType) {
-					fabric.util.requestAnimFrame(function render() {
-						canvas.renderAll();
-						fabric.util.requestAnimFrame(render);
-					});
-				}
-				*/
-				break;
+				return;
+			}
+			switch(o.type) {
+				case 'pointer':
+					APointer().create(canvases[o.slide], o);
+					break;
+				default:
+					var __o = _findObject(o);
+					if (!__o) {
+						arr.push(o);
+					}
+					break;
+			}
+		} else {
+			arr = o;
+		}
+		if (arr.length > 0) {
+			_createObject(arr, _createHandler);
+		}
+		/* FIXME TODO animation
+		 * https://jsfiddle.net/l2aelba/kro7h6rv/2/
+		if ('Video' === o.fileType || 'Recording' === o.fileType) {
+			fabric.util.requestAnimFrame(function render() {
+				canvas.renderAll();
+				fabric.util.requestAnimFrame(render);
+			});
 		}
+		*/
 	};
 	wb.modifyObj = function(o) { //TODO need to be unified
 		switch(o.type) {
@@ -1029,16 +1061,7 @@ var Wb = function() {
 				_modifyHandler(APointer().create(canvases[o.slide], o))
 				break;
 			default:
-				var arr = [o];
-				if (!!o.objects) {
-					arr = o.objects;
-					for (var i = 0; i < arr.length; ++i) {
-						var _o = arr[i];
-						_o.left += o.left;
-						_o.top += o.top;
-					}
-				}
-				_createObject(o.objects || [o], _modifyHandler);
+				_createObject(o, _modifyHandler);
 				break;
 		}
 	};
@@ -1104,8 +1127,8 @@ var WbArea = (function() {
 					var canvas = wb.getCanvas();
 					if (!!canvas) {
 						var arr = [];
-						if (canvas.getActiveGroup()) {
-							canvas.getActiveGroup().forEachObject(function(o){
+						if (!!canvas.getActiveGroup()) {
+							canvas.getActiveGroup().forEachObject(function(o) {
 								arr.push({
 									uid: o.uid
 									, slide: o.slide
@@ -1309,7 +1332,7 @@ $(function() {
 				}
 			}
 		} catch (err) {
-			//console.log(err);
+			console.log(err);
 			//no-op
 		}
 	});