@aj-shadow/z-abs-complayer-codeeditor-client 0.0.0-aj-beta.221

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/.gitattributes +26 -0
  2. package/LICENSE.txt +96 -0
  3. package/README.md +5 -0
  4. package/npm-shrinkwrap.json +13 -0
  5. package/package.json +10 -0
  6. package/project/client/_build/Bundle-CompLayer-Codeeditor-client.bld +41 -0
  7. package/project/client/_build/Client-CompLayer-Codeeditor-client-jsx.bld +10 -0
  8. package/project/client/_build/Client-CompLayer-Codeeditor-client.bld +10 -0
  9. package/project/client/_build/Client-css-CompLayer-Codeeditor-bundle.bld +9 -0
  10. package/project/client/_build/z-abs-complayer-codeeditor-client.prj +36 -0
  11. package/project/client/actions/action-code-editor-file.js +78 -0
  12. package/project/client/actions/action-code-editor-folder.js +41 -0
  13. package/project/client/actions/action-code-editor-persistent-data.js +23 -0
  14. package/project/client/actions/action-code-editor-project.js +23 -0
  15. package/project/client/actions/action-code-editor-workspace.js +35 -0
  16. package/project/client/actions/data-action-code-editor-file.js +41 -0
  17. package/project/client/actions/data-action-code-editor-folder.js +33 -0
  18. package/project/client/actions/data-action-code-editor-persistent-data.js +27 -0
  19. package/project/client/actions/data-action-code-editor-project.js +20 -0
  20. package/project/client/actions/data-action-code-editor-workspace.js +27 -0
  21. package/project/client/components/middle-code-editor-sidebar.jsx +117 -0
  22. package/project/client/components/middle-code-editor-toolbar.jsx +638 -0
  23. package/project/client/components/middle-code-editor-view.jsx +400 -0
  24. package/project/client/components/middle-code-editor.jsx +50 -0
  25. package/project/client/css/code-editor.css +44 -0
  26. package/project/client/css/scrollbar-dark.css +8 -0
  27. package/project/client/css/scrollbar-light.css +6 -0
  28. package/project/client/css/search.css +40 -0
  29. package/project/client/css/search_light.css +8 -0
  30. package/project/client/css/serach_dark.css +8 -0
  31. package/project/client/css/sidebar-dark.css +21 -0
  32. package/project/client/css/sidebar-light.css +18 -0
  33. package/project/client/css/tab.css +19 -0
  34. package/project/client/css/tab_dark.css +9 -0
  35. package/project/client/css/tab_light.css +9 -0
  36. package/project/client/css/view-dark.css +11 -0
  37. package/project/client/css/view-light.css +10 -0
  38. package/project/client/stores/code-editor-store.js +1044 -0
  39. package/project/z-abs-complayer-codeeditor-client.tree +40 -0
