blob: 14a3b059db2c77b1c5f1c39c9a8e1a192fa67ed2 [file] [log] [blame]
Radek Krejci9b41f5b2018-01-31 14:17:50 +01001import { Injectable } from '@angular/core';
2
3import { Session} from './session';
4import { SessionsService } from './sessions.service';
5
6@Injectable()
Radek Krejci5a69fa32018-02-01 11:03:04 +01007export class ModificationsService {
Radek Krejci9b41f5b2018-01-31 14:17:50 +01008
9 constructor(private sessionsService: SessionsService) {}
10
11 createModificationsRecord(activeSession, path) {
12 if (!activeSession.modifications) {
13 activeSession.modifications = {};
14 }
15
16 if (!(path in activeSession.modifications)) {
17 activeSession.modifications[path] = {};
18 }
19 return activeSession.modifications[path];
20 }
21
22 getModificationsRecord(activeSession, path) {
23 if (!activeSession.modifications) {
24 return null;
25 }
26
27 if (!(path in activeSession.modifications)) {
28 return null;
29 }
30 return activeSession.modifications[path];
31 }
32
33 removeModificationsRecord(activeSession, path = null) {
34 if (!activeSession.modifications) {
35 return;
36 }
37
38 if (path && (path in activeSession.modifications)) {
39 delete activeSession.modifications[path];
40 }
41
42 if (!Object.keys(activeSession.modifications).length) {
43 delete activeSession.modifications;
44 }
45 }
46
47 setDirty(activeSession, node) {
48 if (!activeSession.modifications) {
49 return;
50 }
51
52 if (node['path'] in activeSession.modifications) {
53 node['dirty'] = true;
54 if (activeSession.modifications[node['path']]['type'] == 'change') {
55 activeSession.modifications[node['path']]['original'] = node['value'];
56 }
57 node['value'] = activeSession.modifications[node['path']]['value'];
58 }
59 /* recursion */
60 if ('children' in node) {
61 for (let child of node['children']) {
62 this.setDirty(activeSession, child);
63 }
64 }
65 }
66
67 setEdit(node, set = true) {
68 if (set && node['info']['datatypebase'] == 'empty') {
69 node['value'] = '';
70 return;
71 }
72 node['edit'] = set;
73 }
74
75 setLast(list) {
76 let last;
77 for (let iter of list) {
78 delete iter['last'];
79 last = iter;
80 }
81 last['last'] = true;
82 }
83
84 nodeParent(activeSession, node) {
85 if (node['path'] =='/') {
86 return null;
87 }
88
89 let match = false;
90 let parent = null;
91 let children = activeSession.data['children'];
92 let newChildren;
93
94 while (children || newChildren) {
95 match = false;
96
97 if (children) {
98 for (let iter of children) {
99 if (node['path'] == iter['path']) {
100 match = true;
101 children = null;
102 newChildren = null;
103 break;
104 } else if (node['path'].startsWith(iter['path'] + '/')) {
105 match = true;
106 parent = iter;
107 children = iter['children'];
108 if (('new' in node) && ('newChildren' in iter)) {
109 newChildren = iter['newChildren'];
110 } else {
111 newChildren = null;
112 }
113 break;
114 }
115 }
116 if (!match) {
117 children = null;
118 }
119 }
120 if (match) {
121 continue;
122 }
123 if (newChildren) {
124 for (let iter of newChildren) {
125 if (node['path'] == iter['path']) {
126 match = true;
127 children = null;
128 newChildren = null;
129 break;
130 } else if (node['path'].startsWith(iter['path'] + '/')) {
131 match = true;
132 parent = iter;
133 children = iter['children'];
134 if (('new' in node) && ('newChildren' in iter)) {
135 newChildren = iter['newChildren'];
136 } else {
137 newChildren = null;
138 }
139 break;
140 }
141 }
142 if (!match) {
143 children = null;
144 }
145 }
146 }
147
148 if (!parent) {
149 parent = activeSession.data;
150 }
151 return parent;
152 }
153
154 schemaName(parent, child):string {
155 if (parent['module'] != child['module']) {
156 return child['module'] + ':' + child['name'];
157 } else {
158 return child['name'];
159 }
160 }
161
162 delete(activeSession, node) {
163 if ('new' in node) {
164 /* removing newly created subtree */
165 let parent = this.nodeParent(activeSession, node);
166 if ('new' in parent) {
167 /* removing just a subtree of the created tree */
168 for (let i in parent['children']) {
169 if (parent['children'][i] == node) {
170 parent['children'].splice(i, 1);
171 break;
172 }
173 }
174 } else {
175 this.removeModificationsRecord(activeSession, node['path']);
176 for (let i in parent['newChildren']) {
177 if (parent['newChildren'][i]['path'] == node['path']) {
178 parent['newChildren'].splice(i, 1);
179 break;
180 }
181 }
182 if (!parent['newChildren'].length) {
183 delete parent['newChildren'];
184 }
185 }
186 } else {
187 let record = this.createModificationsRecord(activeSession, node['path']);
188
189 if (!('type' in record)) {
190 /* new record */
191 record['type'] = 'delete';
192 record['original'] = node;
193 node['deleted'] = true;
194 node['dirty'] = true;
195 } else if (record['type'] == 'change') {
196 record['type'] = 'delete';
197 node['value'] = record['original'];
198 delete record['original'];
199 delete record['value'];
200 node['deleted'] = true;
201 }
202 }
203 }
204
205 change(activeSession, node, leafValue) {
206 if (!('new' in node)) {
207 let record = this.createModificationsRecord(activeSession, node['path']);
208 if (!('type' in record)) {
209 console.log(record);
210 /* new record */
211 if (node['value'] == leafValue) {
212 /* no change to the original value */
213 this.setEdit(node, false);
214 this.removeModificationsRecord(activeSession);
215 return;
216 }
217 record['type'] = 'change';
218 record['original'] = node['value'];
219 record['value'] = leafValue;
220 node['dirty'] = true;
221 } else if (record['type'] == 'change' && record['original'] == leafValue) {
222 console.log(record);
223 /* change back to the original value, remove the change record */
224 this.removeModificationsRecord(activeSession, node['path']);
225 node['dirty'] = false;
226 } else {
227 console.log(record);
228 /* another change of existing change record */
229 record['value'] = leafValue;
230 node['dirty'] = true;
231 }
232 }
233
234 node['value'] = leafValue;
235 this.setEdit(node, false);
236 }
237
238 createOpen(schemas, node) {
239 //console.trace();
240 node['schemaChildren'] = schemas;
241 node['creatingChild'] = {};
242
243 if (schemas.length) {
244 if (('newChildren' in node) && node['newChildren'].length) {
245 delete node['newChildren'][node['newChildren'].length - 1]['last']
246 } else if (('children' in node) && node['children'].length) {
247 delete node['children'][node['children'].length - 1]['last'];
248 }
249 }
250 }
251
252 createClose(node, reason='abort') {
253 //console.trace();
254 if (reason == 'abort' && node['schemaChildren'].length) {
255 if (('newChildren' in node) && node['newChildren'].length) {
256 node['newChildren'][node['newChildren'].length - 1]['last'] = true;
257 } else if (('children' in node) && node['children'].length) {
258 node['children'][node['children'].length - 1]['last'] = true;
259 }
260 }
261 delete node['creatingChild'];
262 delete node['schemaChildren'];
263 }
264
265 create(activeSession, node, index) {
266 //console.trace();
267 let newNode = {};
268 newNode['new'] = true;
269 newNode['info'] = node['schemaChildren'][index];
270 if (node['path'] == '/') {
271 newNode['path'] = '/' + this.schemaName(node['info'], newNode['info']);
272 } else {
273 newNode['path'] = node['path'] + '/' + this.schemaName(node['info'], newNode['info']);
274 }
275 newNode['dirty'] = true;
276
277 if ('new' in node) {
278 if (!('children' in node)) {
279 node['children'] = []
280 }
281 node['children'].push(newNode)
282 } else {
283 if (!('newChildren' in node)) {
284 node['newChildren'] = [];
285 }
286 node['newChildren'].push(newNode);
287 }
288
289 switch(newNode['info']['type']) {
290 case 1: { /* container */
291 node['schemaChildren'].splice(index, 1);
292
293 newNode['children'] = [];
294 /* open creation dialog for nodes inside the created container */
295 this.sessionsService.childrenSchemas(activeSession.key, newNode['info']['path'], newNode).then(result => {
296 this.createOpen(result, newNode);
297 });
298 break;
299 }
300 case 4: { /* leaf */
301 node['schemaChildren'].splice(index, 1);
302
303 newNode['value'] = newNode['info']['default'];
304 this.setEdit(newNode, true)
305 break;
306 }
307 case 16: { /* list */
308 let search;
309 if ('new' in node) {
310 search = node['children'];
311 } else {
312 search = node['newChildren'];
313 }
314 let pos = 1;
315 if (search.length) {
316 for (let sibling of search) {
317 if (sibling['path'].substr(0, newNode['path'].length + 1) == newNode['path'] + '[') {
318 let n = parseInt(sibling['path'].substring(newNode['path'].length + 1));
319 if (n >= pos) {
320 pos = n + 1;
321 }
322 }
323 }
324 }
325 newNode['path'] = newNode['path'] + '[' + pos + ']';
326
327 newNode['children'] = [];
328 /* open creation dialog for nodes inside the created list */
329 this.sessionsService.childrenSchemas(activeSession.key, newNode['info']['path'], newNode).then(result => {
330 this.createOpen(result, newNode);
331
332 if (newNode['schemaChildren'].length) {
333 for (let i in newNode['schemaChildren']) {
334 if (!newNode['schemaChildren'][i]['key']) {
335 continue;
336 }
337 let newKey = {};
338 newKey['new'] = true;
339 newKey['info'] = newNode['schemaChildren'][i];
340 newKey['path'] = newNode['path'] + '/' + this.schemaName(newNode['info'], newKey['info']);
341 newKey['dirty'] = true;
342 this.setEdit(newKey, true)
343 newNode['children'].push(newKey)
344 newNode['schemaChildren'].splice(i, 1);
345 }
346 }
347 });
348
349 break;
350 }
351 }
352
353 if (!node['schemaChildren'].length) {
354 newNode['last'] = true;
355 this.createClose(node, 'success');
356 }
357
358 if (!('new' in node)) {
359 /* store the record about the newly created data */
360 let record = this.createModificationsRecord(activeSession, newNode['path']);
361 if (('type' in record) && record['type'] == 'delete') {
362 record['type'] = 'change';
363 record['value'] = newNode;
364 delete record['original']['deleted'];
365 for (let i in node['children']) {
366 if (node['children'][i] == record['original']) {
367 node['children'].splice(i, 1);
368 break;
369 }
370 }
371 } else {
372 record['type'] = 'create';
373 record['data'] = newNode;
374 }
375 }
376 console.log(node)
377 }
378
379 cancelModification(activeSession, node = activeSession.data, recursion = true) {
380 if ('creatingChild' in node) {
381 delete node['creatingChild'];
382 }
383 if ('deleted' in node) {
384 node['dirty'] = false;
385 node['deleted'] = false;
386 }
387
388 if ('new' in node) {
389 /* removing newly created subtree */
390 let parent = this.nodeParent(activeSession, node);
391 if ('new' in parent) {
392 /* removing just a subtree of the created tree */
393 for (let i in parent['children']) {
394 if (parent['children'][i] == node) {
395 if (Number(i) > 0 && parent['children'][i]['last']) {
396 parent['children'][Number(i) - 1]['last'] = true;
397 }
398 parent['children'].splice(i, 1);
399 break;
400 }
401 }
402 } else {
403 this.removeModificationsRecord(activeSession, node['path']);
404 for (let i in parent['newChildren']) {
405 if (parent['newChildren'][i]['path'] == node['path']) {
406 if (Number(i) > 0 && parent['newChildren'][i]['last']) {
407 parent['newChildren'][Number(i) - 1]['last'] = true;
408 }
409 parent['newChildren'].splice(i, 1);
410 break;
411 }
412 }
413 if (!parent['newChildren'].length) {
414 delete parent['newChildren'];
415 }
416 }
417
418 if (node['info']['type'] == 1 || node['info']['type'] == 4) {
419 /* fix the list of nodes to create in parent */
420 let schemas;
421 if (!('schemaChildren' in parent)) {
422 schemas = [];
423 } else {
424 schemas = parent['schemaChildren'];
425 }
426 schemas.push(node['info']);
427 this.createOpen(schemas, parent)
428 }
429 } else if (activeSession.modifications) {
430 let record = this.getModificationsRecord(activeSession, node['path']);
431 if (record) {
432 node['dirty'] = false;
433 if (record['type'] == 'change') {
434 node['value'] = record['original'];
435 }
436 this.removeModificationsRecord(activeSession, node['path']);
437 if (!activeSession.modifications) {
438 return;
439 }
440 }
441 }
442
443 /* recursion */
444 if (recursion && 'children' in node) {
445 if ('newChildren' in node) {
446 for (let child of node['newChildren']) {
447 let record = this.getModificationsRecord(activeSession, child['path']);
448 if (record['type'] == 'change') {
449 if (node['children'].length) {
450 node['children'][node['children'].length - 1]['last'] = false;
451 }
452 record['original']['last'] = true;
453 node['children'].push(record['original'])
454 }
455 this.removeModificationsRecord(activeSession, child['path']);
456 }
457 delete node['newChildren'];
458 if (('children' in node) && node['children'].length) {
459 node['children'][node['children'].length - 1]['last'] = true;
460 }
461 }
462 let last;
463 for (let child of node['children']) {
464 this.cancelModification(activeSession, child);
465 delete child['last'];
466 last = child;
467 }
468 last['last'] = true;
469 }
470 }
471}