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
}
});