Projekt

Obecné

Profil

« Předchozí | Další » 

Revize 78a6bb59

Přidáno uživatelem Pavel Fidranský před více než 6 roky(ů)

UI for saving diagrams to database

Zobrazit rozdíly:

sources/src/main/webapp/js/app.js
29 29
	/** @prop {object} API Application programming interface paths. */
30 30
	this.API = {
31 31
		loadGraphData: 'api/load-graph-data',
32
		saveDiagram: 'api/save-diagram',
33
		removeDiagram: 'api/remove-diagram',
32 34
	};
33 35

  
34 36
	/** @prop {float} headerHeight Current height of the application header. */
......
58 60
	/** TODO: jsDoc */
59 61
	this.attributeTypeList = [];
60 62

  
63
	/** TODO: jsDoc */
64
	this.possibleEnumValues = {};
65

  
61 66
	/**
62 67
	 * Loads graph using diagram (if available).
63 68
	 * @param diagramId Diagram identifier.
......
273 278
				scale: 1,
274 279
			});
275 280
		});
276
		
281

  
282
		// save to database button
283
		var saveDiagramToDatabaseButton = document.getElementById('btnSaveDiagramToDatabase');
284
		if (saveDiagramToDatabaseButton) {
285
			saveDiagramToDatabaseButton.addEventListener('click', function(e) {
286
				var diagramId = app.utils.getQueryVariable('diagramId');
287
				if (diagramId === false) diagramId = null;
288

  
289
				var diagramName = prompt('Enter new diagram name:');
290
				if (diagramName === null || diagramName === '') return false;
291

  
292
				$.ajax({
293
					'type': 'POST',
294
					'url': app.API.saveDiagram,
295
					'data': {
296
						'diagram_id': diagramId,
297
						'name': diagramName,
298
						'graph_json': JSON.stringify(self.graphExporter.run()),
299
						'public': 0,
300
					},
301
					'success': function() {
302
						alert('Saved.');
303
					},
304
					'error': function(xhr) {
305
						switch (xhr.status) {
306
							case 401:
307
								alert('You are either not logged in or not an owner of this diagram.');
308
								break;
309
							default:
310
								alert('Something went wrong.');
311
						}
312
					},
313
				});
314
			});
315
		}
316

  
277 317
		// window resize
278 318
		window.addEventListener('resize', function(e) {
279 319
			self.headerHeight = getHeaderHeight();
sources/src/main/webapp/js/components/edge.js
238 238
		rootElement.remove();
239 239
	};
240 240

  
241
	/**
242
	 * Exports the edge to a new, plain JS object.
243
	 * @returns {Object} exported edge
244
	 */
245
	this.export = function() {
246
		return {
247
			subedgeInfo: props.subedgeInfo,
248
			from: this.getFrom().id,
249
			to: this.getTo().id,
250
			text: '',
251
			id: this.id,
252
		};
253
	};
254

  
241 255
	/**
242 256
	 * Edge click interaction. Highlights the edge and vertices related to it. Reveals edge popover.
243 257
	 * @param {Event} e Click event.
sources/src/main/webapp/js/components/group.js
262 262
		}
263 263
	};
264 264

  
265
	/**
266
	 * @returns true if the group is currently highlighted (in any way), otherwise false
267
	 */
268
	this.isHighlighted = function() {
269
		return highlighted;
270
	};
271

  
265 272
	/**
266 273
	 * Toggles highlighting of the group.
267 274
	 * @param {boolean} newValue True to highlight the group, false to unhighlight.
......
444 451
		});
445 452
	};
446 453

  
454
	/**
455
	 * Exports the group to a new, plain JS object.
456
	 * @returns {Object} exported group
457
	 */
458
	this.export = function() {
459
		var verticesId = vertexList.map(function(vertex) {
460
			return vertex.id;
461
		});
462

  
463
		return {
464
			groupId: this.id,
465
			id: this.id,
466
			name: this.name,
467
			verticesId: verticesId,
468
			verticesEdgeFromId: [],	// TODO: what to put in here?
469
			verticesEdgeToId: [],	// TODO: what to put in here?
470
		};
471
	};
472

  
447 473
	/**
448 474
	 * @returns {Element} SVG DOM element.
449 475
	 */
sources/src/main/webapp/js/components/vertex.js
9 9
	/** @prop {integer} archetype Identifier of the vertex archetype. */
10 10
	this.archetype = props.archetype;
11 11
	/** @prop {string} name Name of the vertex. */
12
	this.name = props.title.split(':')[1];
