106 Commits

Author SHA1 Message Date
Paulo Gustavo Veiga
efe562f057 Minor fix. 2013-02-20 14:20:11 -03:00
Paulo Gustavo Veiga
d2b7b640d9 Fix print issue loading cached maps. 2013-02-20 14:16:00 -03:00
Paulo Gustavo Veiga
79f5e51513 Finish LDAP support. 2013-02-20 13:15:31 -03:00
Paulo Gustavo Veiga
0f605d89f0 Enable security configuration from properties. 2013-02-17 23:10:04 -03:00
Paulo Gustavo Veiga
cb6828c08e Minor fixes
Update Spring 3.1.3 fixed.
2013-02-17 21:26:42 -03:00
Paulo Gustavo Veiga
3ff67910c9 Add LDAP support. 2013-02-17 21:00:08 -03:00
Paulo Gustavo Veiga
51f531f6b4 Fix revert on zip format. 2013-02-13 23:13:27 -03:00
Paulo Gustavo Veiga
fc22dd32a2 Compiles. 2013-02-13 23:08:55 -03:00
Paulo Gustavo Veiga
deca7e51b2 Fix npe. 2013-02-13 23:06:18 -03:00
Paulo Gustavo Veiga
28ffead0a0 Fix npe. 2013-02-13 22:51:55 -03:00
Paulo Gustavo Veiga
d1dfb48be5 Add new files. 2013-02-13 22:46:45 -03:00
Paulo Gustavo Veiga
9360a27f15 Show more rows on history. 2013-02-13 21:41:47 -03:00
Paulo Gustavo Veiga
cc8ff94b10 Fix encoding issue on import. 2013-02-11 13:25:07 -03:00
Paulo Gustavo Veiga
f245116e48 Fix deleted object would be re-saved by cascade (remove deleted object from associations): [com.wisemapping.model.Collaboration#114902]; nested exception is org.hibernate.ObjectDeletedException: deleted object would be re-saved by cascade (remove deleted object from associations): [com.wisemapping.model.Collaboration#114902] 2013-02-10 16:14:32 -03:00
Paulo Gustavo Veiga
7bd87c50ac - Disable cache ... 2013-02-10 15:24:37 -03:00
Paulo Gustavo Veiga
86d5c98ed7 - Fix security issues when the map is loaded from the rest service. Two URL has been defined for each type of access. 2013-02-07 21:56:36 -03:00
Paulo Gustavo Veiga
5d05f21803 - Fix security issues when the map is loaded from the rest service. Two URL has been defined for each type of access. 2013-02-07 21:44:20 -03:00
Paulo Gustavo Veiga
6e2880c8cc - Review security for print. This is required for enable public sharing of maps. The issue is when the map is not public in the editor. 2013-02-03 17:47:48 -03:00
Paulo Gustavo Veiga
87ce3fc0a9 - Print is not public
- Public maps now are shared using REST
2013-02-03 17:33:19 -03:00
Paulo Gustavo Veiga
92849b02eb Finish moving mindmap loading to rest. 2013-02-03 13:47:31 -03:00
Paulo Gustavo Veiga
829655f253 Add dummy parameter when the service is readOnly. 2013-02-03 13:19:24 -03:00
Paulo Gustavo Veiga
b4bdad796e Use the same PersitenceManager for public maps. 2013-02-03 12:54:46 -03:00
Paulo Gustavo Veiga
d52e2c04a6 Fix encoding on returning maps. 2013-02-03 12:51:12 -03:00
Paulo Gustavo Veiga
edc3351fd8 Fix httpBase servlet request property. 2013-02-03 12:38:04 -03:00
Paulo Gustavo Veiga
73a664ab97 Minor fix. 2013-01-31 22:57:49 -03:00
Paulo Gustavo Veiga
cabca992d1 Map are loaded using Rest service. 2013-01-31 22:50:21 -03:00
Paulo Gustavo Veiga
e734ea350c Add /f secuence scape. 2013-01-31 20:27:17 -03:00
Paulo Gustavo Veiga
ac7af5b8f1 Minor fix. 2013-01-31 20:10:50 -03:00
Paulo Gustavo Veiga
43e9f8fcad Fix firefox issue with \b caracters. 2013-01-31 20:01:15 -03:00
Paulo Gustavo Veiga
7a401b648e Copy and Paste of nodes was not working. Fixed. 2013-01-31 15:44:43 -03:00
Paulo Gustavo Veiga
82ff47220d Disable browser cache. 2013-01-31 14:49:04 -03:00
Paulo Gustavo Veiga
f3d88e91c4 Fix typo 2013-01-26 01:07:29 -03:00
Paulo Gustavo Veiga
37419cba66 Fix delete issue removing in hsql. History is now removed in advance. 2013-01-26 00:52:05 -03:00
Paulo Gustavo Veiga
8b0465bda6 Fix null object reference on editor. 2012-12-02 21:59:21 -03:00
Paulo Gustavo Veiga
765b1fc80e Exported images are now centered. 2012-12-02 16:37:09 -03:00
Paulo Gustavo Veiga
0d8b6b210e - Add metadata descriptor to template page
- Add png export tests.
2012-12-01 19:09:31 -03:00
Paulo Gustavo Veiga
d2c287684f Improve img quality export. 2012-12-01 17:58:01 -03:00
Paulo Gustavo Veiga
bad11bea88 Fix freemind import/export notes. 2012-12-01 17:22:54 -03:00
Paulo Gustavo Veiga
6c1188314b Control attributes order for freemind serialization. 2012-12-01 16:25:37 -03:00
Paulo Gustavo Veiga
f4f97d3112 Add disclamer for tutotial video reproduction. 2012-11-30 22:25:45 -03:00
Paulo Gustavo Veiga
a958fcbd6e Minor typo. 2012-11-30 22:11:30 -03:00
Paulo Gustavo Veiga
02b31e463b Add help icon to the toolbar. 2012-11-30 22:08:51 -03:00
Paulo Gustavo Veiga
6fe53446ce Add link to tutorial video. 2012-11-30 22:03:11 -03:00
Paulo Gustavo Veiga
5d62bf520a Fix collapsed nodes. 2012-11-28 22:14:52 -03:00
Paulo Gustavo Veiga
12448fc6cb Central node never can be collapsed. 2012-11-28 22:09:29 -03:00
Paulo Gustavo Veiga
ebd6f886d5 Try to fix issues with encoding. 2012-11-28 21:45:13 -03:00
Paulo Gustavo Veiga
66e4b0fb19 Update to Spring 3.1.2 2012-11-26 10:43:50 -03:00
Paulo Gustavo Veiga
f34ec25610 Add new icon. 2012-11-24 14:36:18 -03:00
Paulo Gustavo Veiga
46264991b9 Pogress SQL fix. 2012-11-24 14:16:49 -03:00
Paulo Gustavo Veiga
b9748ca23a Add some documentation for password reset. 2012-11-24 12:56:12 -03:00
Paulo Gustavo Veiga
fe99c9a238 Fix zoom issue. 2012-11-22 00:46:24 -03:00
Paulo Gustavo Veiga
9f495f1e76 Fix event error on firefox 1.6. 2012-11-22 00:30:49 -03:00
Paulo Gustavo Veiga
dd1698b5d9 Fix sharing. 2012-11-22 00:22:39 -03:00
Paulo Gustavo Veiga
c5bf91a9fe Disable debug info. 2012-11-22 00:12:12 -03:00
Paulo Gustavo Veiga
ac8309819c Fix Firefox issue with null values. 2012-11-22 00:05:46 -03:00
Paulo Gustavo Veiga
e1e9c9ebeb Minot fix. 2012-11-20 00:17:33 -03:00
Paulo Gustavo Veiga
4062b6771c Fix some issues. 2012-11-20 00:11:06 -03:00
Paulo Gustavo Veiga
0cdabba5eb Fix issue in embedded and public view toolbar. 2012-11-20 00:02:42 -03:00
Paulo Gustavo Veiga
064b8f1071 Change add nodes toolbar action. 2012-11-19 23:31:10 -03:00
Paulo Gustavo Veiga
c3dcd8f3a9 Fix i18n encodding issue. 2012-11-19 22:47:20 -03:00
Paulo Gustavo Veiga
b717a5f910 Remove add from editor. 2012-11-19 21:59:40 -03:00
Paulo Gustavo Veiga
1602421544 Another try. 2012-11-19 21:56:39 -03:00
Paulo Gustavo Veiga
fe44da9b43 Move add to right. 2012-11-19 21:49:56 -03:00
Paulo Gustavo Veiga
2a8ae4c397 Change add location. 2012-11-19 21:19:30 -03:00
Paulo Gustavo Veiga
7f7a67872e Reset all edition actions before delete. 2012-11-18 20:58:23 -03:00
Paulo Gustavo Veiga
322b0ba13e Fix wrong debug transformation. 2012-11-18 20:17:16 -03:00
Paulo Gustavo Veiga
0aa2d67698 Add a small add to test. 2012-11-18 19:29:10 -03:00
Paulo Gustavo Veiga
3c0055b767 Disable ads. 2012-11-18 18:54:56 -03:00
Paulo Gustavo Veiga
2549305621 Add more adds . 2012-11-18 13:38:17 -03:00
Paulo Gustavo Veiga
42564b2759 Fix stared issue. 2012-11-18 13:25:57 -03:00
Paulo Gustavo Veiga
032df5fdf4 Do not update map tiemstamp on map metadata modification. 2012-11-17 21:28:23 -03:00
Paulo Gustavo Veiga
dbbe8901b7 Move add to fixed. 2012-11-17 18:00:55 -03:00
Paulo Gustavo Veiga
91f27c4e10 Fix ads on editor. 2012-11-17 17:47:11 -03:00
Paulo Gustavo Veiga
91aeddee70 Avoid scrolling on drag. 2012-11-17 17:18:40 -03:00
Paulo Gustavo Veiga
fab3c96097 Minor fix for add. 2012-11-17 15:57:02 -03:00
Paulo Gustavo Veiga
b89b08b7b3 Add add to login page and editor page. 2012-11-17 15:43:06 -03:00
Paulo Gustavo Veiga
ed37b20dfc Add debug info. 2012-11-17 14:38:34 -03:00
Paulo Gustavo Veiga
f44e616a4b Minor fix. 2012-11-17 13:57:06 -03:00
Paulo Gustavo Veiga
e70f2726a3 Delete command topic. 2012-11-17 13:54:46 -03:00
Paulo Gustavo Veiga
964505abd4 Filter some useless error for debug. 2012-11-17 13:46:02 -03:00
Paulo Gustavo Veiga
ce932e57e0 Fix issue deleting multiple relationships. 2012-11-17 13:42:46 -03:00
Paulo Gustavo Veiga
2ec9e70245 Relationship source position during drag is not positioned in the center anymore. 2012-11-17 12:23:24 -03:00
Paulo Gustavo Veiga
fc6d91f59e Fix relationship central node positioning problem ... 2012-11-17 12:02:59 -03:00
Paulo Gustavo Veiga
f8a6607de9 Fix equals bug. 2012-11-17 09:59:53 -03:00
Paulo Gustavo Veiga
ca0b5bfcbe Undo of a deleted topic keep into account if the nodes are visible or not. 2012-11-17 00:24:17 -03:00
Paulo Gustavo Veiga
be545d7103 Add german message bundle. 2012-11-16 23:44:23 -03:00
Paulo Gustavo Veiga
3832844ee6 Fix german resource. 2012-11-16 23:36:46 -03:00
Paulo Gustavo Veiga
b3234675cc Fix lazy initialization bug. 2012-11-16 23:29:01 -03:00
Paulo Gustavo Veiga
146c6d8a17 Add more debug ... 2012-11-16 23:17:46 -03:00
Paulo Gustavo Veiga
37e11a5b05 Add more debug... 2012-11-16 23:11:45 -03:00
Paulo Gustavo Veiga
ea5f1afa40 Change file encoding to UTF-8. 2012-11-16 23:02:37 -03:00
Paulo Gustavo Veiga
2e0339492d Add german support. 2012-11-16 22:47:18 -03:00
Paulo Gustavo Veiga
f8d6cdebc4 Merge branch 'master' into db-purge 2012-11-16 22:39:19 -03:00
Paulo Gustavo Veiga
58ed80d763 Avoid additional checks ... 2012-11-16 22:37:29 -03:00
Ralf Mueller
61569bc571 Added german language message files. 2012-11-15 16:15:26 +01:00
Paulo Gustavo Veiga
7ba21f85bf Fix 'element could not be removed:[object Object] fixed. 2012-11-14 23:46:28 -03:00
Paulo Gustavo Veiga
2c5f7139d5 Add new priority icons. 2012-11-14 21:19:56 -03:00
Paulo Gustavo Veiga
0c433352c5 Minor fix. 2012-11-14 20:53:59 -03:00
Paulo Gustavo Veiga
07c8a1d8c7 Update session for the same user. 2012-11-14 20:44:59 -03:00
Paulo Gustavo Veiga
6560973237 Replace all User.equals for Collaborator.identityEquality 2012-11-14 20:35:09 -03:00
Paulo Gustavo Veiga
596aeeebc4 Keep fixing user issues. 2012-11-14 20:33:42 -03:00
Paulo Gustavo Veiga
16e59a0879 Fix collaboration equal issue. 2012-11-14 20:17:55 -03:00
Paulo Gustavo Veiga
2861a7b5f9 Fix user comparator. 2012-11-14 20:00:46 -03:00
Paulo Gustavo Veiga
b1172f16cc Fix more lock issues. 2012-11-13 21:01:04 -03:00
Paulo Gustavo Veiga
71762ff629 Add more debug. 2012-11-13 13:44:33 -03:00
Paulo Gustavo Veiga
00fd168489 Keep fixing session issues. 2012-11-13 13:34:35 -03:00
195 changed files with 23959 additions and 2129 deletions

View File

@@ -78,7 +78,7 @@ The following code is an example of how to add attach to the div dragImageNode t
designer.addDraggedNode(event, node);
});
In the example, a new node is created with text "Node Text !!!!" and a note and a link associated to it when the user drop the node. Something to pay attention is the node.setMetadata("{}"), this attributes will be persisted during the serialization. Here you can store all the data you need.
In the example, a new node is created with text "Node Text !!!!" and a note and a link associated to it when the user drop the node. Something to pay attention is the node.setMetadata("{}"), this delegated will be persisted during the serialization. Here you can store all the data you need.
2) Support for dragging Images: Similar to the point 1,drag support is registered to the div dragImageNode.

View File

@@ -8,7 +8,7 @@ BASE_DIR=`pwd`
TARGET_DIR=$BASE_DIR/target
JETTY_DIR=$TARGET_DIR/wisemapping-$WISE_VERSION
WISE_WEBAPP_DIR=$JETTY_DIR/webapps/wisemapping
JETTY_VERSION=8.1.5.v20120716
JETTY_VERSION=8.1.8.v20121106
JETTY_DIST_DIR=jetty-distribution-${JETTY_VERSION}
JETTY_ZIP=${JETTY_DIST_DIR}.zip

14
java.iml Normal file
View File

@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<module org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule="true" type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_6" inherit-compiler-output="false">
<output url="file://$MODULE_DIR$/target/classes" />
<output-test url="file://$MODULE_DIR$/target/test-classes" />
<exclude-output />
<content url="file://$MODULE_DIR$">
<excludeFolder url="file://$MODULE_DIR$/target" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

View File

@@ -228,6 +228,7 @@
<include>layout/EventBus.js</include>
<include>MessageBundle_en.js</include>
<include>MessageBundle_es.js</include>
<include>MessageBundle_de.js</include>
<include>MessageBundle_fr.js</include>
<include>MessageBundle_pt_BR.js</include>
<include>MessageBundle_zh_CN.js</include>

View File