@@ -0,0 +1,1044 @@
1
+
2
+ 'use strict';
3
+
4
+ import { DataActionCodeEditorWorkspaceGet, DataActionCodeEditorWorkspaceNew, DataActionCodeEditorWorkspaceSearch } from '../actions/data-action-code-editor-workspace';
5
+ import { DataActionCodeEditorProjectUpdate, DataActionCodeEditorProjectToggle } from '../actions/data-action-code-editor-project';
6
+ import { DataActionCodeEditorFileGet, DataActionCodeEditorFileNew, DataActionCodeEditorFileRename, DataActionCodeEditorFileUpdate, DataActionCodeEditorFileDelete } from '../actions/data-action-code-editor-file';
7
+ import { DataActionCodeEditorFolderGet, DataActionCodeEditorFolderNew, DataActionCodeEditorFolderUpdate, DataActionCodeEditorFolderDelete } from '../actions/data-action-code-editor-folder';
8
+ import { ActionCodeEditorFileGet } from '../actions/action-code-editor-file';
9
+ import { ActionCodeEditorFolderGet } from '../actions/action-code-editor-folder';
10
+ import { ActionCodeEditorWorkspaceSearch } from '../actions/action-code-editor-workspace';
11
+ import { ActionModalDialogResult } from 'z-abs-complayer-modaldialog-client/client/actions/action-modal-dialog';
12
+ import StoreBaseRealtime from 'z-abs-corelayer-client/client/store/store-base-realtime';
13
+ import GuidGenerator from 'z-abs-corelayer-cs/clientServer/guid-generator';
14
+ import Project from 'z-abs-corelayer-cs/clientServer/project';
15
+
16
+
17
+ class CodeEditorStore extends StoreBaseRealtime {
18
+ static showWorkspace = false;
19
+ static START_PATH = '/start';
20
+ static START_PATH_LENGTH = CodeEditorStore.START_PATH.length;
21
+ static CODE_EDITOR_PATH = '/code-editor';
22
+ static CODE_EDITOR_PATH_LENGTH = CodeEditorStore.CODE_EDITOR_PATH.length;
23
+ static IS_FILE = 0;
24
+ static IS_FOLDER = 1;
25
+ static IS_SEARCH = 2;
26
+ static SEARCH_FILES = 'SearchLines';
27
+ static LOG_FILES = 'LogLines';
28
+ static TYPE_FOLDER = 'folder';
29
+ static TYPE_FILE = 'file';
30
+ static TYPE_SEARCH = 'search';
31
+
32
+ constructor() {
33
+ super({
34
+ project: new Project(),
35
+ projects: new Map(),
36
+ selectedProjectId: '',
37
+ files: new Map(),
38
+ searchLines: new Map([
39
+ [CodeEditorStore.SEARCH_FILES, new Map()],
40
+ [CodeEditorStore.LOG_FILES, new Map()]
41
+ ]),
42
+ current: {
43
+ file: null,
44
+ folder: null,
45
+ type: '',
46
+ url: {
47
+ pathname: '',
48
+ query: {},
49
+ line: 1,
50
+ css: undefined
51
+ }
52
+ },
53
+ build: {
54
+ errors: []
55
+ },
56
+ persistentData: {
57
+ darkMode: false,
58
+ emptyLine: true
59
+ },
60
+ eol: '\n'
61
+ });
62
+ }
63
+
64
+ _getAppName() {
65
+ return this.state.current.url.query?.workspace ? this.state.current.url.query.workspace : window.actorJsReleaseData.appName;
66
+ }
67
+
68
+ _getWorkspaceName() {
69
+ return this.state.current.url.query?.workspace ? this.state.current.url.query.workspace : window.actorJsReleaseData.appName;
70
+ }
71
+
72
+ onInit() {
73
+ const url = this._parseUrl(location.pathname, location.search);
74
+ const appName = url.query.workspace ? url.query.workspace : window.actorJsReleaseData.appName;
75
+ const workspaceName = url.query.workspace ? url.query.workspace : window.actorJsReleaseData.appName;
76
+ this.sendDataAction(new DataActionCodeEditorWorkspaceGet(appName, workspaceName, true));
77
+ }
78
+
79
+ onActionCodeEditorWorkspaceGet(action) {
80
+ const appName = action.appName ? action.appName : this._getAppName();
81
+ const workspaceName = action.workspaceName ? action.workspaceName : this._getWorkspaceName();
82
+ this.sendDataAction(new DataActionCodeEditorWorkspaceGet(appName, workspaceName, false));
83
+ }
84
+
85
+ onActionCodeEditorPersistentDataUpdate(action) {
86
+ const persistentData = this.deepCopy(this.state.persistentData);
87
+ const parent = action.parentName ? persistentData[action.parentName] : persistentData;
88
+ parent[action.name] = action.value;
89
+ this.updateState({persistentData: {$set: parent}});
90
+ }
91
+
92
+ onActionCodeEditorWorkspaceNew(action) {
93
+ this.sendDataAction(new DataActionCodeEditorWorkspaceNew(action.appName, action.workspaceName));
94
+ }
95
+
96
+ onActionCodeEditorWorkspaceSearch(action) {
97
+ this.sendDataAction(new DataActionCodeEditorWorkspaceSearch(action));
98
+ }
99
+
100
+ onActionCodeEditorWorkspaceSearchSet(action) {
101
+ this._setCurrentSearch(action.key);
102
+ }
103
+
104
+ onActionCodeEditorFileSet(action) {
105
+ const node = this._getNode(action.url);
106
+ if(node) {
107
+ this.updateState({searchLines: (searchLine) => {
108
+ const search = searchLine.get(action.name);
109
+ if(search) {
110
+ const line = {
111
+ line: action.line,
112
+ type: action.type
113
+ };
114
+ const lines = search.get(action.url);
115
+ if(lines) {
116
+ if(!lines.some(obj => obj.line === line.line)) {
117
+ lines.push(line);
118
+ }
119
+ }
120
+ else {
121
+ search.set(action.url, [line]);
122
+ }
123
+ }
124
+ }});
125
+ const project = this._getProject(node.projectId);
126
+ this.onActionCodeEditorFileGet(new ActionCodeEditorFileGet(node.projectId, node.node.key, node.node.title, node.node.data.path, node.node.data.type, project.plugin, project.workspaceName));
127
+ }
128
+ }
129
+
130
+ onActionCodeEditorFileGet(action) {
131
+ const file = this.state.files.get(action.key);
132
+ if(!file) {
133
+ const project = this._getProject(action.projectId);
134
+ this.sendDataAction(new DataActionCodeEditorFileGet(`${action.path}/${action.title}`, action.projectId, action.key, action.title, action.path, action.type, project.type, project.plugin, project.workspaceName));
135
+ }
136
+ else {
137
+ this._setCurrentFile(file, null, file.valid);
138
+ }
139
+ }
140
+
141
+ onActionCodeEditorFileNew(action) {
142
+ const project = this._getProject(action.projectId);
143
+ this.sendDataAction(new DataActionCodeEditorFileNew(action, project.type, project.plugin, project.workspaceName));
144
+ }
145
+
146
+ onActionCodeEditorFileAdd(action) {
147
+ let node = null;
148
+ let projectType = null;
149
+ let projectPlugin = null;
150
+ let projectWorkspaceName = null;
151
+ this._updateProject(action.projectId, (project, app) => {
152
+ node = project.addFile(action.title, action.path, action.type);
153
+ project.sortParent(node);
154
+ if(!app) {
155
+ projectType = project.type;
156
+ projectPlugin = project.plugin;
157
+ }
158
+ else {
159
+ projectWorkspaceName = project.workspaceName;
160
+ }
161
+ });
162
+ this.sendDataAction(new DataActionCodeEditorFileGet(`${node.data.path}/${node.title}`, action.projectId, node.key, node.title, node.data.path, node.data.type, projectType, projectPlugin, projectWorkspaceName));
163
+ }
164
+
165
+ onActionCodeEditorFileRename(action) {
166
+ const project = this._getProject(action.projectId);
167
+ this.sendDataAction(new DataActionCodeEditorFileRename(`${action.path}/${action.title}`, `${action.path}/${action.newTitle}`, project.type, project.plugin, action, project.workspaceName));
168
+ }
169
+
170
+ onActionCodeEditorFileUpdate(action) {
171
+ const file = this.state.files.get(action.key);
172
+ const project = this._getProject(file.projectId);
173
+ this.sendDataAction(new DataActionCodeEditorFileUpdate(action.key, file.title, file.path, file.content, project.type, project.plugin, project.workspaceName));
174
+ }
175
+
176
+ onActionCodeEditorFileUpdateAll(action) {
177
+ action.keys.forEach((key) => {
178
+ const file = this.state.files.get(key);
179
+ const project = this._getProject(file.projectId);
180
+ this.sendDataAction(new DataActionCodeEditorFileUpdate(key, file.title, file.path, file.content, project.type, project.plugin, project.workspaceName));
181
+ });
182
+ }
183
+
184
+ onActionCodeEditorFileEdit(action) {
185
+ const file = this.state.files.get(action.key);
186
+ this.updateState({current: {file: { content: {$set: action.content}}}});
187
+ this.updateState({current: {file: { codeChanged: {$set: action.content !== file.contentOriginal}}}});
188
+ this.updateState({files: (files) => {
189
+ files.set(action.key, this.state.current.file);
190
+ }});
191
+ }
192
+
193
+ onActionCodeEditorFileClose(action) {
194
+ const file = this.state.files.get(action.key);
195
+ const nextFile = this._getNextFile(file);
196
+ this.updateState({files: (files) => {
197
+ files.delete(action.key);
198
+ }});
199
+ this._setCurrentFile(nextFile, file, true);
200
+ }
201
+
202
+ onActionCodeEditorFileRemove(action) {
203
+ const file = this.state.files.get(action.key) || this.state.current.file;
204
+ const nextFile = this._getNextFile(file);
205
+ this.updateState({files: (files) => {
206
+ files.delete(action.key);
207
+ }});
208
+ this._updateProject(action.projectId, (project, app) => {
209
+ project.removeNode(file.path, file.key);
210
+ });
211
+ if(nextFile) {
212
+ this._setCurrentFile(nextFile, file, true);
213
+ }
214
+ else {
215
+ this._setCurrentFile(null, null, false);
216
+ const node = this._getNode(file.path);
217
+ const folder = this._createFolder(node.projectId, node.node);
218
+ this._setCurrentFolder(folder, true);
219
+ }
220
+ }
221
+
222
+ onActionCodeEditorFileDelete(action) {
223
+ const file = this.state.files.get(action.key);
224
+ const project = this._getProject(action.projectId);
225
+ this.sendDataAction(new DataActionCodeEditorFileDelete(`${file.path}/${file.title}`, project.type, project.plugin, action, project.workspaceName));
226
+ }
227
+
228
+ onActionCodeEditorFolderGet(action) {
229
+ const project = this._getProject(action.projectId);
230
+ this.sendDataAction(new DataActionCodeEditorFolderGet(action, project.type, project.plugin, project.workspaceName));
231
+ }
232
+
233
+ onActionCodeEditorFolderNew(action) {
234
+ const project = this._getProject(action.projectId);
235
+ this.sendDataAction(new DataActionCodeEditorFolderNew(action, project.type, project.plugin, project.workspaceName));
236
+ }
237
+
238
+ onActionCodeEditorFolderAdd(action) {
239
+ let node = null;
240
+ let currentProject = null;
241
+ this._updateProject(action.projectId, (project, app) => {
242
+ currentProject = project;
243
+ node = project.addFolder(action.title, action.data);
244
+ project.sortParent(node);
245
+ });
246
+ const folder = this._createFolder(currentProject.projectId, node);
247
+ this._setCurrentFolder(folder, true);
248
+ }
249
+
250
+ onActionCodeEditorFolderUpdate(action) {
251
+ const project = this._getProject(action.projectId);
252
+ this.sendDataAction(new DataActionCodeEditorFolderUpdate(`${action.data.path}/${action.title}`, `${action.data.path}/${action.newTitle}`, action, project.type, project.plugin, project.workspaceName));
253
+ }
254
+
255
+ onActionCodeEditorFolderRemove(action) {
256
+ const node = this._getNode(`${action.data.path}/${action.title}`);
257
+ const children = this.state.project.getAllFileChildren(node.node);
258
+
259
+ children.forEach((child) => {
260
+ const file = this.state.files.get(child.key);
261
+ if(file) {
262
+ this.onActionCodeEditorFileClose({key: child.key});
263
+ }
264
+ });
265
+ const nodeParent = this._getNode(node.node.data.path);
266
+ const folder = this._createFolder(nodeParent.projectId, nodeParent.node);
267
+ this._updateProject(action.projectId, (project, app) => {
268
+ project.removeNode(action.data.path, action.key);
269
+ });
270
+ this._setCurrentFolder(folder, true);
271
+ }
272
+
273
+ onActionCodeEditorFolderDelete(action) {
274
+ const project = this._getProject(action.projectId);
275
+ this.sendDataAction(new DataActionCodeEditorFolderDelete(action, project.type, project.plugin, project.workspaceName));
276
+ }
277
+
278
+ onActionCodeEditorFileMove(action) {
279
+ let found = false;
280
+ let foundFromKey = false;
281
+ let foundToKey = false;
282
+ let newMap = new Map();
283
+ let fromFile = null;
284
+ this.state.files.forEach((file, key) => {
285
+ if(!found) {
286
+ if(action.fromKey === key) {
287
+ foundFromKey = true;
288
+ found = true;
289
+ }
290
+ else if(action.toKey === key) {
291
+ fromFile = this.state.files.get(action.fromKey);
292
+ newMap.set(action.fromKey, fromFile);
293
+ newMap.set(action.toKey, file);
294
+ foundToKey = true;
295
+ found = true;
296
+ }
297
+ else {
298
+ newMap.set(key, file);
299
+ }
300
+ }
301
+ else {
302
+ if(foundFromKey) {
303
+ if(action.toKey === key) {
304
+ newMap.set(action.toKey, file);
305
+ fromFile = this.state.files.get(action.fromKey);
306
+ newMap.set(action.fromKey, fromFile);
307
+ }
308
+ else if(action.fromKey !== key) {
309
+ newMap.set(key, file);
310
+ }
311
+ }
312
+ else if(foundToKey) {
313
+ if(action.fromKey !== key) {
314
+ newMap.set(key, file);
315
+ }
316
+ }
317
+ }
318
+ });
319
+ this.updateState({files: {$set: newMap}});
320
+ this._setCurrentFile(fromFile, null, true);
321
+ }
322
+
323
+ onActionCodeEditorProjectUpdateAll(action) {
324
+ action.projectIds.forEach((projectId) => {
325
+ const project = this._getProject(projectId);
326
+ if(!project.type) {
327
+ this.sendDataAction(new DataActionCodeEditorProjectUpdate(project.projectId, project.source, this._getAppName()));
328
+ }
329
+ else {
330
+ this.sendDataAction(new DataActionCodeEditorProjectUpdate(project.projectId, project.source, project.source[0].title, project.type, project.plugin));
331
+ }
332
+ });
333
+ }
334
+
335
+ onActionCodeEditorProjectToggle(action) {
336
+ let isApp = true;
337
+ this._updateProject(action.projectId, (project, app) => {
338
+ isApp = app;
339
+ project.toggle(action.key, action.expanded);
340
+ });
341
+ const project = this._getProject(action.projectId);
342
+ if(isApp) {
343
+ this.sendDataAction(new DataActionCodeEditorProjectToggle(action, this.state.project.source, this._getAppName()));
344
+ }
345
+ else {
346
+ this.sendDataAction(new DataActionCodeEditorProjectToggle(action, project.source, project.source[0].title, project.type));
347
+ }
348
+ }
349
+
350
+ onActionActorEditorBuild(action) {
351
+ this.sendDataAction(new DataActionCodeEditorBuild(this.state.current.file.content, this.state.current.file.path, this.state.current.file.title));
352
+ }
353
+
354
+ onDataActionCodeEditorWorkspaceGet(action) {
355
+ const response = action.getResponse();
356
+ if(response.isSuccess()) {
357
+ if(Array.isArray(response.data)) {
358
+ this.updateState({project: (project) => {
359
+ project.set(response.data[0], null, action.workspaceName);
360
+ }});
361
+ this.updateState({eol: {$set: response.data[2]}});
362
+ this.updateState({projects: (projects) => {
363
+ projects.clear();
364
+ const projectsExternal = response.data[1];
365
+ projectsExternal.sort((a, b) => {
366
+ if(a.source[0].title < b.source[0].title) {
367
+ return -1;
368
+ }
369
+ else if(a.source[0].title > b.source[0].title) {
370
+ return 1;
371
+ }
372
+ else {
373
+ return 0;
374
+ }
375
+ });
376
+ this.updateState({files: (files) => {
377
+ if(0 !== files.size) {
378
+ files.clear();
379
+ }
380
+ }});
381
+ for(let i = 0; i < projectsExternal.length; ++i) {
382
+ const projectData = projectsExternal[i];
383
+ const project = new Project(projectData.source, projectData.type, projectData.plugin);
384
+ projects.set(project.projectId, project);
385
+ }
386
+ }});
387
+ }
388
+ const url = this._parseUrl(location.pathname, location.search);
389
+ this.updateState({current: {url: {$set: url}}});
390
+ if(action.open) {
391
+ // TODO: LINE
392
+ const filesData = {
393
+ file: url.query.file ? `.${url.query.file}` : null,
394
+ folder: url.query.folder ? `.${url.query.folder}` : null,
395
+ search: url.query.search,
396
+ filesToLoad: [],
397
+ filesNotLoaded: 0,
398
+ filesLoaded: new Map(),
399
+ searchesToLoad: [],
400
+ searchesNotLoaded: 0,
401
+ searchesLoaded: new Map()
402
+ };
403
+ if(url.query.files) {
404
+ filesData.filesToLoad = url.query.files.split(',');
405
+ filesData.filesNotLoaded = filesData.filesToLoad.length;
406
+ const filesNotToLoad = [];
407
+ filesData.filesToLoad.forEach((fileToLoad) => {
408
+ const fileToLoadParam = fileToLoad.split(';');
409
+ const currentUrl = `.${fileToLoadParam[1]}`;
410
+ const node = this._getNode(currentUrl);
411
+ if(node) {
412
+ const project = this._getProject(node.projectId);
413
+ this.sendDataAction(new DataActionCodeEditorFileGet(currentUrl, node.projectId, node.node.key, node.node.title, node.node.data.path, node.node.data.type, project.type, project.plugin, project.workspaceName, filesData));
414
+ }
415
+ else {
416
+ filesNotToLoad.push(fileToLoad);
417
+ }
418
+ });
419
+ if(0 !== filesNotToLoad.length) {
420
+ filesData.filesNotLoaded -= filesNotToLoad.length;
421
+ filesNotToLoad.forEach((fileNotToLoad) => {
422
+ const index = filesData.filesToLoad.indexOf(fileNotToLoad);
423
+ if(-1 !== index) {
424
+ filesData.filesToLoad.splice(index, 1);
425
+ }
426
+ });
427
+ }
428
+ }
429
+ if(url.query.searches) {
430
+ filesData.searchesToLoad = url.query.searches.split(',');
431
+ filesData.searchesNotLoaded = filesData.searchesToLoad.length;
432
+ filesData.searchesToLoad.forEach((searchToLoad) => {
433
+ const params = searchToLoad.split(';');
434
+ this.onActionCodeEditorWorkspaceSearch(new ActionCodeEditorWorkspaceSearch(params[1], params[2], params[0], filesData));
435
+ });
436
+ }
437
+ if(url.query.folder) {
438
+ const node = this._getNode(`.${url.query.folder}`);
439
+ if(node) {
440
+ const project = this._getProject(node.projectId);
441
+ this.sendDataAction(new DataActionCodeEditorFolderGet(new ActionCodeEditorFolderGet(node.projectId, node.node.key, node.node.title, node.node.data, project.workspaceNam), project.type, project.plugin, project.workspaceName));
442
+ }
443
+ }
444
+ }
445
+ else {
446
+ if(query?.workspace !== action.appName) {
447
+ this.updateState({current: {url: {query: {workspace: {$set: action.appName}}}}});
448
+ this._setCurrentFile(null, null, false);
449
+ }
450
+ else {
451
+
452
+ }
453
+ }
454
+ }
455
+ }
456
+
457
+ onDataActionCodeEditorWorkspaceNew(action) {
458
+ const response = action.getResponse();
459
+ if(response.isSuccess()) {
460
+ //this.updateState({current: {workspace: {$set: new Map(response.data)}}});
461
+ }
462
+ }
463
+
464
+ _filesDataLoaded(action) {
465
+ const pathname = action.filesData.file;
466
+ const filesToLoad = action.filesData.filesToLoad;
467
+ const searchesToLoad = action.filesData.searchesToLoad;
468
+ let currentFile = null;
469
+ let currentSearchKey = null;
470
+ let currentFileValid = false;
471
+ const loadOrder = new Map();
472
+ filesToLoad.forEach((fileToLoad) => {
473
+ const fileToLoadParams = fileToLoad.split(';');
474
+ loadOrder.set(Number.parseInt(fileToLoadParams[0]), {
475
+ type: CodeEditorStore.IS_FILE,
476
+ params: fileToLoadParams
477
+ });
478
+ });
479
+ searchesToLoad.forEach((searchToLoad) => {
480
+ const searchToLoadParams = searchToLoad.split(';');
481
+ loadOrder.set(Number.parseInt(searchToLoadParams[0]), {
482
+ type: CodeEditorStore.IS_SEARCH,
483
+ params: searchToLoadParams
484
+ });
485
+ });
486
+ const length = loadOrder.size;
487
+ for(let i = 0; i < length; ++i) {
488
+ const loadData = loadOrder.get(i);
489
+ if(CodeEditorStore.IS_FILE === loadData.type) {
490
+ const fileLoaded = action.filesData.filesLoaded.get(`.${loadData.params[1]}`);
491
+ if(action.filesData.file === `${fileLoaded.file.path}/${fileLoaded.file.title}`) {
492
+ currentFile = fileLoaded.file;
493
+ currentFileValid = fileLoaded.valid;
494
+ }
495
+ this.updateState({files: (files) => {
496
+ files.set(fileLoaded.file.key, fileLoaded.file);
497
+ }});
498
+ }
499
+ else if(CodeEditorStore.IS_SEARCH === loadData.type) {
500
+ const searchLoaded = action.filesData.searchesLoaded.get(loadData.params[0]);
501
+ if(action.filesData.search === `${searchLoaded.search};${searchLoaded.rules}`) {
502
+ currentSearchKey = searchLoaded.key;
503
+ }
504
+ this.updateState({files: (files) => {
505
+ files.set(searchLoaded.key, searchLoaded);
506
+ }});
507
+ }
508
+ }
509
+ if(currentFile) {
510
+ this._setCurrentFile(currentFile, null, currentFileValid);
511
+ }
512
+ if(currentSearchKey) {
513
+ this._setCurrentSearch(currentSearchKey);
514
+ }
515
+ if(action.filesData.folder) {
516
+ const node = this._getNode(action.filesData.folder);
517
+ if(node) {
518
+ const project = this._getProject(node.projectId);
519
+ this.sendDataAction(new DataActionCodeEditorFolderGet(new ActionCodeEditorFolderGet(node.projectId, node.node.key, node.node.title, node.node.data, project.workspaceNam), project.type, project.plugin, project.workspaceName));
520
+ }
521
+ }
522
+ }
523
+
524
+ onDataActionCodeEditorWorkspaceSearch(action) {
525
+ const response = action.getResponse();
526
+ if(response.isSuccess()) {
527
+ const data = {
528
+ key: GuidGenerator.create(),
529
+ tabType: CodeEditorStore.TYPE_SEARCH,
530
+ title: ` ${action.search.length <= 23 ? action.search : action.search.substring(0, 20) + '...'}`,
531
+ search: action.search,
532
+ rules: action.rules,
533
+ data: response.data
534
+ };
535
+ if(!action.filesData) {
536
+ this.updateState({files: (files) => {
537
+ files.set(data.key, data);
538
+ }});
539
+ this._setCurrentSearch(data.key);
540
+ }
541
+ else {
542
+ action.filesData.searchesLoaded.set(action.index, data);
543
+ if(0 === --action.filesData.searchesNotLoaded && 0 === action.filesData.filesNotLoaded) {
544
+ this._filesDataLoaded(action);
545
+ }
546
+ }
547
+ }
548
+ }
549
+
550
+ onDataActionCodeEditorFileGet(action) {
551
+ const response = action.getResponse();
552
+ const isSuccess = response.isSuccess();
553
+ const file = isSuccess ? {
554
+ key: action.key,
555
+ tabType: CodeEditorStore.TYPE_FILE,
556
+ projectId: action.projectId,
557
+ title: action.title,
558
+ path: action.path,
559
+ type: action.type,
560
+ plugin: action.plugin,
561
+ workspaceName: action.workspaceName,
562
+ content: response.data,
563
+ contentOriginal: response.data,
564
+ codeChanged: false,
565
+ codeBuilt: false,
566
+ valid: true
567
+ } : {
568
+ key: action.key,
569
+ tabType: CodeEditorStore.TYPE_FILE,
570
+ projectId: action.projectId,
571
+ title: action.title,
572
+ path: action.path,
573
+ type: action.type,
574
+ plugin: action.plugin,
575
+ workspaceName: action.workspaceName,
576
+ content: '',
577
+ contentOriginal: '',
578
+ codeChanged: false,
579
+ codeBuilt: false,
580
+ valid: false
581
+ };
582
+ this._updateProject(file.projectId, (project, app) => {
583
+ const node = project.findNode(`${file.path}/${file.title}`);
584
+ node.data.valid = isSuccess;
585
+ });
586
+ if(!action.filesData) {
587
+ this.updateState({files: (files) => { files.set(file.key, file); }});
588
+ this._setCurrentFile(file, null, isSuccess);
589
+ }
590
+ else {
591
+ action.filesData.filesLoaded.set(`${file.path}/${file.title}`, {
592
+ file,
593
+ valid: isSuccess
594
+ });
595
+ if(0 === --action.filesData.filesNotLoaded && 0 === action.filesData.searchesNotLoaded) {
596
+ this._filesDataLoaded(action);
597
+ }
598
+ }
599
+ }
600
+
601
+ onDataActionCodeEditorFileNew(action) {
602
+ const response = action.getResponse();
603
+ if(response.isSuccess()) {
604
+ let node;
605
+ let projectType;
606
+ let projectPlugin;
607
+ let projectWorkspaceName;
608
+ this._updateProject(action.projectId, (project, app) => {
609
+ node = project.addFile(response.data, action.path, action.type);
610
+ project.sortParent(node);
611
+ if(!app) {
612
+ projectType = project.type;
613
+ projectPlugin= project.plugin;
614
+ }
615
+ else {
616
+ projectWorkspaceName = project.workspaceName;
617
+ }
618
+ });
619
+ this.sendDataAction(new DataActionCodeEditorFileGet(`${node.data.path}/${node.title}`, action.projectId, node.key, node.title, node.data.path, node.data.type, projectType, projectPlugin, projectWorkspaceName));
620
+ }
621
+ }
622
+
623
+ onDataActionCodeEditorFileRename(action) {
624
+ const response = action.getResponse();
625
+ if(response.isSuccess()) {
626
+ let node = this._getNode(`${action.path}/${action.title}`);
627
+ this._updateProject(action.projectId, (project, app) => {
628
+ project.renameFile(node.node, action.newTitle);
629
+ });
630
+ let file = this.state.files.get(node.node.key);
631
+ const updatedFile = this.shallowCopy(file);
632
+ updatedFile.title = action.newTitle;
633
+ this.updateState({files: (files) => {
634
+ file = files.set(node.node.key, updatedFile);
635
+ }});
636
+ this._setCurrentFile(updatedFile, null, true);
637
+ }
638
+ }
639
+
640
+ onDataActionCodeEditorFileUpdate(action) {
641
+ const response = action.getResponse();
642
+ if(response.isSuccess()) {
643
+ let file = this.state.files.get(action.key);
644
+ if(file) {
645
+ let updatedFile = this.shallowCopy(file);
646
+ updatedFile.codeChanged = false;
647
+ updatedFile.contentOriginal = action.content;
648
+ this.updateState({files: (files) => {
649
+ files.set(action.key, updatedFile);
650
+ }});
651
+ if(this.state.current.file.key === action.key) {
652
+ this.updateState({current: {file: {$set: updatedFile}}});
653
+ }
654
+ }
655
+ }
656
+ }
657
+
658
+ onDataActionCodeEditorFileDelete(action) {
659
+ const response = action.getResponse();
660
+ if(response.isSuccess()) {
661
+ this.onActionCodeEditorFileRemove(action);
662
+ }
663
+ }
664
+
665
+ onDataActionCodeEditorFolderGet(action) {
666
+ const response = action.getResponse();
667
+ if(response.isSuccess()) {
668
+ const project = this._getProject(action.projectId);
669
+ if(project) {
670
+ const node = project.findNode(`${action.data.path}/${action.title}`);
671
+ if(node) {
672
+ const folder = this._createFolder(action.projectId, node);
673
+ this._setCurrentFolder(folder, response.data);
674
+ }
675
+ }
676
+ }
677
+ }
678
+
679
+ onDataActionCodeEditorFolderNew(action) {
680
+ const response = action.getResponse();
681
+ if(response.isSuccess()) {
682
+ let node = null;
683
+ let currentProject = null;
684
+ this._updateProject(action.projectId, (project, app) => {
685
+ currentProject = project;
686
+ node = project.addFolder(action.title, action.data);
687
+ project.sortParent(node);
688
+ });
689
+ const folder = this._createFolder(currentProject.projectId, node);
690
+ this._setCurrentFolder(folder, true);
691
+ }
692
+ }
693
+
694
+ onDataActionCodeEditorFolderUpdate(action) {
695
+ const response = action.getResponse();
696
+ if(response.isSuccess()) {
697
+ let node = this._getNode(`${action.data.path}/${action.title}`);
698
+ const children = this.state.project.getAllFileChildren(node.node);
699
+ this._updateProject(action.projectId, (project, app) => {
700
+ project.renamePathRecursive(node.node, action.newTitle);
701
+ });
702
+ node = this._getNode(`${action.data.path}/${action.newTitle}`);
703
+ const folder = this._createFolder(node.projectId, node.node);
704
+ this._setCurrentFolder(folder, true);
705
+ children.forEach((child) => {
706
+ let file;
707
+ this.updateState({files: (files) => {
708
+ file = files.get(child.key);
709
+ if(file) {
710
+ file = this.shallowCopy(file);
711
+ file.path = child.data.path;
712
+ files.set(child.key, file);
713
+ }
714
+ }});
715
+ /*if(this.state.current.file && this.state.current.file.key === child.key) {
716
+ this.updateState({current: {file: {$set: file}}});
717
+ }*/
718
+ });
719
+ }
720
+ }
721
+
722
+ onDataActionCodeEditorFolderDelete(action) {
723
+ const response = action.getResponse();
724
+ if(response.isSuccess()) {
725
+ this.onActionCodeEditorFolderRemove(action);
726
+ }
727
+ }
728
+
729
+ onDataActionCodeEditorProjectUpdate(action) {
730
+ const response = action.getResponse();
731
+ if(response.isSuccess()) {
732
+ this._updateProject(action.projectId, (project, app) => {
733
+ project.setSaved();
734
+ });
735
+ }
736
+ }
737
+
738
+ onDataActionCodeEditorProjectToggle(action) {
739
+ const response = action.getResponse();
740
+ if(response.isSuccess()) {
741
+ }
742
+ }
743
+
744
+ _getNextFile(file) {
745
+ let next;
746
+ let mapIter = this.state.files.values();
747
+ let iter = mapIter.next();
748
+ while(!iter.done) {
749
+ if(iter.value.key === file.key) {
750
+ if(next) {
751
+ return next;
752
+ }
753
+ else {
754
+ return mapIter.next().value;
755
+ }
756
+ }
757
+ next = iter.value;
758
+ iter = mapIter.next();
759
+ }
760
+ }
761
+
762
+ _getProject(projectId) {
763
+ if(projectId === this.state.project.projectId) {
764
+ return this.state.project;
765
+ }
766
+ else {
767
+ return this.state.projects.get(projectId);
768
+ }
769
+ }
770
+
771
+ _updateProject(projectId, cb) {
772
+ if(projectId === this.state.project.projectId) {
773
+ this.updateState({project: (project) => cb(project, true)});
774
+ }
775
+ else {
776
+ this.updateState({projects: (projects) => {
777
+ const project = projects.get(projectId);
778
+ if(project) {
779
+ const clonedProject = project.clone();
780
+ cb(clonedProject, false);
781
+ projects.set(projectId, clonedProject); // MUST update projectObject to trigger React.
782
+ }
783
+ }});
784
+ }
785
+ }
786
+
787
+ _setSelectedProject(projectId) {
788
+ if(projectId !== this.state.selectedProjectId) {
789
+ if(this.state.selectedProjectId) {
790
+ this._updateProject(this.state.selectedProjectId, (project, app) => {
791
+ project.unSelect();
792
+ });
793
+ }
794
+ this.updateState({selectedProjectId: {$set: projectId}});
795
+ }
796
+ }
797
+
798
+ _getNode(file) {
799
+ const node = this.state.project.findNode(file);
800
+ if(node) {
801
+ return {
802
+ projectId: this.state.project.projectId,
803
+ node: node
804
+ };
805
+ }
806
+ else {
807
+ for(let projectItem of this.state.projects) {
808
+ const project = projectItem[1];
809
+ const node = project.findNode(file);
810
+ if(node) {
811
+ return {
812
+ projectId: project.projectId,
813
+ node: node
814
+ };
815
+ }
816
+ }
817
+ }
818
+ }
819
+
820
+ _createFolder(projectId, node) {
821
+ return {
822
+ projectId: projectId,
823
+ key: node.key,
824
+ title: node.title,
825
+ data: node.data
826
+ };
827
+ }
828
+
829
+ _setCurrentFile(fileAdd, fileRemove, valid) {
830
+ this.updateState({current: {file: {$set: fileAdd}}});
831
+ this.updateState({current: {folder: {$set: null}}});
832
+ if(fileRemove) {
833
+ if("search" === fileRemove.tabType) {
834
+ this._updateSearch();
835
+ }
836
+ else {
837
+ const url = this._removeUrl(fileRemove.path, fileRemove.title, true);
838
+ const parsedUrl = this._parseUrl(url);
839
+ this.updateState({current: {url: {$set: parsedUrl}}});
840
+ this.history(url, {replace: true, noSlash:true});
841
+ }
842
+ }
843
+ if(fileAdd) {
844
+ if("search" === fileAdd.tabType) {
845
+ this._setCurrentSearch(fileAdd.key);
846
+ }
847
+ else {
848
+ this._updateProject(fileAdd.projectId, (project, app) => {
849
+ project.select(fileAdd.key, true);
850
+ const node = project.findNode(`${fileAdd.path}/${fileAdd.title}`);
851
+ if(node) {
852
+ node.data.valid = valid;
853
+ }
854
+ });
855
+ this._setSelectedProject(fileAdd.projectId);
856
+ this.updateState({current: {type: {$set: CodeEditorStore.TYPE_FILE}}});
857
+ const url = this._addUrl(fileAdd.path, fileAdd.title, true);
858
+ const parsedUrl = this._parseUrl(url);
859
+ this.updateState({current: {url: {$set: parsedUrl}}});
860
+ this.history(url, {replace: true, noSlash:true});
861
+ }
862
+ }
863
+ else {
864
+ if(this.state.selectedProjectId) {
865
+ this._updateProject(this.state.selectedProjectId, (project, app) => {
866
+ project.unSelect();
867
+ });
868
+ }
869
+ this.updateState({current: {type: {$set: ''}}});
870
+ const url = this._addUrl(null, null, true);
871
+ const parsedUrl = this._parseUrl(url);
872
+ this.updateState({current: {url: {$set: parsedUrl}}});
873
+ this.history(url, {replace: true, noSlash:true});
874
+ }
875
+ }
876
+
877
+ _setCurrentFolder(folder, valid) {
878
+ this._updateProject(folder.projectId, (project, app) => {
879
+ project.select(folder.key, true);
880
+ const node = project.findNode(`${folder.data.path}/${folder.title}`);
881
+ if(node) {
882
+ node.data.valid = valid;
883
+ }
884
+ });
885
+ this._setSelectedProject(folder.projectId);
886
+ this.updateState({current: {folder: {$set: folder}}});
887
+ this.updateState({current: {type: {$set: CodeEditorStore.TYPE_FOLDER}}});
888
+ const url = this._addUrl(folder.data.path, folder.title, false);
889
+ const parsedUrl = this._parseUrl(url);
890
+ this.updateState({current: {url: {$set: parsedUrl}}});
891
+ this.history(url, {replace: true, noSlash:true});
892
+ }
893
+
894
+ _setCurrentSearch(key) {
895
+ const data = this.state.files.get(key);
896
+ this.updateState({current: {file: {$set: data}}});
897
+ this.updateState({current: {type: {$set: CodeEditorStore.TYPE_SEARCH}}});
898
+ const url = this._updateSearch(`${data.search};${data.rules}`);
899
+ const parsedUrl = this._parseUrl(url);
900
+ this.updateState({current: {url: {$set: parsedUrl}}});
901
+ this.history(url, {replace: true, noSlash:true});
902
+ }
903
+
904
+ _parseUrl(pathname, search) {
905
+ if(!search) {
906
+ const index = pathname.indexOf('?');
907
+ if(-1 !== index) {
908
+ search = pathname.substring(index);
909
+ pathname = pathname.substring(0, index);
910
+ }
911
+ }
912
+ let currentPathname = '';
913
+ if(-1 !== pathname.indexOf(CodeEditorStore.START_PATH)) {
914
+ currentPathname = `.${pathname.substring(CodeEditorStore.START_PATH_LENGTH)}`;
915
+ }
916
+ else if(-1 !== pathname.indexOf(CodeEditorStore.CODE_EDITOR_PATH)) {
917
+ currentPathname = `.${pathname.substring(CodeEditorStore.CODE_EDITOR_PATH_LENGTH)}`;
918
+ }
919
+ else {
920
+ currentPathname = `.${pathname}`;
921
+ }
922
+ const url = {
923
+ pathname: currentPathname,
924
+ query: {}
925
+ };
926
+ if(search && search.length > 1) {
927
+ const searchs = search.substring(1).split('&');
928
+ if(searchs && searchs.length >= 1) {
929
+ searchs.forEach((searchPart) => {
930
+ const queryParam = searchPart.split('=');
931
+ if(2 === queryParam.length) {
932
+ url.query[queryParam[0]] = queryParam[1];
933
+ if('files' === queryParam[0]) {
934
+ let filesQuery = ''
935
+ const filesParam = queryParam[1].split(',');
936
+ filesParam.forEach((fileParam) => {
937
+ const params = fileParam.split(';');
938
+ filesQuery += `${params[0]};${params[1]},`;
939
+ if(params[2] && params[3]) {
940
+ this.updateContext(() => {
941
+ this.updateState({searchLines: (searchLine) => {
942
+ const logFiles = searchLine.get(CodeEditorStore.LOG_FILES);
943
+ if(logFiles) {
944
+ const lines = logFiles.get(params[1]);
945
+ const line = {
946
+ line: params[2],
947
+ type: params[3]
948
+ };
949
+ if(lines) {
950
+ if(!lines.some(obj => obj.line === params[2])) {
951
+ lines.push(line);
952
+ }
953
+ }
954
+ else {
955
+ logFiles.set(params[1], [line]);
956
+ }
957
+ }
958
+ }});
959
+ });
960
+ }
961
+ });
962
+ url.query[queryParam[0]] = filesQuery.substring(0, filesQuery.length - 1);
963
+ }
964
+ }
965
+ });
966
+ }
967
+ }
968
+ return url;
969
+ }
970
+
971
+ _addUrlSearch(resultingUrl, name, param) {
972
+ if(param) {
973
+ if(resultingUrl.p) {
974
+ resultingUrl.p += '&';
975
+ }
976
+ resultingUrl.p += `${name}=${param}`;
977
+ }
978
+ }
979
+
980
+ _generateQuery(url, type) {
981
+ const query = this.state.current.url.query;
982
+ let file = CodeEditorStore.IS_FILE === type ? (url ? url : '') : (CodeEditorStore.IS_FOLDER === type ? query.file : '');
983
+ let folder = CodeEditorStore.IS_FOLDER === type ? url : '';
984
+ let search = CodeEditorStore.IS_SEARCH === type ? url : '';
985
+ let files = [];
986
+ let searches = [];
987
+ let index = -1;
988
+ this.state.files.forEach((file) => {
989
+ if("search" === file.tabType) {
990
+ searches.push(`${++index};${file.search};${file.rules}`);
991
+ }
992
+ else {
993
+ files.push(`${++index};${file.path.substring(1)}/${file.title}`);
994
+ }
995
+ });
996
+ const resultingUrl = {
997
+ p: ''
998
+ };
999
+ this._addUrlSearch(resultingUrl, 'file', file);
1000
+ this._addUrlSearch(resultingUrl, 'folder', folder);
1001
+ this._addUrlSearch(resultingUrl, 'search', search);
1002
+ this._addUrlSearch(resultingUrl, 'files', files.join(','));
1003
+ this._addUrlSearch(resultingUrl, 'searches', searches.join(','));
1004
+ if(resultingUrl.p) {
1005
+ resultingUrl.p = `?${resultingUrl.p}`;
1006
+ }
1007
+ return resultingUrl.p;
1008
+ }
1009
+
1010
+ _addUrl(path, title, isFile) {
1011
+ const query = this.state.current.url.query;
1012
+ if(CodeEditorStore.showWorkspace) {
1013
+ if(path && title) {
1014
+ const url = `${path.substring(1)}/${title}`
1015
+ return `${url}?workspace=${query.workspace}`;
1016
+ }
1017
+ else {
1018
+ return `?workspace=${query.workspace}`;
1019
+ }
1020
+ }
1021
+ else {
1022
+ const url = (path && title) ? `${path.substring(1)}/${title}` : null;
1023
+ return this._generateQuery(url, isFile ? CodeEditorStore.IS_FILE : CodeEditorStore.IS_FOLDER);
1024
+ }
1025
+ }
1026
+
1027
+ _removeUrl(path, title, isFile) {
1028
+ const query = this.state.current.url.query;
1029
+ if(CodeEditorStore.showWorkspace) {
1030
+
1031
+ }
1032
+ else {
1033
+ const url = `${path.substring(1)}/${title}`
1034
+ return this._generateQuery(url, isFile ? CodeEditorStore.IS_FILE : CodeEditorStore.IS_FOLDER);
1035
+ }
1036
+ }
1037
+
1038
+ _updateSearch(search) {
1039
+ return this._generateQuery(search, CodeEditorStore.IS_SEARCH);
1040
+ }
1041
+ }
1042
+
1043
+
1044
+ module.exports = CodeEditorStore.export(CodeEditorStore);