12
	this.name = props.title.split(':')[1];	// TODO: archetype prefix is useless
13 13
	/** @prop {array} symbol Symbol of the group. */
14 14
	this.symbol = app.markSymbol.getMarkSymbol();
15 15

  
......
256 256
		}
257 257
	};
258 258

  
259
	/**
260
	 * @returns true if the vertex is currently highlighted (in any way), otherwise false
261
	 */
262
	this.isHighlighted = function() {
263
		return highlighted;
264
	};
265

  
259 266
	/**
260 267
	 * Toggles highlighting of the vertex.
261 268
	 * @param {boolean} newValue True to highlight the vertex, false to unhighlight.
......
455 462
		});
456 463
	};
457 464

  
465
	/**
466
	 * Exports the vertex to a new, plain JS object.
467
	 * @returns {Object} exported vertex
468
	 */
469
	this.export = function() {
470
		return {
471
			archetype: this.archetype,
472
			attributes: props.attributes,
473
			id: this.id,
474
			originalId: this.id,
475
			text: '',
476
			title: 'XXX:' + this.name,	// TODO: archetype prefix is useless
477
		};
478
	};
479

  
458 480
	/**
459 481
	 * @returns {Element} SVG DOM element.
460 482
	 */
sources/src/main/webapp/js/graphExporter.js
4 4
function GraphExporter() {
5 5

  
6 6
	/**
7
	 * Exports positions of edges and vertices in graph to JSON.
7
	 * Exports graph to JSON.
8 8
	 */
9 9
	this.run = function() {
10
		var edgesExport = app.edgeList.map(function(edge) {
10
		// vertices
11
		var vertices = app.vertexList.map(function(vertex) {
12
			return vertex.export();
13
		});
14

  
15
		// edges
16
		var edges = app.edgeList.map(function(edge) {
17
			return edge.export();
18
		});
19

  
20
		// groups
21
		var groups = app.groupList.map(function(group) {
22
			return group.export();
23
		});
24

  
25
		// positions of nodes
26
		var positions = app.nodeList.map(function(node) {
27
			if (node instanceof Vertex) {
28
				var id = 'vertex' + node.id;
29
			} else if (node instanceof Group) {
30
				var id = 'group' + node.id;
31
			} else {
32
				var id = node.id;
33
			}
34

  
35
			var position = node.getPosition();
36

  
11 37
			return {
12
				id: edge.id,
13
				from: edge.getFrom().id,
14
				to: edge.getTo().id,
38
				id: id,
39
				x: position.x,
40
				y: position.y,
15 41
			};
16 42
		});
17 43

  
18
		var verticesExport = app.vertexList.map(function(vertex) {
44
		// nodes excluded to the sidebar
45
		var excludedNodeList = app.sidebarComponent.excludedNodeListComponent.getNodeList();
46
		var sideBar = excludedNodeList.map(function(node) {
19 47
			return {
20
				id: vertex.id,
21
				name: vertex.name,
22
				position: vertex.getPosition(),
23
				isExcluded: vertex.isExcluded(),
48
				id: node.id,
49
				isHighlighted: node.isHighlighted(),
24 50
			};
25 51
		});
26 52

  
27 53
		return {
28
			edges: edgesExport,
29
			vertices: verticesExport,
54
			attributeTypes: app.attributeTypeList,
55
			edgeArchetypes: app.archetype.edge,
56
			vertexArchetypes: app.archetype.vertex,
57
			vertices: vertices,
58
			edges: edges,
59
			possibleEnumValues: app.possibleEnumValues,
60
			archetypeIcons: app.archetype.icon,
61
			groups: groups,
62
			positions: positions,
63
			sideBar: sideBar,
64
			selectedVertex: null,	// TODO: selected == highlighted
65
			selectedEdge: null,	// TODO selected == highlighted
30 66
		};
31
	};
67
	}
32 68

  
33 69
}
sources/src/main/webapp/js/graphLoader.js
15 15

  
16 16
		var canvasSize = ((data.vertices.length * 75) / Math.round(Math.sqrt(data.vertices.length))) + 1000;
17 17

  
18
		app.attributeTypeList = data.attributeTypes;
19

  
20 18
		// store archetypes
21 19
		app.archetype.vertex = data.vertexArchetypes;
22 20
		app.archetype.edge = data.edgeArchetypes;
23 21
		app.archetype.icon = data.archetypeIcons;
24 22

  
23
		app.attributeTypeList = data.attributeTypes;
24
		app.possibleEnumValues = data.possibleEnumValues;
25

  
25 26
		// construct vertices
26 27
		var vertexMap = {};
27 28
		data.vertices.forEach(function(component) {
28 29
			var vertex = new Vertex(component);
29 30

  
30
			vertex.setPosition(new Coordinates(
31
				Math.floor(Math.random() * canvasSize),
32
				Math.floor(Math.random() * canvasSize),
33
			));
31
			// position
32
			var position = data.positions.find(function(position) {
33
				return position.id === ('vertex' + vertex.id);
34
			});
35

  
36
			if (app.utils.isDefined(position)) {
37
				vertex.setPosition(new Coordinates(position.x, position.y));
38

  
39
			} else {
40
				// set random
41
				vertex.setPosition(new Coordinates(
42
					Math.floor(Math.random() * canvasSize),
43
					Math.floor(Math.random() * canvasSize),
44
				));
45
			}
34 46

  
35 47
			app.nodeList.push(vertex);
36 48
			app.vertexList.push(vertex);
......
71 83
			app.viewportComponent.addEdge(edge);
72 84
		});
73 85

  
74
		// center viewport
75
		app.viewportComponent.center();
76

  
77 86
		// find unconnected vertices
78 87
		app.vertexList.filter(function(vertex) {
79 88
			return vertex.isUnconnected();
......
85 94
		// construct groups
86 95
		data.groups.forEach(function(component) {
87 96
			var group = new Group(component);
88
			group.setExcluded(true);
89 97

  
98
			// vertices
90 99
			app.vertexList.filter(function(vertex) {
91 100
				return component.verticesId.indexOf(vertex.id) > -1;
92 101
			}).forEach(function(vertex) {
93 102
				group.addVertex(vertex);
94 103
			});
95 104

  
105
			// position
106
			var position = data.positions.find(function(position) {
107
				return position.id === ('group' + group.id);
108
			});
109

  
110
			if (app.utils.isDefined(position)) {
111
				group.setPosition(new Coordinates(position.x, position.y));
112

  
113
			} else {
114
				// set random
115
				group.setPosition(new Coordinates(
116
					Math.floor(Math.random() * canvasSize),
117
					Math.floor(Math.random() * canvasSize),
118
				));
119
			}
120

  
96 121
			app.nodeList.push(group);
97 122
			app.groupList.push(group);
98 123

  
99
			app.sidebarComponent.excludedNodeListComponent.add(group);
124
			app.viewportComponent.addGroup(group);
125
		});
126

  
127
		// exclude nodes
128
		data.sideBar.forEach(function(excludedNode) {
129
			var node = app.nodeList.find(function(node) {
130
				return node.id === excludedNode.id;
131
			});
132

  
133
			if (app.utils.isDefined(node)) {
134
				node.exclude();
135

  
136
				app.sidebarComponent.excludedNodeListComponent.add(node);
137
			}
100 138
		});
101 139

  
140
		// center viewport
141
		app.viewportComponent.center();
142

  
102 143
		// update status bar
103 144
		app.sidebarComponent.statusBarComponent.setComponentCount(data.vertices.length);
104 145
	};
sources/src/main/webapp/js/utils/utils.js
73 73
		})
74 74
	};
75 75

  
76
	/**
77
	 * Extracts value of a query parameter from the current URL.
78
	 * {@link https://css-tricks.com/snippets/javascript/get-url-variables/}
79
	 * 
80
	 * @param {string} variable 
81
	 * @returns value of the query parameter or false if the parameter does not exist
82
	 */
83
	this.getQueryVariable = function(variable) {
84
		var query = window.location.search.substring(1);
85
		var vars = query.split('&');
86

  
87
		for (var i = 0; i < vars.length; i++) {
88
			var pair = vars[i].split('=');
89

  
90
			if (pair[0] == variable) {
91
				return pair[1];
92
			}
93
		}
94

  
95
		return false;
96
	}
97

  
76 98
}
sources/src/main/webapp/showGraph.jsp
145 145
						</li>
146 146
						<c:if test="${isLoggedIn}">
147 147
							<li>
148
								<button class="btn save-diagram" id="btnSaveDiagramToDb" title="Save diagram.">
148
								<hr class="navbar-separator">
149
							</li>
150
							<li>
151
								<button class="btn save-diagram" id="btnSaveDiagramToDatabase" title="Save diagram.">
149 152
									<img src="images/icon_save.png" id="applyLayoutImg" alt="Save diagram">
150 153
								</button>
151 154
							</li>

Také k dispozici: Unified diff