@@ -29,16 +29,12 @@ mindplot.ConnectionLine = new Class({
var ctrlPoints = this._getCtrlPoints(sourceNode, targetNode);
if (targetNode.getType() == mindplot.model.INodeModel.CENTRAL_TOPIC_TYPE) {
line = this._createLine(lineType, mindplot.ConnectionLine.CURVED);
if (line.getType() == "CurvedLine") {
line.setSrcControlPoint(ctrlPoints[0]);
line.setDestControlPoint(ctrlPoints[1]);
}
line.setSrcControlPoint(ctrlPoints[0]);
line.setDestControlPoint(ctrlPoints[1]);
} else {
line = this._createLine(lineType, mindplot.ConnectionLine.SIMPLE_CURVED);
if (line.getType() == "CurvedLine") {
line.setSrcControlPoint(ctrlPoints[0]);
line.setDestControlPoint(ctrlPoints[1]);
}
line.setSrcControlPoint(ctrlPoints[0]);
line.setDestControlPoint(ctrlPoints[1]);
}
// Set line styles ...
var strokeColor = mindplot.ConnectionLine.getStrokeColor();

View File

@@ -440,8 +440,9 @@ mindplot.Designer = new Class({
}
// Execute event ...
var topic = nodes[0];
this._actionDispatcher.shrinkBranch([topic.getId()], !topic.areChildrenShrunken());
if (topic.getType() != mindplot.model.INodeModel.CENTRAL_TOPIC_TYPE) {
this._actionDispatcher.shrinkBranch([topic.getId()], !topic.areChildrenShrunken());
}
},
createChildForSelectedNode:function () {
@@ -697,6 +698,9 @@ mindplot.Designer = new Class({
var targetTopicId = model.getToNode();
var targetTopic = dmodel.findTopicById(targetTopicId);
$assert(targetTopic, "targetTopic could not be found:" + targetTopicId + dmodel.getTopics().map(function (e) {
return e.getId()
}));
// Build relationship line ....
var result = new mindplot.Relationship(sourceTopic, targetTopic, model);
@@ -749,7 +753,16 @@ mindplot.Designer = new Class({
}
},
_resetEdition:function () {
var screenManager = this._workspace.getScreenManager();
screenManager.fireEvent("update");
screenManager.fireEvent("mouseup");
this._relPivot.dispose();
},
deleteSelectedEntities:function () {
// Is there some action in progress ?.
this._resetEdition();
var topics = this.getModel().filterSelectedTopics();
var relation = this.getModel().filterSelectedRelationships();

View File

@@ -252,7 +252,7 @@ mindplot.DesignerKeyboard = new Class({
designer.zoomOut();
},
'ctrl++':function (event) {
'ctrl+=':function (event) {
event.preventDefault();
event.stopPropagation();

View File

@@ -115,14 +115,16 @@ mindplot.DragTopic = new Class({
},
removeFromWorkspace:function (workspace) {
// Remove drag shadow.
workspace.removeChild(this._elem2d);
this._isInWorkspace = false;
if (this._isInWorkspace) {
// Remove drag shadow.
workspace.removeChild(this._elem2d);
// Remove pivot shape. To improve performace it will not be removed. Only the visibility will be changed.
var dragPivot = this._getDragPivot();
dragPivot.setVisibility(false);
// Remove pivot shape. To improve performance it will not be removed. Only the visibility will be changed.
var dragPivot = this._getDragPivot();
dragPivot.setVisibility(false);
this._isInWorkspace = false;
}
},
isInWorkspace:function () {
@@ -130,10 +132,12 @@ mindplot.DragTopic = new Class({
},
addToWorkspace:function (workspace) {
workspace.appendChild(this._elem2d);
var dragPivot = this._getDragPivot();
dragPivot.addToWorkspace(workspace);
this._isInWorkspace = true;
if (!this._isInWorkspace) {
workspace.appendChild(this._elem2d);
var dragPivot = this._getDragPivot();
dragPivot.addToWorkspace(workspace);
this._isInWorkspace = true;
}
},
_getDragPivot:function () {

View File

@@ -102,7 +102,6 @@ mindplot.ImageIcon = new Class({
}
});
mindplot.ImageIcon.prototype.ICON_FAMILIES = [
{"id":"face", "icons":["face_plain", "face_sad", "face_crying", "face_smile", "face_surprise", "face_wink"]},
{"id":"funy", "icons":["funy_angel", "funy_devilish", "funy_glasses", "funy_grin", "funy_kiss", "funy_monkey"]},
@@ -114,6 +113,7 @@ mindplot.ImageIcon.prototype.ICON_FAMILIES = [
{"id":"onoff", "icons":["onoff_clock", "onoff_clock_red", "onoff_add", "onoff_delete", "onoff_status_offline", "onoff_status_online"]},
{"id":"money", "icons":["money_money", "money_dollar", "money_euro", "money_pound", "money_yen", "money_coins", "money_ruby"]},
{"id":"time", "icons":["time_calendar", "time_clock", "time_hourglass"]},
{"id":"number", "icons":["number_1", "number_2", "number_3", "number_4", "number_5", "number_6", "number_7", "number_8", "number_9"]},
{"id":"chart", "icons":["chart_bar", "chart_line", "chart_curve", "chart_pie", "chart_organisation"]},
{"id":"sign", "icons":["sign_warning", "sign_info", "sign_stop", "sign_help", "sign_cancel"]},
{"id":"hard", "icons":["hard_cd", "hard_computer", "hard_controller", "hard_driver_disk", "hard_ipod", "hard_keyboard", "hard_mouse", "hard_printer"]},
@@ -126,7 +126,7 @@ mindplot.ImageIcon.prototype.ICON_FAMILIES = [
{"id":"bullet", "icons":["bullet_black", "bullet_blue", "bullet_green", "bullet_orange", "bullet_red", "bullet_pink", "bullet_purple"]},
{"id":"tag", "icons":["tag_blue", "tag_green", "tag_orange", "tag_red", "tag_pink", "tag_yellow"]},
{"id":"object", "icons":["object_bell", "object_clanbomber", "object_key", "object_pencil", "object_phone", "object_magnifier", "object_clip", "object_music", "object_star", "object_wizard", "object_house", "object_cake", "object_camera", "object_palette", "object_rainbow"]},
{"id":"weather", "icons":["weather_clear-night", "weather_clear", "weather_few-clouds-night", "weather_few-clouds", "weather_overcast", "weather_severe-alert", "weather_showers-scattered", "weather_showers", "weather_snow", "weather_storm"]}
{"id":"weather", "icons":["weather_clear-night", "weather_clear", "weather_few-clouds-night", "weather_few-clouds", "weather_overcast", "weather_severe-alert", "weather_showers-scattered", "weather_showers", "weather_snow", "weather_storm"]},
{"id":"task", "icons":["task_0", "task_25", "task_50", "task_75", "task_100"]}
];

View File

@@ -18,8 +18,10 @@
mindplot.LocalStorageManager = new Class({
Extends:mindplot.PersistenceManager,
initialize:function () {
initialize:function (documentUrl,forceLoad) {
this.parent();
this.documentUrl = documentUrl;
this.forceLoad = forceLoad;
},
saveMapXml:function (mapId, mapXml, pref, saveHistory, events) {
@@ -32,10 +34,10 @@ mindplot.LocalStorageManager = new Class({
loadMapDom:function (mapId) {
var xml = localStorage.getItem(mapId + "-xml");
if (xml == null) {
// Let's try to open one from the local directory ...
if (xml == null || this.forceLoad) {
var xmlRequest = new Request({
url:'samples/' + mapId + '.xml',
url:this.documentUrl.replace("{id}", mapId),
headers:{"Content-Type":"text/plain","Accept":"application/xml"},
method:'get',
async:false,
onSuccess:function (responseText) {

View File

@@ -98,28 +98,7 @@ mindplot.MainTopic = new Class({
},
workoutIncomingConnectionPoint:function (sourcePosition) {
$assert(sourcePosition, 'sourcePoint can not be null');
var pos = this.getPosition();
var size = this.getSize();
var isAtRight = mindplot.util.Shape.isAtRight(sourcePosition, pos);
var result = mindplot.util.Shape.calculateRectConnectionPoint(pos, size, isAtRight);
if (this.getShapeType() == mindplot.model.TopicShape.LINE) {
result.y = result.y + (this.getSize().height / 2);
}
// Move a little the position...
var offset = mindplot.Topic.CONNECTOR_WIDTH / 2;
if (this.getPosition().x > 0) {
result.x = result.x + offset;
} else {
result.x = result.x - offset;
}
result.x = Math.ceil(result.x);
result.y = Math.ceil(result.y);
return result;
return mindplot.util.Shape.workoutIncomingConnectionPoint(this, sourcePosition);
},
workoutOutgoingConnectionPoint:function (targetPosition) {

View File

@@ -191,7 +191,7 @@ mindplot.MultilineTextEditor = new Class({
// Set editor's initial size
var displayFunc = function () {
// Position the editor and set the size...
var textShape = this._topic.getTextShape();
var textShape = topic.getTextShape();
textShape.positionRelativeTo(this._containerElem, {
position:{x:'left', y:'top'},
edge:{x:'left', y:'top'}

View File

@@ -83,14 +83,19 @@ mindplot.Relationship = new Class({
var targetTopic = this._targetTopic;
var targetPosition = targetTopic.getPosition();
if (targetTopic.getType() == mindplot.model.INodeModel.CENTRAL_TOPIC_TYPE) {
targetPosition = mindplot.util.Shape.workoutIncomingConnectionPoint(targetTopic, sourcePosition);
}
var sPos, tPos;
this._line2d.setStroke(2);
var ctrlPoints = this._line2d.getControlPoints();
if (!this._line2d.isDestControlPointCustom() && !this._line2d.isSrcControlPointCustom()) {
var defaultPoints = mindplot.util.Shape.calculateDefaultControlPoints(sourcePosition, targetPosition);
ctrlPoints[0].x = defaultPoints[0].x;
ctrlPoints[0].y = defaultPoints[0].y;
ctrlPoints[1].x = defaultPoints[1].x;
ctrlPoints[1].y = defaultPoints[1].y;
}
@@ -101,6 +106,7 @@ mindplot.Relationship = new Class({
var tpoint = new core.Point();
tpoint.x = parseInt(ctrlPoints[1].x) + parseInt(targetPosition.x);
tpoint.y = parseInt(ctrlPoints[1].y) + parseInt(targetPosition.y);
sPos = mindplot.util.Shape.calculateRelationShipPointCoordinates(sourceTopic, spoint);
tPos = mindplot.util.Shape.calculateRelationShipPointCoordinates(targetTopic, tpoint);

View File

@@ -43,7 +43,9 @@ mindplot.RelationshipPivot = new Class({
this._pivot = new web2d.CurvedLine();
this._pivot.setStyle(web2d.CurvedLine.SIMPLE_LINE);
this._pivot.setFrom(sourcePos.x, sourcePos.y);
var fromPos = this._calculateFromPosition(sourcePos);
this._pivot.setFrom(fromPos.x, fromPos.y);
this._pivot.setTo(targetPos.x, targetPos.y);
this._pivot.setStroke(2, 'solid', strokeColor);
@@ -54,7 +56,6 @@ mindplot.RelationshipPivot = new Class({
this._startArrow.setStrokeWidth(2);
this._startArrow.setFrom(sourcePos.x, sourcePos.y);
this._workspace.appendChild(this._pivot);
this._workspace.appendChild(this._startArrow);
@@ -99,8 +100,13 @@ mindplot.RelationshipPivot = new Class({
var pos = screen.getWorkspaceMousePosition(event);
// Leave the arrow a couple of pixels away from the cursor.
var gapDistance = Math.sign(pos.x - this._sourceTopic.getPosition().x) * 5;
var sourcePosition = this._sourceTopic.getPosition();
var gapDistance = Math.sign(pos.x - sourcePosition.x) * 5;
var sPos = this._calculateFromPosition(pos);
this._pivot.setFrom(sPos.x, sPos.y);
// Update target position ...
this._pivot.setTo(pos.x - gapDistance, pos.y);
var controlPoints = this._pivot.getControlPoints();
@@ -118,6 +124,21 @@ mindplot.RelationshipPivot = new Class({
event.stopPropagation();
},
_calculateFromPosition:function (toPosition) {
// Calculate origin position ...
var sourcePosition = this._sourceTopic.getPosition();
if (this._sourceTopic.getType() == mindplot.model.INodeModel.CENTRAL_TOPIC_TYPE) {
sourcePosition = mindplot.util.Shape.workoutIncomingConnectionPoint(this._sourceTopic, toPosition);
}
var controlPoint = mindplot.util.Shape.calculateDefaultControlPoints(sourcePosition, toPosition);
var spoint = new core.Point();
spoint.x = parseInt(controlPoint[0].x) + parseInt(sourcePosition.x);
spoint.y = parseInt(controlPoint[0].y) + parseInt(sourcePosition.y);
return mindplot.util.Shape.calculateRelationShipPointCoordinates(this._sourceTopic, spoint);
},
_connectOnFocus:function (targetTopic) {
var sourceTopic = this._sourceTopic;
var mindmap = this._designer.getMindmap();

View File

@@ -20,13 +20,13 @@ mindplot.RESTPersistenceManager = new Class({
Extends:mindplot.PersistenceManager,
initialize:function (options) {
this.parent();
$assert(options.saveUrl, "saveUrl can not be null");
$assert(options.documentUrl, "documentUrl can not be null");
$assert(options.revertUrl, "revertUrl can not be null");
$assert(options.lockUrl, "lockUrl can not be null");
$assert(options.session, "session can not be null");
$assert(options.timestamp, "timestamp can not be null");
this.saveUrl = options.saveUrl;
this.documentUrl = options.documentUrl;
this.revertUrl = options.revertUrl;
this.lockUrl = options.lockUrl;
this.timestamp = options.timestamp;
@@ -43,8 +43,8 @@ mindplot.RESTPersistenceManager = new Class({
var persistence = this;
var query = "minor=" + !saveHistory;
query = query + (this.timestamp ? "&timestamp=" + this.timestamp : "");
query = query + (this.session ? "&session=" + this.session : "");
query = query + "&timestamp=" + this.timestamp;
query = query + "&session=" + this.session;
if (!persistence.onSave) {
@@ -56,7 +56,7 @@ mindplot.RESTPersistenceManager = new Class({
}, 10000);
var request = new Request({
url:this.saveUrl.replace("{id}", mapId) + "?" + query,
url:this.documentUrl.replace("{id}", mapId) + "?" + query,
method:'put',
async:!sync,
@@ -99,10 +99,7 @@ mindplot.RESTPersistenceManager = new Class({
}
}
events.onError(userMsg);
// @Todo: Only for debug. Remove.
persistence.onSave = false;
throw new Error("responseText:" + responseText + ",status:" + this.status);
},
headers:{"Content-Type":"application/json", "Accept":"application/json"},
@@ -163,6 +160,29 @@ mindplot.RESTPersistenceManager = new Class({
severity = "INFO";
}
return {severity:severity, message:message};
},
loadMapDom:function (mapId) {
// Let's try to open one from the local directory ...
var xml;
var xmlRequest = new Request({
url:this.documentUrl.replace("{id}", mapId) + "/xml",
method:'get',
async:false,
headers:{"Content-Type":"text/plain","Accept":"application/xml"},
onSuccess:function (responseText) {
xml = responseText;
}
});
xmlRequest.send();
// If I could not load it from a file, hard code one.
if (xml == null) {
throw new Error("Map could not be loaded");
}
var parser = new DOMParser();
return parser.parseFromString(xml, "text/xml");
}
}
);

View File

@@ -270,6 +270,11 @@ mindplot.CommandContext = new Class({
return mindmap.createNode(mindplot.NodeModel.MAIN_TOPIC_TYPE);
},
addTopic:function (topic) {
var mindmap = this._designer.getMindmap();
return mindmap.addBranch(topic.getModel());
},
connect:function (childTopic, parentTopic) {
childTopic.connectTo(parentTopic, this._designer._workspace);
},

View File

@@ -598,7 +598,7 @@ mindplot.Topic = new Class({
areChildrenShrunken:function () {
var model = this.getModel();
return model.areChildrenShrunken();
return model.areChildrenShrunken() && !this.isCentralTopic();
},
isCollapsed:function () {
@@ -888,7 +888,12 @@ mindplot.Topic = new Class({
_setRelationshipLinesVisibility:function (value) {
this._relationships.each(function (relationship) {
relationship.setVisibility(value);
var sourceTopic = relationship.getSourceTopic();
var targetTopic = relationship.getTargetTopic();
var targetParent = targetTopic.getModel().getParent();
var sourceParent = sourceTopic.getModel().getParent();
relationship.setVisibility(value && (targetParent == null || !targetParent.areChildrenShrunken()) && (sourceParent == null || !sourceParent.areChildrenShrunken()));
});
},
@@ -1203,7 +1208,7 @@ mindplot.Topic = new Class({
var relationships = child.getRelationships();
result = result.concat(relationships);
if(!child.areChildrenShrunken()){
if (!child.areChildrenShrunken()) {
var innerChilds = this._flatten2DElements(child);
result = result.concat(innerChilds);
}

View File

@@ -41,6 +41,8 @@ mindplot.commands.AddTopicCommand = new Class({
var parentTopic = commandContext.findTopics(parentId)[0];
commandContext.connect(topic, parentTopic);
}
}else {
commandContext.addTopic(topic);
}
// Select just created node ...

View File

@@ -149,6 +149,20 @@ mindplot.commands.DeleteCommand = new Class({
return this._collectInDepthRelationships(topic);
}, this);
result.append(rels.flatten());
if (result.length > 0) {
// Filter for unique ...
result = result.sort(function (a, b) {
return a.getModel().getId() - b.getModel().getId();
});
var ret = [result[0]];
for (var i = 1; i < result.length; i++) { // start loop at 1 as element 0 can never be a duplicate
if (result[i - 1] !== result[i]) {
ret.push(result[i]);
}
}
result = ret;
}
return result;
}

View File

@@ -93,7 +93,7 @@ mindplot.model.RelationshipModel = new Class({
this._startArrow = startArrow;
},
clone:function (model) {
clone:function () {
var result = new mindplot.model.RelationshipModel(this._sourceTargetId, this._targetTopicId);
result._id = this._id;
result._lineType = this._lineType;

View File

@@ -92,7 +92,7 @@ mindplot.persistence.XMLSerializer_Pela = new Class({
}
if (topic.areChildrenShrunken()) {
if (topic.areChildrenShrunken() && topic.getType() != mindplot.model.INodeModel.CENTRAL_TOPIC_TYPE) {
parentTopic.setAttribute('shrink', 'true');
}
@@ -319,7 +319,8 @@ mindplot.persistence.XMLSerializer_Pela = new Class({
}
var isShrink = domElem.getAttribute('shrink');
if ($defined(isShrink)) {
// Hack: Some production maps has been stored with the central topic collapsed. This is a bug.
if ($defined(isShrink) && type!=mindplot.model.INodeModel.CENTRAL_TOPIC_TYPE) {
topic.setChildrenShrunken(isShrink);
}

View File

@@ -46,15 +46,16 @@ mindplot.util.Shape =
calculateRelationShipPointCoordinates:function (topic, controlPoint) {
var size = topic.getSize();
var position = topic.getPosition();
var div = (position.x - controlPoint.x);
div = (Math.abs(div) > 0.1 ? div : 0.1); // Prevent division by 0.
var m;
var yGap = position.y - controlPoint.y;
var xGap = position.x - controlPoint.x;
var disable = Math.abs(yGap) < 5 || Math.abs(xGap) < 5 || Math.abs(yGap - xGap) < 5;
var m = (position.y - controlPoint.y) / div;
var y, x;
var gap = 5;
if (controlPoint.y > position.y + (size.height / 2)) {
y = position.y + (size.height / 2) + gap;
x = position.x - ((position.y - y) / m);
x = !disable ? position.x - ((position.y - y) / (yGap / xGap)) : position.x;
if (x > position.x + (size.width / 2)) {
x = position.x + (size.width / 2);
} else if (x < position.x - (size.width / 2)) {
@@ -62,7 +63,7 @@ mindplot.util.Shape =
}
} else if (controlPoint.y < position.y - (size.height / 2)) {
y = position.y - (size.height / 2) - gap;
x = position.x - ((position.y - y) / m);
x = !disable ? position.x - ((position.y - y) / (yGap / xGap)) : position.x;
if (x > position.x + (size.width / 2)) {
x = position.x + (size.width / 2);
} else if (x < position.x - (size.width / 2)) {
@@ -70,10 +71,10 @@ mindplot.util.Shape =
}
} else if (controlPoint.x < (position.x - size.width / 2)) {
x = position.x - (size.width / 2) - gap;
y = position.y - (m * (position.x - x));
y = !disable ? position.y - ((yGap / xGap) * (position.x - x)) : position.y;
} else {
x = position.x + (size.width / 2) + gap;
y = position.y - (m * (position.x - x));
y = !disable ? position.y - ((yGap / xGap) * (position.x - x)) : position.y;
}
return new core.Point(x, y);
@@ -97,6 +98,31 @@ mindplot.util.Shape =
var y2 = m * (x2 - tarPos.x) + tarPos.y;
return [new core.Point(-srcPos.x + x1, -srcPos.y + y1), new core.Point(-tarPos.x + x2, -tarPos.y + y2)];
},
workoutIncomingConnectionPoint:function (targetNode, sourcePosition) {
$assert(sourcePosition, 'sourcePoint can not be null');
var pos = targetNode.getPosition();
var size = targetNode.getSize();
var isAtRight = mindplot.util.Shape.isAtRight(sourcePosition, pos);
var result = mindplot.util.Shape.calculateRectConnectionPoint(pos, size, isAtRight);
if (targetNode.getShapeType() == mindplot.model.TopicShape.LINE) {
result.y = result.y + (targetNode.getSize().height / 2);
}
// Move a little the position...
var offset = mindplot.Topic.CONNECTOR_WIDTH / 2;
if (!isAtRight) {
result.x = result.x + offset;
} else {
result.x = result.x - offset;
}
result.x = Math.ceil(result.x);
result.y = Math.ceil(result.y);
return result;
}
};

View File

@@ -29,7 +29,7 @@ mindplot.widget.IconPanel = new Class({
buildPanel:function () {
var content = new Element('div', {'class':'toolbarPanel', 'id':'IconsPanel'});
content.setStyles({width:253, height:210, padding:5});
content.setStyles({width:253, height:230, padding:5});
content.addEvent("click", function (event) {
event.stopPropagation()
});

View File

@@ -99,7 +99,7 @@ mindplot.widget.LinkEditor = new Class({
});
openButton.inject(form);
openButton.addEvent('click',function(){
window.open(input.value,"_blank", "status=1,width=700,height=450,resize=1");
window.open(input.value,"_blank", "status=1,width=700,height=450,resizable=1");
});

View File

@@ -223,9 +223,10 @@ mindplot.widget.Menu = new Class({
this._registerTooltip('export', $msg('EXPORT'));
this._addButton('print', false, false, function () {
this.save(saveElem, designer, false);
var baseUrl = window.location.href.substring(0, window.location.href.lastIndexOf("c/maps/"));
window.open(baseUrl + 'c/maps/' + mapId + '/print');
});
}.bind(this));
this._registerTooltip('print', $msg('PRINT'));
@@ -274,7 +275,7 @@ mindplot.widget.Menu = new Class({
}
this._addButton('addTopic', true, false, function () {
designer.createChildForSelectedNode();
designer.createSiblingForSelectedNode();
});
this._registerTooltip('addTopic', $msg('ADD_TOPIC'), "Enter");
@@ -432,6 +433,20 @@ mindplot.widget.Menu = new Class({
});
}
var videoElem = $("tutorialVideo");
if (videoElem) {
var width = 900;
var height = 500;
var left = (screen.width / 2) - (width / 2);
var top = (screen.height / 2) - (height / 2);
videoElem.addEvent('click', function (event) {
window.open("https://www.youtube.com/tv?vq=medium#/watch?v=rKxZwNKs9cE", "_blank", 'toolbar=no, location=no, directories=no, status=no, menubar=no, scrollbars=no, resizable=yes, copyhistory=no, width=' + width + ', height=' + height + ', top=' + top + ', left=' + left);
event.preventDefault();
});
}
},
_registerEvents:function (designer) {

View File

@@ -0,0 +1,59 @@
ZOOM_IN=Ansicht vergrößern
ZOOM_OUT=Ansicht verkleinern
TOPIC_SHAPE=Themen Gestaltung
TOPIC_ADD=Thema hinzufügen
TOPIC_DELETE=Thema löschen
TOPIC_ICON=Symbol hinzufügen
TOPIC_LINK=Verbindung hinzufügen
TOPIC_RELATIONSHIP=Beziehung
TOPIC_COLOR=Themenfarbe
TOPIC_BORDER_COLOR=Thema Randfarbe
TOPIC_NOTE=Notiz hinzufügen
FONT_FAMILY=Schrifttyp
FONT_SIZE=Schriftgröße
FONT_BOLD=Fette Schrift
FONT_ITALIC=Kursive Schrift
UNDO=Rückgängig machen
REDO=Wiederholen
INSERT=Einfügen
SAVE=Sichern
NOTE=Notiz
ADD_TOPIC=Thema hinzufügen
LOADING=Laden ...
EXPORT=Exportieren
PRINT=Drucken
PUBLISH=Publizieren
COLLABORATE=Mitbenutzen
HISTORY=Historie
DISCARD_CHANGES=Änderungen verwerfen
FONT_COLOR=Textfarbe
SAVING=Sichern ...
SAVE_COMPLETE=Sichern abgeschlossen
ZOOM_IN_ERROR=Zoom zu hoch.
ZOOM_ERROR=Es kann nicht weiter vergrößert bzw. verkelinert werden.
ONLY_ONE_TOPIC_MUST_BE_SELECTED=Thema konnte nicht angelegt werden. Bitte wählen Sie nur ein Thema aus.
ONE_TOPIC_MUST_BE_SELECTED=Thema konnte nicht angelegt werden. Es muss ein Thema ausgewählt werden.
ONLY_ONE_TOPIC_MUST_BE_SELECTED_COLLAPSE=Kinderknoten können nicht eingefaltet werden. Es muss ein Thema ausgewäht werden.
SAVE_COULD_NOT_BE_COMPLETED=Sichern wurde nicht abgeschlossen. Versuchen Sie es später nocheinmal.
UNEXPECTED_ERROR_LOADING=E tut uns Leid, ein unerwarteter Fehler ist aufgetreten.\nVersuchen Sie, den Editor neu zu laden. Falls das Problem erneut auftritt, bitte kontaktieren Sie uns unter support@wisemapping.com.
MAIN_TOPIC=Hauptthema
SUB_TOPIC=Unterthema
ISOLATED_TOPIC=Isoliertes Thema
CENTRAL_TOPIC=Zentrales Thema
SHORTCUTS=Tastaturkürzel
ENTITIES_COULD_NOT_BE_DELETED=Konnte das Thema oder die Beziehung nicht löschen. Es muss mindest ein Eintrag ausgewählt sein.
AT_LEAST_ONE_TOPIC_MUST_BE_SELECTED=Es muss mindestens ein Thema ausgewählt sein.
CLIPBOARD_IS_EMPTY=Es gibt nichts zu kopieren. Die Zwischenablage ist leer.
CENTRAL_TOPIC_CAN_NOT_BE_DELETED=Das zentrale Thema kann nicht gelöscht werden.
RELATIONSHIP_COULD_NOT_BE_CREATED=Die Beziehung konnte nicht angelegt werden. Es muss erst ein Vater-Thema ausgewählt werden, um die Beziehung herzustellen.
SELECTION_COPIED_TO_CLIPBOARD=Themen in der Zwischenablage
WRITE_YOUR_TEXT_HERE=Schreiben Sie ihre Notiz hier ...
REMOVE=Entfernen
ACCEPT=Akzeptieren
CANCEL=Abbrechen
LINK=Verbindung
OPEN_LINK=Öffne URL

View File

@@ -89,7 +89,7 @@ function testElementFill()
assertEquals(opacity, fill.opacity);
}
// Set attributes
// Set delegated
elem.setAttribute('fillColor', color);
elem.setAttribute('fillOpacity', opacity);

View File

@@ -30,6 +30,7 @@ function createStorageManager(mindplot) {
},
loadMapDom : function(mapId) {
var xml;
var xmlRequest = new Request({
url: this.backendUrl + mapId,
method: 'get',

View File

@@ -1,6 +1,5 @@
@import "compatibility.less";
@import "css/libraries/moodialog/css/MooDialog.css";
/********************************************************************************/
/* Header & Toolbar Styles */
/********************************************************************************/
@@ -13,7 +12,8 @@ body {
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
overflow:hidden;
overflow: hidden;
position: fixed
}
div#mindplot {
@@ -21,7 +21,7 @@ div#mindplot {
top: 0;
left: 0;
width: 100%;
height:100%;
height: 100%;
border: 0;
overflow: hidden;
}
@@ -36,8 +36,8 @@ div#small_error_icon {
background-color: #dfcf3c;
padding: 5px 15px;
color: #666666;
/*font-weight: bold;*/
/*width: 100px;*/
/*font-weight: bold;*/
/*width: 100px;*/
font-size: 13px;
-moz-border-radius: 3px;
-webkit-border-radius: 3px;
@@ -49,8 +49,8 @@ div#small_error_icon {
background-color: #dfcf3c;
padding: 5px 15px;
color: #666666;
/*font-weight: bold;*/
/*width: 100px;*/
/*font-weight: bold;*/
/*width: 100px;*/
font-size: 13px;
-moz-border-radius: 3px;
-webkit-border-radius: 3px;
@@ -150,18 +150,18 @@ div#small_error_icon {
/* Modal dialogs definitions */
div.modalDialog {
position: fixed;
top: 50%;
left: 50%;
z-index: 11000;
width: 500px;
margin: -250px 0 0 -250px;
background-color: #ffffff;
border: 1px solid #999;
padding: 10px;
overflow: auto;
position: fixed;
top: 50%;
left: 50%;
z-index: 11000;
width: 500px;
margin: -250px 0 0 -250px;
background-color: #ffffff;
border: 1px solid #999;
padding: 10px;
overflow: auto;
/* IE6-7 */
/* IE6-7 */
-webkit-border-radius: 6px;
-moz-border-radius: 6px;
border-radius: 6px;
@@ -178,31 +178,40 @@ div.modalDialog .content {
padding: 5px 5px;
}
div.modalDialog .title
{
div.modalDialog .title {
font-weight: bold;
text-shadow: 1px 1px 0 #fff;
border-bottom: 1px solid #eee;
padding: 5px 15px;
font-size: 18px;
}
/*--- End Modal Dialog Form ---*/
.publishModalDialog .content{
height:420px;
.publishModalDialog .content {
height: 420px;
}
.exportModalDialog .content{
height:400px;
.exportModalDialog .content {
height: 400px;
}
.shareModalDialog .content {
height:440px;
height: 440px;
}
div.shareModalDialog {
width: 550px;
}
#tutorialVideo{
background: url(../images/help.png) no-repeat left center;
padding-left: 19px;
}
#keyboardShortcuts{
background: url(../images/help.png) no-repeat left center;
padding-left: 19px;
}

View File

@@ -1,6 +1,9 @@
@import "editor.less";
/* Overwrite some styles */
body{
position: inherit;
}
div#headerInfo {
height: 0;

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

View File

@@ -87,7 +87,7 @@ function buildDesigner(options) {
}
} else {
persistence = new mindplot.LocalStorageManager();
persistence = new mindplot.LocalStorageManager("samples/{id}.xml");
}
mindplot.PersistenceManager.init(persistence);

View File

@@ -22,4 +22,6 @@ Deleting a based on the user id:
* Template Path: /service/admin/users/{userId}
* curl "http://{host.name}:{host.port}/{context.path}/service/admin/users/{userId}" --request delete --basic -u "admin@wisemapping.org:admin"
Changing Password:
Template Path: /service/admin/users/{userId}/password
* curl "http://{host.name}:{host.port}/{context.path}/service/admin/users/{userId}/password" --request put --basic -u "admin@wisemapping.org:admin" -H "Content-Type:text/plain" --data "<new_password>"

View File

@@ -28,7 +28,7 @@
</repositories>
<properties>
<org.springframework.version>3.1.0.RELEASE</org.springframework.version>
<org.springframework.version>3.1.3.RELEASE</org.springframework.version>
</properties>
<dependencies>
@@ -77,6 +77,12 @@
<version>${org.springframework.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-ldap</artifactId>
<version>${org.springframework.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>

View File

@@ -57,11 +57,9 @@ public class MindmapManagerImpl
final Criteria hibernateCriteria = getSession().createCriteria(MindMapHistory.class);
hibernateCriteria.add(Restrictions.eq("mindmapId", mindmapId));
hibernateCriteria.addOrder(Order.desc("creationTime"));
// Mientras no haya paginacion solo los 10 primeros
// This line throws errors in some environments, so getting all history and taking firsts 10 records
// hibernateCriteria.setMaxResults(10);
List list = hibernateCriteria.list();
return list.subList(0, (10 < list.size() ? 10 : list.size()));
hibernateCriteria.setMaxResults(30);
return hibernateCriteria.list();
}
@Override
@@ -203,6 +201,13 @@ public class MindmapManagerImpl
@Override
public void removeMindmap(@NotNull final Mindmap mindMap) {
// Delete history first ...
final Criteria hibernateCriteria = getSession().createCriteria(MindMapHistory.class);
hibernateCriteria.add(Restrictions.eq("mindmapId", mindMap.getId()));
List list = hibernateCriteria.list();
getHibernateTemplate().deleteAll(list);
// Delete mindmap ....
getHibernateTemplate().delete(mindMap);
}

View File

@@ -28,4 +28,8 @@ abstract public class ClientException extends WiseMappingException {
public Severity getSeverity() {
return this.severity;
}
public String getTechInfo() {
return getMessage();
}
}

View File

@@ -23,11 +23,11 @@ import org.jetbrains.annotations.NotNull;
public class MultipleSessionsOpenException
extends ClientException
{
public static final String MSG_KEY = "MINDMAP_TIMESTAMP_OUTDATED";
public static final String MSG_KEY = "MINDMAP_OUTDATED_BY_YOU";
public MultipleSessionsOpenException(@NotNull String msg)
public MultipleSessionsOpenException(@NotNull String techInfo)
{
super(msg,Severity.INFO);
super(techInfo,Severity.INFO);
}
@NotNull
@@ -35,9 +35,4 @@ public class MultipleSessionsOpenException
protected String getMsgBundleKey() {
return MSG_KEY;
}
@Override
protected Object[] getMsgBundleArgs() {
return new String[]{"you"};
}
}

View File

@@ -26,8 +26,8 @@ public class SessionExpiredException
public static final String MSG_KEY = "MINDMAP_TIMESTAMP_OUTDATED";
private User lastUpdater;
public SessionExpiredException(@NotNull User lastUpdater) {
super("Map has been updated by " + (lastUpdater != null ? lastUpdater.getEmail() : ""), Severity.FATAL);
public SessionExpiredException(@NotNull String debugInfo, @NotNull User lastUpdater) {
super(debugInfo, Severity.FATAL);
this.lastUpdater = lastUpdater;
}

View File

@@ -18,6 +18,9 @@
package com.wisemapping.exporter;
import org.apache.batik.parser.AWTTransformProducer;
import org.apache.batik.parser.ParseException;
import org.apache.batik.parser.TransformListParser;
import org.apache.batik.transcoder.Transcoder;
import org.apache.batik.transcoder.TranscoderException;
import org.apache.batik.transcoder.TranscoderInput;
@@ -34,22 +37,23 @@ import org.xml.sax.SAXException;
import sun.misc.BASE64Encoder;
import javax.servlet.ServletContext;
import javax.xml.bind.JAXBException;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.stream.XMLStreamException;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.xpath.*;
import java.awt.geom.AffineTransform;
import java.io.*;
import java.util.regex.Pattern;
public class ExporterFactory {
private static final String GROUP_NODE_NAME = "g";
private static final String RECT_NODE_NAME = "rect";
private static final String IMAGE_NODE_NAME = "image";
public static final int MARGING = 50;
private File baseImgDir;
public ExporterFactory(@NotNull final ServletContext servletContext) throws ParserConfigurationException {
@@ -60,7 +64,7 @@ public class ExporterFactory {
this.baseImgDir = baseImgDir;
}
public void export(@NotNull ExportProperties properties, @Nullable String xml, @NotNull OutputStream output, @Nullable String mapSvg) throws TranscoderException, IOException, ParserConfigurationException, SAXException, XMLStreamException, TransformerException, JAXBException, ExportException {
public void export(@NotNull ExportProperties properties, @Nullable String xml, @NotNull OutputStream output, @Nullable String mapSvg) throws ExportException, IOException, TranscoderException {
final ExportFormat format = properties.getFormat();
switch (format) {
@@ -73,8 +77,7 @@ public class ExporterFactory {
transcoder.addTranscodingHint(ImageTranscoder.KEY_WIDTH, size.getWidth());
// Create the transcoder input.
final Document document = normalizeSvg(mapSvg, false);
final String svgString = domToString(document);
final String svgString = normalizeSvg(mapSvg, false);
final TranscoderInput input = new TranscoderInput(new CharArrayReader(svgString.toCharArray()));
TranscoderOutput trascoderOutput = new TranscoderOutput(output);
@@ -94,8 +97,7 @@ public class ExporterFactory {
transcoder.addTranscodingHint(ImageTranscoder.KEY_WIDTH, size.getWidth());
// Create the transcoder input.
final Document document = normalizeSvg(mapSvg, false);
final String svgString = domToString(document);
final String svgString = normalizeSvg(mapSvg, false);
final TranscoderInput input = new TranscoderInput(new CharArrayReader(svgString.toCharArray()));
TranscoderOutput trascoderOutput = new TranscoderOutput(output);
@@ -109,10 +111,8 @@ public class ExporterFactory {
final Transcoder transcoder = new PDFTranscoder();
// Create the transcoder input.
final Document document = normalizeSvg(mapSvg, false);
final String svgString = domToString(document);
final String svgString = normalizeSvg(mapSvg, false);
final TranscoderInput input = new TranscoderInput(new CharArrayReader(svgString.toCharArray()));
TranscoderOutput trascoderOutput = new TranscoderOutput(output);
// Save the image.
@@ -120,8 +120,8 @@ public class ExporterFactory {
break;
}
case SVG: {
final Document dom = normalizeSvg(mapSvg, true);
output.write(domToString(dom).getBytes("UTF-8"));
final String svgString = normalizeSvg(mapSvg, true);
output.write(svgString.getBytes("UTF-8"));
break;
}
case FREEMIND: {
@@ -134,47 +134,56 @@ public class ExporterFactory {
}
}
private Document normalizeSvg(@NotNull String svgXml, boolean embedImg) throws XMLStreamException, ParserConfigurationException, IOException, SAXException, TransformerException {
private String normalizeSvg(@NotNull String svgXml, boolean embedImg) throws ExportException {
final DocumentBuilder documentBuilder = getDocumentBuilder();
if (!svgXml.trim().startsWith("<svg xmlns=\"http://www.w3.org/2000/svg\"")) {
svgXml = svgXml.replaceFirst("<svg ", "<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" ");
} else {
svgXml = svgXml.replaceFirst("<svg ", "<svg xmlns:xlink=\"http://www.w3.org/1999/xlink\" ");
}
// Hacks for some legacy cases ....
svgXml = svgXml.replaceAll("NaN,", "0");
svgXml = svgXml.replaceAll(",NaN", "0");
Document document;
try {
final Reader in = new CharArrayReader(svgXml.toCharArray());
final InputSource is = new InputSource(in);
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
final DocumentBuilder documentBuilder = factory.newDocumentBuilder();
document = documentBuilder.parse(is);
if (!svgXml.trim().startsWith("<svg xmlns=\"http://www.w3.org/2000/svg\"")) {
svgXml = svgXml.replaceFirst("<svg ", "<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" ");
} else {
svgXml = svgXml.replaceFirst("<svg ", "<svg xmlns:xlink=\"http://www.w3.org/1999/xlink\" ");
}
// Hacks for some legacy cases ....
svgXml = svgXml.replaceAll("NaN,", "0");
svgXml = svgXml.replaceAll(",NaN", "0");
// Bratik do not manage nbsp properly.
svgXml = svgXml.replaceAll(Pattern.quote("&nbsp;"), " ");
Document document;
try {
final Reader in = new CharArrayReader(svgXml.toCharArray());
final InputSource is = new InputSource(in);
document = documentBuilder.parse(is);
} catch (SAXException e) {
// It must be a corrupted SVG format. Try to hack it and try again ...
svgXml = svgXml.replaceAll("<image([^>]+)>", "<image$1/>");
final Reader in = new CharArrayReader(svgXml.toCharArray());
final InputSource is = new InputSource(in);
document = documentBuilder.parse(is);
}
resizeSVG(document);
final Node child = document.getFirstChild();
inlineImages(document, (Element) child);
return domToString(document);
} catch (ParserConfigurationException e) {
throw new ExportException(e);
} catch (IOException e) {
throw new ExportException(e);
} catch (SAXException e) {
// It must be a corrupted SVG format. Try to hack it and try again ...
svgXml = svgXml.replaceAll("<image([^>]+)>", "<image$1/>");
final Reader in = new CharArrayReader(svgXml.toCharArray());
final InputSource is = new InputSource(in);
document = documentBuilder.parse(is);
throw new ExportException(e);
} catch (TransformerException e) {
throw new ExportException(e);
}
fitSvg(document);
final Node child = document.getFirstChild();
fixImageTagHref(document, (Element) child);
return document;
}
private static DocumentBuilder getDocumentBuilder() throws ParserConfigurationException {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
return factory.newDocumentBuilder();
}
private static String domToString(@NotNull Document document) throws TransformerException {
@@ -198,7 +207,7 @@ public class ExporterFactory {
return result.toString();
}
private void fixImageTagHref(@NotNull Document document, @NotNull Element element) {
private void inlineImages(@NotNull Document document, @NotNull Element element) {
final NodeList list = element.getChildNodes();
@@ -207,7 +216,7 @@ public class ExporterFactory {
// find all groups
if (GROUP_NODE_NAME.equals(node.getNodeName())) {
// Must continue looking ....
fixImageTagHref(document, (Element) node);
inlineImages(document, (Element) node);
} else if (IMAGE_NODE_NAME.equals(node.getNodeName())) {
@@ -277,68 +286,72 @@ public class ExporterFactory {
}
}
private static void fitSvg(Document document) {
// viewBox size
int mapWidth = 1024;
int mapHeight = 768;
// some browser return width and heigth with precision
float currentMaxWidth = 0;
float currentMaxHeight = 0;
private static void resizeSVG(@NotNull Document document) throws ExportException {
final Element svgNode = (Element) document.getFirstChild();
final NodeList list = svgNode.getChildNodes();
try {
XPathFactory xPathfactory = XPathFactory.newInstance();
XPath xpath = xPathfactory.newXPath();
XPathExpression expr = xpath.compile("/svg/g/rect");
for (int i = 0; i < list.getLength(); i++) {
final Node node = list.item(i);
// find all groups
if (GROUP_NODE_NAME.equals(node.getNodeName())) {
final NamedNodeMap groupAttributes = node.getAttributes();
NodeList nl = (NodeList) expr.evaluate(document, XPathConstants.NODESET);
final int length = nl.getLength();
double maxX = 0, minX = 0, minY = 0, maxY = 0;
final String[] transformUnit = getTransformUnit(groupAttributes);
int groupPositionX = Integer.parseInt(transformUnit[0].trim());
int groupPositionY = 0;
if (transformUnit.length > 1) {
groupPositionY = Integer.parseInt(transformUnit[1].trim());
for (int i = 0; i < length; i++) {
final Element rectElem = (Element) nl.item(i);
final Element gElem = (Element) rectElem.getParentNode();
final TransformListParser p = new TransformListParser();
final AWTTransformProducer tp = new AWTTransformProducer();
p.setTransformListHandler(tp);
p.parse(gElem.getAttribute("transform"));
final AffineTransform transform = tp.getAffineTransform();
double yPos = transform.getTranslateY();
if (yPos > 0) {
yPos += Double.parseDouble(rectElem.getAttribute("height"));
}
maxY = maxY < yPos ? yPos : maxY;
minY = minY > yPos ? yPos : minY;
double xPos = transform.getTranslateX();
if (xPos > 0) {
xPos += Double.parseDouble(rectElem.getAttribute("width"));
}
int signumX = Integer.signum(groupPositionX);
int signumY = Integer.signum(groupPositionY);
final NodeList groupChildren = node.getChildNodes();
for (int idx = 0; idx < groupChildren.getLength(); idx++) {
final Node rectNode = groupChildren.item(idx);
float curentHeight = 0;
float curentWidth = 0;
// If has a rect use the rect to calcular the real width of the topic
if (RECT_NODE_NAME.equals(rectNode.getNodeName())) {
final NamedNodeMap rectAttributes = rectNode.getAttributes();
final Node attributeHeight = rectAttributes.getNamedItem("height");
final Node attributeWidth = rectAttributes.getNamedItem("width");
curentHeight = Float.valueOf(attributeHeight.getNodeValue());
curentWidth = Float.valueOf(attributeWidth.getNodeValue());
}
float newMaxWidth = groupPositionX + (curentWidth * signumX);
if (Math.abs(currentMaxWidth) < Math.abs(newMaxWidth)) {
currentMaxWidth = newMaxWidth;
}
float newMaxHeight = groupPositionY + curentHeight * signumY;
if (Math.abs(currentMaxHeight) < Math.abs(newMaxHeight)) {
currentMaxHeight = newMaxHeight;
}
}
maxX = maxX < xPos ? xPos : maxX;
minX = minX > xPos ? xPos : minX;
}
}
svgNode.setAttribute("viewBox", -Math.abs(currentMaxWidth) + " " + -Math.abs(currentMaxHeight) + " " + Math.abs(currentMaxWidth * 2) + " " + Math.abs(currentMaxHeight * 2));
svgNode.setAttribute("width", Float.toString(mapWidth / 2));
svgNode.setAttribute("height", Float.toString(mapHeight / 2));
svgNode.setAttribute("preserveAspectRatio", "xMinYMin");
// Add some extra margin ...
maxX += MARGING;
minX += -MARGING;
maxY += MARGING;
minY += -MARGING;
// Calculate dimentions ...
final double width = maxX + Math.abs(minX);
final double height = maxY + Math.abs(minY);
// Finally, update centers ...
final Element svgNode = (Element) document.getFirstChild();
svgNode.setAttribute("viewBox", minX + " " + minY + " " + width + " " + height);
svgNode.setAttribute("width", Double.toString(width));
svgNode.setAttribute("height", Double.toString(height));
svgNode.setAttribute("preserveAspectRatio", "xMinYMin");
} catch (XPathExpressionException e) {
throw new ExportException(e);
} catch (ParseException e) {
throw new ExportException(e);
} catch (NumberFormatException e) {
throw new ExportException(e);
} catch (DOMException e) {
throw new ExportException(e);
}
}
private static String[] getTransformUnit(NamedNodeMap groupAttributes) {

View File

@@ -225,7 +225,7 @@ public class FreemindExporter
private void addNote(com.wisemapping.jaxb.freemind.Node fnode, com.wisemapping.jaxb.wisemap.TopicType mindmapTopic) throws IOException, SAXException, ParserConfigurationException {
final Note note = mindmapTopic.getNote();
if (note != null) {
final String noteStr = note.getText() != null ? note.getText() : note.getTextAttr();
final String noteStr = note.getValue() != null ? note.getValue() : note.getTextAttr();
if (noteStr != null) {
final Richcontent richcontent = buildRichContent(noteStr, "NOTE");
fnode.getArrowlinkOrCloudOrEdge().add(richcontent);

View File

@@ -42,6 +42,8 @@ public class RequestPropertiesInterceptor extends HandlerInterceptorAdapter {
@Value("${site.baseurl}")
private String siteUrl;
@Value("${security.type}")
private String securityType;
public boolean preHandle(@NotNull HttpServletRequest request, @NotNull HttpServletResponse response, Object object) throws Exception {
@@ -49,6 +51,8 @@ public class RequestPropertiesInterceptor extends HandlerInterceptorAdapter {
request.setAttribute("google.analytics.account", analyticsAccount);
request.setAttribute("google.ads.enabled", adsEnabled);
request.setAttribute("site.homepage", siteHomepage);
request.setAttribute("security.type", securityType);
// If the property could not be resolved, try to infer one from the request...
if ("${site.baseurl}".equals(siteUrl)) {

View File

@@ -18,12 +18,17 @@
package com.wisemapping.importer;
import java.io.OutputStream;
import org.apache.xml.serialize.OutputFormat;
import org.apache.xml.serialize.XMLSerializer;
import org.jetbrains.annotations.NotNull;
import org.w3c.dom.Document;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
@SuppressWarnings("deprecation")
public class JaxbCDATAMarshaller {
@@ -38,7 +43,7 @@ public class JaxbCDATAMarshaller {
// When processing xml that doesn't use namespaces, simply omit the
// namespace prefix as shown in the third CDataElement below.
of.setCDataElements(
new String[]{"^text"}); //
new String[]{"^text","^note"}); //
// set any other options you'd like
// of.setPreserveSpace(true);
@@ -46,10 +51,106 @@ public class JaxbCDATAMarshaller {
of.setEncoding("UTF-8");
// create the serializer
XMLSerializer result = new XMLSerializer(of);
XMLSerializer result = new XMLSerializer(of) {
@Override
public void startElement(String s, String s1, String s2, Attributes attributes) throws SAXException {
super.startElement(s, s1, s2, new SortedAttributesDecorator(attributes));
}
};
result.setOutputByteStream(out);
return result;
}
private static class SortedAttributesDecorator implements Attributes {
final Map<Integer, Integer> sortedToUnsorted = new HashMap<Integer, Integer>();
final Map<Integer, Integer> unsortedToSorted = new HashMap<Integer, Integer>();
private Attributes delegated;
SortedAttributesDecorator(final Attributes delegated) {
this.delegated = delegated;
int length = this.getLength();
// Sort by local part ...
final Map<String, Integer> sortedMap = new TreeMap<String, Integer>();
for (int i = 0; i < length; i++) {
final String localName = delegated.getLocalName(i);
sortedMap.put(localName, i);
}
Set<String> keySet = sortedMap.keySet();
int sortedIndex = 0;
for (String key : keySet) {
final Integer unsortedIndex = sortedMap.get(key);
sortedToUnsorted.put(sortedIndex, unsortedIndex);
unsortedToSorted.put(unsortedIndex, sortedIndex);
sortedIndex++;
}
}
@Override
public int getLength() {
return delegated.getLength();
}
@Override
public String getURI(int index) {
return delegated.getURI(sortedToUnsorted.get(index));
}
@Override
public String getLocalName(int index) {
return delegated.getLocalName(sortedToUnsorted.get(index));
}
@Override
public String getQName(int index) {
return delegated.getQName(sortedToUnsorted.get(index));
}
@Override
public String getType(int index) {
return delegated.getType(sortedToUnsorted.get(index));
}
@Override
public String getValue(int index) {
return delegated.getValue(sortedToUnsorted.get(index));
}
@Override
public int getIndex(String uri, String localName) {
int unsorted = delegated.getIndex(uri, localName);
return unsortedToSorted.get(unsorted);
}
@Override
public int getIndex(String qName) {
int unsorted = delegated.getIndex(qName);
return unsortedToSorted.get(unsorted);
}
@Override
public String getType(String uri, String localName) {
return delegated.getType(uri, localName);
}
@Override
public String getType(String qName) {
return delegated.getType(qName);
}
@Override
public String getValue(String uri, String localName) {
return delegated.getValue(uri, localName);
}
@Override
public String getValue(String qName) {
return delegated.getValue(qName);
}
}
}

View File

@@ -298,7 +298,7 @@ public class FreemindImporter
if (textNote == null) // It is not a note is a BlinkingNodeHook or AutomaticLayout Hook
{
textNote = EMPTY_NOTE;
mindmapNote.setText(textNote);
mindmapNote.setValue(textNote);
currentWiseTopic.setNote(mindmapNote);
}
} else if (element instanceof Richcontent) {
@@ -312,7 +312,7 @@ public class FreemindImporter
String text = html2text(content);
final com.wisemapping.jaxb.wisemap.Note mindmapNote = new com.wisemapping.jaxb.wisemap.Note();
text = text != null ? text : EMPTY_NOTE;
mindmapNote.setText(text);
mindmapNote.setValue(text);
currentWiseTopic.setNote(mindmapNote);
}

View File

@@ -19,37 +19,36 @@
package com.wisemapping.model;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.Serializable;
import java.util.Calendar;
import java.util.Set;
import java.util.HashSet;
import java.util.Set;
public class Collaborator implements Serializable {
public class Collaborator implements Serializable {
private long id;
private String email;
private Calendar creationDate;
private Set<Collaboration> collaborations = new HashSet<Collaboration>();
public Collaborator() {}
public Collaborator() {
}
public Collaborator(Set<Collaboration> collaborations) {
public Collaborator(Set<Collaboration> collaborations) {
this.collaborations = collaborations;
}
public void setCollaborations(Set<Collaboration> collaborations)
{
public void setCollaborations(Set<Collaboration> collaborations) {
this.collaborations = collaborations;
}
public void addCollaboration(@NotNull Collaboration collaboration)
{
collaborations.add(collaboration);
public void addCollaboration(@NotNull Collaboration collaboration) {
collaborations.add(collaboration);
}
public Set<Collaboration> getCollaborations()
{
public Set<Collaboration> getCollaborations() {
return collaborations;
}
@@ -76,4 +75,40 @@ public class Collaborator implements Serializable {
public void setCreationDate(Calendar creationDate) {
this.creationDate = creationDate;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Collaborator that = (Collaborator) o;
if (id != that.getId()) return false;
if (email != null ? !email.equals(that.getEmail()) : that.getEmail() != null) return false;
return true;
}
@Override
public int hashCode() {
long id = this.getId();
String email = this.getEmail();
int result = (int) (id ^ (id >>> 32));
result = 31 * result + (email != null ? email.hashCode() : 0);
return result;
}
public boolean identityEquality(@Nullable Collaborator that) {
if (this == that) return true;
if (that == null) return false;
if (id != that.getId()) return false;
if (email != null ? !email.equals(that.getEmail()) : that.getEmail() != null) return false;
return true;
}
}

View File

@@ -44,5 +44,7 @@ public enum IconFamily {
BULLET,
TAG,
OBJECT,
WEATHER;
WEATHER,
TASK,
NUMBER
}

View File

@@ -18,8 +18,10 @@
package com.wisemapping.model;
import com.wisemapping.util.ZipUtils;
import org.jetbrains.annotations.Nullable;
import java.io.IOException;
import java.util.Calendar;
public class MindMapHistory {
@@ -71,7 +73,11 @@ public class MindMapHistory {
return xml;
}
public void setXml(byte[] xml) {
this.xml = xml;
public void setXml(byte[] value) {
xml = value;
}
public byte[] getUnzipXml() throws IOException {
return ZipUtils.zipToBytes(xml);
}
}

View File

@@ -28,7 +28,6 @@ import org.jetbrains.annotations.Nullable;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.Calendar;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;
@@ -83,14 +82,14 @@ public class Mindmap {
throws IOException {
byte[] result = this.xml;
if (result != null) {
result = ZipUtils.stringToZip(new String(result, UTF_8));
result = ZipUtils.bytesToZip(result);
}
return result;
}
public void setZippedXml(byte[] xml)
throws IOException {
this.xml = ZipUtils.zipToString(xml).getBytes(UTF_8);
this.xml = ZipUtils.zipToBytes(xml);
}
public Set<Collaboration> getCollaborations() {
@@ -111,7 +110,14 @@ public class Mindmap {
@Nullable
public Collaboration findCollaboration(@NotNull Collaborator collaborator) {
return this.findCollaboration(collaborator.getEmail());
Collaboration result = null;
for (Collaboration collaboration : collaborations) {
if (collaboration.getCollaborator().identityEquality(collaborator)) {
result = collaboration;
break;
}
}
return result;
}
@Nullable
@@ -167,11 +173,21 @@ public class Mindmap {
this.title = title;
}
@NotNull
public String getXmlAsJsLiteral()
throws IOException {
String xml = this.getXmlStr();
if (xml != null) {
xml = StringEscapeUtils.escapeJavaScript(xml);
xml = xml.replace("'", "\\'");
xml = xml.replace("\n", "\\n");
xml = xml.replace("\r", "");
xml = xml.replace("\\b", "\\\\b");
xml = xml.replace("\\t", "\\\\t");
xml = xml.replace("\\r", "\\\\r");
xml = xml.replace("\\f", "\\\\f");
xml = xml.trim();
}
return xml;
}

View File

@@ -45,12 +45,6 @@ public class MindmapIcons {
public static final MindmapIcon ARROW_LEFT = new MindmapIcon(IconFamily.ARROW, "left");
public static final MindmapIcon ARROW_RIGHT = new MindmapIcon(IconFamily.ARROW, "right");
// public static final MindmapIcon TASK_ONE = new MindmapIcon(IconFamily.TASK, "one");
// public static final MindmapIcon TASK_TWO = new MindmapIcon(IconFamily.TASK, "two");
// public static final MindmapIcon TASK_THREE = new MindmapIcon(IconFamily.TASK, "three");
// public static final MindmapIcon TASK_FOUR = new MindmapIcon(IconFamily.TASK, "four");
// public static final MindmapIcon TASK_FIVE = new MindmapIcon(IconFamily.TASK, "five");
// public static final MindmapIcon ARROWC_UNDO = new MindmapIcon(IconFamily.ARROWC, "undo");
public static final MindmapIcon ARROWC_ANTICLOCK_WISE = new MindmapIcon(IconFamily.ARROWC, "rotate_anticlockwise");
public static final MindmapIcon ARROWC_CLOCK_WISE = new MindmapIcon(IconFamily.ARROWC, "rotate_clockwise");
@@ -83,16 +77,23 @@ public class MindmapIcons {
public static final MindmapIcon TAG_RED = new MindmapIcon(IconFamily.TAG, "red");
public static final MindmapIcon TAG_PINK = new MindmapIcon(IconFamily.TAG, "pink");
public static final MindmapIcon TAG_YELLOW = new MindmapIcon(IconFamily.TAG, "yellow");
public static final MindmapIcon TAG_PURPLE = new MindmapIcon(IconFamily.TAG, "purple");
// public static final MindmapIcon NUMBER_ONE = new MindmapIcon(IconFamily.NUMBER, "one");
// public static final MindmapIcon NUMBER_TWO = new MindmapIcon(IconFamily.NUMBER, "two");
// public static final MindmapIcon NUMBER_THREE = new MindmapIcon(IconFamily.NUMBER, "three");
// public static final MindmapIcon NUMBER_FOUR = new MindmapIcon(IconFamily.NUMBER, "four");
// public static final MindmapIcon NUMBER_FIVE = new MindmapIcon(IconFamily.NUMBER, "five");
// public static final MindmapIcon NUMBER_SIX = new MindmapIcon(IconFamily.NUMBER, "six");
// public static final MindmapIcon NUMBER_SEVEN = new MindmapIcon(IconFamily.NUMBER, "seven");
// public static final MindmapIcon NUMBER_EIGHT = new MindmapIcon(IconFamily.NUMBER, "eight");
// public static final MindmapIcon NUMBER_NINE = new MindmapIcon(IconFamily.NUMBER, "nine");
public static final MindmapIcon NUMBER_1 = new MindmapIcon(IconFamily.NUMBER, "1");
public static final MindmapIcon NUMBER_2 = new MindmapIcon(IconFamily.NUMBER, "2");
public static final MindmapIcon NUMBER_3 = new MindmapIcon(IconFamily.NUMBER, "3");
public static final MindmapIcon NUMBER_4 = new MindmapIcon(IconFamily.NUMBER, "4");
public static final MindmapIcon NUMBER_5 = new MindmapIcon(IconFamily.NUMBER, "5");
public static final MindmapIcon NUMBER_6 = new MindmapIcon(IconFamily.NUMBER, "6");
public static final MindmapIcon NUMBER_7 = new MindmapIcon(IconFamily.NUMBER, "7");
public static final MindmapIcon NUMBER_8 = new MindmapIcon(IconFamily.NUMBER, "8");
public static final MindmapIcon NUMBER_9 = new MindmapIcon(IconFamily.NUMBER, "9");
public static final MindmapIcon TASK_0 = new MindmapIcon(IconFamily.TASK, "0");
public static final MindmapIcon TASK_25 = new MindmapIcon(IconFamily.TASK, "25");
public static final MindmapIcon TASK_50 = new MindmapIcon(IconFamily.TASK, "50");
public static final MindmapIcon TASK_75 = new MindmapIcon(IconFamily.TASK, "75");
public static final MindmapIcon TASK_100 = new MindmapIcon(IconFamily.TASK, "100");
public static final MindmapIcon FUNNY_ANGEL = new MindmapIcon(IconFamily.FUNY, "angel");

View File

@@ -20,10 +20,10 @@ package com.wisemapping.model;
import org.jetbrains.annotations.Nullable;
import javax.servlet.http.HttpSessionBindingEvent;
import javax.servlet.http.HttpSessionBindingListener;
import java.io.Serializable;
import java.util.*;
import java.util.Calendar;
import java.util.HashSet;
import java.util.Set;
public class User
extends Collaborator
@@ -106,28 +106,6 @@ public class User
this.allowSendEmail = allowSendEmail;
}
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
final User user = (User) o;
final String email = getEmail();
if (email != null ? !email.equals(user.getEmail()) : user.getEmail() != null) return false;
if (firstname != null ? !firstname.equals(user.firstname) : user.firstname != null) return false;
return !(lastname != null ? !lastname.equals(user.lastname) : user.lastname != null);
}
public int hashCode() {
int result;
result = (firstname != null ? firstname.hashCode() : 0);
result = 29 * result + (lastname != null ? lastname.hashCode() : 0);
result = 29 * result + (password != null ? password.hashCode() : 0);
result = 29 * result + (getEmail() != null ? getEmail().hashCode() : 0);
return result;
}
@Nullable
public String getLocale() {
return locale;

View File

@@ -85,7 +85,7 @@ public class AdminController extends BaseController {
}
// Finally create the user ...
userService.createUser(delegated, false);
userService.createUser(delegated, false,true);
response.setHeader("Location", "/service/admin/users/" + user.getId());
}

View File

@@ -108,6 +108,6 @@ public class BaseController {
@ResponseStatus(HttpStatus.BAD_REQUEST)
public RestErrors handleClientErrors(@NotNull ClientException ex) {
final Locale locale = LocaleContextHolder.getLocale();
return new RestErrors(ex.getMessage(messageSource, locale),ex.getSeverity());
return new RestErrors(ex.getMessage(messageSource, locale),ex.getSeverity(),ex.getTechInfo());
}
}

View File

@@ -120,7 +120,7 @@ public class MindmapController extends BaseController {
@RequestMapping(value = "maps/{id}/history/{hid}", method = RequestMethod.POST)
@ResponseStatus(value = HttpStatus.NO_CONTENT)
public void updateRevertMindmap(@PathVariable int id, @PathVariable String hid) throws WiseMappingException {
public void updateRevertMindmap(@PathVariable int id, @PathVariable String hid) throws WiseMappingException, IOException {
final Mindmap mindmap = mindmapService.findMindmapById(id);
final User user = Utils.getUser();
@@ -129,8 +129,8 @@ public class MindmapController extends BaseController {
List<MindMapHistory> mindmapHistory = mindmapService.findMindmapHistory(id);
if (mindmapHistory.size() > 0) {
final MindMapHistory mindMapHistory = mindmapHistory.get(0);
mindmap.setXml(mindMapHistory.getXml());
saveMindmap(true, mindmap, user);
mindmap.setZippedXml(mindMapHistory.getXml());
saveMindmapDocument(true, mindmap, user);
}
} else {
mindmapService.revertChange(mindmap, Integer.parseInt(hid));
@@ -165,14 +165,33 @@ public class MindmapController extends BaseController {
mindmap.setXmlStr(xml);
// Update map ...
saveMindmap(minor, mindmap, user);
saveMindmapDocument(minor, mindmap, user);
// Update edition timeout ...
final LockManager lockManager = mindmapService.getLockManager();
final LockInfo lockInfo = lockManager.updateExpirationTimeout(mindmap, user, session);
final LockInfo lockInfo = lockManager.updateExpirationTimeout(mindmap, user);
return lockInfo.getTimestamp();
}
@RequestMapping(method = RequestMethod.GET, value = { "/maps/{id}/document/xml","/maps/{id}/document/xml-pub"},consumes = {"text/plain"}, produces = {"application/xml"})
@ResponseBody
public byte[] retrieveDocument(@PathVariable int id, @NotNull HttpServletResponse response) throws WiseMappingException, IOException {
// I should not return byte, but there is some encoding issue here. Further research needed.
response.setCharacterEncoding("UTF-8");
final Mindmap mindmap = mindmapService.findMindmapById(id);
return mindmap.getXmlStr().getBytes("UTF-8");
}
@RequestMapping(method = RequestMethod.GET, value = { "/maps/{id}/{hid}/document/xml"},consumes = {"text/plain"}, produces = {"application/xml"})
@ResponseBody
public byte[] retrieveDocument(@PathVariable int id, @PathVariable int hid,@NotNull HttpServletResponse response) throws WiseMappingException, IOException {
// I should not return byte, but there is some encoding issue here. Further research needed.
response.setCharacterEncoding("UTF-8");
final MindMapHistory mindmapHistory = mindmapService.findMindmapHistory(id, hid);
return mindmapHistory.getUnzipXml();
}
private void verifyLock(@NotNull Mindmap mindmap, @NotNull User user, long session, long timestamp) throws WiseMappingException {
// The lock was lost, reclaim as the ownership of it.
@@ -183,20 +202,20 @@ public class MindmapController extends BaseController {
}
final LockInfo lockInfo = lockManager.getLockInfo(mindmap);
if (lockInfo.getUser().equals(user)) {
if (lockInfo.getUser().identityEquality(user)) {
final boolean outdated = mindmap.getLastModificationTime().getTimeInMillis() > timestamp;
if (lockInfo.getSession() == session) {
// Timestamp might not be returned to the client. This try to cover this case, ignoring the client timestamp check.
final User lastEditor = mindmap.getLastEditor();
if (outdated && (lockInfo.getPreviousTimestamp() != timestamp || lastEditor == null || !lastEditor.equals(user))) {
throw new SessionExpiredException(lastEditor);
boolean editedBySameUser = lastEditor == null || user.identityEquality(lastEditor);
if (outdated && !editedBySameUser) {
throw new SessionExpiredException("Map has been updated by " + (lastEditor.getEmail()) + ",Timestamp:" + timestamp + "," + mindmap.getLastModificationTime().getTimeInMillis() + ", User:" + lastEditor.getId() + ":" + user.getId() + ",Mail:'" + lastEditor.getEmail() + "':'" + user.getEmail(), lastEditor);
}
} else if (outdated) {
throw new MultipleSessionsOpenException("The map has been updated and not by you. Session lost.");
throw new MultipleSessionsOpenException("Sessions:" + session + ":" + lockInfo.getSession() + ",Timestamp: " + timestamp + ": " + lockInfo.getTimestamp() + ",User:");
}
} else {
throw new SessionExpiredException(lockInfo.getUser());
throw new SessionExpiredException("Different Users.", lockInfo.getUser());
}
}
@@ -243,7 +262,7 @@ public class MindmapController extends BaseController {
}
// Update map ...
saveMindmap(minor, mindmap, user);
saveMindmapDocument(minor, mindmap, user);
}
@@ -263,7 +282,7 @@ public class MindmapController extends BaseController {
// Update map ...
final Mindmap mindmap = mindmapService.findMindmapById(id);
mindmap.setTitle(title);
saveMindmap(true, mindMap, user);
mindmapService.updateMindmap(mindMap, !true);
}
@RequestMapping(method = RequestMethod.PUT, value = "/maps/{id}/collabs", consumes = {"application/json", "application/xml"}, produces = {"application/json", "text/html", "application/xml"})
@@ -334,7 +353,7 @@ public class MindmapController extends BaseController {
// Update map ...
final Mindmap mindmap = mindmapService.findMindmapById(id);
mindmap.setDescription(description);
saveMindmap(true, mindMap, user);
mindmapService.updateMindmap(mindMap, !true);
}
@RequestMapping(method = RequestMethod.PUT, value = "/maps/{id}/publish", consumes = {"text/plain"}, produces = {"application/json", "text/html", "application/xml"})
@@ -350,13 +369,13 @@ public class MindmapController extends BaseController {
// Update map status ...
mindMap.setPublic(Boolean.parseBoolean(value));
saveMindmap(true, mindMap, user);
mindmapService.updateMindmap(mindMap, !true);
}
@RequestMapping(method = RequestMethod.DELETE, value = "/maps/{id}")
@ResponseStatus(value = HttpStatus.NO_CONTENT)
public void updateMap(@PathVariable int id) throws IOException, WiseMappingException {
public void deleteMapById(@PathVariable int id) throws IOException, WiseMappingException {
final User user = Utils.getUser();
final Mindmap mindmap = mindmapService.findMindmapById(id);
mindmapService.removeMindmap(mindmap, user);
@@ -489,7 +508,7 @@ public class MindmapController extends BaseController {
response.setHeader("ResourceId", Integer.toString(clonedMap.getId()));
}
private void saveMindmap(boolean minor, @NotNull final Mindmap mindMap, @NotNull final User user) throws WiseMappingException {
private void saveMindmapDocument(boolean minor, @NotNull final Mindmap mindMap, @NotNull final User user) throws WiseMappingException {
final Calendar now = Calendar.getInstance();
mindMap.setLastModificationTime(now);
mindMap.setLastEditor(user);

View File

@@ -36,7 +36,7 @@ public enum MindmapFilter {
MY_MAPS("my_maps") {
@Override
boolean accept(@NotNull Mindmap mindmap, @NotNull User user) {
return mindmap.getCreator().equals(user);
return mindmap.getCreator().identityEquality(user);
}
},
STARRED("starred") {

View File

@@ -23,6 +23,7 @@ import org.codehaus.jackson.annotate.JsonAutoDetect;
import org.codehaus.jackson.annotate.JsonIgnore;
import org.codehaus.jackson.annotate.JsonIgnoreProperties;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.springframework.context.MessageSource;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.validation.Errors;
@@ -56,6 +57,10 @@ public class RestErrors {
@JsonIgnore
Severity gSeverity;
@Nullable
@JsonIgnore
private String _debugInfo;
public RestErrors() {
}
@@ -64,17 +69,23 @@ public class RestErrors {
this.errors = errors;
this.messageSource = messageSource;
this.gErrors = this.processGlobalErrors(errors, messageSource);
this.gErrors = this.processGlobalErrors(errors);
this.gSeverity = Severity.WARNING;
}
public RestErrors(@NotNull String errorMsg, @NotNull Severity severity) {
gErrors = new ArrayList<String>();
gErrors.add(errorMsg);
this(errorMsg, severity, null);
}
public RestErrors(@NotNull String errorMsg, @NotNull Severity severity, @Nullable String debugInfo) {
this._debugInfo = debugInfo;
this.gErrors = new ArrayList<String>();
this.gErrors.add(errorMsg);
this.gSeverity = severity;
}
private List<String> processGlobalErrors(@NotNull Errors errors, @NotNull MessageSource messageSource) {
private List<String> processGlobalErrors(@NotNull Errors errors) {
final List<String> result = new ArrayList<String>();
final List<ObjectError> globalErrors = errors.getGlobalErrors();
for (ObjectError globalError : globalErrors) {
@@ -83,10 +94,6 @@ public class RestErrors {
return result;
}
public List<String> getGlobalErrors() {
return gErrors;
}
public void setGlobalErrors(List<String> list) {
// Implemented only for XML serialization contract ...
}
@@ -111,7 +118,23 @@ public class RestErrors {
// Implemented only for XML serialization contract ...
}
public void setDebugInfo(@Nullable String debugInfo) {
// Implemented only for XML serialization contract ...
}
@Nullable
public String getGlobalSeverity() {
return this.gSeverity.toString();
}
@Nullable
public String getDebugInfo() {
return _debugInfo;
}
public List<String> getGlobalErrors() {
return gErrors;
}
}

View File

@@ -68,7 +68,7 @@ public class RestLockInfo {
}
public boolean isLockedByMe() {
return isLocked() && lockInfo != null && lockInfo.getUser().equals(user);
return isLocked() && lockInfo != null && lockInfo.getUser().identityEquality(user);
}
public void setLockedByMe(boolean lockedForMe) {

View File

@@ -23,7 +23,6 @@ import com.wisemapping.model.User;
import org.codehaus.jackson.annotate.JsonAutoDetect;
import org.codehaus.jackson.annotate.JsonIgnore;
import org.codehaus.jackson.annotate.JsonIgnoreProperties;
import org.codehaus.jackson.map.annotate.JsonSerialize;
import org.jetbrains.annotations.NotNull;
import javax.xml.bind.annotation.XmlAccessType;
@@ -125,7 +124,7 @@ public class RestUser {
}
RestUser restUser = (RestUser) o;
return this.getDelegated().equals(restUser.getDelegated());
return this.getDelegated().identityEquality(restUser.getDelegated());
}
@Override

View File

@@ -59,14 +59,8 @@ public class TransformView extends AbstractView {
// Build format properties ...
final ExportProperties properties = ExportProperties.create(exportFormat);
if (properties instanceof ExportProperties.ImageProperties) {
final String sizeStr = request.getParameter(IMG_SIZE_PARAMETER);
final ExportProperties.ImageProperties imageProperties = (ExportProperties.ImageProperties) properties;
if (sizeStr != null) {
final ExportProperties.ImageProperties.Size size = ExportProperties.ImageProperties.Size.valueOf(sizeStr);
imageProperties.setSize(size);
} else {
imageProperties.setSize(ExportProperties.ImageProperties.Size.MEDIUM);
}
imageProperties.setSize(ExportProperties.ImageProperties.Size.LARGE);
}
// Set format content type...
@@ -103,6 +97,4 @@ public class TransformView extends AbstractView {
public String getContentType() {
return contentType;
}
private static final String IMG_SIZE_PARAMETER = "imgSize";
}

View File

@@ -27,10 +27,10 @@ import java.util.ArrayList;
import java.util.Collection;
public class UserDetails implements org.springframework.security.core.userdetails.UserDetails {
private com.wisemapping.model.User user;
private com.wisemapping.model.User user;
private boolean isAdmin;
public UserDetails(@NotNull final com.wisemapping.model.User user, boolean isAdmin) {
public UserDetails(@NotNull final com.wisemapping.model.User user, boolean isAdmin) {
this.user = user;
this.isAdmin = isAdmin;
}

View File

@@ -18,13 +18,12 @@
package com.wisemapping.security;
import com.wisemapping.dao.UserManager;
import com.wisemapping.model.User;
import com.wisemapping.service.UserService;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.dao.DataAccessException;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
@@ -37,7 +36,7 @@ public class UserDetailsService
@Override
public UserDetails loadUserByUsername(@NotNull String email) throws UsernameNotFoundException, DataAccessException {
final User user = userService.getUserBy(email);
if (user != null) {
return new UserDetails(user, isAdmin(email));
} else {

View File

@@ -41,7 +41,7 @@ public abstract class BaseSecurityAdvice {
isAllowed = isAllowed(user, ((Integer) argument));
} else if (argument instanceof Collaborator) {
// Read operation find on the user are allowed ...
isAllowed = user.equals(argument);
isAllowed = user.identityEquality((Collaborator) argument);
} else {
throw new IllegalArgumentException("Argument " + argument);
}

View File

@@ -0,0 +1,79 @@
package com.wisemapping.security.ldap;
import com.wisemapping.exceptions.WiseMappingException;
import com.wisemapping.model.User;
import com.wisemapping.security.UserDetails;
import com.wisemapping.service.UserService;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.springframework.ldap.core.DirContextAdapter;
import org.springframework.ldap.core.DirContextOperations;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.ldap.userdetails.UserDetailsContextMapper;
import java.util.Calendar;
import java.util.Collection;
public class LdapUserDetailsContextMapper implements UserDetailsContextMapper {
private UserService userService;
private String adminUser;
public UserService getUserService() {
return userService;
}
public void setUserService(UserService userService) {
this.userService = userService;
}
private boolean isAdmin(@Nullable String email) {
return email != null && adminUser != null && email.trim().endsWith(adminUser);
}
public String getAdminUser() {
return adminUser;
}
public void setAdminUser(String adminUser) {
this.adminUser = adminUser;
}
@Override
public UserDetails mapUserFromContext(@NotNull DirContextOperations userData,
String email, Collection<? extends GrantedAuthority> arg2) {
User user = userService.getUserBy(email);
if (user == null) {
// If the user was not found in the database, create a new one ...
user = new User();
user.setEmail(email);
final String firstName = userData.getStringAttribute("givenName");
user.setFirstname(firstName);
final String lastName = userData.getStringAttribute("sn");
user.setLastname(lastName);
user.setPassword(email);
final Calendar now = Calendar.getInstance();
user.setActivationDate(now);
try {
userService.createUser(user, false,false);
} catch (WiseMappingException e) {
throw new IllegalStateException(e);
}
}
return new UserDetails(user, isAdmin(email));
}
@Override
public void mapUserToContext(org.springframework.security.core.userdetails.UserDetails userDetails, DirContextAdapter dirContextAdapter) {
// To be implemented ...
}
}

View File

@@ -36,6 +36,7 @@ public class LockInfo {
this.user = user;
this.updateTimeout();
this.updateTimestamp(mindmap);
this.session = session;
}
public User getUser() {

View File

@@ -30,13 +30,17 @@ public interface LockManager {
LockInfo getLockInfo(@NotNull Mindmap mindmap);
LockInfo updateExpirationTimeout(@NotNull Mindmap mindmap, @NotNull User user,long session);
LockInfo updateExpirationTimeout(@NotNull Mindmap mindmap, @NotNull User user);
void unlock(@NotNull Mindmap mindmap, @NotNull User user) throws LockException, AccessDeniedSecurityException;
boolean isLockedBy(@NotNull Mindmap mindmap, @NotNull User collaborator);
@NotNull
LockInfo lock(@NotNull Mindmap mindmap, @NotNull User user, long session) throws WiseMappingException;
@NotNull
LockInfo lock(@NotNull Mindmap mindmap, @NotNull User user) throws WiseMappingException;
long generateSession();
}

View File

@@ -63,20 +63,19 @@ class LockManagerImpl implements LockManager {
}
@Override
public LockInfo updateExpirationTimeout(@NotNull Mindmap mindmap, @NotNull User user, long session) {
public LockInfo updateExpirationTimeout(@NotNull Mindmap mindmap, @NotNull User user) {
if (!this.isLocked(mindmap)) {
throw new IllegalStateException("Lock lost for map. No update possible.");
}
final LockInfo result = this.getLockInfo(mindmap);
if (!result.getUser().equals(user)) {
if (!result.getUser().identityEquality(user)) {
throw new IllegalStateException("Could not update map lock timeout if you are not the locking user. User:" + result.getUser() + ", " + user);
}
result.updateTimeout();
result.setSession(session);
result.updateTimestamp(mindmap);
// logger.debug("Timeout updated for:" + mindmap.getId());
logger.debug("Timeout updated for:" + mindmap.getId());
return result;
}
@@ -102,12 +101,24 @@ class LockManagerImpl implements LockManager {
public boolean isLockedBy(@NotNull Mindmap mindmap, @NotNull User collaborator) {
boolean result = false;
final LockInfo lockInfo = this.getLockInfo(mindmap);
if (lockInfo != null && lockInfo.getUser().equals(collaborator)) {
if (lockInfo != null && lockInfo.getUser().identityEquality(collaborator)) {
result = true;
}
return result;
}
@Override
@NotNull
public LockInfo lock(@NotNull Mindmap mindmap, @NotNull User user) throws WiseMappingException {
return this.lock(mindmap, user, System.nanoTime());
}
@Override
public long generateSession() {
return System.nanoTime();
}
@Override
@NotNull
public LockInfo lock(@NotNull Mindmap mindmap, @NotNull User user, long session) throws WiseMappingException {
@@ -123,7 +134,8 @@ class LockManagerImpl implements LockManager {
if (result != null) {
// Update timeout only...
logger.debug("Update timestamp:" + mindmap.getId());
updateExpirationTimeout(mindmap, user, session);
updateExpirationTimeout(mindmap, user);
// result.setSession(session);
} else {
logger.debug("Lock map id:" + mindmap.getId());
result = new LockInfo(user, mindmap, session);
@@ -132,11 +144,6 @@ class LockManagerImpl implements LockManager {
return result;
}
@Override
public long generateSession() {
return System.nanoTime();
}
public LockManagerImpl() {
lockInfoByMapId = new ConcurrentHashMap<Integer, LockInfo>();
expirationTimer.schedule(new TimerTask() {

View File

@@ -23,6 +23,7 @@ import com.wisemapping.exceptions.WiseMappingException;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.IOException;
import java.util.List;
public interface MindmapService {
@@ -57,7 +58,7 @@ public interface MindmapService {
boolean hasPermissions(@Nullable User user, int mapId, CollaborationRole allowedRole);
void revertChange(@NotNull Mindmap map, int historyId) throws WiseMappingException;
void revertChange(@NotNull Mindmap map, int historyId) throws WiseMappingException, IOException;
MindMapHistory findMindmapHistory(int id, int hid) throws WiseMappingException;

View File

@@ -28,7 +28,10 @@ import org.jetbrains.annotations.Nullable;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import java.util.*;
import java.io.IOException;
import java.util.Calendar;
import java.util.List;
import java.util.Set;
public class MindmapServiceImpl
@@ -114,18 +117,19 @@ public class MindmapServiceImpl
final Mindmap mindMap = collaboration.getMindMap();
final Set<Collaboration> collaborations = mindMap.getCollaborations();
if (mindMap.getCreator().getEmail().equals(collaboration.getCollaborator().getEmail())) {
final User creator = mindMap.getCreator();
if (creator.identityEquality(collaboration.getCollaborator())) {
throw new CollaborationException("User is the creator and must have ownership permissions.Creator Email:" + mindMap.getCreator().getEmail() + ",Collaborator:" + collaboration.getCollaborator().getEmail());
}
// When you delete an object from hibernate you have to delete it from *all* collections it exists in...
mindmapManager.removeCollaboration(collaboration);
collaborations.remove(collaboration);
mindmapManager.removeCollaboration(collaboration);
}
@Override
public void removeMindmap(@NotNull Mindmap mindmap, @NotNull User user) throws WiseMappingException {
if (mindmap.getCreator().equals(user)) {
if (mindmap.getCreator().identityEquality(user)) {
mindmapManager.removeMindmap(mindmap);
} else {
final Collaboration collaboration = mindmap.findCollaboration(user);
@@ -239,9 +243,9 @@ public class MindmapServiceImpl
@Override
public void revertChange(@NotNull Mindmap mindmap, int historyId)
throws WiseMappingException {
throws WiseMappingException, IOException {
final MindMapHistory history = mindmapManager.getHistory(historyId);
mindmap.setXml(history.getXml());
mindmap.setZippedXml(history.getXml());
updateMindmap(mindmap, true);
}
@@ -264,7 +268,7 @@ public class MindmapServiceImpl
@Override
public void updateCollaboration(@NotNull Collaborator collaborator, @NotNull Collaboration collaboration) throws WiseMappingException {
if (collaborator.equals(collaboration.getCollaborator())) {
if (!collaborator.identityEquality(collaboration.getCollaborator())) {
throw new WiseMappingException("No enough permissions for this operation.");
}
mindmapManager.updateCollaboration(collaboration);
@@ -276,7 +280,7 @@ public class MindmapServiceImpl
return this.lockManager;
}
private Collaboration getCollaborationBy(String email, Set<Collaboration> collaborations) {
private Collaboration getCollaborationBy(@NotNull final String email, @NotNull final Set<Collaboration> collaborations) {
Collaboration collaboration = null;
for (Collaboration user : collaborations) {

View File

@@ -26,7 +26,7 @@ public interface UserService {
public void activateAccount(long code) throws InvalidActivationCodeException;
public User createUser(@NotNull User user, boolean emailConfirmEnabled) throws WiseMappingException;
public User createUser(@NotNull User user, boolean emailConfirmEnabled,boolean welcomeEmail) throws WiseMappingException;
public void changePassword(@NotNull User user);
@@ -41,4 +41,6 @@ public interface UserService {
public void deleteUser(@NotNull User user);
public void auditLogin(@NotNull User user);
public User getCasUserBy(String uid);
}

View File

@@ -107,7 +107,7 @@ public class UserServiceImpl
userManager.auditLogin(accessAuditory);
}
public User createUser(@NotNull User user, boolean emailConfirmEnabled) throws WiseMappingException {
public User createUser(@NotNull User user, boolean emailConfirmEnabled, boolean welcomeEmail) throws WiseMappingException {
final UUID uuid = UUID.randomUUID();
user.setCreationDate(Calendar.getInstance());
user.setActivationCode(uuid.getLeastSignificantBits());
@@ -120,6 +120,7 @@ public class UserServiceImpl
}
Collaborator col = userManager.getCollaboratorBy(user.getEmail());
if (col != null) {
userManager.createUser(user, col);
} else {
@@ -134,7 +135,7 @@ public class UserServiceImpl
// Send registration email.
if (emailConfirmEnabled) {
notificationService.sendRegistrationEmail(user);
} else {
} else if (welcomeEmail) {
// Send a welcome email ..
notificationService.newAccountCreated(user);
}
@@ -205,4 +206,10 @@ public class UserServiceImpl
public void setVelocityEngine(VelocityEngine velocityEngine) {
this.velocityEngine = velocityEngine;
}
@Override
public User getCasUserBy(String uid) {
// TODO Auto-generated method stub
return null;
}
}

View File

@@ -18,67 +18,46 @@
package com.wisemapping.util;
import java.io.IOException;
import org.apache.commons.io.IOUtils;
import org.jetbrains.annotations.NotNull;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.nio.charset.Charset;
import java.io.IOException;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;
import java.util.zip.ZipEntry;
public class ZipUtils {
public static String zipToString(byte[] zip) throws IOException {
public static byte[] zipToBytes(byte[] zip) throws IOException {
String result = null;
if (zip != null)
{
byte[] result = null;
if (zip != null) {
final ByteArrayInputStream in = new ByteArrayInputStream(zip);
final ZipInputStream zipIn = new ZipInputStream(in);
zipIn.getNextEntry();
byte[] buffer = new byte[512];
int len;
StringBuilder sb_result = new StringBuilder();
while ((len = zipIn.read(buffer)) > 0) {
sb_result.append(new String(buffer, 0, len, Charset.forName("UTF-8")));
}
result = IOUtils.toByteArray(zipIn);
zipIn.closeEntry();
zipIn.close();
result = sb_result.toString();
}
return result;
}
public static byte[] stringToZip(String content) throws IOException {
public static byte[] bytesToZip(@NotNull final byte[] content) throws IOException {
ZipOutputStream zip = null;
ByteArrayOutputStream byteArray = new ByteArrayOutputStream();
ByteArrayInputStream in = new ByteArrayInputStream(content.getBytes("UTF-8"));
final ByteArrayOutputStream byteArray = new ByteArrayOutputStream();
try {
zip = new ZipOutputStream(byteArray);
ZipEntry zEntry = new ZipEntry("content");
zip.putNextEntry(zEntry);
int bytesRead;
byte[] buffer = new byte[8192];
while ((bytesRead = in.read(buffer, 0, 8192)) != -1) {
zip.write(buffer, 0, bytesRead);
}
IOUtils.write(content, zip);
zip.closeEntry();
}
finally
{
if (zip != null)
{
} finally {
if (zip != null) {
zip.flush();
zip.close();
}

View File

@@ -26,8 +26,9 @@ import org.jetbrains.annotations.Nullable;
import java.io.IOException;
import java.text.DateFormat;
import java.util.*;
import java.util.regex.Pattern;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
public class MindMapBean {
private Mindmap mindmap;
@@ -124,10 +125,7 @@ public class MindMapBean {
}
public String getXmlAsJsLiteral() throws IOException {
final String xmlAsJsLiteral = this.mindmap.getXmlAsJsLiteral();
// Firefox is failing for this. Need to be reviewed ...
return xmlAsJsLiteral.replace("\\u0000","");
return this.mindmap.getXmlAsJsLiteral();
}
public String getProperties() throws WiseMappingException {

View File

@@ -0,0 +1,52 @@
/*
* Copyright [2012] [wisemapping]
*
* Licensed under WiseMapping Public License, Version 1.0 (the "License").
* It is basically the Apache License, Version 2.0 (the "License") plus the
* "powered by wisemapping" text requirement on every single page;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the license at
*
* http://www.wisemapping.org/license
*
* 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 com.wisemapping.webmvc;
import org.jetbrains.annotations.NotNull;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
import org.springframework.core.env.PropertiesPropertySource;
import org.springframework.core.env.PropertySourcesPropertyResolver;
import org.springframework.core.io.Resource;
import org.springframework.core.io.UrlResource;
import org.springframework.core.io.support.ResourcePropertySource;
import org.springframework.web.context.ConfigurableWebApplicationContext;
import org.springframework.web.context.support.ServletContextResource;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Properties;
public class ApplicationContextInitializer implements org.springframework.context.ApplicationContextInitializer<ConfigurableWebApplicationContext> {
public void initialize(@NotNull ConfigurableWebApplicationContext ctx) {
try {
final Resource resource = new ServletContextResource(ctx.getServletContext(), "/WEB-INF/app.properties");
final ResourcePropertySource resourcePropertySource = new ResourcePropertySource(resource);
ctx.getEnvironment().getPropertySources().addFirst(resourcePropertySource);
} catch (IOException e) {
throw new IllegalStateException(e);
}
}
}

View File

@@ -21,11 +21,10 @@ package com.wisemapping.webmvc;
import com.wisemapping.exceptions.WiseMappingException;
import com.wisemapping.model.CollaborationRole;
import com.wisemapping.model.Mindmap;
import com.wisemapping.model.MindMapHistory;
import com.wisemapping.model.Mindmap;
import com.wisemapping.model.User;
import com.wisemapping.security.Utils;
import com.wisemapping.service.LockInfo;
import com.wisemapping.service.LockManager;
import com.wisemapping.service.MindmapService;
import com.wisemapping.view.MindMapBean;
@@ -36,9 +35,13 @@ import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.Locale;
@@ -46,24 +49,21 @@ import java.util.Locale;
public class MindmapController {
public static final String LOCK_SESSION_ATTRIBUTE = "lockSession";
@Qualifier("mindmapService")
@Autowired
private MindmapService mindmapService;
@Value("${site.baseurl}")
String siteBaseUrl;
@RequestMapping(value = "maps/import")
public String showImportPage() {
return "mindmapImport";
}
@RequestMapping(value = "maps/{id}/details")
public String showDetails(@PathVariable int id, @NotNull Model model) {
public String showDetails(@PathVariable int id, @NotNull Model model,@NotNull HttpServletRequest request) {
final MindMapBean mindmap = findMindmapBean(id);
model.addAttribute("mindmap", mindmap);
model.addAttribute("baseUrl", siteBaseUrl);
model.addAttribute("baseUrl", request.getAttribute("site.baseurl"));
return "mindmapDetail";
}
@@ -104,16 +104,16 @@ public class MindmapController {
}
@RequestMapping(value = "maps/{id}/publish")
public String showPublishPage(@PathVariable int id, @NotNull Model model) {
public String showPublishPage(@PathVariable int id, @NotNull Model model,@NotNull HttpServletRequest request) {
final Mindmap mindmap = findMindmap(id);
model.addAttribute("mindmap", mindmap);
model.addAttribute("baseUrl", siteBaseUrl);
model.addAttribute("baseUrl", request.getAttribute("site.baseurl"));
return "mindmapPublish";
}
@RequestMapping(value = "maps/{id}/publishf")
public String showPublishPageFull(@PathVariable int id, @NotNull Model model) {
showPublishPage(id, model);
public String showPublishPageFull(@PathVariable int id, @NotNull Model model,@NotNull HttpServletRequest request) {
showPublishPage(id, model,request);
return "mindmapPublishFull";
}
@@ -158,12 +158,10 @@ public class MindmapController {
final LockManager lockManager = this.mindmapService.getLockManager();
if (lockManager.isLocked(mindmap) && !lockManager.isLockedBy(mindmap, collaborator)) {
readOnlyMode = true;
model.addAttribute("mindmapLocked",true);
model.addAttribute("mindmapLocked", true);
} else {
final long session = lockManager.generateSession();
final LockInfo lock = lockManager.lock(mindmap, collaborator, session);
model.addAttribute("lockTimestamp", lock.getTimestamp());
model.addAttribute("lockSession", session);
model.addAttribute("lockTimestamp", mindmap.getLastModificationTime().getTimeInMillis());
model.addAttribute(LOCK_SESSION_ATTRIBUTE, lockManager.generateSession());
}
model.addAttribute("lockInfo", lockManager.getLockInfo(mindmap));
}
@@ -196,12 +194,7 @@ public class MindmapController {
final String result = showMindmapEditorPage(id, model);
model.addAttribute("readOnlyMode", true);
// Change map XML ....
final MindMapBean mindmapBean = (MindMapBean) model.asMap().get("mindmap");
final MindMapHistory mindmapHistory = mindmapService.findMindmapHistory(id, hid);
mindmapBean.getDelegated().setXml(mindmapHistory.getXml());
model.addAttribute("hid",String.valueOf(hid));
return result;
}

View File

@@ -110,7 +110,7 @@ public class UsersController {
user.setPassword(userBean.getPassword());
boolean confirmRegistrationByEmail = false;
userService.createUser(user, confirmRegistrationByEmail);
userService.createUser(user, confirmRegistrationByEmail,true);
// Forward to the success view ...
result = new ModelAndView("userRegistrationSuccess");

View File

@@ -11,7 +11,7 @@
</id>
<property name="loginDate" column="login_Date"/>
<many-to-one name="user"
column="USER_ID"
column="user_id"
not-null="true"
class="com.wisemapping.model.User"
/>

View File

@@ -10,17 +10,17 @@
<generator class="increment"/>
</id>
<property name="roleId" column="ROLE_ID" unique="true" not-null="true"/>
<property name="roleId" column="role_id" unique="true" not-null="true"/>
<!-- Read-only association property -->
<many-to-one name="mindMap"
column="MINDMAP_ID"
column="mindmap_id"
not-null="true"
class="com.wisemapping.model.Mindmap"
/>
<many-to-one name="collaborator"
column="COLABORATOR_ID"
column="colaborator_id"
not-null="true"
class="com.wisemapping.model.Collaborator"
/>

View File

@@ -15,12 +15,12 @@
<set name="collaborations"
cascade="all, delete-orphan"
inverse="true">
<key column="COLABORATOR_ID" not-null="true"/>
<key column="colaborator_id" not-null="true"/>
<one-to-many class="com.wisemapping.model.Collaboration"/>
</set>
<joined-subclass name="com.wisemapping.model.User" table="USER">
<key column="COLABORATOR_ID"/>
<key column="colaborator_id"/>
<property name="firstname"/>
<property name="lastname"/>
<property name="password"/>

View File

@@ -11,7 +11,7 @@
</id>
<property name="mindmapId" column="mindmap_id"/>
<property name="xml" column="XML"/>
<property name="xml" column="xml"/>
<property name="creationTime" column="creation_date"/>
<many-to-one name="editor" column="editor_id" unique="false" not-null="false" lazy="proxy"/>
</class>

View File

@@ -22,7 +22,7 @@
<set name="collaborations"
cascade="all,delete-orphan,save-update"
inverse="true">
<key column="MINDMAP_ID" not-null="true"/>
<key column="mindmap_id" not-null="true"/>
<one-to-many class="com.wisemapping.model.Collaboration"/>
</set>
</class>

View File

@@ -0,0 +1,261 @@
# Default German Support.
NAME=Name
DESCRIPTION=Beschreibung
ADD=Hinzufügen
VIEWERS=Betrachter
USER_REGISTRATION=Benutzerregistrierung
SEND_ME_A_NEW_PASSWORD=Schicke mir ein neues Passwort
CANCEL=Abbrechen
FIRSTNAME=Vorname
LASTNAME=Nachname
EMAIL=Email
HELP=Hilfe
LOGOUT=Abmelden
PASSWORD=Passwort
NEW_PASSWORD=Neues Passwort
CONFIRM_NEW_PASSWORD=Bestätige neues Passwort
MY_WISEMAPS=Meine Wisemaps
RETYPE_PASSWORD=Schreibe Passwort nochmal
REGISTER=Registrierung
REMEMBER_ME=Bleibe angemeldet
SIGN_IN=Anmelden
SIGN_UP=Mitglied werden
ACCOUNT=Benutzerkonto
USERNAME=Benutzername
CLOSE=Schliessen
NOT_READY_A_USER=Noch kein Mitglied?
NOT_READY_A_USER_MESSAGE=Die Mitgliedschaft ist frei und die Registrierung dauert nur einen kurzen Moment
JOIN_NOW=Trete bei!
YOUR_ROLE=Deine Rolle
FORGOT_PASSWORD=Passwort vergessen ?
CHANGE_PASSWORD=Ändere Passwort
CHANGE_LANGUAGE=Ändere Sprache
FAQ=Häufig gestellte Fragen
SHORT_FAQ=FAQ
LOGIN=Anmelden
EXPORT=Exportieren
SVG_EXPORT_FORMAT=Skalierbare Vektor Graphik (SVG)
PDF_EXPORT_FORMAT=Portables Dokumenten Format (PDF)
IMG_EXPORT_FORMAT=Bilddatei (PNG/JPEG)
FREEMIND_EXPORT_FORMAT = Freemind (version 0.9.0)
WISEMAPPING_EXPORT_FORMAT = WiseMapping
LAST_UPDATE=Zuletzt geändert
LAST_UPDATE_BY=Zuletzt geändert von
DELETE=Löschen
SITE.TITLE=WiseMapping
SITE.SLOGAN=Evolution des Visuellen Denkens
KEYBOARD=Tastaturkürzel
KEYBOARD_MSG=Das sind die Tastaturkürzel, die im Editor benutzt werden können!
HOME=Eingangsseite
LOGIN_ERROR=Die eingegebene email Adresse oder das Passwort ist nicht korrekt.
USER_INACTIVE=Ihr Benutzerkonto ist leider noch nicht aktiviert. Sie bekommen eine Benachrrichtigung in Form einer email sobald Ihr Benutzerkonto aktiv ist. Bitte haben Sie noch ein wenig Geduld!
CREW=Die Mannschaft
ALREADY_A_MEMBER=Bereits Mitglied?
TERM_OF_THE_SERVICE=Geschäftsbedingungen
FORGOT_PASSWORD_MESSAGE=Bitte geben Sie eine email Adresse an, damit wir Ihnen helfen können Ihr WiseMapping Konto ausfindig zu machen.
FIELD_REQUIRED=Ein benötigtes Feld kann icht leer gelassen werden
EMAIL_ALREADY_EXIST=Die email Adresse existiert bereits
NO_VALID_EMAIL_ADDRESS=Ungültige email Adresse
USERNAME_ALREADY_EXIST=Der Benutzername existiert bereits
PASSWORD_MISSMATCH=Ihre Passwort Angaben sind nicht identisch
CHANGE_PASSWORD_SUCCESS=Ihr Passwort wurde erfolgreich geändert
WISEMAPPING_ACCOUNT_MESSAGE=Bitte überprüfen Sie die eingegebenen WiseMapping Benutzerkonto Informationen und Geschäftsbedingungen
REGISTRATION_CLICK_ADVICE= Mit der Registrierung erklären Sie ihr Einverständnis mit den Geschäftsbedingungen und Datenschutzregeln von WiseMapping.
REGISTRATION_TITLE_MSG=Bitte fülle die Felder aus, um ein Mitglied der WiseMapping Gemeinschaft zu werden. Die Registrierung is <b>kostenlos</b> und in wenigen Augenblicken erledigt.
CAPTCHA_ERROR=Bitte geben Sie die Buchstaben wie auf dem Bild dargestellt ein.
CREATOR=Urheber
CREATION_TIME=Erstellungs Datum
EDITORS=Verfasser
PUBLIC=Öffentlich
SHARED=Gemeinsam benutzt
ONLY_VIEW_PRIVATE = Diese mindmap kann nur von Ihnen angeschaut werden.
ALL_VIEW_PUBLIC = Diese mindamp können alle Benutzer anschauen.
NEW_MAP_MSG=Erzeuge eine neue map
PUBLISH=Veröffentlichen
PUBLISH_DETAILS=Die Veröffentlichung dieser map macht sie für alle Benutzer im Internet sichtbar.
ACCOUNT_DETAIL=Möchten Sie ihre Benutzereinstellungen ändern? Dann sind Sie hier richtig.
SVG_EXPORT_FORMAT_DETAILS=Skalierbare Vektor Graphik (SVG) ist ein XML Format zur Beschreibung von zwei-dimensionalen Vektorgraphiken. Dieses Format erlaubt den Druck Ihrer maps ohne Verlust von Qualität bei egal welcher Auflösung.
PDF_EXPORT_FORMAT_DETAILS=Exportieren Sie ihre map im Portablen Dokumenten Format (PDF) zur Verwendung in Präsentationen.
IMG_EXPORT_FORMAT_DETAILS=Exportieren Sie eine graphische Repräsentation Ihrer map mit allen Farben und Formen zur Verwendung in Dokumenten oder zur Archivierung.
FREEMIND_EXPORT_FORMAT_DETAILS = FreeMind ist eine schöne und frei erhältliche "Desktop" MindMapping Applikation.
WISEMAPPING_EXPORT_FORMAT_DETAILS = Exportieren Sie ihre map im WiseMapping Dokumentenformat.
TERMSOFUSE=Geschäftsbedingungen
PRIVACYPOLICY= Datenschutzrichtlinien
EXPORT_DETAILS=Exportieren Sie ihre map in einem von Ihnen gewünschtem Format zur Verwendung in Präsentationen oder Weiterleitung mittles elektronischer Post (email).
HERE=hier
WHO_ARE_WE=Wer sind wir?
WELCOME=Willkommen
RENAME=Umbenennen
MAX_CHARACTER_SIZE= Maximal erlaubte Nachrichtenlänge von 512 Buchstaben.
URL=URL
DIRECT_LINK=Direkte Verbindung
BLOG_INCLUSION=Sie können das Quelltextfragment zur Einbettung in Ihren Blog oder Internet Seite anpassen. Stellen Sie sicher, das die korrekten Dimensionen der Darstellungsfläche in ihrer Seite eingestellt sind damit Ihre map sich optimal in Ihre Seite einfügt.
BLOG_SNIPPET=Kopieren Sie dieses Quelltextfragment zur Einbindung in Ihren Blog oder Internet Seite.
ZOOM=Zoom
HISTORY=Historie
SHARE=Veröffentlichen
UNEXPECTED_ERROR=Outch!!. Ein unerwarteter Fehler ist aufgetreten.
UNEXPECTED_ERROR_DETAILS=Es tut uns Leid! Es ist ein Fehler aufgetreten der es uns nicht ermöglicht Ihre Anfrage zu bearbeiten. Bitte versuchen Sie es noch einmal oder gehen Sie zur Anfangsseite.
UNEXPECTED_ERROR_SERVER_ERROR=Es tut uns Leid! Es ist ein Fehler aufgetreten der es uns nicht ermöglicht Ihre Anfrage zu bearbeiten. Aktualisieren Sie diese Seite und versuchen es erneut. Falls der Fehler wieder auftritt, kontaktieren Sie bitte support@wisemapping.com
NO_ENOUGH_PERMISSIONS=Outch!!. Diese map ist nicht mehr verfügbar.
NO_ENOUGH_PERMISSIONS_DETAILS=Sie haben nicht die erforderlichen Rechte, um sich diese map anzusehen. Diese map ist entweder privat oder wurde gelöscht.
IMPORT_MINDMAP_INFO=Sie können FreeMind 0.9 und WiseMapping maps in Ihre List von maps importieren. Wählen Sie die Datei zum Import.
PRINT=Drucken
IMPORT_MAP_ERROR=FreeMind Datei konnte nicht importiert werden. {0}
MAP_TITLE_ALREADY_EXISTS=Sie haben schon eine map mit identischem Namen.
#####FOOTER
COPYRIGHT=Powered by WiseMapping
TERMS_AND_CONDITIONS=Allgemeine Geschäftsbedingungen
CONTACT=Kontakt
ACCOUNT_ACTIVED= Ihr Benutzerkonto wurde aktiviert.
ACCOUNT_ACTIVED_FAIL = Die Aktivierung Ihres Benutzerkonto ist fehlgeschlagen.
NO_HISTORY_RESULTS= Keine Historie verfügbar.
REVERT=rückgängig
INVALID_EMAIL_ERROR = Die email wurde nicht verifiziert.
NO_PRODUCTION_DATABASE_CONFIGURED=Obzwar HSQLDB mit WiseMapping in der Stadardinstallation gebündelt ist, empfehlen wir nicht die Benutzung von HSQLDB in Produktionsumgebungen. Anstatt, bitte verwenden Sie MySQL Version 5.5
IMPORT=Importieren
EMBEDDED_MAP_SIZE=* Hinweis: Sie können die eingebettete Größe der map mit Hife der Parameter 'height' und 'width' einstellen. Sie können ausserdem den Zoom Faktor mit Hilfe des Parameters 'zoom' in der URL einstellen.
EXPORT_FORMAT_RESTRICTIONS=Der Export als Bild, PDF oder SVG ist nur in der Editor Menüleiste verfügbar.
STARRED=Favorit
ALL_MAPS=Alle
MY_MAPS=Meine Maps
SHARED_WITH_ME=Gemeinsam mit mir genutzt
PUBLIC_MAPS=Öffentliche Maps
ACCEPT=Akzeptiert
SAVING=Sichern ...
INFO=Information
DELETE_MINDMAP=Löschen
DUPLICATE=Dulizieren
CREATE=Anlegen
LANGUAGE=Sprache
FILTERS=Filter
MORE=Mehr
ADD_NEW_MAP=Füge neue Map hinzu
IMPORTING=Importieren ...
NEW=Neu
MIND_FILE=Datei
NO_SEARCH_RESULT=Keine map für das gewählte Filterkriterium gefunden.
SEARCH=Suche
GENERAL=Allgemein
SECURITY=Sicherheit
MAP_NAME_HINT=Name der zu erzeugenden map
MAP_DESCRIPTION_HINT=Kurzbeschreibung der map
WARNING=Warnung
DELETE_MAPS_WARNING=Eine gelöschte mindmap kann nicht wieder hergestellt werden. Möchten Sie fortfahren?
THANKS_FOR_SIGN_UP=Vielen Dank für die Registrierung!
SIGN_UP_CONFIRMATION_EMAIL=\ Sie werden in kürze eine Bestätigungsnachricht von WiseMapping erhalten. Darin werden Sie gebeten, Ihr WiseMapping Benutzerkonto zu aktivieren.</br>Bitte wählen Sie die Verbindung in dieser email zur Aktivierung. Danach können Sie eigene maps anlegen und veröffentlichen.
SIGN_UP_SUCCESS=Ihr Benutzerkonot wurde erfolgreich angelegt, drücken Sie <a href\="c/login">hier</a> um sich anzumelden und WiseMapping zu geniessen.
ACCOUNT_DOES_NOT_EXISTS=Diese Nachricht ist nicht registriert oder Ihr Benutzerkonto ist noch nicht aktiviert.
ACCOUNT_DOES_NOT_EXISTS_SUPPORT=Falls das Problem weiterhin auftritt dann senden Sie uns bitte eine Nachricht an <a href\="mailto\:support@wisemapping.com">support@wisemapping.com </a>
SENDING=Senden ...
SIGN_ING=Anmelden ...
ENABLE_PUBLISHING=Mitbenutzung einschalten
FRAME_HEIGHT=Rahmenhöhe
FRAME_WIDTH=Rahmenbreite
EMBED=Eingebettet
PUBLIC_URL=Öffentliche URLs
ADD_PEOPLE=Personen hinzufügen
COLLABORATORS_SEPARATED_BY_COMA=Geben Sie die email Adresse der Mitbenutzer als Komma separierte Liste an
CAN_EDIT=Kann Ändern
CAN_VIEW=Kann Anschauen
EMAIL_NOTIFICATION_MESSAGE=Email Benachrichtigung Einstellungen
ADD_MESSAGE=Nachricht hinzufügen
WHO_CAN_ACCESS=Wer hat Zugriff
IS_OWNER=Ist Besitzer
OPTIONAL_CUSTOM_MESSAGE=Optional\: Fügen Sie eine persönliche Nachricht ein
VIEW=Ansicht
YOU=Sie
INFO_UPDATE_SUCCESS=Ihre Daten sind erfolgreich geändert worden
OR_GREATER=oder größer
IMPORTANT=Wichtig
BROWSER_RECOMMENDATION=Die Browser sind nach Geschwindigkeit und Ausführlichkeit der Tests durch das WiseMappig Team sortiert.
BROWSER_NOT_SUPPORTED_TITLE=Ups\!\!\!. Ihr Browser ist momentan nicht unterstützt!
BROWSER_NOT_SUPPORTED_MSG=Ihr Browser wurde nicht vollständig mit der WiseMapping Applikation getestet, s.d. manche Funktionen nicht zur Verfügung stehen. WiseMapping wurde optimiert für:
BROWSER_NOT_SUPPORTED_TRY_AGAIN=Bitte versuchen Sie es nocheinmal mit einem von WiseMapping unterstützten Browser.
INSTALL_CFG=Tut uns Leid, Microsoft Internet Explorer 8 ist nur teilweise unterstützt.
INSTALL_CFG_REASON = Microsoft Internet Explorer 8 hat keine Unterstützung für HTML 5 SVG. SVG ist die von WiseMapping benutzte Technologie, um mindmaps zu editieren und anzuzeigen. Wir empfehlen eine Aktualisierung auf Microsoft Internet Explorer 9 oder die Benutzung eines anderen Browser wie z.B. Google Chrome, Firefox oder Safari.
INSTALL_CFG_CLICK_HERE=Falls Sie dennoch Microsoft Internet Explorer 8 benutzen möchten, drücken Sie hier, um das Gogle Chrome Frame Plugin zu instalieren. Das Google Chrome Frame Plugin erweitert Internet Explorer mit Unterstützung für HTML 5.
SHOW_REGISTERS=Zeige _MENU_ Einträge
LOADING=Laden ...
NO_MATCHING_FOUND=Keine passenden Einträge gefunden
TABLE_ROWS=_START_-_END_ von _TOTAL_
ACTION=Aktion
CREATE_SIBLING_TOPIC=Erzeuge ein Schwester Thema
CREATE_CHILD_TOPIC=Eryeuge ein Unterthema
DELETE_TOPIC=Lösche Thema
EDIT_TOPIC_TEXT=Editiere Thematext
JUST_START_TYPING=Einfach mit der Eingabe beginnen
CANCEL_TEXT_CHANGES=Textänderungen abbrechen
TOPIC_NAVIGATION=Themen Navigation
ARROW_KEYS=Pfeiltasten
SELECT_MULTIPLE_NODES=Wähle mehrfache Knoten aus
UNDO_EDITION=Änderungen rückgängig machen
REDO_EDITION=Änderung nochmal ausführen
SELECT_ALL_TOPIC=Wähle alle Themen aus
CHANGE_TEXT_BOLD=Ändere Text in fette Schrift
SAVE_CHANGES=Änderungen sichern
CHANGE_TEXT_ITALIC=Ändere Text in kursive Schrift
DESELECT_ALL_TOPIC=Deselektiere alle Themen
SHORTCUTS=Tastenkürzel
COLLAPSE_CHILDREN=Kindknoten zusammenklappen
KEYBOARD_SHORTCUTS_MSG=Tastenkürzel helfen Zeit zu sparen und erlauben die Arbeit nur mit der Tatstatur, s.d. Sie niemals die Hand von der Tastatur nehmen müßen, um die Maus zu bedienen.
COPY_AND_PASTE_TOPICS=Kopieren und Einsetzen von Themen
MULTIPLE_LINES=Füge mehrer Textzeilen hinzu
TERM_OF_USE=Allgemeine Geschäftsbedingungen
# Properties used on the tutorial mindmap ....
TUTORIAL.MULTIPLE_TEXT_STYLES=Mehrfache Textstile
TUTORIAL.DIFFERENT_SHAPES=Verschiedene Formen
TUTORIAL.FANCY_ICONS=Fantasievolle Szmbole
TUTORIAL.MOVE_WITH_ARROWS=Mit Pfeiltasten zwischen Themen auswählen
TUTORIAL.START_TYPING_TO_EDIT_TEXT=Einfach mit dem tippen beginnen, um Text zu editieren
TUTORIAL.CTRL_TO_ADD_CHILD=Drücke Ctrl/Meta+Enter um ein Unterthema einzufügen
TUTORIAL.ENTER_TO_ADD_SIBLING=Drücke Enter um ein Schwesterthema einzufügen
TUTORIAL.MORE_KEY_TIPS=Mehr ?. Drücke auf obige Tastenkürzel
TUTORIAL.DOUBLE_CLICK_TO_ADD=Doppelklick auf den Canvas, um Themen zu erzeugen
TUTORIAL.DRAG_AND_DROP_TO_POSITION=Ziehen des Thema auf die Position
TUTORIAL.DOUBLE_CLICK_TO_EDIT_TEXT=Doppelklic auf ein Thema, um Text zu editieren
TUTORIAL.ADD_NOTES=Füge Notizen hinzu
TUTORIAL.USER_THE_TOOLBAR=Benutze die Werkzeugleiste
TUTORIAL.PUBLISH_YOUR_MAPS=Veröffentliche Ihre map
TUTORIAL.EMBED_IN_BLOGS=In Blog einbinden
TUTORIAL.INVITE_FRIEND=Freunde zur zusammenarbeit einladen
TUTORIAL.SHARING=Mitbenutzung
TUTORIAL.EDITION_USING_MOUSE=Editieren mit der Maus
TUTORIAL.EDITION_USING_KEYBOARD=Editieren mit der Tastatur
TUTORIAL.ADD_LINKS_WEBPAGES=Verbindungen auf Internetseiten hinzufügen
TUTORIAL.TOPIC_PROPERTIES=Themen Eigenschaften
TUTORIAL.HOW_TO_START=Wie fange ich an ?
TUTORIAL.FONT_COLOR=Farbe
TUTORIAL.FONT_STYLE=Stil
TUTORIAL.FONT_TYPE=Typ
TUTORIAL.SAMPLE_NOTE=Das ist eine einfache Notiz!
SUPPORT=Unterstützung
FEEDBACK=Resonanz
CONTACT_US=Kontaktieren Sie uns
#Pending for translation ...
CAPTCHA_LOADING_ERROR=ReCaptcha konnte nicht geladen werden. Sie müssen den Zugriff auf den Google ReCaptcha Dienst sicher stellen.
ACCESS_HAS_BEEN_REVOKED= Upps. Ihre Zugriffsrechte auf diese map sind zurückgesetzt worden. Kontaktieren Sie den Besitzer dieser map.
LICENSE=Lizenz
WELCOME_TO_WISEMAPPING=Wilkommen zu WiseMapping
WELCOME_DETAILS=WiseMapping erlaubt Ihnen das anlegen und anzeigen von maps von überall. Mit WiseMapping können sie: <ul><li>Einbinden von maps in Internetseiten und blogs</li><li>Verbinden von maps mit Dokumenten</li><li>Gemeinsame Nutzung von maps unter Freunden und Kollegen</li><li>Exportieren von maps in SVG,PNG,JPG und FreeMind</li></ul>.
DIRECT_LINK_EXPLANATION=Kopieren und Einsetzen der unten stehenden Verbindung, um die Mitbenutzung der map mit Ihren Freunden und Kollegen zu ermöglichen
TEMPORAL_PASSWORD_SENT=Ihr temporäres Passwort wurde angelegt
TEMPORAL_PASSWORD_SENT_DETAILS=Wir haben Ihnen eine email gesendet, die es Ihnen erlaubt Ihr Passwort zurückzusetzen. Bitte prüfen Sie den Posteingang.
TEMPORAL_PASSWORD_SENT_SUPPORT=Falls sie Probleme haben die email zu empfangen, kontaktieren Sie uns unter <a href\="mailto\:support@wisemapping.com">support@wisemapping.com </a>
TUTORIAL_VIDEO=Tutorial Video

View File

@@ -151,7 +151,7 @@ SIGN_UP_SUCCESS=Your account has been created successfully, click <a href\="c/lo
ACCOUNT_DOES_NOT_EXISTS=The email is not register or you account is not active yet.
ACCOUNT_DOES_NOT_EXISTS_SUPPORT=If the problem persist please send us an email to <a href\="mailto\:support@wisemapping.com">support@wisemapping.com </a>
SENDING=Sending ...
SIGN_ING=Singing in ...
SIGN_ING=Signing in ...
ENABLE_PUBLISHING=Enable Sharing
FRAME_HEIGHT=Frame height
FRAME_WIDTH=Frame width
@@ -183,7 +183,7 @@ INSTALL_CFG_CLICK_HERE=If you still want to use Microsoft Internet Explorer 8, c
SHOW_REGISTERS=Show _MENU_ entries
LOADING=Loading ...
NO_MATCHING_FOUND=No matching records found
TABLE_ROWS=\ _START_-_END_ of _TOTAL_
TABLE_ROWS=_START_-_END_ of _TOTAL_
ACTION=Action
CREATE_SIBLING_TOPIC=Create Sibling Topic
CREATE_CHILD_TOPIC=Create Child Topic
@@ -250,7 +250,9 @@ TEMPORAL_PASSWORD_SENT=Your temporal password has been sent
TEMPORAL_PASSWORD_SENT_DETAILS=We've sent you an email that will allow you to reset your password. Please check your email now.
TEMPORAL_PASSWORD_SENT_SUPPORT=If you have any problem receiving the email, contact us to <a href\="mailto\:support@wisemapping.com">support@wisemapping.com </a>
MINDMAP_TIMESTAMP_OUTDATED=It's not possible to save your changes because your mindmap has been modified by '{0}'. Refresh the page and try again.
MINDMAP_OUTDATED_BY_YOU=It's not possible to save your changes because map is out of date. Do you have multiple tabs opened ?. Refresh the page and try again.
MINDMAP_LOCKED=Map is being edited by {0} <{1}>. Map is opened in read only mode.
TUTORIAL_VIDEO=Tutorial Video

View File

@@ -250,6 +250,7 @@ TEMPORAL_PASSWORD_SENT_DETAILS=Se te ha enviado un mail con los detalles para ca
TEMPORAL_PASSWORD_SENT=Tu contraseña temporal ha sido enviada
MINDMAP_LOCKED=El mapa esta siendo editado por {0} <{1}>. Mapa sera abierto en modo lectura.
MINDMAP_TIMESTAMP_OUTDATED=No es posible grabar sus cambios por que el mapa ha sido modificado por {0}'. Refresque la pagina y intentelo nuevamente.
TUTORIAL_VIDEO=Tutorial Video

View File

@@ -250,6 +250,7 @@ ACCESS_HAS_BEEN_REVOKED= Upps. your access permissions to this map has been revo
LICENSE=License
WELCOME_TO_WISEMAPPING=Welcome to WiseMapping
WELCOME_DETAILS=WiseMapping will enable you to create and read your mind maps everywhere. With WiseMapping you can: <ul><li>Embed mind map it in web pages and blogs</li><li>Link mind map and documents</li><li>Share your maps with friend and colleagues</li><li>Export your maps SVG,PNG,JPG and FreeMind</li></ul>.
TUTORIAL_VIDEO=Tutorial Video

View File

@@ -235,6 +235,7 @@ TUTORIAL.FONT_COLOR=Colore
TUTORIAL.FONT_STYLE=Stili
TUTORIAL.FONT_TYPE=Font
TUTORIAL.SAMPLE_NOTE=Questa è una semplice nota !.
TUTORIAL_VIDEO=Tutorial Video

View File

@@ -235,4 +235,5 @@ TUTORIAL.SAMPLE_NOTE=Esta é uma nota simples !.
SUPPORT=Ajudar
FEEDBACK=Feedback
CONTACT_US=Contato
TUTORIAL_VIDEO=Tutorial Video

View File

@@ -210,4 +210,5 @@ TERM_OF_USE=条款和条件
CONTACT_US=联系我们
FEEDBACK=反馈
SUPPORT=支援
TUTORIAL_VIDEO=Tutorial Video

Some files were not shown because too many files have changed in this diff Show More