Compare commits

..

416 Commits

Author SHA1 Message Date
f076b5590f Release v3.0.0a5 2023-10-27 13:29:47 +10:00
aead5be762 Merge pull request #1475 from Orange-OpenSource/master-3.0
re enable configure dialog
2023-10-26 19:57:38 +10:00
b6db926654 re enable configure dialog 2023-10-26 11:19:24 +02:00
c9ac9f896f Merge pull request #1474 from Orange-OpenSource/master-3.0
3.0 fix not working tests
2023-10-25 21:39:21 +10:00
15e20263e5 fix somes tests 2023-10-25 11:06:15 +02:00
3df22bd177 Merge branch '2.2' into master-3.0
# Conflicts:
#	package.json
#	src/app/components/project-map/drawings-editors/style-editor/style-editor.component.ts
2023-10-24 18:25:10 +10:00
dbcb8a88c8 Pass authentication token when opening ws console. Ref https://github.com/GNS3/gns3-web-ui/issues/1468 2023-10-22 15:50:05 +10:00
76f2314e08 Development on 3.0.0.dev9 2023-10-20 15:52:29 +10:00
97d054bb2b Release v3.0.0a4 2023-10-18 17:41:43 +10:00
931b7b1109 Merge pull request #1465 from GNS3/rbac-tweaking
Adjustments for RBAC system
2023-10-06 18:42:01 +10:00
c7b5d0d2f8 Rename ACE management component to ACL 2023-10-06 18:02:57 +10:00
a71014de81 Change titles for RBAC management 2023-10-06 17:27:00 +10:00
73c9fd3181 Merge pull request #1464 from Orange-OpenSource/master-3.0
Master 3.0: Update group management
2023-09-29 23:23:16 +10:00
ff38d7abb7 Merge branch 'GNS3:master-3.0' into master-3.0 2023-09-29 14:11:29 +02:00
db66a09e3b add linked ACE to user and group detail page 2023-09-29 11:10:53 +02:00
c517e98bb1 Merge pull request #1462 from Orange-OpenSource/master-3.0
PR: Add resources pools management + ACE/ACL management
2023-09-28 18:44:43 +10:00
ed4fd7c06a Merge branch 'GNS3:master-3.0' into master-3.0 2023-09-26 11:07:18 +02:00
4870e58977 ACE management 2023-09-26 11:02:33 +02:00
6b5b784658 Add resources pools management interface 2023-09-25 15:03:07 +02:00
963af81d30 Rename text "is build" to "is built-in" 2023-09-21 19:43:20 +10:00
b106f31b36 Merge pull request #1460 from Orange-OpenSource/master-3.0
Master 3.0, add privileges to role management
2023-09-20 14:05:35 +07:00
39401f3184 fix privilege component test 2023-09-19 11:52:07 +02:00
55c993df71 updte role management: replace permissions by privileges 2023-09-19 11:43:46 +02:00
2c0cd88ca6 create UI to manege privileges to a role 2023-09-18 14:22:41 +02:00
9ca10d6d6a update role api url 2023-09-12 15:53:08 +02:00
7bad625fdd suppression des permissions 2023-09-12 15:03:02 +02:00
bae7bcdd8d Update endpoint paths for user management 2023-09-07 14:46:23 +07:00
6322fea306 Merge pull request #1451 from GNS3/upgrade-angular
Upgrade to Angular 14
2023-08-18 16:47:44 +10:00
318d783370 Merge branch 'master-3.0' into upgrade-angular 2023-08-18 16:24:08 +10:00
93a98f1335 Merge branch '2.2' into master-3.0
# Conflicts:
#	package.json
#	src/app/cartography/components/experimental-map/drawing/drawings/rect/rect.component.html
#	src/app/cartography/converters/map/map-drawing-to-svg-converter.ts
#	src/app/components/preferences/qemu/qemu-vm-template-details/qemu-vm-template-details.component.html
#	src/app/components/project-map/drawings-editors/style-editor/style-editor.component.ts
#	src/app/components/project-map/new-template-dialog/new-template-dialog.component.ts
#	yarn.lock
2023-08-02 18:39:15 +10:00
21ef30ceed Revert "Remove comments from .yarnclean"
This reverts commit 8243238ae3.
2023-06-30 19:03:32 +10:00
8243238ae3 Remove comments from .yarnclean 2023-06-30 18:51:39 +10:00
f9baba7ad9 Merge branch 'master-3.0' into upgrade-angular 2023-06-30 17:57:20 +10:00
45d5663562 Development on 3.0.0.dev7 2023-06-30 17:56:15 +10:00
cb3cf5399d Fix tests 2023-06-30 17:37:12 +10:00
69aa4ac613 Upgrade ng2-file-upload to v3.0.0 2023-06-30 17:29:56 +10:00
0eef66eabf Add CommonJS modules to allowedCommonJsDependencies in angular.json 2023-06-30 17:23:16 +10:00
37813d4ad6 Upgrade material to v14 2023-06-30 12:43:30 +10:00
d67440ae6a Upgrade to Angular 14 2023-06-30 12:11:20 +10:00
b25337f65b Upgrade requests module. Fixes #1448 2023-06-21 18:38:42 +09:30
ac02dede76 Support for UEFI boot mode option for Qemu VMs 2023-06-21 18:10:00 +09:30
17a9e3d089 Merge pull request #1434 from GNS3/vmware-virtualbox-deprecated
Mark VMware and VirtualBox support as deprecated
2023-02-06 06:26:14 +05:45
eff72dc5f8 Fix tests 2023-02-05 10:20:54 +08:00
8e338da896 Warn that VMware and VirtualBox support is deprecated 2023-02-05 10:07:26 +08:00
d982ae0a00 Merge branch 'master' into master-3.0 2023-02-04 16:10:30 +08:00
c6ce67f867 Revert "Handle additional directories for Docker"
This reverts commit fac07ceeb4.
2023-02-01 16:00:59 +08:00
fac07ceeb4 Handle additional directories for Docker 2023-02-01 13:06:03 +08:00
a8aef0729d Fixes after merge 2023-02-01 11:46:12 +08:00
386c98d677 Update build for production in package.json 2023-02-01 11:08:00 +08:00
c12167379d Use 'ChromeHeadless' in karma.conf.js 2023-02-01 10:57:59 +08:00
6aa6647f53 Remove goToSystemStatus() after merge 2023-02-01 10:42:14 +08:00
7ac3a628a4 Merge remote-tracking branch 'origin/master' into master-3.0
# Conflicts:
#	angular.json
#	package.json
#	src/ReleaseNotes.txt
#	src/app/cartography/helpers/font-fixer.spec.ts
#	src/app/cartography/models/node.ts
#	src/app/components/preferences/qemu/add-qemu-vm-template/add-qemu-vm-template.component.html
#	src/app/components/preferences/qemu/add-qemu-vm-template/add-qemu-vm-template.component.ts
#	src/app/components/project-map/node-editors/configurator/docker/configurator-docker.component.ts
#	src/app/components/project-map/project-map-menu/project-map-menu.component.ts
#	src/app/components/project-map/project-map.component.html
#	src/app/components/project-map/project-map.component.ts
#	src/app/components/projects/projects.component.html
#	src/app/components/settings/settings.component.html
#	src/app/components/settings/settings.component.spec.ts
#	src/app/components/template/template-list-dialog/template-list-dialog.component.html
#	src/app/components/template/template.component.html
#	src/app/components/template/template.component.ts
#	src/app/services/link.service.ts
#	yarn.lock
2023-02-01 10:32:12 +08:00
a08f8c5963 Fix error when suspending and configuring a packet filter on a link
(cherry picked from commit aeef3e74ed)
2023-02-01 10:12:38 +08:00
642082e9fb Use a hidden iframe to open console on Firefox
(cherry picked from commit 83d72787f4)
2023-02-01 10:11:27 +08:00
fa8fd3c4a2 Add TPM support for Qemu VMs 2023-01-04 18:54:25 +08:00
e9e3730618 Release 3.0.0a3 2022-12-27 12:51:03 +08:00
fb639c8acd Merge pull request #1405 from GNS3/bugfix-1371
Removed the top banner and logo on the controllers page
2022-10-20 16:16:59 +08:00
6577bfc926 Removed the top banner and logo on the controllers page 2022-10-19 18:29:05 +05:30
88f44554de Merge pull request #1396 from GNS3/bugfix/1379
Bugfix/1379
2022-09-07 23:58:41 +02:00
872ebdae09 unit test cases for lock/unlock 2022-09-07 14:56:34 +05:30
2bc5fc101b Development on v3.0.0dev5 2022-09-07 00:51:36 +02:00
a5030baf62 Release v3.0.0a2 2022-09-07 00:49:27 +02:00
0c0d27fd6e Resolve issue Lock or unlock all items button does not reflect the nodes status on the web-ui workspace GNS3 3.0.0 alpha 1 2022-09-06 17:03:00 +05:30
e6e7122e33 Merge pull request #1389 from GNS3/bugfix/1383
Resolve missing border style options dash dot dot and invisible for l…
2022-08-29 19:28:24 +02:00
20bd0733f2 Change 'Dash Dot' and 'Dash Dot Dot' border styles 2022-08-29 19:23:48 +02:00
3fa923a9d1 Resolve no border style issue 2022-08-27 00:30:34 +05:30
02bd105b86 Merge branch 'bugfix/1383' of https://github.com/GNS3/gns3-web-ui into bugfix/1383 2022-08-26 11:07:18 +05:30
573d36057b add a condition for getting no border and solid border style 2022-08-26 11:06:57 +05:30
0eaa5c714c Add 'Dash Dot Dot' border type in link style editor 2022-08-25 22:17:52 +02:00
1c8e56274a Resolve stroke dasharray value get undefined issue on web ui 2022-08-25 10:44:36 +05:30
43c689b30a remove qt fixer condition 2022-08-24 18:04:20 +05:30
5bee5deb22 convert the qt value into the stroke dasharray 2022-08-24 16:03:50 +05:30
22ef305e81 Add comments 2022-08-23 23:58:21 +02:00
b66af49137 Modified the stroke dasharray value for creating Dash Dot, Dash Dot Dot border style 2022-08-23 16:53:48 +05:30
fcfcb7566d Merge pull request #1388 from GNS3/bugfix/1381
Highlight the current menu item in dropdown menu on mouse over
2022-08-22 12:57:22 +02:00
6fe15bac9c Resolve lighlight the current menu item in dropdown menu on mouse over only light theme 2022-08-22 16:21:10 +05:30
2f9e735928 Merge branch 'bugfix/1383' of https://github.com/GNS3/gns3-web-ui into bugfix/1383 2022-08-22 16:08:52 +05:30
c5837b237a Resolve inconsistent border styles for device links between GNS3 desktop UI and web-ui 2022-08-22 16:06:33 +05:30
1d13862880 Add hover class for highlight the current menu item in dropdown menu on mouse over 2022-08-19 17:11:26 +05:30
651d4c9d32 Change Invisible to No border 2022-08-18 22:21:48 +02:00
d03bd2a667 Merge pull request #1387 from GNS3/bugfix/1361
Resize pop-up windows and remove pagination arrow buttons
2022-08-18 22:14:31 +02:00
f338a2e33d Resolve missing border style options dash dot dot and invisible for links between devices 2022-08-18 18:25:38 +05:30
15f8fff179 Highlight the current menu item in dropdown menu on mouse over 2022-08-18 17:22:42 +05:30
b3aeb148e7 Resize pop-up windows and remove pagination arrow buttons 2022-08-18 12:09:01 +05:30
85f60fbc1c Merge pull request #1386 from GNS3/bugfix/1362
Remove Inner scroll bar for node configuration
2022-08-18 00:07:37 +02:00
228ea78c41 Remove Inner scroll bar for node configuration 2022-08-17 16:51:08 +05:30
c0f5b022e8 Merge pull request #1385 from GNS3/fix-cve-issues
Fix node-fetch CVE issue
2022-08-12 17:41:57 +02:00
1888174ebf Back to electron 13.6.6 2022-08-12 17:31:11 +02:00
3cf1984b39 Update yarn.lock 2022-08-12 12:51:26 +02:00
eda1099b41 Fix node-fetch and electron CVE issues 2022-08-12 11:51:30 +02:00
b309cf92e6 Merge pull request #1382 from GNS3/bugfix/1377
Resolve Cannot set border style for any shapes in Web-UI GNS3 3.0.0 A…
2022-08-12 11:38:43 +02:00
5da993e2f5 Add Border style placeholder in border style selections 2022-08-12 14:51:01 +05:30
8e197a8831 Resolve Cannot set border style for any shapes in Web-UI GNS3 3.0.0 Alpha 1 issue 2022-08-10 17:09:12 +05:30
c80ff95757 Merge pull request #1380 from GNS3/bugfix/1373
Resolve this issue:
2022-08-10 00:35:08 +02:00
6f3b0d2004 Merge branch 'master-3.0' into bugfix/1373 2022-08-10 00:30:11 +02:00
75cb4f0280 update network adapters list 2022-08-09 15:48:48 +05:30
d4ea702a6a Resolve this issue:
Cannot change network card type on Qemu VM templates from Web-UI
2022-08-09 10:09:34 +05:30
a143f0d037 Merge pull request #1376 from GNS3/bugfix/1372
resolve Uploaded images with long names get truncated in image manage…
2022-08-08 23:51:44 +02:00
7b1bd4a170 resolve Uploaded images with long names get truncated in image manager issue 2022-08-08 09:58:15 +05:30
4ad56ed856 Add more video resolutions to Docker containers using VNC in WebUI. Fixes #1375
(cherry picked from commit 83f7d36e2d)
2022-08-08 00:00:55 +02:00
c264268ab8 Update accepted image extensions to upload a new image 2022-08-06 13:10:37 +02:00
835f35d996 Development on v3.0.0dev4 2022-08-04 11:01:45 +02:00
9e61e2cb0b Release v3.0.0a1 2022-08-04 10:58:41 +02:00
cb48ea2715 Merge pull request #1370 from GNS3/bugfixRemovedQemuCode/1363
Bugfix removed qemu code/1363
2022-08-03 11:13:45 +02:00
206d25d032 Set platform with first element in the list 2022-08-03 11:08:30 +02:00
0bb4db78a4 Merge branch 'bugfixRemovedQemuCode/1363' of https://github.com/GNS3/gns3-web-ui into bugfixRemovedQemuCode/1363 2022-08-02 09:48:11 +05:30
e8e5ce8bb9 Remove unused code and Add edit platform in node Configurator pop 2022-08-02 09:47:50 +05:30
8424df0e2b Update configurator-qemu.component.ts 2022-08-02 00:16:01 +02:00
24deb65a0b remove Qemu code 2022-08-01 17:23:04 +05:30
4d5a5b8934 . 2022-08-01 17:18:46 +05:30
408130596a Removed QEMU binaries code 2022-08-01 16:57:44 +05:30
8846415959 . 2022-08-01 16:51:38 +05:30
939e4dfd5b Remove QEMU binaries code from add and edit qemu template. 2022-08-01 16:48:15 +05:30
a1163f0274 Modify platform selection on add new Qemu Component 2022-08-01 10:34:41 +05:30
1e0afa2460 Qemu binaries endpoint, Now we are not using in Frontend side 2022-08-01 10:02:42 +05:30
a2338d905b Merge pull request #1368 from GNS3/enhancement/1360
Enhancement/1360
2022-07-30 15:50:09 +02:00
5bb61bd1bc Resolve Unit test case issues 2022-07-30 16:31:05 +05:30
2a44abadd5 Comment Suggestions have been resolved 2022-07-30 08:58:41 +05:30
37684efe79 Fix typo 2022-07-29 09:35:16 +02:00
c8188ebf9c Comment Suggestions have been resolved 2022-07-29 09:57:56 +05:30
060a1f32cc Merge branch 'bugfix/1366' of https://github.com/GNS3/gns3-web-ui into enhancement/1360 2022-07-29 09:29:04 +05:30
387e5366be add a condition for logo menu 2022-07-27 16:04:43 +05:30
83a6da8cdb update script for deploy 2022-07-27 14:29:10 +05:30
fc5b7b6e34 Enable top left corner menu on other page like setting 2022-07-27 11:48:24 +05:30
f75e7e0e10 Merge pull request #1365 from GNS3/enhancement/1355
Enhancement/1355
2022-07-26 23:50:17 +02:00
73bc8cd4b7 Merge pull request #1359 from GNS3/enhancement/1354
Enhancement/1354
2022-07-26 23:40:10 +02:00
7601a75831 Remove '.' 2022-07-26 23:36:01 +02:00
44c0f75628 Complete improvements on preferences page. 2022-07-26 18:05:12 +05:30
3c23e983ec Fix adding Ethernet switch template 2022-07-26 10:38:47 +02:00
9b6e927c7b Remove unused code and change string into
Your selected files => Your selected projects
2022-07-26 09:18:03 +05:30
17901e9ed2 Preferences page improvement 2022-07-26 08:56:31 +05:30
3024f62d4b Merge pull request #1364 from GNS3/use-themed-symbols
Let the controller allocate symbols
2022-07-25 20:46:05 +02:00
bd118fc4bd Use generic symbol names 2022-07-25 10:53:09 +02:00
97a04a2fba Resolve the top-right menu url issue 2022-07-25 11:49:21 +05:30
cffd8d79a9 Caching yarn dependencies 2022-07-23 11:09:49 +02:00
dc94d22822 Finish merging code from master-3.0 2022-07-23 10:58:17 +02:00
c3bfad647f Merge branch 'master-3.0' into enhancement/1354 2022-07-23 00:52:38 +02:00
e2f4d67a30 Merge pull request #1356 from GNS3/enhancement/1353
Enhancement/1353
2022-07-23 00:41:15 +02:00
698ecfa255 Bring back location column 2022-07-23 00:32:45 +02:00
ff1b991d2a Add missing code 2022-07-23 00:01:17 +02:00
714db5e399 Test with Node matrix 2022-07-22 22:36:37 +02:00
c59dd035eb Rename user management server ref to controller 2022-07-22 21:44:41 +02:00
a79d6c916f Merge branch 'master-3.0' into enhancement/1353 2022-07-22 19:28:39 +02:00
e72c6f6609 Merge branch 'Orange-OpenSource-master-3.0' into master-3.0 2022-07-22 19:16:37 +02:00
f6961777f0 Merge branch 'master-3.0' of https://github.com/Orange-OpenSource/gns3-web-ui into Orange-OpenSource-master-3.0 2022-07-22 19:16:10 +02:00
f340586956 Merge branch 'master-3.0' into enhancement/1353 2022-07-22 18:50:51 +02:00
8929d1d659 Finish to rename server to controller 2022-07-22 18:49:36 +02:00
cb7c445a0b Allow raw image in appliance manager 2022-07-22 12:44:18 +02:00
7c343c51be I change commented files 2022-07-22 13:56:16 +05:30
20fe475791 Removed debugger 2022-07-21 17:56:08 +05:30
974e17395b renamed [server] = "server" => [controller]="controller" 2022-07-21 17:35:05 +05:30
4b0499e373 Renamed e2e testing file function or variable 2022-07-21 16:32:09 +05:30
a6661a24c6 Resolve all commented issue 2022-07-21 14:16:55 +05:30
7a79835a8d I renamed servers service file into controller.service 2022-07-21 13:57:09 +05:30
c682db4595 Rename Server file name into controller 2022-07-21 12:41:12 +05:30
ca601e410b Renamed server.id and serverId into controller.id and controllerId and modified the all unit test cases 2022-07-20 14:28:13 +05:30
845f1f1ad8 I complete unit test case to confirmations for delete all project 2022-07-19 18:18:46 +05:30
3bbd755d0a add route 2022-07-19 17:56:31 +05:30
56a22ec5c8 renamed the delete controller tool tip 2022-07-19 17:43:24 +05:30
8c444059ad I have improved on the projects page like this
1.Allow to delete multiple projects at once (similar to what is done in the image manager).
2. Add an export project action in the actions column. The export icon could be improved.
3.Replace "Duplicate" action by "Save project as" (with same icon as on project settings menu).
4.Delete 'Go to system status' button and add 'System status' entry to top right menu.
5.Delete 'Go to preferences' button and add 'Template preferences' entry to top right menu.
6.Add "Image manager" entry to the top right menu
2022-07-19 17:36:19 +05:30
2755f7226b I reanmed server_id into controller_id everywhere in the code as well. 2022-07-19 10:15:09 +05:30
37cc3f3731 rename component name servers and server Into a controllers or controller 2022-07-18 14:56:02 +05:30
99e022bed8 I change all url everywhere like /servers => /controllers and /server/ => /controller/ 2022-07-18 14:01:09 +05:30
f106ca51da Add cosmetic change 2022-07-18 12:29:52 +05:30
9f80df4360 I changed servers string into controllers string on the server page 2022-07-18 12:01:22 +05:30
46c7c66362 Merge pull request #1352 from GNS3/bugfix/remove-warnings
Bugfix/remove warnings
2022-07-15 18:58:27 +02:00
1cd479751f Set --tsconfig "./src/tsconfig.app.json" in package.json 2022-07-15 00:11:28 +02:00
fe7f65c723 add a path of tsconfig.base.json file in tsconfig 2022-07-14 16:10:33 +05:30
eff4ed11d6 I upadate package @synk/protect instead of "snyk": "^1.915.0" 2022-07-14 11:08:26 +05:30
caa444121e Merge pull request #1331 from GNS3/enhancement/1323
Enhancement/1323
2022-07-13 00:17:48 +02:00
6dcacbaa85 Merge branch 'master-3.0' into enhancement/1323 2022-07-13 00:06:13 +02:00
5cc45a39ca Add window.location.assign() for file downloading. 2022-07-12 11:02:15 +05:30
a61c0bfe07 Merge pull request #1346 from GNS3/enhancement/1344
I have  resolved Support for project importation #1344 issue
2022-07-11 12:21:38 +02:00
e24aa1387b Modified the file upload cancel message 2022-07-07 11:09:33 +05:30
9381578657 1. Improve progress bar and I used common progress bar.
2.  Added cancel button
3. And modified the unit test cases
2022-07-06 20:27:44 +05:30
379a39a98f I have resolved Support for project importation #1344 issue 2022-07-06 16:48:29 +05:30
cb11e8b1a2 Merge pull request #1345 from GNS3/enhancement/1342
I have  added node menu  controls confirmation action dialog in
2022-07-05 14:33:42 +02:00
5bddf9c5fc I added reset all console connection control on nodes menu and removed red circle from nodes action confirmation dialog 2022-07-05 08:59:48 +05:30
9c3667277c Resolve/write an unit test case. 2022-07-04 15:03:49 +05:30
576c108da8 I have added node menu controls confirmation action dialog in
Webui missing prompt for mass state changes of project #1342 issue.
2022-07-04 14:40:27 +05:30
7398c07c6b getpath of export project 2022-07-04 11:51:40 +05:30
5fbb4108dd Change File name like .gns3project 2022-06-23 10:09:32 +05:30
b032c88467 Closed export prject window without waiting 2022-06-22 14:08:26 +05:30
50de71dc5a Merge pull request #1334 from GNS3/bugfix/1317
Bugfix/1317
2022-06-21 12:17:13 +02:00
335ea23b6b Resolve issue of waiting for the download to be finished and removed unused code 2022-06-21 12:05:31 +05:30
40ffe84b77 Removed vm_compute_id 2022-06-21 08:59:18 +05:30
a6b65fc8fe Modify the unit test cases 2022-06-20 18:11:55 +05:30
1d75fefb68 Resolve Allow Virtualbox, VMware and Docker templates to be created issue but not fully tested 2022-06-20 18:05:34 +05:30
59667e3a90 Resolve both issues like:
1.Selecting "none" or "lzma" compression type shouldn't pass a compression level of "None".
2.The export window waits for the project to be downloaded when exporting a large project with images
2022-06-17 19:55:24 +05:30
06852d94d7 Resolve cosmetic issues 2022-06-17 14:54:54 +05:30
be831aaf15 Complete export portable project settings and modified the unit test case 2022-06-17 13:06:42 +05:30
3d0e94257f . 2022-06-13 16:40:17 +05:30
50f6cd2191 Write a unit test case for export project dialog box. 2022-06-13 16:28:44 +05:30
06ed79ec78 Add compression methods short form according to API endpoint and resolve build error 2022-06-13 12:11:49 +05:30
5c1ce1a5ab I complete export project UI and bind export portable project API 2022-06-10 19:20:02 +05:30
ea76493ab8 Merge branch 'master-3.0' into enhancement/1323 2022-06-10 11:00:38 +05:30
7d706a39f1 Merge pull request #1326 from GNS3/bugfix/imageProgressBar
Bugfix/image progress bar
2022-06-10 12:08:53 +08:00
f7696e5453 Create dynamic progress bar 2022-06-09 20:42:08 +05:30
726562d615 Modified progrss bar handler 2022-06-08 18:51:08 +05:30
78f77dc881 Update dependencies like autoprefixer 2022-06-08 09:25:43 +05:30
1787db7c6d Resolve vulnerabilities issue 2022-06-07 23:45:33 +05:30
088b128b57 Resolve progress bar and add dependencies in spec file 2022-06-07 11:19:01 +05:30
b7e314deeb Resolve build issue 2022-06-07 09:03:13 +05:30
fd95c2d43c I added export portable project dialog box 2022-06-07 08:58:51 +05:30
52f10b0c53 . 2022-06-06 14:20:30 +05:30
ecf729fc56 I have resolved image progress bar and undefined event issue 2022-06-06 13:43:39 +05:30
b430ab9a1c Merge pull request #1318 from GNS3/enhancement-JWT/1228
I have modified the JWT Interceptor and added refresh token functiona…
2022-05-31 15:58:18 +07:00
18a014d739 update 2022-05-31 14:12:18 +05:30
07c505187d update user case 2 2022-05-31 13:40:00 +05:30
eb07abe786 Resolve/modified remember me check box user cases 2022-05-31 13:18:52 +05:30
78da4f0efa I have added Remember me tickbox on login component and I resolve an error just before auto re-login 2022-05-31 10:47:32 +05:30
0185dbd8af I have modified the JWT Interceptor and added refresh token functionality 2022-05-27 12:57:56 +05:30
83fa40907e Merge pull request #1316 from GNS3/enhancement/1307
Add common process bar when uploading IOS and IOU images
2022-05-24 22:57:02 +07:00
0ae25095a8 Resolve loader error 2022-05-24 19:54:26 +05:30
ea1e280e66 I resoleved loader error and message 2022-05-24 15:25:06 +05:30
667c8fc7f0 I added a common process bar when IOS and IOU image file uplading 2022-05-24 09:40:46 +05:30
36482c7a96 Merge pull request #1315 from GNS3/bugfix/1314
Bugfix/1314
2022-05-23 15:43:58 +07:00
7aae84b2be . 2022-05-23 12:44:23 +05:30
7049e05c91 I have removed static version (v3) and Now, we are using environment file for current version 2022-05-23 12:40:09 +05:30
e7e55e7eaf Merge pull request #1313 from GNS3/enhancement/1308
I have improved progress bar when uploading files
2022-05-23 13:09:06 +07:00
65c48769b7 Merge pull request #1312 from GNS3/bugfix/1307
I added  authentication token for allow IOU or IOS templates to be cr…
2022-05-23 12:53:31 +07:00
2816202ee5 Changed uppercase to lowercase 2022-05-23 11:15:53 +05:30
434bf57cd1 I removed static version and define in evviroment file 2022-05-23 11:06:00 +05:30
0120a1281c I have modified the file uploading url 2022-05-21 12:30:00 +05:30
824833e621 added Unit test case dependencies 2022-05-20 17:23:14 +05:30
23fe8ae9b8 I have improved progress bar when uploading files 2022-05-20 17:08:43 +05:30
4f90a6d1fd I added authentication token for allow IOU or IOS templates to be created 2022-05-16 18:39:19 +05:30
f055836f44 Merge pull request #1310 from GNS3/bugfix/all-CVE
Bugfix/all CVE
2022-05-14 22:01:25 +07:00
88e1cb66eb I have removed deprecated async() in @angular/core/testing Angular API and Modified some unit test case 2022-05-13 23:38:43 +05:30
2f0cdfc33c I resolved all unit test case 2022-05-13 13:08:13 +05:30
6152f68acf I have changed the unit test case according to Angular API 2022-05-06 19:09:43 +05:30
8ec2b806a9 Merge pull request #1306 from GNS3/bugfix/1223
I removed electron specific Ui / code
2022-05-06 11:56:02 +07:00
dc382348b8 Merge branch 'master-3.0' into bugfix/all-CVE 2022-05-02 16:27:20 +05:30
05d980e6e3 I changed API for dynamic unit cases 2022-05-02 16:24:47 +05:30
fbfb6b7152 Merge pull request #1305 from GNS3/bugFix-1300
Bug fix 1300
2022-05-02 17:30:46 +07:00
834173201b I resolved CVE issues and update yarn lock file 2022-05-02 13:25:18 +05:30
49693efc04 update angular cdk 2022-04-29 17:37:42 +05:30
29f1eb92d8 update angular version 2022-04-29 17:26:12 +05:30
d5287bfb8e I have resolved suggested comments. 2022-04-29 10:20:49 +05:30
a7e637a466 I added checksum key instead of md5sum key 2022-04-28 17:55:15 +05:30
f71a8edc3c I removed electron specific Ui / code 2022-04-26 18:44:14 +05:30
0df6294cc7 I removed unwanted code 2022-04-26 16:51:02 +05:30
7ff43eb582 yarn.lock file added 2022-04-26 14:15:30 +05:30
236a9d11b3 I resolved / Fixed add new template uploading image issue 2022-04-26 13:37:43 +05:30
dc2c4cbbbe fix import for routing and modules 2022-04-25 15:55:25 +02:00
a074bbc617 Merge remote-tracking branch 'upstream/master-3.0' into master-3.0
# Conflicts:
#	src/app/app-routing.module.ts
#	src/app/app.module.ts
2022-04-25 15:50:29 +02:00
4c11b6c012 . 2022-04-22 10:16:38 +05:30
a26a08cb20 Added yarn.lock 2022-04-20 18:12:22 +05:30
7ac6b1ef76 I removed commented code 2022-04-20 17:36:30 +05:30
c929f49aa2 Merge pull request #1299 from GNS3/bugfix/1161
Resolved "Remove GNS3 VM specific code #1161"
2022-04-19 18:15:24 +07:00
d00e56627f Removed commented code 2022-04-19 16:28:59 +05:30
a172b7d41f update deprecated angular API's 2022-04-19 13:30:15 +05:30
f7ba01211e Resolved "Remove GNS3 VM specific code #1161" 2022-04-18 18:01:41 +05:30
002569ed75 update angular material 2022-04-18 16:50:54 +05:30
f23315fd75 update angular cli 2022-04-18 16:29:42 +05:30
2121d29a9e Merge pull request #1171 from GNS3/Change-link-style
Change link style
2022-04-18 14:42:43 +07:00
834cdecd80 Added a comment for location.reload() function 2022-04-18 12:27:43 +05:30
78f2b76a14 I added location.reload() for reload hole page 2022-04-18 12:06:23 +05:30
978b473e8e Merge pull request #1297 from GNS3/bugfix/1201
I resolved " Remove Qemu legacy networking code
2022-04-14 15:00:53 +07:00
d652ae0bbb I resolved " Remove Qemu legacy networking code
#1201".
2022-04-13 19:16:18 +05:30
50a5307d03 Merge remote-tracking branch 'origin/Change-link-style' into Change-link-style
# Conflicts:
#	package.json
#	src/ReleaseNotes.txt
#	src/app/components/project-map/context-menu/context-menu.component.html
#	yarn.lock
2022-04-13 20:03:10 +07:00
408184874c Changing link style 2022-04-13 19:40:48 +07:00
a8043f9423 Update ethernet-link.ts 2022-04-13 19:40:48 +07:00
66cd41018e Updating links data source added 2022-04-13 19:40:48 +07:00
d43e6649c7 Update serial-link.ts 2022-04-13 19:40:48 +07:00
5cb3c43e88 Link styling for ethernet links 2022-04-13 19:40:48 +07:00
97974339b9 Changing style for links added 2022-04-13 19:40:48 +07:00
a1228d009b Edit link style dialog created 2022-04-13 19:40:47 +07:00
67c564caa7 Merge pull request #1291 from GNS3/enhancement/1284
Enhancement/1284
2022-04-13 17:45:34 +07:00
258e9f02c2 Delete multiple images in one go if I select 2 or more images 2022-04-13 15:58:10 +05:30
fcc03f5ad0 Merge pull request #1288 from GNS3/bugfix/1287
I resolved "#1287 Cannot add Qemu template manually"
2022-04-13 16:15:49 +07:00
5e65aff228 I resolved "Cannot add Qemu template manually bug
#1287"
2022-04-13 13:47:03 +05:30
c86769dd4f I added install appliances confirmation dialog, Unit test cases for upload and delete file and suggested changes. 2022-04-12 15:03:40 +05:30
147cae1313 I completed enhancement work #1284 Image manager 2022-04-05 17:10:21 +05:30
97d1bc7596 I resolved "#1287 Cannot add Qemu template manually" 2022-04-04 12:15:56 +05:30
fa0531644d Merge pull request #1290 from GNS3/bugfix/1286
Bugfix/1286
2022-04-01 23:26:15 +08:00
ab89aa8ec8 Resolved "New template dialog is not populated
#1286 "
2022-04-01 16:46:04 +05:30
8adad9c13f I resolved "#1287 cannot open Qemu template manually including adding a Qemu template during step3. 2022-04-01 12:55:14 +05:30
316fe735fc I resolved "#1287 Cannot add Qemu template manually" 2022-03-31 17:32:29 +05:30
f91a5f657f Merge pull request #1285 from GNS3/bugfix/1282
I resolved "Cannot open new template dialog #1282"
2022-03-31 12:47:43 +08:00
6a09772459 I resolved "Cannot open new template dialog #1282" 2022-03-29 18:33:14 +05:30
48bb035b34 Suspend a link or node show status change (#1281)
* Suspend a link or node show status change

* Show the suspended status when we start a packet capture on the link.
2022-03-28 10:02:00 +02:00
9558b2137f Show the suspended status when we start a packet capture on the link. 2022-03-25 11:34:55 +05:30
c2410f0933 Suspend a link or node show status change 2022-03-24 17:28:42 +05:30
2f9999b41c Merge pull request #1276 from GNS3/bugfix/1274
Link added
2022-03-23 17:45:48 +10:00
96a11384a0 removed !important 2022-03-23 12:33:35 +05:30
c938c3a8ca Link added 2022-03-22 12:07:13 +05:30
93188f2aec Add methods documentation 2022-03-21 09:42:40 +01:00
f9cc7f3883 add tests on filter-complete.pipe.ts 2022-03-21 07:56:04 +01:00
160b0eccc0 add tests on display-path.pipe.ts 2022-03-21 07:56:03 +01:00
0b2128f00b add tests on filter-complete.pipe.ts 2022-03-21 07:55:35 +01:00
02c323463c add tests on PermissionPath.ts 2022-03-21 07:55:35 +01:00
067c8a00ec add tests on add-permission-line.component.ts 2022-03-21 07:55:35 +01:00
7d1ed62f30 add tests on method-button.component.ts 2022-03-21 07:55:35 +01:00
349666dcc1 tests on ApiInformationService 2022-03-18 15:13:26 +01:00
3ad28e6d09 tests on display path pipe 2022-03-18 15:11:56 +01:00
5aa7afe15c tests on permission filter pipe 2022-03-18 14:56:37 +01:00
c5434a4e99 disable all unused tests 2022-03-07 09:40:41 +01:00
87a0b951a7 add paths to resolve modules declaration for tests 2022-03-07 09:40:11 +01:00
0154d123a9 add missing import 2022-02-28 13:51:57 +01:00
fc0fdd2e51 bugfix, Permission Link display correctly 2022-02-28 13:51:57 +01:00
b6b9d735f5 update user password + confirm password validator 2022-02-28 13:51:57 +01:00
8df255ebc3 Bug fix, paginators and sort for user group and role lists 2022-02-28 13:51:57 +01:00
02285265e3 add user to groups when creating user + refactor add users when creating group 2022-02-28 13:51:57 +01:00
c400ad551e bug fix, display correctly http error message inside Toaster service 2022-02-28 13:51:57 +01:00
5102039dbd User and group details, add paginator and filter on permissions list 2022-02-28 13:51:57 +01:00
7bff9b40de New group, add user to group functionality 2022-02-28 13:51:57 +01:00
707f5b6c7f Permission object, display object name instead of uuid 2022-02-28 13:51:56 +01:00
6a573110e8 Permissions management, add paginator and filters 2022-02-28 13:51:10 +01:00
0d5f11dfc1 user details, Add/remove permissions 2022-02-28 13:51:10 +01:00
65f1d45dc5 Permission management, create add permission component and apiInformation service, which parse swagger api information schema 2022-02-28 13:51:10 +01:00
2664911455 Add permission management 2022-02-28 13:50:15 +01:00
65172c18b5 Group details, can add role to group 2022-02-28 13:50:11 +01:00
920154e7b9 Add role management 2022-02-28 13:50:11 +01:00
36e39f908b menu, disable management entry if no server was selected 2022-02-28 13:50:11 +01:00
39627c28c8 Management refactoring, creating unique entry in menu for management 2022-02-28 13:50:11 +01:00
b8b7e4d151 group detail, members none case-sensitive sorted a to z 2022-02-28 13:50:11 +01:00
fb7845bbce group details, add filter on members list 2022-02-28 13:50:10 +01:00
a7f6743860 group details, add members pagination 2022-02-28 13:50:10 +01:00
a4e8dee2e1 group detail, page refactoring 2022-02-28 13:50:10 +01:00
4911b0da66 create permission service 2022-02-28 13:50:10 +01:00
6122801f90 group management, add group details 2022-02-28 13:50:10 +01:00
c3f3fafbef user management detail refactor 2022-02-28 13:50:10 +01:00
cbeca9d0ca user management, create edit user detail dialog 2022-02-28 13:50:10 +01:00
eb5437d005 group management, add multiple delete 2022-02-28 13:50:10 +01:00
2e2a59f6f2 group management, add sort on all columns 2022-02-28 13:50:10 +01:00
596a11210f user management, add paginator 2022-02-28 13:50:10 +01:00
11029db956 remove is_admin field in user management list and add field validation on create a new user 2022-02-28 13:50:10 +01:00
0c0d77e220 user management, add multiple user selection 2022-02-28 13:50:10 +01:00
4e207d270e user management, add delete button on each row 2022-02-28 13:50:10 +01:00
9546ed94fe group management, add trash icon on each group to delete it 2022-02-28 13:50:10 +01:00
7219f02783 group management, add create new group functionality 2022-02-28 13:50:10 +01:00
2ea79aaa27 group management, add search filter with group name 2022-02-28 13:50:10 +01:00
e37f1e97fa Add group management list 2022-02-28 13:50:10 +01:00
4e2d043561 Add search filter to user management 2022-02-28 13:50:10 +01:00
d46502b804 Add User management and group management template 2022-02-28 13:50:10 +01:00
108f95de59 Refreshing token implemented in LoginGuard (#1246) 2022-02-08 14:06:20 +01:00
60a9e45e4a Update notification.service.ts 2021-12-29 13:42:08 +01:00
fa22ce5d0f Unisolate action added 2021-12-28 16:52:52 +01:00
8b177013d1 Updates from main branch (#1227)
* Update ReleaseNotes.txt

* Release 2.2.22

* Updating dependencies

* Update package.json

* Update project-map.component.ts

* Updating dependencies

* Update main.yml

* Bump postcss from 7.0.35 to 7.0.36

Bumps [postcss](https://github.com/postcss/postcss) from 7.0.35 to 7.0.36.
- [Release notes](https://github.com/postcss/postcss/releases)
- [Changelog](https://github.com/postcss/postcss/blob/main/CHANGELOG.md)
- [Commits](https://github.com/postcss/postcss/compare/7.0.35...7.0.36)

---
updated-dependencies:
- dependency-name: postcss
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

* Bump ws from 6.2.1 to 6.2.2

Bumps [ws](https://github.com/websockets/ws) from 6.2.1 to 6.2.2.
- [Release notes](https://github.com/websockets/ws/releases)
- [Commits](https://github.com/websockets/ws/compare/6.2.1...6.2.2)

---
updated-dependencies:
- dependency-name: ws
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

* fix: package.json & yarn.lock to reduce vulnerabilities

The following vulnerabilities are fixed with an upgrade:
- https://snyk.io/vuln/SNYK-JS-JSZIP-1251497

* Updating packages to latest versions

* Release 2.2.23

* Updating dependencies

* Bump tar from 6.1.0 to 6.1.6

Bumps [tar](https://github.com/npm/node-tar) from 6.1.0 to 6.1.6.
- [Release notes](https://github.com/npm/node-tar/releases)
- [Changelog](https://github.com/npm/node-tar/blob/main/CHANGELOG.md)
- [Commits](https://github.com/npm/node-tar/compare/v6.1.0...v6.1.6)

---
updated-dependencies:
- dependency-name: tar
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

* Bump url-parse from 1.5.1 to 1.5.3

Bumps [url-parse](https://github.com/unshiftio/url-parse) from 1.5.1 to 1.5.3.
- [Release notes](https://github.com/unshiftio/url-parse/releases)
- [Commits](https://github.com/unshiftio/url-parse/compare/1.5.1...1.5.3)

---
updated-dependencies:
- dependency-name: url-parse
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

* Updating dependencies

* Removing vulnerabilities

* Updating angular-devkit/build-angular

* Update yarn.lock

* Fix for https://github.com/GNS3/gns3-web-ui/issues/1184

* Release 2.2.24

* Option to access system status from servers page

* Updating dependencies

* Release 2.2.25

* Update package.json

* Bump nth-check from 2.0.0 to 2.0.1

Bumps [nth-check](https://github.com/fb55/nth-check) from 2.0.0 to 2.0.1.
- [Release notes](https://github.com/fb55/nth-check/releases)
- [Commits](https://github.com/fb55/nth-check/compare/v2.0.0...v2.0.1)

---
updated-dependencies:
- dependency-name: nth-check
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

* Fix for theming

* Update template.component.ts

* Updating dependencies

* Update yarn.lock

* Update yarn.lock

* Update yarn.lock

* Release 2.2.26

* Update package.json

* show upload file progress when uploading qemu template.

* fix progress bar incorrect when upload file twice

* Updating packages

* Updating packages

* Update package.json

* Update yarn.lock

* updating packages

* Updating angular material

* Fix for error with component factory after migration to angular v13

* Update yarn.lock

* Update .gitignore

* Fix for builds on github

* Removing electron builder

* Removing sentry/cli

* Updating dependencies

* Release web UI 2.2.27

* Reverting updates

* Angular version set to 12.2.12

* Updating snyk version

* Update configurator-docker.component.ts

* Update new-template-dialog.component.html

* Mouse pointer #1219

* Update topology-summary.component.ts

* Update project-map.component.ts

* Update project-map.component.ts

* Release web UI 2.2.28

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: snyk-bot <snyk-bot@snyk.io>
Co-authored-by: potats0 <potatso>
2021-12-28 14:39:15 +01:00
6353207d40 Isolate action added 2021-12-28 00:18:28 +01:00
f721bd0d26 Link to the API doc in the menu 2021-11-10 16:00:52 +01:00
44c530d1b5 Update .gitignore 2021-11-10 12:32:33 +01:00
f2b70d562d Changing link style 2021-07-21 12:30:51 +02:00
6dd81b2406 Merge branch 'master' into Change-link-style 2021-06-22 10:20:10 +02:00
a2085e846a Merge pull request #1168 from GNS3/Remove-GNS3-VM-specific-code
Remove gns3 vm specific code
2021-06-22 09:34:03 +02:00
aa5a328f44 Merge pull request #1172 from GNS3/Loading-symbols-after-migrating-to-v3
Loading symbols after migrating to v3
2021-06-22 09:31:55 +02:00
02c5c85148 Update symbol.service.spec.ts 2021-06-21 15:45:02 +02:00
a7528fe990 Loading symbols after migrating to v3 2021-06-21 15:37:43 +02:00
758f680a28 Update settings.component.html 2021-06-21 13:32:43 +02:00
ac265a90bf Update ethernet-link.ts 2021-06-17 14:45:05 +02:00
44e1b3d656 Updating links data source added 2021-06-17 13:21:42 +02:00
a93125cdd7 Update serial-link.ts 2021-06-17 13:01:36 +02:00
34b974461b Link styling for ethernet links 2021-06-17 12:43:51 +02:00
a2a3f542e6 Changing style for links added 2021-06-16 19:19:39 +02:00
f7e07851f7 Edit link style dialog created 2021-06-16 18:44:12 +02:00
62c94275a9 Removing data from appliance dialog 2021-06-10 16:21:49 +02:00
5270134626 Merge branch 'master-3.0' into Remove-GNS3-VM-specific-code 2021-06-10 15:55:59 +02:00
21dfa56b17 Removing fields related to gns3 vm from templates 2021-06-10 15:50:13 +02:00
8eda2ddcea Merge pull request #1165 from GNS3/Add-navigation-to-user-management-page
Add navigation to user management page
2021-06-10 14:50:28 +02:00
4c7d0b317e Fix for unit tests 2021-06-10 14:09:02 +02:00
8e93fa9d36 Update projects.component.spec.ts 2021-06-10 13:56:26 +02:00
2b81d72232 Removing components related to gns3vm 2021-06-10 13:17:01 +02:00
239d1305fa Merge pull request #1142 from BenoitVuagnat/Add-navigation-to-user-management-page
Add navigation to user management page
2021-06-08 11:36:31 +02:00
717336fbd1 Merge branch 'master-3.0' into Add-navigation-to-user-management-page 2021-06-02 18:28:08 +02:00
48f093360d Update app.module.ts 2021-06-02 13:32:14 +02:00
bac6047247 Update login.component.html 2021-06-02 12:08:20 +02:00
e36d56ff5d Merge branch 'master' into master-3.0 2021-05-28 13:20:47 +02:00
b91a113cf5 Update default-layout.component.html
Added the user management link in the navigation menu
2021-05-28 04:33:32 +02:00
7d95200eb3 Merge branch 'master' into master-3.0 2021-05-28 00:20:16 +02:00
d01fcbcfe1 Merge branch 'master' into master-3.0 2021-05-25 13:00:19 +02:00
e3db70a7d9 Update logged-user.component.html 2021-05-18 16:46:57 +02:00
0e3dd69767 Update default-layout.component.ts 2021-05-17 19:45:57 +02:00
823e9a4b59 https://github.com/GNS3/gns3-web-ui/issues/1143 2021-05-17 15:12:57 +02:00
6b2760c06a fixed page access so it would not go to the default page 2021-05-14 22:43:49 +02:00
eb7da2f565 Merge pull request #1135 from GNS3/Cannot-load-symbols-after-migrating-to-v3
Cannot load symbols after migrating to v3
2021-05-14 15:54:14 +02:00
521b593212 Fix for unit tests 2021-05-14 15:53:42 +02:00
ca7b43a5c2 Fix for symbol dialog 2021-05-14 13:01:41 +02:00
c8f1a4d428 Fix for template component 2021-05-14 12:26:33 +02:00
350ed9a4aa Fix for icons on map 2021-05-14 11:28:07 +02:00
96919f8c05 Merge branch 'master' into master-3.0 2021-05-13 16:01:23 +02:00
faf2dbf276 First step of implementation of user management routing 2021-05-12 19:20:35 +02:00
84d0f803dc Merge branch 'master' into master-3.0 2021-05-10 16:47:48 +02:00
a5b4a12849 Fix for redirection to login page 2021-05-07 20:30:31 +02:00
06ad9c2f07 Fix for login page issues 2021-05-07 19:46:46 +02:00
f7a3df27b8 Logout action added 2021-05-06 02:50:13 +02:00
17acd161d8 Http interceptor added 2021-04-30 13:10:33 +02:00
a27f854bde Update project.service.ts 2021-04-30 01:14:02 +02:00
4a8be81534 Update mapsettings.service.ts 2021-04-30 01:08:48 +02:00
e863c1f6e7 Redirection to login page updated 2021-04-30 00:45:54 +02:00
9835c106d8 Login guard added 2021-04-29 18:15:22 +02:00
71077413b7 Login component added 2021-04-29 17:32:53 +02:00
5cfda3500a Removing old authorization 2021-04-28 17:40:58 +02:00
ab6c43c167 Updating version to 3.0 2021-04-28 15:11:18 +02:00
84f7fabdc8 Removing traceng related code 2021-04-28 12:43:35 +02:00
4eefe89eb1 endpoints updated to v3 2021-04-28 12:32:11 +02:00
a9aa64c7f5 Update link.service.ts 2021-04-28 12:06:46 +02:00
64b814acd7 Exchanging endpoints from v2 to v3 2021-04-28 01:18:52 +02:00
d73f65dc70 Merge branch 'master' into master-3.0 2021-04-28 00:16:30 +02:00
641a542714 Update settings.component.spec.ts 2021-04-16 13:32:03 +02:00
909986af96 Update project-map.component.ts 2021-04-16 13:18:19 +02:00
c6ccaf3c4d Update cloud-nodes-template-details.component.html 2021-04-16 13:15:40 +02:00
56a00bc877 Updating marked package 2021-04-16 12:59:21 +02:00
0015c09ba5 Merge branch 'master' into master-2.3 2021-04-16 12:51:51 +02:00
7bc95954ec Merge branch 'master' into master-2.3 2021-02-02 01:15:32 +01:00
b68b871dd6 Merge pull request #964 from GNS3/Project-readme-support
Project readme support
2020-10-22 00:19:35 +02:00
de6529ddd7 Support for Readme 2020-10-22 00:18:56 +02:00
1fc48b28b3 Merge branch 'master-2.3' into Project-readme-support 2020-10-19 16:57:25 +02:00
0386d97a56 Merge branch 'master' into master-2.3 2020-10-19 16:06:04 +02:00
8205c65799 Update configurator-docker.component.ts 2020-09-09 17:37:15 +02:00
169a06fd3a Validators fo docker configurator 2020-09-09 17:32:48 +02:00
820fa9f690 Merge branch 'master' into master-2.3 2020-09-09 16:46:19 +02:00
20f0b06a77 Project readme support 2020-08-19 13:16:09 +02:00
8d795ebf10 CPUs and memory limitation for Docker containers 2020-08-12 11:55:16 +02:00
cb6cacc557 "Usage" support for cloud templates and nodes 2020-08-10 16:00:57 +02:00
bf4f2dcdb7 Reset link support 2020-08-10 14:30:11 +02:00
774 changed files with 23113 additions and 13967 deletions

View File

@ -2,7 +2,7 @@ name: Build
on:
push:
branches:
- '**'
- '**'
pull_request:
branches:
- master
@ -10,16 +10,19 @@ on:
jobs:
build:
runs-on: windows-latest
runs-on: ubuntu-latest
strategy:
matrix:
node: [ 14, 16, 18 ]
name: Node ${{ matrix.node }}
steps:
- uses: actions/checkout@v2
- name: Setup node 14
uses: actions/setup-node@v2
- uses: actions/checkout@v3
- name: Setup Node ${{ matrix.node }}
uses: actions/setup-node@v3
with:
node-version: 14.x
- uses: c-hive/gha-yarn-cache@v1
node-version: ${{ matrix.node }}
cache: 'yarn'
- name: Install JS dependencies
run: yarn install
run: yarn install --frozen-lockfile --immutable
- name: Test
run: yarn test

1
.gitignore vendored
View File

@ -12,6 +12,7 @@
/scripts/build
/scripts/dist
/env
/.angular
# dependencies
/node_modules

3
.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,3 @@
{
"angular.enable-strict-mode-prompt": false
}

View File

@ -3,11 +3,11 @@ __tests__
node_modules/*/test
node_modules/*/tests
powered-test
e2e
#e2e
# asset directories
docs
doc
#doc
website
images

View File

@ -1,247 +1,234 @@
{
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
"version": 1,
"newProjectRoot": "projects",
"projects": {
"gns3-web-ui": {
"root": "",
"sourceRoot": "src",
"projectType": "application",
"architect": {
"build": {
"builder": "@angular-devkit/build-angular:browser",
"options": {
"allowedCommonJsDependencies": [
"rxjs",
"rxjs-compat",
"uuid",
"css-tree",
"save-svg-as-png",
"angular-draggable-droppable",
"dom-set",
"dom-plane",
"mousetrap",
"@mattlewis92/dom-autoscroller",
"rxjs/Rx",
"rxjs/add/operator/map",
"rxjs-compat/add/operator/map",
"classnames",
"stylenames",
"ipaddr.js"
],
"outputPath": "dist",
"index": "src/index.html",
"main": "src/main.ts",
"tsConfig": "src/tsconfig.app.json",
"polyfills": "src/polyfills.ts",
"assets": [
"src/assets",
"src/favicon.ico",
"src/ReleaseNotes.txt"
],
"styles": [
"node_modules/bootstrap/dist/css/bootstrap.min.css",
"node_modules/notosans-fontface/css/notosans-fontface.min.css",
"src/styles.scss",
"src/theme.scss"
],
"scripts": [],
"vendorChunk": true,
"extractLicenses": false,
"buildOptimizer": true,
"sourceMap": true,
"optimization": false,
"namedChunks": true,
"aot": true
},
"configurations": {
"production": {
"budgets": [
{
"type": "anyComponentStyle",
"maximumWarning": "6kb"
}
],
"optimization": true,
"outputHashing": "all",
"sourceMap": {
"hidden": true,
"scripts": true,
"styles": false
},
"namedChunks": false,
"extractLicenses": true,
"vendorChunk": false,
"buildOptimizer": true,
"fileReplacements": [
{
"replace": "src/environments/environment.ts",
"with": "src/environments/environment.prod.ts"
}
]
},
"electronProd": {
"budgets": [
{
"type": "anyComponentStyle",
"maximumWarning": "6kb"
}
],
"optimization": true,
"outputHashing": "all",
"sourceMap": false,
"namedChunks": false,
"extractLicenses": true,
"vendorChunk": false,
"buildOptimizer": true,
"fileReplacements": [
{
"replace": "src/environments/environment.ts",
"with": "src/environments/environment.electron.prod.ts"
}
]
},
"electronDev": {
"budgets": [
{
"type": "anyComponentStyle",
"maximumWarning": "6kb"
}
],
"fileReplacements": [
{
"replace": "src/environments/environment.ts",
"with": "src/environments/environment.electron.ts"
}
]
},
"githubProd": {
"budgets": [
{
"type": "anyComponentStyle",
"maximumWarning": "6kb"
}
],
"optimization": true,
"outputHashing": "all",
"sourceMap": false,
"namedChunks": false,
"extractLicenses": true,
"vendorChunk": false,
"buildOptimizer": true,
"fileReplacements": [
{
"replace": "src/environments/environment.ts",
"with": "src/environments/environment.github.prod.ts"
}
]
}
}
},
"serve": {
"builder": "@angular-devkit/build-angular:dev-server",
"options": {
"browserTarget": "gns3-web-ui:build"
},
"configurations": {
"production": {
"browserTarget": "gns3-web-ui:build:production"
},
"electronProd": {
"browserTarget": "gns3-web-ui:build:electronProd"
},
"electronDev": {
"browserTarget": "gns3-web-ui:build:electronDev"
},
"githubProd": {
"browserTarget": "gns3-web-ui:build:githubProd"
}
}
},
"extract-i18n": {
"builder": "@angular-devkit/build-angular:extract-i18n",
"options": {
"browserTarget": "gns3-web-ui:build"
}
},
"test": {
"builder": "@angular-devkit/build-angular:karma",
"options": {
"main": "src/test.ts",
"karmaConfig": "./karma.conf.js",
"polyfills": "src/polyfills.ts",
"tsConfig": "src/tsconfig.spec.json",
"scripts": [],
"styles": [
"node_modules/bootstrap/dist/css/bootstrap.min.css",
"node_modules/notosans-fontface/css/notosans-fontface.min.css",
"src/styles.scss",
"src/theme.scss"
],
"sourceMap": false,
"assets": [
"src/assets",
"src/favicon.ico"
]
}
},
"lint": {
"builder": "@angular-devkit/build-angular:tslint",
"options": {
"tsConfig": [
"src/tsconfig.app.json",
"src/tsconfig.spec.json"
],
"exclude": [
"**/node_modules/**",
"**/*.spec.ts"
]
}
}
},
"schematics": {
"@schematics/angular:component": {
"style": "scss"
}
}
},
"gns3-web-ui-e2e": {
"root": "e2e",
"sourceRoot": "e2e",
"projectType": "application",
"architect": {
"e2e": {
"builder": "@angular-devkit/build-angular:protractor",
"options": {
"protractorConfig": "./protractor.conf.js",
"devServerTarget": "gns3-web-ui:serve"
}
},
"lint": {
"builder": "@angular-devkit/build-angular:tslint",
"options": {
"tsConfig": [
"e2e/tsconfig.e2e.json"
],
"exclude": [
"**/node_modules/**"
]
}
}
}
}
},
"defaultProject": "gns3-web-ui",
"schematics": {
"@schematics/angular:component": {
"prefix": "app",
"style": "scss"
},
"@schematics/angular:directive": {
"prefix": "app"
}
},
"cli": {
"analytics": false
}
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
"version": 1,
"newProjectRoot": "projects",
"projects": {
"gns3-web-ui": {
"root": "",
"sourceRoot": "src",
"projectType": "application",
"architect": {
"build": {
"builder": "@angular-devkit/build-angular:browser",
"options": {
"allowedCommonJsDependencies": [
"rxjs",
"rxjs-compat",
"uuid",
"css-tree",
"save-svg-as-png",
"angular-draggable-droppable",
"dom-set",
"dom-plane",
"mousetrap",
"@mattlewis92/dom-autoscroller",
"rxjs/Rx",
"rxjs/add/operator/map",
"rxjs-compat/add/operator/map",
"classnames",
"stylenames",
"source-map-js",
"spark-md5",
"xterm",
"xterm-addon-attach",
"xterm-addon-fit"
],
"outputPath": "dist",
"index": "src/index.html",
"main": "src/main.ts",
"tsConfig": "src/tsconfig.app.json",
"polyfills": "src/polyfills.ts",
"assets": [
"src/assets",
"src/favicon.ico",
"src/ReleaseNotes.txt"
],
"styles": [
"node_modules/bootstrap/dist/css/bootstrap.min.css",
"node_modules/notosans-fontface/css/notosans-fontface.min.css",
"src/styles.scss",
"src/theme.scss"
],
"scripts": [],
"vendorChunk": true,
"extractLicenses": false,
"buildOptimizer": true,
"sourceMap": true,
"optimization": false,
"namedChunks": true,
"aot": true
},
"configurations": {
"production": {
"budgets": [{
"type": "anyComponentStyle",
"maximumWarning": "6kb"
}],
"optimization": true,
"outputHashing": "all",
"sourceMap": {
"hidden": true,
"scripts": true,
"styles": false
},
"namedChunks": false,
"extractLicenses": true,
"vendorChunk": false,
"buildOptimizer": true,
"fileReplacements": [{
"replace": "src/environments/environment.ts",
"with": "src/environments/environment.prod.ts"
}]
},
"electronProd": {
"budgets": [{
"type": "anyComponentStyle",
"maximumWarning": "6kb"
}],
"optimization": true,
"outputHashing": "all",
"sourceMap": false,
"namedChunks": false,
"extractLicenses": true,
"vendorChunk": false,
"buildOptimizer": true,
"fileReplacements": [{
"replace": "src/environments/environment.ts",
"with": "src/environments/environment.electron.prod.ts"
}]
},
"electronDev": {
"budgets": [{
"type": "anyComponentStyle",
"maximumWarning": "6kb"
}],
"fileReplacements": [{
"replace": "src/environments/environment.ts",
"with": "src/environments/environment.electron.ts"
}]
},
"githubProd": {
"budgets": [{
"type": "anyComponentStyle",
"maximumWarning": "6kb"
}],
"optimization": true,
"outputHashing": "all",
"sourceMap": false,
"namedChunks": false,
"extractLicenses": true,
"vendorChunk": false,
"buildOptimizer": true,
"fileReplacements": [{
"replace": "src/environments/environment.ts",
"with": "src/environments/environment.github.prod.ts"
}]
}
}
},
"serve": {
"builder": "@angular-devkit/build-angular:dev-server",
"options": {
"browserTarget": "gns3-web-ui:build"
},
"configurations": {
"production": {
"browserTarget": "gns3-web-ui:build:production"
},
"electronProd": {
"browserTarget": "gns3-web-ui:build:electronProd"
},
"electronDev": {
"browserTarget": "gns3-web-ui:build:electronDev"
},
"githubProd": {
"browserTarget": "gns3-web-ui:build:githubProd"
}
}
},
"extract-i18n": {
"builder": "@angular-devkit/build-angular:extract-i18n",
"options": {
"browserTarget": "gns3-web-ui:build"
}
},
"test": {
"builder": "@angular-devkit/build-angular:karma",
"options": {
"main": "src/test.ts",
"karmaConfig": "./karma.conf.js",
"polyfills": "src/polyfills.ts",
"tsConfig": "src/tsconfig.spec.json",
"scripts": [],
"styles": [
"node_modules/bootstrap/dist/css/bootstrap.min.css",
"node_modules/notosans-fontface/css/notosans-fontface.min.css",
"src/styles.scss",
"src/theme.scss"
],
"sourceMap": false,
"assets": [
"src/assets",
"src/favicon.ico"
]
}
},
"lint": {
"builder": "@angular-devkit/build-angular:tslint",
"options": {
"tsConfig": [
"src/tsconfig.app.json",
"src/tsconfig.spec.json"
],
"exclude": [
"**/node_modules/**",
"**/*.spec.ts"
]
}
}
},
"schematics": {
"@schematics/angular:component": {
"style": "scss"
}
}
},
"gns3-web-ui-e2e": {
"root": "e2e",
"sourceRoot": "e2e",
"projectType": "application",
"architect": {
"e2e": {
"builder": "@angular-devkit/build-angular:protractor",
"options": {
"protractorConfig": "./protractor.conf.js",
"devServerTarget": "gns3-web-ui:serve"
}
},
"lint": {
"builder": "@angular-devkit/build-angular:tslint",
"options": {
"tsConfig": [
"e2e/tsconfig.e2e.json"
],
"exclude": [
"**/node_modules/**"
]
}
}
}
}
},
"schematics": {
"@schematics/angular:component": {
"prefix": "app",
"style": "scss"
},
"@schematics/angular:directive": {
"prefix": "app"
}
},
"cli": {
"analytics": false
}
}

View File

@ -0,0 +1,43 @@
import { TestHelper } from './helpers/common.po';
import { ControllersPage } from './helpers/controller.po';
describe('Controllers page', () => {
let page: ControllersPage;
let helper: TestHelper;
beforeEach(() => {
page = new ControllersPage();
helper = new TestHelper();
});
xit('user should have possibility to add controller', async () => {
// arrange
page.maximizeWindow();
await page.navigateToControllersPage();
// act
let text = await page.getAddControllerNotificationText();
// assert
expect(text).toBe("We've discovered GNS3 controller on 127.0.0.1:3080, would you like to add to the list?");
});
it('user should see added controller in the list', async () => {
// arrange
page.maximizeWindow();
await page.navigateToControllersPage();
await page.clickAddController();
helper.sleep(1000);
// act
let firstRowOfControllersTable = await page.checkControllersTable();
let controllerData = [];
await helper.asyncForEach(firstRowOfControllersTable, async (element) => {
controllerData.push(await element.getText());
});
// assert
expect(controllerData).toContain('127.0.0.1');
expect(controllerData).toContain('3080');
});
});

View File

@ -1,41 +1,41 @@
import { browser, by } from 'protractor';
import { TestHelper } from './common.po';
export class ServersPage {
export class ControllersPage {
helper = new TestHelper();
maximizeWindow() {
browser.driver.manage().window().maximize();
}
navigateToServersPage() {
return browser.get('/servers');
navigateToControllersPage() {
return browser.get('/controllers');
}
getAddServerNotificationText() {
getAddControllerNotificationText() {
return browser.driver.findElement(by.className('mat-card-content')).getText();
}
async clickAddServer() {
let serversTable = await this.checkServersTable();
if (serversTable.length === 0) {
async clickAddController() {
let controllerTable = await this.checkControllersTable();
if (controllerTable.length === 0) {
let buttons = await browser.driver.findElements(by.className('mat-button mat-button-base'));
await buttons[3].click();
}
}
checkServersTable() {
checkControllersTable() {
return browser.driver.findElements(by.css('mat-cell'));
}
async navigateToServerProjects() {
async navigateToControllerProjects() {
this.helper.sleep(2000);
let hyperlinks = await browser.driver.findElements(by.css('a.table-link'));
let serverLink;
let controllerLink;
await this.helper.asyncForEach(hyperlinks, async (element) => {
let text = await element.getText();
if (text === '127.0.0.1') serverLink = element;
if (text === '127.0.0.1') controllerLink = element;
});
await serverLink.click();
await controllerLink.click();
}
}

View File

@ -1,24 +1,24 @@
import { TestHelper } from './helpers/common.po';
import { ProjectMapPage } from './helpers/project-map.po';
import { ProjectsPage } from './helpers/project.po';
import { ServersPage } from './helpers/server.po';
import { ControllersPage } from './helpers/controller.po';
describe('Project map page', () => {
let serversPage: ServersPage;
let controllersPage: ControllersPage;
let projectsPage: ProjectsPage;
let projectMapPage: ProjectMapPage;
let helper: TestHelper;
beforeEach(async () => {
serversPage = new ServersPage();
controllersPage = new ControllersPage();
projectsPage = new ProjectsPage();
projectMapPage = new ProjectMapPage();
helper = new TestHelper();
serversPage.maximizeWindow();
await serversPage.navigateToServersPage();
await serversPage.clickAddServer();
await serversPage.navigateToServerProjects();
controllersPage.maximizeWindow();
await controllersPage.navigateToControllersPage();
await controllersPage.clickAddController();
await controllersPage.navigateToControllerProjects();
await projectsPage.openAddProjectDialog();
helper.sleep(2000);
await projectsPage.createProject();

View File

@ -1,24 +1,24 @@
import { TestHelper } from './helpers/common.po';
import { ProjectsPage } from './helpers/project.po';
import { ServersPage } from './helpers/server.po';
import { ControllersPage } from './helpers/controller.po';
describe('Projects page', () => {
let serversPage: ServersPage;
let controllersPage: ControllersPage;
let projectsPage: ProjectsPage;
let helper: TestHelper;
beforeEach(() => {
serversPage = new ServersPage();
controllersPage = new ControllersPage();
projectsPage = new ProjectsPage();
helper = new TestHelper();
});
it('user should have possibility to create new project', async () => {
// arrange
serversPage.maximizeWindow();
await serversPage.navigateToServersPage();
await serversPage.clickAddServer();
await serversPage.navigateToServerProjects();
controllersPage.maximizeWindow();
await controllersPage.navigateToControllersPage();
await controllersPage.clickAddController();
await controllersPage.navigateToControllerProjects();
helper.sleep(2000);
//act
@ -28,6 +28,6 @@ describe('Projects page', () => {
helper.sleep(2000);
//assert
expect(helper.getCurrentUrl()).toMatch('server/1/project/');
expect(helper.getCurrentUrl()).toMatch('controller/1/project/');
});
});

View File

@ -1,43 +0,0 @@
import { TestHelper } from './helpers/common.po';
import { ServersPage } from './helpers/server.po';
describe('Servers page', () => {
let page: ServersPage;
let helper: TestHelper;
beforeEach(() => {
page = new ServersPage();
helper = new TestHelper();
});
xit('user should have possibility to add server', async () => {
// arrange
page.maximizeWindow();
await page.navigateToServersPage();
// act
let text = await page.getAddServerNotificationText();
// assert
expect(text).toBe("We've discovered GNS3 server on 127.0.0.1:3080, would you like to add to the list?");
});
it('user should see added server in the list', async () => {
// arrange
page.maximizeWindow();
await page.navigateToServersPage();
await page.clickAddServer();
helper.sleep(1000);
// act
let firstRowOfServersTable = await page.checkServersTable();
let serverData = [];
await helper.asyncForEach(firstRowOfServersTable, async (element) => {
serverData.push(await element.getText());
});
// assert
expect(serverData).toContain('127.0.0.1');
expect(serverData).toContain('3080');
});
});

View File

@ -15,7 +15,7 @@ files:
- renderer.js
- sentry.js
- installed-software.js
- local-server.js
- local-controller.js
- console-executor.js
- package.json

View File

@ -19,13 +19,13 @@ module.exports = function (config) {
dir: require('path').join(__dirname, 'coverage'), reports: [ 'html', 'lcovonly' ],
fixWebpackSourcePaths: true
},
reporters: ['progress', 'kjhtml'],
port: 9876,
colors: true,
logLevel: config.LOG_INFO,
autoWatch: true,
browsers: ['Chrome'],
browsers: ['ChromeHeadless'],
singleRun: true
});
};

View File

@ -8,9 +8,9 @@ const { app } = require('electron')
const isWin = /^win/.test(process.platform);
let runningServers = {};
let runningControllers = {};
exports.getLocalServerPath = async () => {
exports.getLocalControllerPath = async () => {
let binary = isWin ? 'gns3server.exe': 'gns3server';
return findBinary('exe.', binary);
}
@ -20,27 +20,27 @@ exports.getUbridgePath = async () => {
return findBinary('ubridge', binary);
}
exports.startLocalServer = async (server) => {
return await run(server, {
exports.startLocalController = async (controller) => {
return await run(controller, {
logStdout: true
});
}
exports.stopLocalServer = async (server) => {
return await stop(server.name);
exports.stopLocalController = async (controller) => {
return await stop(controller.name);
}
exports.getRunningServers = () => {
return Object.keys(runningServers);
exports.getRunningControllers = () => {
return Object.keys(runningControllers);
}
exports.stopAllLocalServers = async () => {
exports.stopAllLocalControllers = async () => {
return await stopAll();
}
async function findBinary(binaryDirectory, filename) {
const lookupDirectories = [
__dirname,
__dirname,
path.dirname(app.getPath('exe'))
];
@ -60,7 +60,7 @@ async function findBinaryInDirectory(baseDirectory, binaryDirectory, filename) {
}
const files = fs.readdirSync(distDirectory);
let binaryPath = null;
files.forEach((directory) => {
@ -77,33 +77,33 @@ async function findBinaryInDirectory(baseDirectory, binaryDirectory, filename) {
}
function getServerArguments(server, overrides, configPath) {
let serverArguments = [];
if(server.host) {
serverArguments.push('--host');
serverArguments.push(server.host);
function getControllerArguments(controller, overrides, configPath) {
let controllerArguments = [];
if(controller.host) {
controllerArguments.push('--host');
controllerArguments.push(controller.host);
}
if(server.port) {
serverArguments.push('--port');
serverArguments.push(server.port);
if(controller.port) {
controllerArguments.push('--port');
controllerArguments.push(controller.port);
}
serverArguments.push('--local');
controllerArguments.push('--local');
if(configPath) {
serverArguments.push('--config');
serverArguments.push(configPath);
controllerArguments.push('--config');
controllerArguments.push(configPath);
}
return serverArguments;
return controllerArguments;
}
function getChannelForServer(server) {
return `local-server-run-${server.name}`;
function getChannelForController(controller) {
return `local-controller-run-${controller.name}`;
}
function notifyStatus(status) {
ipcMain.emit('local-server-status-events', status);
ipcMain.emit('local-controller-status-events', status);
}
function filterOutput(line) {
@ -120,44 +120,44 @@ function filterOutput(line) {
}
async function stopAll() {
for(var serverName in runningServers) {
let result, error = await stop(serverName);
for(var controllerName in runningControllers) {
let result, error = await stop(controllerName);
}
console.log(`Stopped all servers`);
console.log(`Stopped all controllers`);
}
async function stop(serverName) {
async function stop(controllerName) {
let pid = undefined;
const runningServer = runningServers[serverName];
const runningController = runningControllers[controllerName];
if(runningServer !== undefined && runningServer.process) {
pid = runningServer.process.pid;
if(runningController !== undefined && runningController.process) {
pid = runningController.process.pid;
}
console.log(`Stopping '${serverName}' with PID='${pid}'`);
console.log(`Stopping '${controllerName}' with PID='${pid}'`);
const stopped = new Promise((resolve, reject) => {
if(pid === undefined) {
resolve(`Server '${serverName} is already stopped`);
delete runningServers[serverName];
resolve(`Controller '${controllerName} is already stopped`);
delete runningControllers[controllerName];
return;
}
kill(pid, (error) => {
if(error) {
console.error(`Error occured during stopping '${serverName}' with PID='${pid}'`);
console.error(`Error occured during stopping '${controllerName}' with PID='${pid}'`);
reject(error);
}
else {
delete runningServers[serverName];
console.log(`Stopped '${serverName}' with PID='${pid}'`);
resolve(`Stopped '${serverName}' with PID='${pid}'`);
delete runningControllers[controllerName];
console.log(`Stopped '${controllerName}' with PID='${pid}'`);
resolve(`Stopped '${controllerName}' with PID='${pid}'`);
notifyStatus({
serverName: serverName,
controllerName: controllerName,
status: 'stopped',
message: `Server '${serverName}' stopped'`
message: `Controller '${controllerName}' stopped'`
});
}
});
@ -166,11 +166,11 @@ async function stop(serverName) {
return stopped;
}
async function getIniFile(server) {
return path.join(app.getPath('userData'), `gns3_server_${server.id}.ini`);
async function getIniFile(controller) {
return path.join(app.getPath('userData'), `gns3_controller_${controller.id}.ini`);
}
async function configure(configPath, server) {
async function configure(configPath, controller) {
if(!fs.existsSync(configPath)) {
fs.closeSync(fs.openSync(configPath, 'w'));
console.log(`Configuration file '${configPath}' has been created.`);
@ -178,20 +178,20 @@ async function configure(configPath, server) {
var config = ini.parse(fs.readFileSync(configPath, 'utf-8'));
if(server.path) {
config.path = server.path;
if(controller.path) {
config.path = controller.path;
}
if(server.host) {
config.host = server.host;
if(controller.host) {
config.host = controller.host;
}
if(server.port) {
config.port = server.port;
if(controller.port) {
config.port = controller.port;
}
if(server.ubridge_path) {
config.ubridge_path = server.ubridge_path;
if(controller.ubridge_path) {
config.ubridge_path = controller.ubridge_path;
}
fs.writeFileSync(configPath, ini.stringify(config, { section: 'Server' }));
fs.writeFileSync(configPath, ini.stringify(config, { section: 'Controller' }));
}
async function setPATHEnv() {
@ -216,7 +216,7 @@ async function setPATHEnv() {
process.env.PATH = extra.join(";");
}
async function run(server, options) {
async function run(controller, options) {
if(!options) {
options = {};
}
@ -226,34 +226,34 @@ async function run(server, options) {
console.log(`Configuring`);
const configPath = await getIniFile(server);
await configure(configPath, server);
const configPath = await getIniFile(controller);
await configure(configPath, controller);
console.log(`Setting up PATH`);
await setPATHEnv();
console.log(`Running '${server.path}'`);
console.log(`Running '${controller.path}'`);
let serverProcess = spawn(server.path, getServerArguments(server, {}, configPath));
let controllerProcess = spawn(controller.path, getControllerArguments(controller, {}, configPath));
notifyStatus({
serverName: server.name,
controllerName: controller.name,
status: 'started',
message: `Server '${server.name}' started'`
message: `Controller '${controller.name}' started'`
});
runningServers[server.name] = {
process: serverProcess
runningControllers[controller.name] = {
process: controllerProcess
};
serverProcess.stdout.on('data', function(data) {
controllerProcess.stdout.on('data', function(data) {
const line = data.toString();
const { isCritical, errorMessage } = filterOutput(line);
if(isCritical) {
notifyStatus({
serverName: server.name,
controllerName: controller.name,
status: 'stderr',
message: `Server reported error: '${errorMessage}`
message: `Controller reported error: '${errorMessage}`
});
}
@ -262,25 +262,25 @@ async function run(server, options) {
}
});
serverProcess.stderr.on('data', function(data) {
controllerProcess.stderr.on('data', function(data) {
if(logSterr) {
console.log(data.toString());
}
});
serverProcess.on('exit', (code, signal) => {
controllerProcess.on('exit', (code, signal) => {
notifyStatus({
serverName: server.name,
controllerName: controller.name,
status: 'errored',
message: `Server '${server.name}' has exited with status='${code}'`
message: `controller '${controller.name}' has exited with status='${code}'`
});
});
serverProcess.on('error', (err) => {
controllerProcess.on('error', (err) => {
notifyStatus({
serverName: server.name,
controllerName: controller.name,
status: 'errored',
message: `Server errored: '${err}`
message: `Controller errored: '${err}`
});
});
@ -297,9 +297,9 @@ async function main() {
}
if(ipcMain) {
ipcMain.on('local-server-run', async function (event, server) {
const responseChannel = getChannelForServer();
await run(server);
ipcMain.on('local-controller-run', async function (event, controller) {
const responseChannel = getChannelForController();
await run(controller);
event.sender.send(responseChannel, {
success: true
});
@ -318,4 +318,4 @@ if (require.main === module) {
});
main();
}
}

View File

@ -1,6 +1,6 @@
{
"name": "gns3-web-ui",
"version": "2.2.54",
"version": "3.0.0a5",
"author": {
"name": "GNS3 Technology Inc.",
"email": "developers@gns3.com"
@ -36,98 +36,100 @@
"generate-licenses-file": "yarn license-checker --production --csv --out licenses.csv",
"prebuildforelectron": "node set-variables-in-env.js --set src/environments/environment.electron.prod.ts",
"postbuildforelectron": "node set-variables-in-env.js --unset src/environments/environment.electron.prod.ts",
"postinstall": "ngcc --properties es5 browser module main --first-only --create-ivy-entry-points && ngcc --properties es2015 browser module main --first-only --create-ivy-entry-points",
"snyk-protect": "snyk protect",
"postinstall": "ngcc --properties es2020 browser module main --first-only --create-ivy-entry-points --tsconfig \"./src/tsconfig.app.json\" && ngcc --properties es2020 browser module main --first-only --create-ivy-entry-points --tsconfig \"./src/tsconfig.app.json\"",
"snyk-protect": "snyk-protect",
"prepare": "yarn run snyk-protect"
},
"private": true,
"dependencies": {
"@angular/animations": "^12.2.12",
"@angular/cdk": "^12.2.12",
"@angular/common": "^12.2.12",
"@angular/compiler": "^12.2.12",
"@angular/core": "^12.2.12",
"@angular/forms": "^12.2.12",
"@angular/material": "^12.2.12",
"@angular/platform-browser": "^12.2.12",
"@angular/platform-browser-dynamic": "^12.2.12",
"@angular/router": "^12.2.12",
"@angular/animations": "^14.3.0",
"@angular/cdk": "^14.2.7",
"@angular/common": "^14.3.0",
"@angular/compiler": "^14.3.0",
"@angular/core": "^14.3.0",
"@angular/forms": "^14.3.0",
"@angular/material": "^14.2.7",
"@angular/platform-browser": "^14.3.0",
"@angular/platform-browser-dynamic": "^14.3.0",
"@angular/router": "^14.3.0",
"@sentry/browser": "^6.14.1",
"@snyk/protect": "^1.972.0",
"@types/jest": "^27.0.2",
"@types/mocha": "^9.0.0",
"@types/mocha": "^9.1.1",
"@types/react": "^17.0.34",
"@types/react-dom": "^17.0.11",
"angular-draggable-droppable": "^5.0.0",
"angular-draggable-droppable": "^6.1.0",
"angular-resizable-element": "^3.4.0",
"autoprefixer": "10.4.5",
"bootstrap": "^5.1.3",
"command-exists": "^1.2.9",
"core-js": "^3.19.1",
"css-tree": "^1.1.3",
"core-js": "^3.22.3",
"css-tree": "^2.1.0",
"d3-ng2-service": "^2.2.0",
"eev": "^0.1.5",
"ini": "^2.0.0",
"ipaddr.js": "^2.1.0",
"ini": "^3.0.0",
"marked": "^4.0.14",
"material-design-icons": "^3.0.1",
"mousetrap": "^1.6.5",
"ng-circle-progress": "^1.6.0",
"ng2-file-upload": "^1.4.0",
"ng2-file-upload": "^3.0.0",
"ngx-childprocess": "^0.0.6",
"ngx-device-detector": "^2.1.1",
"ngx-device-detector": "4.0.1",
"ngx-electron": "^2.2.0",
"node-fetch": "^3.2.10",
"notosans-fontface": "1.2.2",
"notosans-fontface": "^1.3.0",
"postcss-loader": "^6.2.1",
"prettier-plugin-organize-imports": "^2.3.4",
"rxjs": "^6.6.7",
"rxjs-compat": "^6.6.7",
"save-svg-as-png": "^1.4.17",
"snyk": "^1.1064.0",
"spark-md5": "^3.0.2",
"svg-crowbar": "^0.7.0",
"tree-kill": "^1.2.2",
"tslib": "^2.3.1",
"tslib": "^2.4.0",
"typeface-roboto": "^1.1.13",
"xterm": "^4.15.0",
"xterm": "^4.18.0",
"xterm-addon-attach": "^0.6.0",
"xterm-addon-fit": "^0.5.0",
"yargs": "^17.2.1",
"zone.js": "~0.11.4"
"yargs": "^17.4.1",
"zone.js": "^0.11.5"
},
"devDependencies": {
"@angular-devkit/build-angular": "^12.2.12",
"@angular/cli": "^12.2.12",
"@angular/compiler-cli": "^12.2.12",
"@angular/language-service": "^12.2.12",
"@sentry/cli": "^1.71.0",
"@sentry/electron": "^2.5.4",
"@types/jasmine": "^3.10.2",
"@angular-devkit/build-angular": "^14.2.12",
"@angular/cli": "^14.2.12",
"@angular/compiler-cli": "^14.3.0",
"@angular/language-service": "^14.3.0",
"@sentry/cli": "^2.0.4",
"@sentry/electron": "^3.0.7",
"@types/jasmine": "^4.0.3",
"@types/jasminewd2": "^2.0.10",
"@types/node": "16.11.6",
"codelyzer": "^6.0.2",
"electron": "^13.6.6",
"electron-builder": "^22.9.1",
"@types/node": "^17.0.31",
"codelyzer": "^0.0.28",
"electron": "13.6.6",
"electron-builder": "^23.0.3",
"file-loader": "^6.2.0",
"jasmine-core": "~3.10.1",
"jasmine-spec-reporter": "~7.0.0",
"jasmine-core": "^4.1.0",
"jasmine-spec-reporter": "^7.0.0",
"jquery": "^3.6.0",
"karma": "^6.3.16",
"karma-chrome-launcher": "~3.1.0",
"karma": "^6.3.19",
"karma-chrome-launcher": "^3.1.1",
"karma-cli": "^2.0.0",
"karma-coverage-istanbul-reporter": "~3.0.3",
"karma-jasmine": "~4.0.1",
"karma-coverage-istanbul-reporter": "^3.0.3",
"karma-jasmine": "^5.0.0",
"karma-jasmine-html-reporter": "^1.7.0",
"license-checker": "^25.0.1",
"popper.js": "^1.16.1",
"prettier": "^2.4.1",
"prettier": "^2.6.2",
"protractor": "^7.0.0",
"replace": "^1.2.1",
"rxjs-tslint": "^0.1.8",
"ts-mockito": "^2.6.1",
"ts-node": "~10.4.0",
"ts-node": "^10.7.0",
"tslint": "^6.1.3",
"tslint-config-prettier": "^1.18.0",
"typescript": "4.2.3",
"webpack": "5.76.0",
"yarn-upgrade-all": "^0.5.4"
"typescript": "4.6.4",
"webpack": "^5.72.0",
"yarn-upgrade-all": "^0.7.1"
},
"greenkeeper": {
"ignore": [

View File

@ -1,6 +1,6 @@
setuptools==78.1.1
setuptools==65.5.1
cx_Freeze==5.1.1
requests==2.32.4
requests==2.31.0
packaging==20.9
appdirs==1.4.4
psutil==5.8.0

View File

@ -1,10 +1,9 @@
GNS3 WebUI is web implementation of user interface for GNS3 software.
Current version: 2.2.32
Current version: 2.2.24
Bug Fixes & enhancements
- Fixed generated capture file is not valid
- Fixed Docker additional directories
- security fixes
Current version: 2020.4.0-beta.1
@ -68,7 +67,7 @@ GNS3 Web UI 2020.2.0-beta.4
Bug Fixes
- New port setting for GNS3 VM preferences
- Option to auto-hide menu toolbar on the left side
- Server type in template preferences
-Controller type in template preferences
- Error when selecting existing Docker image
- Default values in templates
- TypeError: Cannot read property 'message' of undefined

View File

@ -1,9 +1,10 @@
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { BundledServerFinderComponent } from './components/bundled-server-finder/bundled-server-finder.component';
import { BundledControllerFinderComponent } from './components/bundled-controller-finder/bundled-controller-finder.component';
import { DirectLinkComponent } from './components/direct-link/direct-link.component';
import { HelpComponent } from './components/help/help.component';
import { InstalledSoftwareComponent } from './components/installed-software/installed-software.component';
import { LoginComponent } from './components/login/login.component';
import { PageNotFoundComponent } from './components/page-not-found/page-not-found.component';
import { BuiltInPreferencesComponent } from './components/preferences/built-in/built-in-preferences.component';
import { CloudNodesAddTemplateComponent } from './components/preferences/built-in/cloud-nodes/cloud-nodes-add-template/cloud-nodes-add-template.component';
@ -23,7 +24,6 @@ import { AddIosTemplateComponent } from './components/preferences/dynamips/add-i
import { CopyIosTemplateComponent } from './components/preferences/dynamips/copy-ios-template/copy-ios-template.component';
import { IosTemplateDetailsComponent } from './components/preferences/dynamips/ios-template-details/ios-template-details.component';
import { IosTemplatesComponent } from './components/preferences/dynamips/ios-templates/ios-templates.component';
import { Gns3vmComponent } from './components/preferences/gns3vm/gns3vm.component';
import { AddIouTemplateComponent } from './components/preferences/ios-on-unix/add-iou-template/add-iou-template.component';
import { CopyIouTemplateComponent } from './components/preferences/ios-on-unix/copy-iou-template/copy-iou-template.component';
import { IouTemplateDetailsComponent } from './components/preferences/ios-on-unix/iou-template-details/iou-template-details.component';
@ -44,157 +44,261 @@ import { VpcsTemplateDetailsComponent } from './components/preferences/vpcs/vpcs
import { VpcsTemplatesComponent } from './components/preferences/vpcs/vpcs-templates/vpcs-templates.component';
import { ProjectMapComponent } from './components/project-map/project-map.component';
import { ProjectsComponent } from './components/projects/projects.component';
import { ServersComponent } from './components/servers/servers.component';
import { ControllersComponent } from './components/controllers/controllers.component';
import { ConsoleComponent } from './components/settings/console/console.component';
import { SettingsComponent } from './components/settings/settings.component';
import { ListOfSnapshotsComponent } from './components/snapshots/list-of-snapshots/list-of-snapshots.component';
import { SystemStatusComponent } from './components/system-status/system-status.component';
import { WebConsoleFullWindowComponent } from './components/web-console-full-window/web-console-full-window.component';
import { ConsoleGuard } from './guards/console-guard';
import { LoginGuard } from './guards/login-guard';
import { DefaultLayoutComponent } from './layouts/default-layout/default-layout.component';
import { ServerResolve } from './resolvers/server-resolve';
import { ControllerResolve } from './resolvers/controller-resolve';
import { UserManagementComponent } from './components/user-management/user-management.component';
import { LoggedUserComponent } from './components/users/logged-user/logged-user.component';
import { ImageManagerComponent } from './components/image-manager/image-manager.component';
import { UserDetailComponent } from "./components/user-management/user-detail/user-detail.component";
import { UserDetailResolver } from "./resolvers/user-detail.resolver";
import { ManagementComponent } from "./components/management/management.component";
import { UserGroupsResolver } from "./resolvers/user-groups.resolver";
import { GroupManagementComponent } from "./components/group-management/group-management.component";
import { RoleManagementComponent } from "./components/role-management/role-management.component";
import { GroupDetailsComponent } from "./components/group-details/group-details.component";
import { GroupMembersResolver } from "./resolvers/group-members.resolver";
import { GroupResolver } from "./resolvers/group.resolver";
import { GroupRoleResolver } from "./resolvers/group-role.resolver";
import { RoleDetailComponent } from "./components/role-management/role-detail/role-detail.component";
import { RoleDetailResolver } from "./resolvers/role-detail.resolver";
import { AclManagementComponent } from "@components/acl-management/acl-management.component";
import { ResourcePoolsManagementComponent } from "@components/resource-pools-management/resource-pools-management.component";
import { ResourcePoolDetailsComponent } from "@components/resource-pool-details/resource-pool-details.component";
import { ResourcePoolsResolver } from "@resolvers/resource-pools.resolver";
import { GroupAcesResolver } from "@resolvers/group-ace.resolver.ts.resolver";
import { UserAcesResolver } from "@resolvers/user-aces.resolver";
const routes: Routes = [
{
path: '',
component: DefaultLayoutComponent,
children: [
{ path: '', redirectTo: 'servers', pathMatch: 'full' },
{ path: 'servers', component: ServersComponent },
{ path: 'bundled', component: BundledServerFinderComponent },
{ path: '', redirectTo: 'controllers', pathMatch: 'full' },
{ path: 'controllers', component: ControllersComponent },
{ path: 'bundled', component: BundledControllerFinderComponent },
{ path: 'controller/:controller_id/login', component: LoginComponent },
{ path: 'controller/:controller_id/loggeduser', component: LoggedUserComponent },
{path : 'controller/:controller_id/image-manager', component: ImageManagerComponent},
{
path: 'server/:server_id/projects',
path: 'controller/:controller_id/projects',
component: ProjectsComponent,
resolve: { server: ServerResolve },
canActivate: [LoginGuard],
resolve: { controller: ControllerResolve },
},
{ path: 'controller/:controller_id/help', component: HelpComponent },
{ path: 'controller/:controller_id/settings', component: SettingsComponent },
{ path: 'controller/:controller_id/settings/console', component: ConsoleComponent },
{
path: 'controller/:controller_id/management/users/:user_id',
component: UserDetailComponent,
canActivate: [LoginGuard],
resolve: {
user: UserDetailResolver,
groups: UserGroupsResolver,
aces: UserAcesResolver,
controller: ControllerResolve},
},
{
path: 'controller/:controller_id/management/resourcePools/:pool_id',
component: ResourcePoolDetailsComponent,
canActivate: [LoginGuard],
resolve: {
pool: ResourcePoolsResolver,
controller: ControllerResolve
}
},
{ path: 'help', component: HelpComponent },
{ path: 'settings', component: SettingsComponent },
{ path: 'settings/console', component: ConsoleComponent },
{ path: 'installed-software', component: InstalledSoftwareComponent },
{ path: 'server/:server_id/systemstatus', component: SystemStatusComponent },
{ path: 'controller/:controller_id/systemstatus', component: SystemStatusComponent, canActivate: [LoginGuard] },
{ path: 'server/:server_ip/:server_port/project/:project_id', component: DirectLinkComponent },
{ path: 'controller/:controller_ip/:controller_port/project/:project_id', component: DirectLinkComponent, canActivate: [LoginGuard] },
{
path: 'server/:server_id/project/:project_id/snapshots',
path: 'controller/:controller_id/project/:project_id/snapshots',
component: ListOfSnapshotsComponent,
resolve: { server: ServerResolve },
canActivate: [LoginGuard],
resolve: { controller: ControllerResolve },
},
{ path: 'server/:server_id/preferences', component: PreferencesComponent },
{ path: 'server/:server_id/preferences/gns3vm', component: Gns3vmComponent },
// { path: 'server/:server_id/preferences/general', component: GeneralPreferencesComponent },
{ path: 'server/:server_id/preferences/builtin', component: BuiltInPreferencesComponent },
{ path: 'controller/:controller_id/preferences', component: PreferencesComponent, canActivate: [LoginGuard] },
// { path: 'controller/:controller_id/preferences/general', component: GeneralPreferencesComponent },
{ path: 'controller/:controller_id/preferences/builtin', component: BuiltInPreferencesComponent, canActivate: [LoginGuard] },
{ path: 'server/:server_id/preferences/builtin/ethernet-hubs', component: EthernetHubsTemplatesComponent },
{ path: 'controller/:controller_id/preferences/builtin/ethernet-hubs', component: EthernetHubsTemplatesComponent, canActivate: [LoginGuard] },
{
path: 'server/:server_id/preferences/builtin/ethernet-hubs/addtemplate',
path: 'controller/:controller_id/preferences/builtin/ethernet-hubs/addtemplate',
component: EthernetHubsAddTemplateComponent,
canActivate: [LoginGuard]
},
{
path: 'server/:server_id/preferences/builtin/ethernet-hubs/:template_id',
path: 'controller/:controller_id/preferences/builtin/ethernet-hubs/:template_id',
component: EthernetHubsTemplateDetailsComponent,
canActivate: [LoginGuard]
},
{
path: 'server/:server_id/preferences/builtin/ethernet-switches',
path: 'controller/:controller_id/preferences/builtin/ethernet-switches',
component: EthernetSwitchesTemplatesComponent,
canActivate: [LoginGuard]
},
{
path: 'server/:server_id/preferences/builtin/ethernet-switches/addtemplate',
path: 'controller/:controller_id/preferences/builtin/ethernet-switches/addtemplate',
component: EthernetSwitchesAddTemplateComponent,
canActivate: [LoginGuard]
},
{
path: 'server/:server_id/preferences/builtin/ethernet-switches/:template_id',
path: 'controller/:controller_id/preferences/builtin/ethernet-switches/:template_id',
component: EthernetSwitchesTemplateDetailsComponent,
canActivate: [LoginGuard]
},
{ path: 'server/:server_id/preferences/builtin/cloud-nodes', component: CloudNodesTemplatesComponent },
{ path: 'controller/:controller_id/preferences/builtin/cloud-nodes', component: CloudNodesTemplatesComponent, canActivate: [LoginGuard] },
{
path: 'server/:server_id/preferences/builtin/cloud-nodes/addtemplate',
path: 'controller/:controller_id/preferences/builtin/cloud-nodes/addtemplate',
component: CloudNodesAddTemplateComponent,
canActivate: [LoginGuard]
},
{
path: 'server/:server_id/preferences/builtin/cloud-nodes/:template_id',
path: 'controller/:controller_id/preferences/builtin/cloud-nodes/:template_id',
component: CloudNodesTemplateDetailsComponent,
canActivate: [LoginGuard]
},
//{ path: 'server/:server_id/preferences/dynamips', component: DynamipsPreferencesComponent },
{ path: 'server/:server_id/preferences/dynamips/templates', component: IosTemplatesComponent },
{ path: 'server/:server_id/preferences/dynamips/templates/addtemplate', component: AddIosTemplateComponent },
{ path: 'server/:server_id/preferences/dynamips/templates/:template_id', component: IosTemplateDetailsComponent },
//{ path: 'controller/:controller_id/preferences/dynamips', component: DynamipsPreferencesComponent },
{ path: 'controller/:controller_id/preferences/dynamips/templates', component: IosTemplatesComponent, canActivate: [LoginGuard] },
{ path: 'controller/:controller_id/preferences/dynamips/templates/addtemplate', component: AddIosTemplateComponent, canActivate: [LoginGuard] },
{ path: 'controller/:controller_id/preferences/dynamips/templates/:template_id', component: IosTemplateDetailsComponent, canActivate: [LoginGuard] },
{
path: 'server/:server_id/preferences/dynamips/templates/:template_id/copy',
path: 'controller/:controller_id/preferences/dynamips/templates/:template_id/copy',
component: CopyIosTemplateComponent,
canActivate: [LoginGuard]
},
// { path: 'server/:server_id/preferences/qemu', component: QemuPreferencesComponent },
{ path: 'server/:server_id/preferences/qemu/templates', component: QemuVmTemplatesComponent },
// { path: 'controller/:controller_id/preferences/qemu', component: QemuPreferencesComponent },
{ path: 'controller/:controller_id/preferences/qemu/templates', component: QemuVmTemplatesComponent, canActivate: [LoginGuard] },
{
path: 'server/:server_id/preferences/qemu/templates/:template_id/copy',
path: 'controller/:controller_id/preferences/qemu/templates/:template_id/copy',
component: CopyQemuVmTemplateComponent,
canActivate: [LoginGuard]
},
{ path: 'server/:server_id/preferences/qemu/templates/:template_id', component: QemuVmTemplateDetailsComponent },
{ path: 'server/:server_id/preferences/qemu/addtemplate', component: AddQemuVmTemplateComponent },
{ path: 'controller/:controller_id/preferences/qemu/templates/:template_id', component: QemuVmTemplateDetailsComponent, canActivate: [LoginGuard] },
{ path: 'controller/:controller_id/preferences/qemu/addtemplate', component: AddQemuVmTemplateComponent, canActivate: [LoginGuard] },
// { path: 'server/:server_id/preferences/vpcs', component: VpcsPreferencesComponent },
{ path: 'server/:server_id/preferences/vpcs/templates', component: VpcsTemplatesComponent },
{ path: 'server/:server_id/preferences/vpcs/templates/:template_id', component: VpcsTemplateDetailsComponent },
{ path: 'server/:server_id/preferences/vpcs/addtemplate', component: AddVpcsTemplateComponent },
// { path: 'controller/:controller_id/preferences/vpcs', component: VpcsPreferencesComponent },
{ path: 'controller/:controller_id/preferences/vpcs/templates', component: VpcsTemplatesComponent, canActivate: [LoginGuard] },
{ path: 'controller/:controller_id/preferences/vpcs/templates/:template_id', component: VpcsTemplateDetailsComponent, canActivate: [LoginGuard] },
{ path: 'controller/:controller_id/preferences/vpcs/addtemplate', component: AddVpcsTemplateComponent, canActivate: [LoginGuard] },
// { path: 'server/:server_id/preferences/virtualbox', component: VirtualBoxPreferencesComponent },
{ path: 'server/:server_id/preferences/virtualbox/templates', component: VirtualBoxTemplatesComponent },
// { path: 'controller/:controller_id/preferences/virtualbox', component: VirtualBoxPreferencesComponent },
{ path: 'controller/:controller_id/preferences/virtualbox/templates', component: VirtualBoxTemplatesComponent, canActivate: [LoginGuard] },
{
path: 'server/:server_id/preferences/virtualbox/templates/:template_id',
path: 'controller/:controller_id/preferences/virtualbox/templates/:template_id',
component: VirtualBoxTemplateDetailsComponent,
canActivate: [LoginGuard]
},
{ path: 'server/:server_id/preferences/virtualbox/addtemplate', component: AddVirtualBoxTemplateComponent },
{ path: 'controller/:controller_id/preferences/virtualbox/addtemplate', component: AddVirtualBoxTemplateComponent, canActivate: [LoginGuard] },
// { path: 'server/:server_id/preferences/vmware', component: VmwarePreferencesComponent },
{ path: 'server/:server_id/preferences/vmware/templates', component: VmwareTemplatesComponent },
// { path: 'controller/:controller_id/preferences/vmware', component: VmwarePreferencesComponent },
{ path: 'controller/:controller_id/preferences/vmware/templates', component: VmwareTemplatesComponent, canActivate: [LoginGuard] },
{
path: 'server/:server_id/preferences/vmware/templates/:template_id',
path: 'controller/:controller_id/preferences/vmware/templates/:template_id',
component: VmwareTemplateDetailsComponent,
canActivate: [LoginGuard]
},
{ path: 'server/:server_id/preferences/vmware/addtemplate', component: AddVmwareTemplateComponent },
{ path: 'controller/:controller_id/preferences/vmware/addtemplate', component: AddVmwareTemplateComponent, canActivate: [LoginGuard] },
// { path: 'server/:server_id/preferences/traceng', component: TracengPreferencesComponent },
// { path: 'server/:server_id/preferences/traceng/templates', component: TracengTemplatesComponent },
// { path: 'server/:server_id/preferences/traceng/templates/:template_id', component: TracengTemplateDetailsComponent },
// { path: 'server/:server_id/preferences/traceng/addtemplate', component: AddTracengTemplateComponent },
{ path: 'server/:server_id/preferences/docker/templates', component: DockerTemplatesComponent },
{ path: 'controller/:controller_id/preferences/docker/templates', component: DockerTemplatesComponent, canActivate: [LoginGuard] },
{
path: 'server/:server_id/preferences/docker/templates/:template_id',
path: 'controller/:controller_id/preferences/docker/templates/:template_id',
component: DockerTemplateDetailsComponent,
canActivate: [LoginGuard]
},
{
path: 'server/:server_id/preferences/docker/templates/:template_id/copy',
path: 'controller/:controller_id/preferences/docker/templates/:template_id/copy',
component: CopyDockerTemplateComponent,
canActivate: [LoginGuard]
},
{ path: 'controller/:controller_id/preferences/docker/addtemplate', component: AddDockerTemplateComponent, canActivate: [LoginGuard] },
{ path: 'controller/:controller_id/preferences/iou/templates', component: IouTemplatesComponent, canActivate: [LoginGuard] },
{ path: 'controller/:controller_id/preferences/iou/templates/:template_id', component: IouTemplateDetailsComponent, canActivate: [LoginGuard] },
{
path: 'controller/:controller_id/preferences/iou/templates/:template_id/copy',
component: CopyIouTemplateComponent,
canActivate: [LoginGuard]
},
{ path: 'controller/:controller_id/preferences/iou/addtemplate', component: AddIouTemplateComponent, canActivate: [LoginGuard] },
{
path: 'controller/:controller_id/management',
component: ManagementComponent,
children: [
{
path: 'users',
component: UserManagementComponent
},
{
path: 'groups',
component: GroupManagementComponent
},
{
path: 'roles',
component: RoleManagementComponent
},
{
path: "pools",
component: ResourcePoolsManagementComponent
},
{
path: 'ACL',
component: AclManagementComponent
}
]
},
{
path: 'controller/:controller_id/management/groups/:user_group_id',
component: GroupDetailsComponent,
resolve: {
members: GroupMembersResolver,
controller: ControllerResolve,
group: GroupResolver,
aces: GroupAcesResolver
}
},
{
path: 'controller/:controller_id/management/roles/:role_id',
component: RoleDetailComponent,
resolve: {
role: RoleDetailResolver,
controller: ControllerResolve
}
},
{ path: 'server/:server_id/preferences/docker/addtemplate', component: AddDockerTemplateComponent },
{ path: 'server/:server_id/preferences/iou/templates', component: IouTemplatesComponent },
{ path: 'server/:server_id/preferences/iou/templates/:template_id', component: IouTemplateDetailsComponent },
{ path: 'server/:server_id/preferences/iou/templates/:template_id/copy', component: CopyIouTemplateComponent },
{ path: 'server/:server_id/preferences/iou/addtemplate', component: AddIouTemplateComponent },
],
},
{
path: 'server/:server_id/project/:project_id',
path: 'controller/:controller_id/project/:project_id',
component: ProjectMapComponent,
canActivate: [LoginGuard],
canDeactivate: [ConsoleGuard],
},
{
path: 'server/:server_id/project/:project_id/nodes/:node_id',
path: 'controller/:controller_id/project/:project_id/nodes/:node_id',
component: WebConsoleFullWindowComponent,
canActivate: [LoginGuard]
},
{
path: 'static/web-ui/server/:server_id/project/:project_id/nodes/:node_id',
path: 'static/web-ui/controller/:controller_id/project/:project_id/nodes/:node_id',
component: WebConsoleFullWindowComponent,
canActivate: [LoginGuard]
},
{
path: '**',
component: PageNotFoundComponent,
},
}
];
@NgModule({
@ -207,4 +311,5 @@ const routes: Routes = [
],
exports: [RouterModule],
})
export class AppRoutingModule {}
export class AppRoutingModule {
}

View File

@ -1,4 +1,4 @@
<div [ngClass]="{ dark: darkThemeEnabled, light: !darkThemeEnabled }">
<router-outlet></router-outlet>
<!-- <app-adbutler></app-adbutler> -->
<app-adbutler></app-adbutler>
</div>

View File

@ -1,5 +1,5 @@
import { NO_ERRORS_SCHEMA } from '@angular/core';
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { MatIconModule } from '@angular/material/icon';
import { RouterTestingModule } from '@angular/router/testing';
import { ElectronService, NgxElectronModule } from 'ngx-electron';
@ -16,8 +16,8 @@ describe('AppComponent', () => {
let electronService: ElectronService;
let settingsService: SettingsService;
beforeEach(async(() => {
TestBed.configureTestingModule({
beforeEach(async() => {
await TestBed.configureTestingModule({
declarations: [AppComponent],
imports: [RouterTestingModule, MatIconModule, NgxElectronModule],
providers: [SettingsService, ProgressService],
@ -26,7 +26,7 @@ describe('AppComponent', () => {
electronService = TestBed.inject(ElectronService);
settingsService = TestBed.inject(SettingsService);
}));
});
beforeEach(() => {
fixture = TestBed.createComponent(AppComponent);
@ -34,29 +34,29 @@ describe('AppComponent', () => {
fixture.detectChanges();
});
it('should create the app', async(() => {
it('should create the app', async() => {
const app = fixture.debugElement.componentInstance;
expect(app).toBeTruthy();
}));
await expect(app).toBeTruthy();
});
it('should have footer', async(() => {
it('should have footer', async() => {
const compiled = fixture.debugElement.nativeElement;
expect(compiled.querySelector('router-outlet').textContent).toEqual('');
}));
await expect(compiled.querySelector('router-outlet').textContent).toEqual('');
});
it('should receive changed settings and forward to electron', async(() => {
spyOnProperty(electronService, 'isElectronApp').and.returnValue(true);
it('should receive changed settings and forward to electron', async() => {
await spyOnProperty(electronService, 'isElectronApp').and.returnValue(true);
settingsService.setReportsSettings(true);
component.ngOnInit();
settingsService.setReportsSettings(false);
}));
});
it('should receive changed settings and do not forward to electron', async(() => {
it('should receive changed settings and do not forward to electron', async() => {
const spy = createSpyObj('Electron.IpcRenderer', ['send']);
spyOnProperty(electronService, 'isElectronApp').and.returnValue(false);
settingsService.setReportsSettings(true);
component.ngOnInit();
settingsService.setReportsSettings(false);
expect(spy.send).not.toHaveBeenCalled();
}));
await expect(spy.send).not.toHaveBeenCalled();
});
});

View File

@ -1,7 +1,8 @@
/* tslint:disable */
import { DragDropModule } from '@angular/cdk/drag-drop';
import { OverlayModule } from '@angular/cdk/overlay';
import { CdkTableModule } from '@angular/cdk/table';
import { HttpClientModule } from '@angular/common/http';
import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http';
import { ErrorHandler, NgModule } from '@angular/core';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { MatSidenavModule } from '@angular/material/sidenav';
@ -29,7 +30,7 @@ import { ProgressDialogService } from './common/progress-dialog/progress-dialog.
import { ProgressComponent } from './common/progress/progress.component';
import { ProgressService } from './common/progress/progress.service';
import { AdbutlerComponent } from './components/adbutler/adbutler.component';
import { BundledServerFinderComponent } from './components/bundled-server-finder/bundled-server-finder.component';
import { BundledControllerFinderComponent } from './components/bundled-controller-finder/bundled-controller-finder.component';
import { InformationDialogComponent } from './components/dialogs/information-dialog.component';
import { DirectLinkComponent } from './components/direct-link/direct-link.component';
import { DrawingAddedComponent } from './components/drawings-listeners/drawing-added/drawing-added.component';
@ -74,7 +75,6 @@ import { DynamipsPreferencesComponent } from './components/preferences/dynamips/
import { IosTemplateDetailsComponent } from './components/preferences/dynamips/ios-template-details/ios-template-details.component';
import { IosTemplatesComponent } from './components/preferences/dynamips/ios-templates/ios-templates.component';
import { GeneralPreferencesComponent } from './components/preferences/general/general-preferences.component';
import { Gns3vmComponent } from './components/preferences/gns3vm/gns3vm.component';
import { AddIouTemplateComponent } from './components/preferences/ios-on-unix/add-iou-template/add-iou-template.component';
import { CopyIouTemplateComponent } from './components/preferences/ios-on-unix/copy-iou-template/copy-iou-template.component';
import { IouTemplateDetailsComponent } from './components/preferences/ios-on-unix/iou-template-details/iou-template-details.component';
@ -85,10 +85,6 @@ import { CopyQemuVmTemplateComponent } from './components/preferences/qemu/copy-
import { QemuPreferencesComponent } from './components/preferences/qemu/qemu-preferences/qemu-preferences.component';
import { QemuVmTemplateDetailsComponent } from './components/preferences/qemu/qemu-vm-template-details/qemu-vm-template-details.component';
import { QemuVmTemplatesComponent } from './components/preferences/qemu/qemu-vm-templates/qemu-vm-templates.component';
import { AddTracengTemplateComponent } from './components/preferences/traceng/add-traceng/add-traceng-template.component';
import { TracengPreferencesComponent } from './components/preferences/traceng/traceng-preferences/traceng-preferences.component';
import { TracengTemplateDetailsComponent } from './components/preferences/traceng/traceng-template-details/traceng-template-details.component';
import { TracengTemplatesComponent } from './components/preferences/traceng/traceng-templates/traceng-templates.component';
import { AddVirtualBoxTemplateComponent } from './components/preferences/virtual-box/add-virtual-box-template/add-virtual-box-template.component';
import { VirtualBoxPreferencesComponent } from './components/preferences/virtual-box/virtual-box-preferences/virtual-box-preferences.component';
import { VirtualBoxTemplateDetailsComponent } from './components/preferences/virtual-box/virtual-box-template-details/virtual-box-template-details.component';
@ -117,6 +113,7 @@ import { DeleteActionComponent } from './components/project-map/context-menu/act
import { DuplicateActionComponent } from './components/project-map/context-menu/actions/duplicate-action/duplicate-action.component';
import { EditConfigActionComponent } from './components/project-map/context-menu/actions/edit-config/edit-config-action.component';
import { EditStyleActionComponent } from './components/project-map/context-menu/actions/edit-style-action/edit-style-action.component';
import { EditLinkStyleActionComponent } from './components/project-map/context-menu/actions/edit-link-style-action/edit-link-style-action.component';
import { EditTextActionComponent } from './components/project-map/context-menu/actions/edit-text-action/edit-text-action.component';
import { ExportConfigActionComponent } from './components/project-map/context-menu/actions/export-config/export-config-action.component';
import { HttpConsoleNewTabActionComponent } from './components/project-map/context-menu/actions/http-console-new-tab/http-console-new-tab-action.component';
@ -134,13 +131,16 @@ import { StartCaptureOnStartedLinkActionComponent } from './components/project-m
import { StartCaptureActionComponent } from './components/project-map/context-menu/actions/start-capture/start-capture-action.component';
import { StartNodeActionComponent } from './components/project-map/context-menu/actions/start-node-action/start-node-action.component';
import { StopCaptureActionComponent } from './components/project-map/context-menu/actions/stop-capture/stop-capture-action.component';
import { StopNodeActionComponent } from './components/project-map/context-menu/actions/stop-node-action/stop-node-action.component';
import { IsolateNodeActionComponent } from './components/project-map/context-menu/actions/isolate-node-action/isolate-node-action.component';
import { UnisolateNodeActionComponent } from './components/project-map/context-menu/actions/unisolate-node-action/unisolate-node-action.component';
import {StopNodeActionComponent } from './components/project-map/context-menu/actions/stop-node-action/stop-node-action.component';
import { SuspendLinkActionComponent } from './components/project-map/context-menu/actions/suspend-link/suspend-link-action.component';
import { SuspendNodeActionComponent } from './components/project-map/context-menu/actions/suspend-node-action/suspend-node-action.component';
import { ContextMenuComponent } from './components/project-map/context-menu/context-menu.component';
import { ConfigDialogComponent } from './components/project-map/context-menu/dialogs/config-dialog/config-dialog.component';
import { DrawLinkToolComponent } from './components/project-map/draw-link-tool/draw-link-tool.component';
import { StyleEditorDialogComponent } from './components/project-map/drawings-editors/style-editor/style-editor.component';
import { LinkStyleEditorDialogComponent } from './components/project-map/drawings-editors/link-style-editor/link-style-editor.component';
import { TextEditorDialogComponent } from './components/project-map/drawings-editors/text-editor/text-editor.component';
import { HelpDialogComponent } from './components/project-map/help-dialog/help-dialog.component';
import { NodeCreatedLabelStylesFixer } from './components/project-map/helpers/node-created-label-styles-fixer';
@ -165,7 +165,6 @@ import { ConfiguratorDialogNatComponent } from './components/project-map/node-ed
import { ConfiguratorDialogQemuComponent } from './components/project-map/node-editors/configurator/qemu/configurator-qemu.component';
import { QemuImageCreatorComponent } from './components/project-map/node-editors/configurator/qemu/qemu-image-creator/qemu-image-creator.component';
import { ConfiguratorDialogSwitchComponent } from './components/project-map/node-editors/configurator/switch/configurator-switch.component';
import { ConfiguratorDialogTracengComponent } from './components/project-map/node-editors/configurator/traceng/configurator-traceng.component';
import { ConfiguratorDialogVirtualBoxComponent } from './components/project-map/node-editors/configurator/virtualbox/configurator-virtualbox.component';
import { ConfiguratorDialogVmwareComponent } from './components/project-map/node-editors/configurator/vmware/configurator-vmware.component';
import { ConfiguratorDialogVpcsComponent } from './components/project-map/node-editors/configurator/vpcs/configurator-vpcs.component';
@ -175,6 +174,7 @@ import { PacketFiltersDialogComponent } from './components/project-map/packet-ca
import { StartCaptureDialogComponent } from './components/project-map/packet-capturing/start-capture/start-capture.component';
import { ProjectMapMenuComponent } from './components/project-map/project-map-menu/project-map-menu.component';
import { ProjectMapComponent } from './components/project-map/project-map.component';
import { ProjectReadmeComponent } from './components/project-map/project-readme/project-readme.component';
import { ScreenshotDialogComponent } from './components/project-map/screenshot-dialog/screenshot-dialog.component';
import { WebConsoleComponent } from './components/project-map/web-console/web-console.component';
import { AddBlankProjectDialogComponent } from './components/projects/add-blank-project-dialog/add-blank-project-dialog.component';
@ -182,15 +182,15 @@ import { ChooseNameDialogComponent } from './components/projects/choose-name-dia
import { ConfirmationBottomSheetComponent } from './components/projects/confirmation-bottomsheet/confirmation-bottomsheet.component';
import { ConfirmationDialogComponent } from './components/projects/confirmation-dialog/confirmation-dialog.component';
import { EditProjectDialogComponent } from './components/projects/edit-project-dialog/edit-project-dialog.component';
import { ReadmeEditorComponent } from './components/projects/edit-project-dialog/readme-editor/readme-editor.component';
import { ImportProjectDialogComponent } from './components/projects/import-project-dialog/import-project-dialog.component';
import { ProjectNameValidator } from './components/projects/models/projectNameValidator';
import { NavigationDialogComponent } from './components/projects/navigation-dialog/navigation-dialog.component';
import { ProjectsComponent } from './components/projects/projects.component';
import { SaveProjectDialogComponent } from './components/projects/save-project-dialog/save-project-dialog.component';
import { AddServerDialogComponent } from './components/servers/add-server-dialog/add-server-dialog.component';
import { ConfigureGns3VMDialogComponent } from './components/servers/configure-gns3vm-dialog/configure-gns3vm-dialog.component';
import { ServerDiscoveryComponent } from './components/servers/server-discovery/server-discovery.component';
import { ServersComponent } from './components/servers/servers.component';
import { AddControllerDialogComponent } from './components/controllers/add-controller-dialog/add-controller-dialog.component';
import { ControllerDiscoveryComponent } from './components/controllers/controller-discovery/controller-discovery.component';
import { ControllersComponent } from './components/controllers/controllers.component';
import { ConsoleComponent } from './components/settings/console/console.component';
import { SettingsComponent } from './components/settings/settings.component';
import { CreateSnapshotDialogComponent } from './components/snapshots/create-snapshot-dialog/create-snapshot-dialog.component';
@ -204,18 +204,19 @@ import { TemplateComponent } from './components/template/template.component';
import { TopologySummaryComponent } from './components/topology-summary/topology-summary.component';
import { WebConsoleFullWindowComponent } from './components/web-console-full-window/web-console-full-window.component';
import { DataSourceFilter } from './filters/dataSourceFilter';
import { AuthImageFilter } from './filters/authImageFilter';
import { DateFilter } from './filters/dateFilter.pipe';
import { NameFilter } from './filters/nameFilter.pipe';
import { ProjectsFilter } from './filters/projectsFilter.pipe';
import { SearchFilter } from './filters/searchFilter.pipe';
import { TemplateFilter } from './filters/templateFilter.pipe';
import { ConsoleGuard } from './guards/console-guard';
import { LoginGuard } from './guards/login-guard';
import { ProjectWebServiceHandler } from './handlers/project-web-service-handler';
import { DefaultLayoutComponent } from './layouts/default-layout/default-layout.component';
import { MATERIAL_IMPORTS } from './material.imports';
import { ServerResolve } from './resolvers/server-resolve';
import { ControllerResolve } from './resolvers/controller-resolve';
import { ApplianceService } from './services/appliances.service';
import { ProtocolHandlerService } from './services/protocol-handler.service';
import { BuiltInTemplatesConfigurationService } from './services/built-in-templates-configuration.service';
import { BuiltInTemplatesService } from './services/built-in-templates.service';
import { ComputeService } from './services/compute.service';
@ -223,9 +224,8 @@ import { DockerConfigurationService } from './services/docker-configuration.serv
import { DockerService } from './services/docker.service';
import { DrawingService } from './services/drawing.service';
import { ExternalSoftwareDefinitionService } from './services/external-software-definition.service';
import { Gns3vmService } from './services/gns3vm.service';
import { GoogleAnalyticsService } from './services/google-analytics.service';
import { HttpServer, ServerErrorHandler } from './services/http-server.service';
import { HttpController, ControllerErrorHandler } from './services/http-controller.service';
import { InfoService } from './services/info.service';
import { InstalledSoftwareService } from './services/installed-software.service';
import { IosConfigurationService } from './services/ios-configuration.service';
@ -244,10 +244,10 @@ import { ProjectService } from './services/project.service';
import { QemuConfigurationService } from './services/qemu-configuration.service';
import { QemuService } from './services/qemu.service';
import { RecentlyOpenedProjectService } from './services/recentlyOpenedProject.service';
import { ServerManagementService } from './services/server-management.service';
import { ServerSettingsService } from './services/server-settings.service';
import { ServerDatabase } from './services/server.database';
import { ServerService } from './services/server.service';
import { ControllerManagementService } from './services/controller-management.service';
import { ControllerSettingsService } from './services/controller-settings.service';
import { ControllerDatabase } from './services/controller.database';
import { ControllerService } from './services/controller.service';
import { SettingsService } from './services/settings.service';
import { ConsoleService } from './services/settings/console.service';
import { DefaultConsoleService } from './services/settings/default-console.service';
@ -258,7 +258,6 @@ import { TemplateService } from './services/template.service';
import { ThemeService } from './services/theme.service';
import { ToasterService } from './services/toaster.service';
import { ToolsService } from './services/tools.service';
import { TracengService } from './services/traceng.service';
import { UpdatesService } from './services/updates.service';
import { VersionService } from './services/version.service';
import { VirtualBoxConfigurationService } from './services/virtual-box-configuration.service';
@ -269,337 +268,403 @@ import { VpcsConfigurationService } from './services/vpcs-configuration.service'
import { VpcsService } from './services/vpcs.service';
import { NonNegativeValidator } from './validators/non-negative-validator';
import { RotationValidator } from './validators/rotation-validator';
import { MarkedDirective } from './directives/marked.directive';
import { LoginComponent } from './components/login/login.component';
import { LoginService } from './services/login.service';
import { HttpRequestsInterceptor } from './interceptors/http.interceptor';
import { UserManagementComponent } from './components/user-management/user-management.component';
import { UserService } from './services/user.service';
import { LoggedUserComponent } from './components/users/logged-user/logged-user.component';
import { AddUserDialogComponent } from './components/user-management/add-user-dialog/add-user-dialog.component';
import { UserFilterPipe } from './filters/user-filter.pipe';
import { GroupManagementComponent } from './components/group-management/group-management.component';
import { GroupFilterPipe } from './filters/group-filter.pipe';
import { AddGroupDialogComponent } from './components/group-management/add-group-dialog/add-group-dialog.component';
import { DeleteGroupDialogComponent } from './components/group-management/delete-group-dialog/delete-group-dialog.component';
import { DeleteUserDialogComponent } from './components/user-management/delete-user-dialog/delete-user-dialog.component';
import { GroupDetailsComponent } from './components/group-details/group-details.component';
import { UserDetailComponent } from './components/user-management/user-detail/user-detail.component';
import { AddUserToGroupDialogComponent } from './components/group-details/add-user-to-group-dialog/add-user-to-group-dialog.component';
import { RemoveToGroupDialogComponent } from '@components/group-details/remove-to-group-dialog/remove-to-group-dialog.component';
import { PaginatorPipe } from './components/group-details/paginator.pipe';
import { MembersFilterPipe } from './components/group-details/members-filter.pipe';
import { ManagementComponent } from './components/management/management.component';
import {MatCheckboxModule} from "@angular/material/checkbox";
import { RoleManagementComponent } from './components/role-management/role-management.component';
import { RoleFilterPipe } from './components/role-management/role-filter.pipe';
import { AddRoleDialogComponent } from './components/role-management/add-role-dialog/add-role-dialog.component';
import { DeleteRoleDialogComponent } from './components/role-management/delete-role-dialog/delete-role-dialog.component';
import { RoleDetailComponent } from './components/role-management/role-detail/role-detail.component';
import {MatSlideToggleModule} from '@angular/material/slide-toggle';
import {MatAutocompleteModule} from "@angular/material/autocomplete";;
import { AddRoleToGroupComponent } from './components/group-details/add-role-to-group/add-role-to-group.component';
import {MatFormFieldModule} from "@angular/material/form-field";
import { ChangeUserPasswordComponent } from './components/user-management/user-detail/change-user-password/change-user-password.component';
import {MatMenuModule} from "@angular/material/menu";
import { ImageManagerComponent } from './components/image-manager/image-manager.component';
import { AddImageDialogComponent } from './components/image-manager/add-image-dialog/add-image-dialog.component';
import { DeleteAllImageFilesDialogComponent } from './components/image-manager/deleteallfiles-dialog/deleteallfiles-dialog.component';
import { UploadingProcessbarComponent } from './common/uploading-processbar/uploading-processbar.component';
import { ExportPortableProjectComponent } from './components/export-portable-project/export-portable-project.component';
import { NodesMenuConfirmationDialogComponent } from './components/project-map/nodes-menu/nodes-menu-confirmation-dialog/nodes-menu-confirmation-dialog.component';
import { ConfirmationDeleteAllProjectsComponent } from './components/projects/confirmation-delete-all-projects/confirmation-delete-all-projects.component';
import { ProjectMapLockConfirmationDialogComponent } from './components/project-map/project-map-menu/project-map-lock-confirmation-dialog/project-map-lock-confirmation-dialog.component';
import { AclManagementComponent } from "@components/acl-management/acl-management.component";
import { AddAceDialogComponent } from './components/acl-management/add-ace-dialog/add-ace-dialog.component';
import { AutocompleteComponent } from './components/acl-management/add-ace-dialog/autocomplete/autocomplete.component';
import { DeleteAceDialogComponent } from './components/acl-management/delete-ace-dialog/delete-ace-dialog.component';
import { AceFilterPipe } from './filters/ace-filter.pipe';
import { CdkAccordionModule } from "@angular/cdk/accordion";
import { CdkTreeModule } from "@angular/cdk/tree";
import { PrivilegeComponent } from './components/role-management/role-detail/privilege/privilege.component';
import { GroupPrivilegesPipe } from './components/role-management/role-detail/privilege/group-privileges.pipe';
import { ResourcePoolsManagementComponent } from './components/resource-pools-management/resource-pools-management.component';
import { AddResourcePoolDialogComponent } from './components/resource-pools-management/add-resource-pool-dialog/add-resource-pool-dialog.component';
import { DeleteResourcePoolComponent } from './components/resource-pools-management/delete-resource-pool/delete-resource-pool.component';
import { ResourcePoolsFilterPipe } from './components/resource-pools-management/resource-pools-filter.pipe';
import { ResourcePoolDetailsComponent } from './components/resource-pool-details/resource-pool-details.component';
import { DeleteResourceConfirmationDialogComponent } from './components/resource-pool-details/delete-resource-confirmation-dialog/delete-resource-confirmation-dialog.component';
@NgModule({
declarations: [
AppComponent,
ProjectMapComponent,
ServersComponent,
AddServerDialogComponent,
CreateSnapshotDialogComponent,
SnapshotMenuItemComponent,
ProjectsComponent,
AddBlankProjectDialogComponent,
ImportProjectDialogComponent,
ConfirmationDialogComponent,
DefaultLayoutComponent,
ProgressDialogComponent,
ContextMenuComponent,
ContextConsoleMenuComponent,
StartNodeActionComponent,
StopNodeActionComponent,
TemplateComponent,
TemplateListDialogComponent,
MoveLayerDownActionComponent,
MoveLayerUpActionComponent,
EditStyleActionComponent,
EditTextActionComponent,
DeleteActionComponent,
DuplicateActionComponent,
PacketFiltersActionComponent,
StartCaptureActionComponent,
StopCaptureActionComponent,
ResumeLinkActionComponent,
SuspendLinkActionComponent,
SettingsComponent,
PreferencesComponent,
BundledServerFinderComponent,
ProgressComponent,
ServerDiscoveryComponent,
NodeSelectInterfaceComponent,
DrawLinkToolComponent,
InstalledSoftwareComponent,
DrawingAddedComponent,
DrawingResizedComponent,
TextAddedComponent,
TextEditedComponent,
NodeDraggedComponent,
NodeLabelDraggedComponent,
DrawingDraggedComponent,
LinkCreatedComponent,
InterfaceLabelDraggedComponent,
InstallSoftwareComponent,
StyleEditorDialogComponent,
TextEditorDialogComponent,
PacketFiltersDialogComponent,
QemuPreferencesComponent,
QemuVmTemplatesComponent,
AddQemuVmTemplateComponent,
QemuVmTemplateDetailsComponent,
GeneralPreferencesComponent,
VpcsPreferencesComponent,
VpcsTemplatesComponent,
AddVpcsTemplateComponent,
VpcsTemplateDetailsComponent,
VirtualBoxPreferencesComponent,
VirtualBoxTemplatesComponent,
VirtualBoxTemplateDetailsComponent,
AddVirtualBoxTemplateComponent,
BuiltInPreferencesComponent,
EthernetHubsTemplatesComponent,
EthernetHubsAddTemplateComponent,
EthernetHubsTemplateDetailsComponent,
CloudNodesTemplatesComponent,
CloudNodesAddTemplateComponent,
CloudNodesTemplateDetailsComponent,
EthernetSwitchesTemplatesComponent,
EthernetSwitchesAddTemplateComponent,
EthernetSwitchesTemplateDetailsComponent,
DynamipsPreferencesComponent,
IosTemplatesComponent,
IosTemplateDetailsComponent,
AddIosTemplateComponent,
SymbolsComponent,
VmwarePreferencesComponent,
VmwareTemplatesComponent,
VmwareTemplateDetailsComponent,
AddVmwareTemplateComponent,
DeleteConfirmationDialogComponent,
HelpDialogComponent,
StartCaptureDialogComponent,
DeleteTemplateComponent,
DockerTemplatesComponent,
AddDockerTemplateComponent,
DockerTemplateDetailsComponent,
IouTemplatesComponent,
AddIouTemplateComponent,
IouTemplateDetailsComponent,
CopyQemuVmTemplateComponent,
CopyIosTemplateComponent,
CopyIouTemplateComponent,
CopyDockerTemplateComponent,
EmptyTemplatesListComponent,
SymbolsMenuComponent,
SearchFilter,
DateFilter,
NameFilter,
DataSourceFilter,
TemplateFilter,
ProjectsFilter,
ListOfSnapshotsComponent,
CustomAdaptersComponent,
NodesMenuComponent,
AdbutlerComponent,
ConsoleDeviceActionComponent,
ShowNodeActionComponent,
ConsoleComponent,
NodesMenuComponent,
ProjectMapMenuComponent,
HelpComponent,
ConfigEditorDialogComponent,
EditConfigActionComponent,
LogConsoleComponent,
SaveProjectDialogComponent,
TopologySummaryComponent,
InfoDialogComponent,
BringToFrontActionComponent,
ExportConfigActionComponent,
ImportConfigActionComponent,
ConsoleDeviceActionBrowserComponent,
ChangeSymbolDialogComponent,
ChangeSymbolActionComponent,
EditProjectDialogComponent,
ReloadNodeActionComponent,
SuspendNodeActionComponent,
ConfigActionComponent,
ConfiguratorDialogVpcsComponent,
ConfiguratorDialogEthernetHubComponent,
ConfiguratorDialogEthernetSwitchComponent,
PortsComponent,
ConfiguratorDialogSwitchComponent,
ConfiguratorDialogVirtualBoxComponent,
CustomAdaptersTableComponent,
ConfiguratorDialogQemuComponent,
ConfiguratorDialogCloudComponent,
UdpTunnelsComponent,
ConfiguratorDialogAtmSwitchComponent,
ConfiguratorDialogVmwareComponent,
ConfiguratorDialogIouComponent,
ConfiguratorDialogIosComponent,
ConfiguratorDialogDockerComponent,
ConfiguratorDialogNatComponent,
ConfiguratorDialogTracengComponent,
AddTracengTemplateComponent,
TracengPreferencesComponent,
TracengTemplatesComponent,
TracengTemplateDetailsComponent,
QemuImageCreatorComponent,
ChooseNameDialogComponent,
StartCaptureOnStartedLinkActionComponent,
LockActionComponent,
NavigationDialogComponent,
ScreenshotDialogComponent,
PageNotFoundComponent,
AlignHorizontallyActionComponent,
AlignVerticallyActionComponent,
ConfirmationBottomSheetComponent,
ConfigDialogComponent,
Gns3vmComponent,
ConfigureGns3VMDialogComponent,
ImportApplianceComponent,
DirectLinkComponent,
SystemStatusComponent,
StatusInfoComponent,
StatusChartComponent,
OpenFileExplorerActionComponent,
HttpConsoleActionComponent,
WebConsoleComponent,
ConsoleWrapperComponent,
HttpConsoleNewTabActionComponent,
WebConsoleFullWindowComponent,
NewTemplateDialogComponent,
ChangeHostnameActionComponent,
ChangeHostnameDialogComponent,
ApplianceInfoDialogComponent,
InformationDialogComponent,
TemplateNameDialogComponent,
ConfigureCustomAdaptersDialogComponent,
EditNetworkConfigurationDialogComponent
],
imports: [
BrowserModule,
HttpClientModule,
AppRoutingModule,
FormsModule,
ReactiveFormsModule,
BrowserAnimationsModule,
CdkTableModule,
CartographyModule,
NgxElectronModule,
FileUploadModule,
MatSidenavModule,
ResizableModule,
DragAndDropModule,
DragDropModule,
NgxChildProcessModule,
MATERIAL_IMPORTS,
NgCircleProgressModule.forRoot(),
OverlayModule,
],
providers: [
SettingsService,
{ provide: ErrorHandler, useClass: ToasterErrorHandler },
D3Service,
VersionService,
ProjectService,
SymbolService,
ServerService,
TemplateService,
NodeService,
LinkService,
DrawingService,
HttpServer,
SnapshotService,
ProgressDialogService,
ToasterService,
ProgressService,
ProjectWebServiceHandler,
LinksDataSource,
NodesDataSource,
SymbolsDataSource,
LogEventsDataSource,
SelectionManager,
InRectangleHelper,
DrawingsDataSource,
ServerErrorHandler,
ServerDatabase,
ProjectNameValidator,
ToolsService,
ServerSettingsService,
QemuService,
VpcsService,
TemplateMocksService,
VirtualBoxService,
BuiltInTemplatesService,
IosService,
InstalledSoftwareService,
ExternalSoftwareDefinitionService,
PlatformService,
IosConfigurationService,
QemuConfigurationService,
VirtualBoxConfigurationService,
VpcsConfigurationService,
BuiltInTemplatesConfigurationService,
VmwareService,
VmwareConfigurationService,
DockerService,
DockerConfigurationService,
IouService,
IouConfigurationService,
RecentlyOpenedProjectService,
ServerManagementService,
MapScaleService,
ConsoleService,
DefaultConsoleService,
NodeCreatedLabelStylesFixer,
NonNegativeValidator,
RotationValidator,
MapSettingsService,
InfoService,
ComputeService,
TracengService,
PacketCaptureService,
ProtocolHandlerService,
NotificationService,
Gns3vmService,
ThemeService,
GoogleAnalyticsService,
NodeConsoleService,
ServerResolve,
ConsoleGuard,
Title,
ApplianceService,
UpdatesService,
],
entryComponents: [
AddServerDialogComponent,
CreateSnapshotDialogComponent,
ProgressDialogComponent,
TemplateListDialogComponent,
AddBlankProjectDialogComponent,
ImportProjectDialogComponent,
ConfirmationDialogComponent,
StyleEditorDialogComponent,
PacketFiltersDialogComponent,
TextEditorDialogComponent,
SymbolsComponent,
DeleteConfirmationDialogComponent,
HelpDialogComponent,
StartCaptureDialogComponent,
ConfigEditorDialogComponent,
SaveProjectDialogComponent,
InfoDialogComponent,
ChangeSymbolDialogComponent,
EditProjectDialogComponent,
ConfigureGns3VMDialogComponent,
ConfiguratorDialogVpcsComponent,
ConfiguratorDialogEthernetHubComponent,
ConfiguratorDialogEthernetSwitchComponent,
ConfiguratorDialogSwitchComponent,
ConfiguratorDialogVirtualBoxComponent,
ConfiguratorDialogQemuComponent,
ConfiguratorDialogCloudComponent,
ConfiguratorDialogAtmSwitchComponent,
ConfiguratorDialogVmwareComponent,
ConfiguratorDialogIouComponent,
ConfiguratorDialogIosComponent,
ConfiguratorDialogDockerComponent,
ConfiguratorDialogNatComponent,
ConfiguratorDialogTracengComponent,
QemuImageCreatorComponent,
ChooseNameDialogComponent,
NavigationDialogComponent,
ScreenshotDialogComponent,
ConfirmationBottomSheetComponent,
ConfigDialogComponent,
AdbutlerComponent,
NewTemplateDialogComponent,
ChangeHostnameDialogComponent,
ApplianceInfoDialogComponent,
ConfigureCustomAdaptersDialogComponent,
EditNetworkConfigurationDialogComponent,
],
bootstrap: [AppComponent],
declarations: [
AppComponent,
LoggedUserComponent,
ProjectMapComponent,
LoginComponent,
ControllersComponent,
AddControllerDialogComponent,
CreateSnapshotDialogComponent,
SnapshotMenuItemComponent,
ProjectsComponent,
AddBlankProjectDialogComponent,
ImportProjectDialogComponent,
ConfirmationDialogComponent,
DefaultLayoutComponent,
ProgressDialogComponent,
ContextMenuComponent,
ContextConsoleMenuComponent,
StartNodeActionComponent,
IsolateNodeActionComponent,
UnisolateNodeActionComponent,
StopNodeActionComponent,
TemplateComponent,
TemplateListDialogComponent,
MoveLayerDownActionComponent,
MoveLayerUpActionComponent,
EditStyleActionComponent,
EditLinkStyleActionComponent,
EditTextActionComponent,
DeleteActionComponent,
DuplicateActionComponent,
PacketFiltersActionComponent,
StartCaptureActionComponent,
StopCaptureActionComponent,
ResumeLinkActionComponent,
SuspendLinkActionComponent,
SettingsComponent,
PreferencesComponent,
BundledControllerFinderComponent,
ProgressComponent,
ControllerDiscoveryComponent,
NodeSelectInterfaceComponent,
DrawLinkToolComponent,
InstalledSoftwareComponent,
DrawingAddedComponent,
DrawingResizedComponent,
TextAddedComponent,
TextEditedComponent,
NodeDraggedComponent,
NodeLabelDraggedComponent,
DrawingDraggedComponent,
LinkCreatedComponent,
InterfaceLabelDraggedComponent,
InstallSoftwareComponent,
StyleEditorDialogComponent,
LinkStyleEditorDialogComponent,
TextEditorDialogComponent,
PacketFiltersDialogComponent,
QemuPreferencesComponent,
QemuVmTemplatesComponent,
AddQemuVmTemplateComponent,
QemuVmTemplateDetailsComponent,
GeneralPreferencesComponent,
VpcsPreferencesComponent,
VpcsTemplatesComponent,
AddVpcsTemplateComponent,
VpcsTemplateDetailsComponent,
VirtualBoxPreferencesComponent,
VirtualBoxTemplatesComponent,
VirtualBoxTemplateDetailsComponent,
AddVirtualBoxTemplateComponent,
BuiltInPreferencesComponent,
EthernetHubsTemplatesComponent,
EthernetHubsAddTemplateComponent,
EthernetHubsTemplateDetailsComponent,
CloudNodesTemplatesComponent,
CloudNodesAddTemplateComponent,
CloudNodesTemplateDetailsComponent,
EthernetSwitchesTemplatesComponent,
EthernetSwitchesAddTemplateComponent,
EthernetSwitchesTemplateDetailsComponent,
DynamipsPreferencesComponent,
IosTemplatesComponent,
IosTemplateDetailsComponent,
AddIosTemplateComponent,
SymbolsComponent,
VmwarePreferencesComponent,
VmwareTemplatesComponent,
VmwareTemplateDetailsComponent,
AddVmwareTemplateComponent,
DeleteConfirmationDialogComponent,
HelpDialogComponent,
StartCaptureDialogComponent,
DeleteTemplateComponent,
DockerTemplatesComponent,
AddDockerTemplateComponent,
DockerTemplateDetailsComponent,
IouTemplatesComponent,
AddIouTemplateComponent,
IouTemplateDetailsComponent,
CopyQemuVmTemplateComponent,
CopyIosTemplateComponent,
CopyIouTemplateComponent,
CopyDockerTemplateComponent,
EmptyTemplatesListComponent,
SymbolsMenuComponent,
SearchFilter,
DateFilter,
NameFilter,
DataSourceFilter,
TemplateFilter,
ProjectsFilter,
AuthImageFilter,
ListOfSnapshotsComponent,
CustomAdaptersComponent,
NodesMenuComponent,
AdbutlerComponent,
ConsoleDeviceActionComponent,
ShowNodeActionComponent,
ConsoleComponent,
NodesMenuComponent,
ProjectMapMenuComponent,
HelpComponent,
ConfigEditorDialogComponent,
EditConfigActionComponent,
LogConsoleComponent,
SaveProjectDialogComponent,
TopologySummaryComponent,
InfoDialogComponent,
BringToFrontActionComponent,
ExportConfigActionComponent,
ImportConfigActionComponent,
ConsoleDeviceActionBrowserComponent,
ChangeSymbolDialogComponent,
ChangeSymbolActionComponent,
EditProjectDialogComponent,
ReloadNodeActionComponent,
SuspendNodeActionComponent,
ConfigActionComponent,
ConfiguratorDialogVpcsComponent,
ConfiguratorDialogEthernetHubComponent,
ConfiguratorDialogEthernetSwitchComponent,
PortsComponent,
ConfiguratorDialogSwitchComponent,
ConfiguratorDialogVirtualBoxComponent,
CustomAdaptersTableComponent,
ConfiguratorDialogQemuComponent,
ConfiguratorDialogCloudComponent,
UdpTunnelsComponent,
ConfiguratorDialogAtmSwitchComponent,
ConfiguratorDialogVmwareComponent,
ConfiguratorDialogIouComponent,
ConfiguratorDialogIosComponent,
ConfiguratorDialogDockerComponent,
ConfiguratorDialogNatComponent,
QemuImageCreatorComponent,
ChooseNameDialogComponent,
StartCaptureOnStartedLinkActionComponent,
LockActionComponent,
NavigationDialogComponent,
ScreenshotDialogComponent,
PageNotFoundComponent,
AlignHorizontallyActionComponent,
AlignVerticallyActionComponent,
ConfirmationBottomSheetComponent,
ConfigDialogComponent,
ImportApplianceComponent,
DirectLinkComponent,
SystemStatusComponent,
StatusInfoComponent,
StatusChartComponent,
OpenFileExplorerActionComponent,
HttpConsoleActionComponent,
WebConsoleComponent,
ConsoleWrapperComponent,
HttpConsoleNewTabActionComponent,
WebConsoleFullWindowComponent,
NewTemplateDialogComponent,
ChangeHostnameActionComponent,
ChangeHostnameDialogComponent,
ApplianceInfoDialogComponent,
ReadmeEditorComponent,
MarkedDirective,
InformationDialogComponent,
TemplateNameDialogComponent,
ConfigureCustomAdaptersDialogComponent,
EditNetworkConfigurationDialogComponent,
UserManagementComponent,
ProjectReadmeComponent,
AddGroupDialogComponent,
GroupFilterPipe,
GroupManagementComponent,
AddUserDialogComponent,
UserFilterPipe,
DeleteGroupDialogComponent,
DeleteUserDialogComponent,
GroupDetailsComponent,
UserDetailComponent,
AddUserToGroupDialogComponent,
RemoveToGroupDialogComponent,
PaginatorPipe,
MembersFilterPipe,
ManagementComponent,
RoleManagementComponent,
RoleFilterPipe,
AddRoleDialogComponent,
DeleteRoleDialogComponent,
RoleDetailComponent,
RemoveToGroupDialogComponent,
AddRoleToGroupComponent,
ChangeUserPasswordComponent,
ChangeUserPasswordComponent,
ProjectReadmeComponent,
ImageManagerComponent,
AddImageDialogComponent,
DeleteAllImageFilesDialogComponent,
UploadingProcessbarComponent,
ExportPortableProjectComponent,
NodesMenuConfirmationDialogComponent,
ConfirmationDeleteAllProjectsComponent,
ProjectMapLockConfirmationDialogComponent,
AclManagementComponent,
AddAceDialogComponent,
AutocompleteComponent,
DeleteAceDialogComponent,
AceFilterPipe,
PrivilegeComponent,
GroupPrivilegesPipe,
ResourcePoolsManagementComponent,
AddResourcePoolDialogComponent,
DeleteResourcePoolComponent,
ResourcePoolsFilterPipe,
ResourcePoolDetailsComponent,
DeleteResourceConfirmationDialogComponent,
],
imports: [
BrowserModule,
HttpClientModule,
AppRoutingModule,
FormsModule,
ReactiveFormsModule,
BrowserAnimationsModule,
CdkTableModule,
CartographyModule,
NgxElectronModule,
FileUploadModule,
MatSidenavModule,
MatFormFieldModule,
MatMenuModule,
ResizableModule,
DragAndDropModule,
DragDropModule,
NgxChildProcessModule,
MATERIAL_IMPORTS,
NgCircleProgressModule.forRoot(),
OverlayModule,
MatSlideToggleModule,
MatCheckboxModule,
MatAutocompleteModule,
CdkAccordionModule,
CdkTreeModule,
],
providers: [
SettingsService,
{ provide: ErrorHandler, useClass: ToasterErrorHandler },
{ provide: HTTP_INTERCEPTORS, useClass: HttpRequestsInterceptor, multi: true },
VersionService,
D3Service,
ProjectService,
SymbolService,
ControllerService,
TemplateService,
NodeService,
LinkService,
DrawingService,
HttpController,
SnapshotService,
ProgressDialogService,
ToasterService,
ProgressService,
ProjectWebServiceHandler,
LinksDataSource,
NodesDataSource,
SymbolsDataSource,
LogEventsDataSource,
SelectionManager,
InRectangleHelper,
DrawingsDataSource,
ControllerErrorHandler,
ControllerDatabase,
ProjectNameValidator,
ToolsService,
ControllerSettingsService,
QemuService,
VpcsService,
TemplateMocksService,
VirtualBoxService,
BuiltInTemplatesService,
IosService,
InstalledSoftwareService,
ExternalSoftwareDefinitionService,
PlatformService,
IosConfigurationService,
QemuConfigurationService,
VirtualBoxConfigurationService,
VpcsConfigurationService,
BuiltInTemplatesConfigurationService,
VmwareService,
VmwareConfigurationService,
DockerService,
DockerConfigurationService,
IouService,
IouConfigurationService,
RecentlyOpenedProjectService,
ControllerManagementService,
MapScaleService,
ConsoleService,
DefaultConsoleService,
NodeCreatedLabelStylesFixer,
NonNegativeValidator,
RotationValidator,
MapSettingsService,
InfoService,
ComputeService,
PacketCaptureService,
NotificationService,
ThemeService,
GoogleAnalyticsService,
NodeConsoleService,
ControllerResolve,
LoginGuard,
ConsoleGuard,
Title,
ApplianceService,
UpdatesService,
LoginService,
UserService
],
bootstrap: [AppComponent]
})
export class AppModule {
constructor(protected _googleAnalyticsService: GoogleAnalyticsService) {}

View File

@ -5,6 +5,7 @@ import { MatMenuModule } from '@angular/material/menu';
import { ANGULAR_MAP_DECLARATIONS } from './angular-map.imports';
import { D3MapComponent } from './components/d3-map/d3-map.component';
import { DraggableSelectionComponent } from './components/draggable-selection/draggable-selection.component';
import { LinkEditingComponent } from './components/link-editing/link-editing.component';
import { DrawingAddingComponent } from './components/drawing-adding/drawing-adding.component';
import { DrawingResizingComponent } from './components/drawing-resizing/drawing-resizing.component';
import { ExperimentalMapComponent } from './components/experimental-map/experimental-map.component';
@ -73,6 +74,7 @@ import { SerialLinkWidget } from './widgets/links/serial-link';
SelectionControlComponent,
SelectionSelectComponent,
DraggableSelectionComponent,
LinkEditingComponent,
MovingCanvasDirective,
ZoomingCanvasDirective,
],

View File

@ -44,5 +44,6 @@
<app-drawing-resizing></app-drawing-resizing>
<app-selection-control></app-selection-control>
<app-selection-select></app-selection-select>
<app-text-editor #textEditor [server]="server" [svg]="svg"></app-text-editor>
<app-text-editor #textEditor [controller]="controller" [svg]="svg"></app-text-editor>
<app-draggable-selection [svg]="svg"></app-draggable-selection>
<app-link-editing [svg]="svg"></app-link-editing>

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@ -1,23 +1,17 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { D3MapComponent } from './d3-map.component';
describe('D3MapComponent', () => {
let component: D3MapComponent;
let fixture: ComponentFixture<D3MapComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [D3MapComponent],
}).compileComponents();
}));
});
// beforeEach(() => {
// fixture = TestBed.createComponent(MapComponent);
// component = fixture.componentInstance;
// fixture.detectChanges();
// });
//
// it('should create', () => {
// expect(component).toBeTruthy();
// });
it('should create', () => {
expect(component)
});
});

View File

@ -13,7 +13,7 @@ import { select, Selection } from 'd3-selection';
import { Subscription } from 'rxjs';
import { Link } from '../../../models/link';
import { Project } from '../../../models/project';
import { Server } from '../../../models/server';
import { Controller } from '../../../models/controller';
import { Symbol } from '../../../models/symbol';
import { MapScaleService } from '../../../services/mapScale.service';
import { MapSettingsService } from '../../../services/mapsettings.service';
@ -43,7 +43,7 @@ export class D3MapComponent implements OnInit, OnChanges, OnDestroy {
@Input() drawings: Drawing[] = [];
@Input() symbols: Symbol[] = [];
@Input() project: Project;
@Input() server: Server;
@Input() controller: Controller;
@Input() width = 1500;
@Input() height = 600;

View File

@ -42,7 +42,7 @@ describe('DraggableSelectionComponent', () => {
let interfaceLabelDragEventEmitter: EventEmitter<DraggableDrag<MapLinkNode>>;
let interfaceLabelEndEventEmitter: EventEmitter<DraggableEnd<MapLinkNode>>;
beforeEach(async(() => {
beforeEach(async () => {
mockedGraphDataManager = new MockedGraphDataManager();
nodesStartEventEmitter = new EventEmitter<DraggableStart<MapNode>>();
@ -110,7 +110,7 @@ describe('DraggableSelectionComponent', () => {
interfaceDragged: { emit: () => {} },
};
TestBed.configureTestingModule({
await TestBed.configureTestingModule({
providers: [
{ provide: NodesWidget, useValue: nodesWidgetStub },
{ provide: DrawingsWidget, useValue: drawingsWidgetStub },
@ -126,7 +126,7 @@ describe('DraggableSelectionComponent', () => {
],
declarations: [DraggableSelectionComponent],
}).compileComponents();
}));
});
beforeEach(() => {
fixture = TestBed.createComponent(DraggableSelectionComponent);

View File

@ -1,4 +1,4 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
import { DrawingsEventSource } from '../../events/drawings-event-source';
import { Context } from '../../models/context';
@ -9,8 +9,8 @@ describe('DrawingAddingComponent', () => {
let fixture: ComponentFixture<DrawingAddingComponent>;
let drawingsEventSource = new DrawingsEventSource();
beforeEach(async(() => {
TestBed.configureTestingModule({
beforeEach(async() => {
await TestBed.configureTestingModule({
imports: [NoopAnimationsModule],
providers: [
{ provide: DrawingsEventSource, useValue: drawingsEventSource },
@ -18,7 +18,7 @@ describe('DrawingAddingComponent', () => {
],
declarations: [DrawingAddingComponent],
}).compileComponents();
}));
});
beforeEach(() => {
fixture = TestBed.createComponent(DrawingAddingComponent);

View File

@ -1,5 +1,5 @@
import { EventEmitter } from '@angular/core';
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
import { DrawingsEventSource } from '../../events/drawings-event-source';
import { ResizingEnd } from '../../events/resizing';
@ -30,8 +30,8 @@ describe('DrawingResizingComponent', () => {
let drawingsWidgetMock = new DrawingWidgetMock();
let drawingsEventSource = new DrawingsEventSource();
beforeEach(async(() => {
TestBed.configureTestingModule({
beforeEach(async() => {
await TestBed.configureTestingModule({
imports: [NoopAnimationsModule],
providers: [
{ provide: DrawingsWidget, useValue: drawingsWidgetMock },
@ -39,7 +39,7 @@ describe('DrawingResizingComponent', () => {
],
declarations: [DrawingResizingComponent],
}).compileComponents();
}));
});
beforeEach(() => {
fixture = TestBed.createComponent(DrawingResizingComponent);

View File

@ -1,15 +1,15 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { DraggableComponent } from './draggable.component';
describe('DraggableComponent', () => {
let component: DraggableComponent;
let fixture: ComponentFixture<DraggableComponent>;
beforeEach(async(() => {
beforeEach(async() => {
TestBed.configureTestingModule({
declarations: [DraggableComponent],
}).compileComponents();
}));
});
beforeEach(() => {
fixture = TestBed.createComponent(DraggableComponent);
@ -17,7 +17,7 @@ describe('DraggableComponent', () => {
fixture.detectChanges();
});
// it('should create', () => {
// expect(component).toBeTruthy();
// });
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -5,13 +5,13 @@
(dragging)="OnDragging($event)"
(dragged)="OnDragged($event)"
>
<svg:g *ngIf="is(drawing.element, 'ellipse')" [app-ellipse]="drawing.element" />
<svg:g *ngIf="is(drawing?.element, 'ellipse')" [app-ellipse]="drawing?.element" />
<svg:g *ngIf="is(drawing.element, 'image')" [app-image]="drawing.element" />
<svg:g *ngIf="is(drawing?.element, 'image')" [app-image]="drawing?.element" />
<svg:g *ngIf="is(drawing.element, 'line')" [app-line]="drawing.element" />
<svg:g *ngIf="is(drawing?.element, 'line')" [app-line]="drawing?.element" />
<svg:g *ngIf="is(drawing.element, 'rect')" [app-rect]="drawing.element" />
<svg:g *ngIf="is(drawing?.element, 'rect')" [app-rect]="drawing?.element" />
<svg:g *ngIf="is(drawing.element, 'text')" [app-text]="drawing.element" />
<svg:g *ngIf="is(drawing?.element, 'text')" [app-text]="drawing?.element" />
</svg:g>

Before

Width:  |  Height:  |  Size: 563 B

After

Width:  |  Height:  |  Size: 573 B

View File

@ -1,15 +1,18 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import {ComponentFixture, TestBed } from '@angular/core/testing';
import { DrawingsEventSource } from 'app/cartography/events/drawings-event-source';
import { SvgToDrawingConverter } from 'app/cartography/helpers/svg-to-drawing-converter';
import { DrawingComponent } from './drawing.component';
describe('DrawingComponent', () => {
let component: DrawingComponent;
let fixture: ComponentFixture<DrawingComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
beforeEach(async() => {
await TestBed.configureTestingModule({
declarations: [DrawingComponent],
providers:[SvgToDrawingConverter,DrawingsEventSource]
}).compileComponents();
}));
});
beforeEach(() => {
fixture = TestBed.createComponent(DrawingComponent);
@ -17,7 +20,7 @@ describe('DrawingComponent', () => {
fixture.detectChanges();
});
// it('should create', () => {
// expect(component).toBeTruthy();
// });
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -21,17 +21,17 @@ export class DrawingComponent implements OnInit {
private svgToDrawingConverter: SvgToDrawingConverter,
private drawingsEventSource: DrawingsEventSource,
private cd: ChangeDetectorRef
) {}
) { }
ngOnInit() {
try {
this.drawing.element = this.svgToDrawingConverter.convert(this.drawing.svg);
} catch (error) {}
} catch (error) { }
}
OnDragging(evt) {
this.drawing.x = evt.x;
this.drawing.y = evt.y;
this.drawing.x = evt ? evt.x : '';
this.drawing.y = evt ? evt.y : '';
this.cd.detectChanges();
}
@ -64,6 +64,8 @@ export class DrawingComponent implements OnInit {
}
get transformation() {
return `translate(${this.drawing.x},${this.drawing.y}) rotate(${this.drawing.rotation})`;
if (this.drawing) {
return `translate(${this.drawing.x},${this.drawing.y}) rotate(${this.drawing.rotation})`;
}
}
}

View File

@ -1,12 +1,12 @@
<svg:ellipse
class="ellipse_element noselect"
[attr.fill]="ellipse.fill"
[attr.fill]="ellipse?.fill"
[attr.fill-opacity]="fill_opacity"
[attr.stroke]="ellipse.stroke"
[attr.stroke]="ellipse?.stroke"
[attr.stroke-width]="stroke_width"
[attr.stroke-dasharray]="stroke_dasharray"
[attr.cx]="ellipse.cx"
[attr.cy]="ellipse.cy"
[attr.rx]="ellipse.rx"
[attr.ry]="ellipse.ry"
[attr.cx]="ellipse?.cx"
[attr.cy]="ellipse?.cy"
[attr.rx]="ellipse?.rx"
[attr.ry]="ellipse?.ry"
/>

Before

Width:  |  Height:  |  Size: 332 B

After

Width:  |  Height:  |  Size: 338 B

View File

@ -1,15 +1,17 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { QtDasharrayFixer } from 'app/cartography/helpers/qt-dasharray-fixer';
import { EllipseComponent } from './ellipse.component';
describe('EllipseComponent', () => {
let component: EllipseComponent;
let fixture: ComponentFixture<EllipseComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
beforeEach(async() => {
await TestBed.configureTestingModule({
declarations: [EllipseComponent],
providers:[QtDasharrayFixer]
}).compileComponents();
}));
});
beforeEach(() => {
fixture = TestBed.createComponent(EllipseComponent);
@ -17,7 +19,7 @@ describe('EllipseComponent', () => {
fixture.detectChanges();
});
// it('should create', () => {
// expect(component).toBeTruthy();
// });
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -15,21 +15,21 @@ export class EllipseComponent implements OnInit {
ngOnInit() {}
get fill_opacity() {
if (isFinite(this.ellipse.fill_opacity)) {
if (this.ellipse && isFinite(this.ellipse.fill_opacity)) {
return this.ellipse.fill_opacity;
}
return null;
}
get stroke_width() {
if (isFinite(this.ellipse.stroke_width)) {
if (this.ellipse && isFinite(this.ellipse.stroke_width)) {
return this.ellipse.stroke_width;
}
return null;
}
get stroke_dasharray() {
if (this.ellipse.stroke_dasharray) {
if (this.ellipse && this.ellipse.stroke_dasharray) {
return this.qtDasharrayFixer.fix(this.ellipse.stroke_dasharray);
}
return null;

View File

@ -1,6 +1,6 @@
<svg:image
class="image_element noselect"
[attr.xlink:href]="image.data"
[attr.width]="image.width"
[attr.height]="image.height"
[attr.xlink:href]="image?.data"
[attr.width]="image?.width"
[attr.height]="image?.height"
/>

Before

Width:  |  Height:  |  Size: 140 B

After

Width:  |  Height:  |  Size: 143 B

View File

@ -1,15 +1,15 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { ImageComponent } from './image.component';
describe('ImageComponent', () => {
let component: ImageComponent;
let fixture: ComponentFixture<ImageComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ImageComponent],
}).compileComponents();
}));
});
beforeEach(() => {
fixture = TestBed.createComponent(ImageComponent);
@ -17,7 +17,7 @@ describe('ImageComponent', () => {
fixture.detectChanges();
});
// it('should create', () => {
// expect(component).toBeTruthy();
// });
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -8,6 +8,7 @@ import { ImageElement } from '../../../../../models/drawings/image-element';
})
export class ImageComponent implements OnInit {
@Input('app-image') image: ImageElement;
data:any
constructor() {}

View File

@ -1,10 +1,10 @@
<svg:line
class="line_element noselect"
[attr.stroke]="line.stroke"
[attr.stroke-width]="stroke_width"
[attr.stroke]="line?.stroke"
[attr.stroke-width]="stroke_width ?? ''"
[attr.stroke-dasharray]="stroke_dasharray"
[attr.x1]="line.x1"
[attr.x2]="line.x2"
[attr.y1]="line.y1"
[attr.y2]="line.y2"
[attr.x1]="line?.x1"
[attr.x2]="line?.x2"
[attr.y1]="line?.y1"
[attr.y2]="line?.y2"
/>

Before

Width:  |  Height:  |  Size: 245 B

After

Width:  |  Height:  |  Size: 256 B

View File

@ -1,15 +1,17 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import {ComponentFixture, TestBed } from '@angular/core/testing';
import { QtDasharrayFixer } from 'app/cartography/helpers/qt-dasharray-fixer';
import { LineComponent } from './line.component';
describe('LineComponent', () => {
let component: LineComponent;
let fixture: ComponentFixture<LineComponent>;
beforeEach(async(() => {
beforeEach(async() => {
TestBed.configureTestingModule({
declarations: [LineComponent],
providers:[QtDasharrayFixer]
}).compileComponents();
}));
});
beforeEach(() => {
fixture = TestBed.createComponent(LineComponent);
@ -17,7 +19,7 @@ describe('LineComponent', () => {
fixture.detectChanges();
});
// it('should create', () => {
// expect(component).toBeTruthy();
// });
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -15,14 +15,14 @@ export class LineComponent implements OnInit {
ngOnInit() {}
get stroke_width() {
if (isFinite(this.line.stroke_width)) {
if (this.line && isFinite(this.line.stroke_width)) {
return this.line.stroke_width;
}
return null;
}
get stroke_dasharray() {
if (this.line.stroke_dasharray) {
if ( this.line && this.line.stroke_dasharray) {
return this.qtDasharrayFixer.fix(this.line.stroke_dasharray);
}
return null;

View File

@ -1,12 +1,12 @@
<svg:rect
class="rect_element noselect"
[attr.fill]="rect.fill"
[attr.fill-opacity]="fill_opacity"
[attr.stroke]="rect.stroke"
[attr.fill]="rect?.fill"
[attr.fill-opacity]="fill_opacity ? fill_opacity : '' "
[attr.stroke]="rect?.stroke"
[attr.stroke-width]="stroke_width"
[attr.stroke-dasharray]="stroke_dasharray"
[attr.width]="rect.width"
[attr.height]="rect.height"
[attr.rx]="rect.rx"
[attr.ry]="rect.ry"
[attr.width]="rect?.width"
[attr.height]="rect?.height"
[attr.rx]="rect?.rx"
[attr.ry]="rect?.ry"
/>

Before

Width:  |  Height:  |  Size: 322 B

After

Width:  |  Height:  |  Size: 349 B

View File

@ -1,15 +1,17 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import {ComponentFixture, TestBed } from '@angular/core/testing';
import { QtDasharrayFixer } from 'app/cartography/helpers/qt-dasharray-fixer';
import { RectComponent } from './rect.component';
describe('RectComponent', () => {
let component: RectComponent;
let fixture: ComponentFixture<RectComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [RectComponent],
providers:[QtDasharrayFixer]
}).compileComponents();
}));
});
beforeEach(() => {
fixture = TestBed.createComponent(RectComponent);
@ -17,7 +19,7 @@ describe('RectComponent', () => {
fixture.detectChanges();
});
// it('should create', () => {
// expect(component).toBeTruthy();
// });
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -15,21 +15,21 @@ export class RectComponent implements OnInit {
ngOnInit() {}
get fill_opacity() {
if (isFinite(this.rect.fill_opacity)) {
return this.rect.fill_opacity;
if (this.rect && isFinite(this.rect.fill_opacity)) {
return this.rect.fill_opacity ? this.rect.fill_opacity : null;
}
return null;
}
get stroke_width() {
if (isFinite(this.rect.stroke_width)) {
return this.rect.stroke_width;
if (this.rect && isFinite(this.rect.stroke_width)) {
return this.rect.stroke_width ? this.rect.stroke_width : null;
}
return null;
}
get stroke_dasharray() {
if (this.rect.stroke_dasharray) {
if (this.rect && this.rect.stroke_dasharray) {
return this.qtDasharrayFixer.fix(this.rect.stroke_dasharray);
}
return null;

View File

@ -3,7 +3,7 @@
class="text_element noselect"
[attr.style]="style"
[attr.text-decoration]="textDecoration"
[attr.fill]="text.fill"
[attr.fill]="text?.fill"
[attr.transform]="transformation"
>
<svg:tspan *ngFor="let line of lines; index as i" xml:space="preserve" x="0" [attr.dy]="i == 0 ? '0em' : '1.4em'">

Before

Width:  |  Height:  |  Size: 338 B

After

Width:  |  Height:  |  Size: 339 B

View File

@ -1,15 +1,17 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { FontFixer } from 'app/cartography/helpers/font-fixer';
import { TextComponent } from './text.component';
describe('TextComponent', () => {
let component: TextComponent;
let fixture: ComponentFixture<TextComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
beforeEach(async() => {
await TestBed.configureTestingModule({
declarations: [TextComponent],
providers:[FontFixer]
}).compileComponents();
}));
});
beforeEach(() => {
fixture = TestBed.createComponent(TextComponent);
@ -17,7 +19,7 @@ describe('TextComponent', () => {
fixture.detectChanges();
});
// it('should create', () => {
// expect(component).toBeTruthy();
// });
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -19,10 +19,12 @@ export class TextComponent implements OnInit, DoCheck {
transformation = '';
constructor(private fontFixer: FontFixer, private sanitizer: DomSanitizer) {}
constructor(private fontFixer: FontFixer, private sanitizer: DomSanitizer) { }
ngOnInit() {
this.lines = this.getLines(this.text.text);
if (this.text) {
this.lines = this.getLines(this.text.text);
}
}
ngDoCheck() {
@ -30,32 +32,38 @@ export class TextComponent implements OnInit, DoCheck {
}
get style() {
const font = this.fontFixer.fix(this.text);
if (this.text) {
const font = this.fontFixer.fix(this.text);
const styles: string[] = [];
if (font.font_family) {
styles.push(`font-family: "${this.text.font_family}"`);
const styles: string[] = [];
if (font.font_family) {
styles.push(`font-family: "${this.text.font_family}"`);
}
if (font.font_size) {
styles.push(`font-size: ${this.text.font_size}pt`);
}
if (font.font_weight) {
styles.push(`font-weight: ${this.text.font_weight}`);
}
return this.sanitizer.bypassSecurityTrustStyle(styles.join('; '));
}
if (font.font_size) {
styles.push(`font-size: ${this.text.font_size}pt`);
}
if (font.font_weight) {
styles.push(`font-weight: ${this.text.font_weight}`);
}
return this.sanitizer.bypassSecurityTrustStyle(styles.join('; '));
}
get textDecoration() {
return this.text.text_decoration;
if (this.text) {
return this.text.text_decoration;
}
}
calculateTransformation() {
const tspans = this.textRef.nativeElement.getElementsByTagName('tspan');
if (tspans.length > 0) {
const height = this.textRef.nativeElement.getBBox().height / tspans.length;
return `translate(${TextComponent.MARGIN}, ${height - TextComponent.MARGIN})`;
if (this.textRef != undefined) {
const tspans = this.textRef.nativeElement.getElementsByTagName('tspan');
if (tspans.length > 0) {
const height = this.textRef.nativeElement.getBBox().height / tspans.length;
return `translate(${TextComponent.MARGIN}, ${height - TextComponent.MARGIN})`;
}
return '';
}
return '';
}
getLines(text: string) {

View File

@ -1,15 +1,28 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ChangeDetectorRef, ElementRef, Injectable } from '@angular/core';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { CssFixer } from 'app/cartography/helpers/css-fixer';
import { InterfaceLabelComponent } from './interface-label.component';
describe('InterfaceLabelComponent', () => {
export class MockElementRef extends ElementRef {
constructor() { super(null || undefined); }
nativeElement={}
}
xdescribe('InterfaceLabelComponent', () => {
let component: InterfaceLabelComponent;
let fixture: ComponentFixture<InterfaceLabelComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [InterfaceLabelComponent],
providers: [
CssFixer,
ChangeDetectorRef,
{ provide: ElementRef, useValue: new MockElementRef() },
]
}).compileComponents();
}));
});
beforeEach(() => {
fixture = TestBed.createComponent(InterfaceLabelComponent);
@ -17,7 +30,7 @@ describe('InterfaceLabelComponent', () => {
fixture.detectChanges();
});
// it('should create', () => {
// expect(component).toBeTruthy();
// });
it('should create', () => {
expect(component).toBeTruthy()
});
});

View File

@ -30,9 +30,9 @@ export class InterfaceLabelComponent implements OnInit {
private ref: ChangeDetectorRef,
private sanitizer: DomSanitizer,
private cssFixer: CssFixer
) {}
) { }
ngOnInit() {}
ngOnInit() { }
@Input('x')
set x(value) {
@ -89,9 +89,11 @@ export class InterfaceLabelComponent implements OnInit {
}
get transform() {
const bbox = this.elementRef.nativeElement.getBBox();
const x = this.label.x;
const y = this.label.y + bbox.height;
return `translate(${x}, ${y}) rotate(${this.label.rotation}, ${x}, ${y})`;
if (this.elementRef.nativeElement.getBBox) {
const bbox = this.elementRef.nativeElement.getBBox()
const x = this.label.x;
const y = this.label.y + bbox.height;
return `translate(${x}, ${y}) rotate(${this.label.rotation}, ${x}, ${y})`;
}
}
}

View File

@ -1,13 +1,13 @@
<svg:g
class="link"
[attr.link_id]="link.id"
[attr.map-source]="link.source.id"
[attr.map-target]="link.target.id"
[attr.link_id]="link?.id"
[attr.map-source]="link?.source?.id"
[attr.map-target]="link?.target?.id"
[attr.transform]="transform"
>
<svg:path
#path
*ngIf="link.linkType == 'ethernet'"
*ngIf="link?.linkType == 'ethernet'"
class="ethernet_link"
stroke="#000"
stroke-width="2"
@ -16,7 +16,7 @@
<svg:path
#path
*ngIf="link.linkType == 'serial'"
*ngIf="link?.linkType == 'serial'"
class="serial_link"
stroke="#B22222"
fill="none"
@ -24,27 +24,27 @@
[attr.d]="d"
/>
<svg:g [app-status]="link.source.status" [direction]="'source'" [path]="path" [d]="d" />
<svg:g [app-status]="link?.source?.status" [direction]="'source'" [path]="path" [d]="d" />
<svg:g [app-status]="link.target.status" [direction]="'target'" [path]="path" [d]="d" />
<svg:g [app-status]="link?.target?.status" [direction]="'target'" [path]="path" [d]="d" />
<svg:g
*ngIf="showInterfaceLabels"
[app-interface-label]
[x]="link.source.x + link.nodes[0].label.x"
[y]="link.source.y + link.nodes[0].label.y"
[text]="link.nodes[0].label.text"
[style]="link.nodes[0].label.style"
[rotation]="link.nodes[0].label.rotation"
[x]="link?.source?.x + link?.nodes[0]?.label?.x"
[y]="link?.source?.y + link?.nodes[0]?.label?.y"
[text]="link?.nodes[0]?.label?.text"
[style]="link?.nodes[0]?.label?.style"
[rotation]="link?.nodes[0]?.label?.rotation"
/>
<svg:g
*ngIf="showInterfaceLabels"
[app-interface-label]
[x]="link.target.x + link.nodes[1].label.x"
[y]="link.target.y + link.nodes[1].label.y"
[text]="link.nodes[1].label.text"
[style]="link.nodes[1].label.style"
[rotation]="link.nodes[1].label.rotation"
[x]="link?.target?.x + link?.nodes[1]?.label?.x"
[y]="link?.target?.y + link?.nodes[1]?.label?.y"
[text]="link?.nodes[1]?.label?.text"
[style]="link?.nodes[1]?.label?.style"
[rotation]="link?.nodes[1]?.label?.rotation"
/>
</svg:g>

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@ -1,15 +1,18 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { MultiLinkCalculatorHelper } from 'app/cartography/helpers/multi-link-calculator-helper';
import { LinkComponent } from './link.component';
describe('LinkComponent', () => {
let component: LinkComponent;
let fixture: ComponentFixture<LinkComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [LinkComponent],
providers: [
{ provide: MultiLinkCalculatorHelper, useValue: {} }
]
}).compileComponents();
}));
});
beforeEach(() => {
fixture = TestBed.createComponent(LinkComponent);
@ -17,7 +20,7 @@ describe('LinkComponent', () => {
fixture.detectChanges();
});
// it('should create', () => {
// expect(component).toBeTruthy();
// });
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -33,7 +33,7 @@ export class LinkComponent implements OnInit, OnDestroy {
private nodeChangedSubscription: Subscription;
constructor(private multiLinkCalculatorHelper: MultiLinkCalculatorHelper, private ref: ChangeDetectorRef) {}
constructor(private multiLinkCalculatorHelper: MultiLinkCalculatorHelper, private ref: ChangeDetectorRef) { }
ngOnInit() {
this.ref.detectChanges();
@ -49,19 +49,21 @@ export class LinkComponent implements OnInit, OnDestroy {
}
get strategy(): LinkStrategy {
if (this.link.linkType === 'serial') {
if (this.link && this.link != undefined && this.link.linkType === 'serial') {
return this.serialLinkStrategy;
}
return this.ethernetLinkStrategy;
}
get transform() {
const translation = this.multiLinkCalculatorHelper.linkTranslation(
this.link.distance,
this.link.source,
this.link.target
);
return `translate (${translation.dx}, ${translation.dy})`;
if (this.link) {
const translation = this.multiLinkCalculatorHelper.linkTranslation(
this.link.distance,
this.link.source,
this.link.target
);
return `translate (${translation.dx}, ${translation.dy})`;
}
}
get d() {

View File

@ -5,8 +5,9 @@ import { LinkStrategy } from './link-strategy';
export class EthernetLinkStrategy implements LinkStrategy {
public d(link: MapLink): string {
const points = [
[link.source.x + link.source.width / 2, link.source.y + link.source.height / 2],
[link.target.x + link.target.width / 2, link.target.y + link.target.height / 2],
[link?.source?.x + link?.source?.width / 2, link?.source.y + link?.source?.height / 2],
[link?.target?.x + link?.target?.width / 2, link?.target?.y + link?.target?.height / 2],
];
const line_generator = path();

View File

@ -1,8 +1,8 @@
<svg:g class="node" [attr.transform]="'translate(' + node.x + ',' + node.y + ')'">
<svg:g class="node" [attr.transform]="'translate(' + node?.x + ',' + node?.y + ')'">
<svg:image
#image
[attr.width]="node.width"
[attr.height]="node.height"
[attr.width]="node?.width"
[attr.height]="node?.height"
[attr.x]="0"
[attr.y]="0"
[attr.xlink:href]="symbol"
@ -11,6 +11,6 @@
(dragged)="OnDragged($event)"
/>
<svg:text #label class="label" [attr.style]="label_style" [attr.x]="label_x" [attr.y]="label_y">
{{ node.label.text }}
{{ node?.label?.text }}
</svg:text>
</svg:g>

Before

Width:  |  Height:  |  Size: 484 B

After

Width:  |  Height:  |  Size: 490 B

View File

@ -1,15 +1,23 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { NodesEventSource } from 'app/cartography/events/nodes-event-source';
import { CssFixer } from 'app/cartography/helpers/css-fixer';
import { FontFixer } from 'app/cartography/helpers/font-fixer';
import { NodeComponent } from './node.component';
describe('NodeComponent', () => {
let component: NodeComponent;
let fixture: ComponentFixture<NodeComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
beforeEach(async() => {
await TestBed.configureTestingModule({
declarations: [NodeComponent],
providers:[
CssFixer,
FontFixer,
NodesEventSource,
]
}).compileComponents();
}));
});
beforeEach(() => {
fixture = TestBed.createComponent(NodeComponent);
@ -17,7 +25,7 @@ describe('NodeComponent', () => {
fixture.detectChanges();
});
// it('should create', () => {
// expect(component).toBeTruthy();
// });
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -49,7 +49,7 @@ export class NodeComponent implements OnInit, OnDestroy, OnChanges, AfterViewIni
protected element: ElementRef,
private cd: ChangeDetectorRef,
private nodesEventSource: NodesEventSource
) {}
) { }
ngOnInit() {
// this.nodeChangedSubscription = this.nodeChanged.subscribe((node: Node) => {
@ -85,42 +85,52 @@ export class NodeComponent implements OnInit, OnDestroy, OnChanges, AfterViewIni
}
get symbol(): string {
const symbol = this.symbols.find((s: Symbol) => s.symbol_id === this.node.symbol);
if (symbol) {
return 'data:image/svg+xml;base64,' + btoa(symbol.raw);
if (this.symbols) {
const symbol = this.symbols.find((s: Symbol) => s.symbol_id === this.node.symbol);
if (symbol) {
return 'data:image/svg+xml;base64,' + btoa(symbol.raw);
}
// @todo; we need to have default image
return 'data:image/svg+xml;base64,none';
}
// @todo; we need to have default image
return 'data:image/svg+xml;base64,none';
}
get label_style() {
let styles = this.cssFixer.fix(this.node.label.style);
styles = this.fontFixer.fixStyles(styles);
return this.sanitizer.bypassSecurityTrustStyle(styles);
if (this.node != undefined) {
let styles = this.cssFixer.fix(this.node.label.style);
styles = this.fontFixer.fixStyles(styles);
return this.sanitizer.bypassSecurityTrustStyle(styles);
}
}
get label_x(): number {
if (this.node.label.x === null) {
// center
const bbox = this.label.nativeElement.getBBox();
if (this.node != undefined) {
if (this.node.label.x === null) {
// center
const bbox = this.label.nativeElement.getBBox();
return -bbox.width / 2;
return -bbox.width / 2;
}
return this.node.label.x + NodeComponent.NODE_LABEL_MARGIN;
}
return this.node.label.x + NodeComponent.NODE_LABEL_MARGIN;
}
get label_y(): number {
this.labelHeight = this.getLabelHeight();
if (this.node.label.x === null) {
// center
return -this.node.height / 2 - this.labelHeight;
if (this.node != undefined) {
if (this.node.label.x === null) {
// center
return -this.node.height / 2 - this.labelHeight;
}
return this.node.label.y + this.labelHeight - NodeComponent.NODE_LABEL_MARGIN;
}
return this.node.label.y + this.labelHeight - NodeComponent.NODE_LABEL_MARGIN;
}
private getLabelHeight() {
const bbox = this.label.nativeElement.getBBox();
return bbox.height;
if (this.label != undefined) {
const bbox = this.label.nativeElement.getBBox();
return bbox.height;
}
}
}

View File

@ -1,23 +1,24 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { SelectionComponent } from './selection.component';
describe('SelectionComponent', () => {
let component: SelectionComponent;
let fixture: ComponentFixture<SelectionComponent>;
beforeEach(async(() => {
beforeEach(() => {
TestBed.configureTestingModule({
declarations: [SelectionComponent],
}).compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(SelectionComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
afterEach(() => {
fixture.destroy()
})
// it('should create', () => {
// expect(component).toBeTruthy();
// });
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -1,5 +1,5 @@
import { AfterViewInit, ChangeDetectorRef, Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
import { Observable, Subscription } from 'rxjs';
import { Observable, Subscription} from 'rxjs';
import { Rectangle } from '../../../models/rectangle';
@Component({
@ -28,15 +28,14 @@ export class SelectionComponent implements OnInit, AfterViewInit {
ngAfterViewInit() {
const down = Observable.fromEvent(this.svg, 'mousedown').do((e: MouseEvent) => e.preventDefault());
down.subscribe((e: MouseEvent) => {
if (e.target !== this.svg) {
return;
}
this.started = true;
this.startX = e.clientX + window.scrollX;
this.startY = e.clientY + window.scrollY;
this.startX = e?.clientX + window?.scrollX;
this.startY = e?.clientY + window?.scrollY;
this.width = 0;
this.height = 0;
this.visible = true;
@ -51,7 +50,7 @@ export class SelectionComponent implements OnInit, AfterViewInit {
const scrollWindow = Observable.fromEvent(document, 'scroll').startWith({});
const move = Observable.combineLatest(mouseMove, scrollWindow);
const move = Observable.combineLatest([mouseMove, scrollWindow]);
const drag = down.mergeMap((md: MouseEvent) => {
return move
@ -76,11 +75,11 @@ export class SelectionComponent implements OnInit, AfterViewInit {
this.visible = false;
this.started = false;
this.width = e.clientX - this.startX + window.scrollX;
this.height = e.clientY - this.startY + window.scrollY;
this.ref.detectChanges();
this.selectedEvent([this.startX, this.startY], [this.width, this.height]);
})
)

View File

@ -1,15 +1,15 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { StatusComponent } from './status.component';
describe('StatusComponent', () => {
let component: StatusComponent;
let fixture: ComponentFixture<StatusComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
beforeEach(async() => {
await TestBed.configureTestingModule({
declarations: [StatusComponent],
}).compileComponents();
}));
});
beforeEach(() => {
fixture = TestBed.createComponent(StatusComponent);

View File

@ -0,0 +1,31 @@
import { Component, Input, OnDestroy, OnInit } from '@angular/core';
import { select } from 'd3-selection';
import { Subscription } from 'rxjs';
import { LinksEventSource } from '../../events/links-event-source';
import { MapLink } from '../../models/map/map-link';
import { LinksWidget } from '../../widgets/links';
@Component({
selector: 'app-link-editing',
templateUrl: './link-editing.component.html',
styleUrls: ['./link-editing.component.scss'],
})
export class LinkEditingComponent implements OnInit, OnDestroy {
private linkEditedSubscription: Subscription;
@Input('svg') svg: SVGSVGElement;
constructor(
private linksWidget: LinksWidget,
private linksEventSource: LinksEventSource ) {}
ngOnInit() {
const svg = select(this.svg);
this.linkEditedSubscription = this.linksEventSource.edited.subscribe((link: MapLink) => {
this.linksWidget.redrawLink(svg, link);
});
}
ngOnDestroy() {
this.linkEditedSubscription.unsubscribe();
}
}

View File

@ -1,15 +1,18 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { SelectionManager } from 'app/cartography/managers/selection-manager';
import { MapChangeDetectorRef } from 'app/cartography/services/map-change-detector-ref';
import { SelectionSelectComponent } from './selection-select.component';
describe('SelectionSelectComponent', () => {
let component: SelectionSelectComponent;
let fixture: ComponentFixture<SelectionSelectComponent>;
beforeEach(async(() => {
beforeEach(async () => {
TestBed.configureTestingModule({
declarations: [SelectionSelectComponent],
providers: [MapChangeDetectorRef,SelectionManager]
}).compileComponents();
}));
});
beforeEach(() => {
fixture = TestBed.createComponent(SelectionSelectComponent);
@ -17,7 +20,7 @@ describe('SelectionSelectComponent', () => {
fixture.detectChanges();
});
// it('should create', () => {
// expect(component).toBeTruthy();
// });
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -1,5 +1,5 @@
import { Renderer2 } from '@angular/core';
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
import { MockedLinkService } from '../../../components/project-map/project-map.component.spec';
import { LinkService } from '../../../services/link.service';
@ -18,7 +18,7 @@ describe('TextEditorComponent', () => {
let fixture: ComponentFixture<TextEditorComponent>;
let mockedLinkService: MockedLinkService = new MockedLinkService();
beforeEach(async(() => {
beforeEach(async() => {
TestBed.configureTestingModule({
imports: [NoopAnimationsModule],
providers: [
@ -35,7 +35,7 @@ describe('TextEditorComponent', () => {
],
declarations: [TextEditorComponent],
}).compileComponents();
}));
});
beforeEach(() => {
fixture = TestBed.createComponent(TextEditorComponent);

View File

@ -13,7 +13,7 @@ import { select } from 'd3-selection';
import { Subscription } from 'rxjs';
import { StyleProperty } from '../../../components/project-map/drawings-editors/text-editor/text-editor.component';
import { Link } from '../../../models/link';
import { Server } from '../../../models/server';
import { Controller } from '../../../models/controller';
import { LinkService } from '../../../services/link.service';
import { MapScaleService } from '../../../services/mapScale.service';
import { ToolsService } from '../../../services/tools.service';
@ -37,7 +37,7 @@ import { Node } from '../../models/node';
export class TextEditorComponent implements OnInit, OnDestroy {
@ViewChild('temporaryTextElement') temporaryTextElement: ElementRef;
@Input('svg') svg: SVGSVGElement;
@Input('server') server: Server;
@Input('controller') controller: Controller;
leftPosition: string = '0px';
topPosition: string = '0px';
@ -185,7 +185,7 @@ export class TextEditorComponent implements OnInit, OnDestroy {
let link: Link = this.linksDataSource.get(this.editedLink.linkId);
link.nodes.find((n) => n.node_id === this.editedNode.node_id).label.text = innerText;
this.linkService.updateLink(this.server, link).subscribe((link: Link) => {
this.linkService.updateLink(this.controller, link).subscribe((link: Link) => {
rootElement
.selectAll<SVGTextElement, TextElement>('text.editingMode')
.attr('visibility', 'visible')

View File

@ -15,6 +15,7 @@ export class LinkToMapLinkConverter implements Converter<Link, MapLink> {
mapLink.captureFilePath = link.capture_file_path;
mapLink.capturing = link.capturing;
mapLink.filters = link.filters;
mapLink.link_style = link.link_style;
mapLink.linkType = link.link_type;
mapLink.nodes = link.nodes.map((linkNode) =>
this.linkNodeToMapLinkNode.convert(linkNode, { link_id: link.link_id })

View File

@ -14,11 +14,11 @@ export class MapDrawingToSvgConverter implements Converter<MapDrawing, string> {
let elem = ``;
if (mapDrawing.element instanceof RectElement) {
elem = `<rect fill=\"${mapDrawing.element.fill}\" fill-opacity=\"${mapDrawing.element.fill_opacity}\" height=\"${mapDrawing.element.height}\" width=\"${mapDrawing.element.width}\" stroke=\"${mapDrawing.element.stroke}\" stroke-width=\"${mapDrawing.element.stroke_width}\" rx=\"${mapDrawing.element.rx}\" ry=\"${mapDrawing.element.ry}\" />`;
elem = `${mapDrawing.element.stroke_dasharray == '' ? `<rect fill=\"${mapDrawing.element.fill}\" fill-opacity=\"${mapDrawing.element.fill_opacity}\" height=\"${mapDrawing.element.height}\" width=\"${mapDrawing.element.width}\" rx=\"${mapDrawing.element.rx}\" ry=\"${mapDrawing.element.ry}\" />` :`<rect fill=\"${mapDrawing.element.fill}\" fill-opacity=\"${mapDrawing.element.fill_opacity}\" height=\"${mapDrawing.element.height}\" width=\"${mapDrawing.element.width}\" stroke=\"${mapDrawing.element.stroke}\" stroke-width=\"${mapDrawing.element.stroke_width}\" stroke-dasharray=\"${mapDrawing.element.stroke_dasharray}\" rx=\"${mapDrawing.element.rx}\" ry=\"${mapDrawing.element.ry}\" />`}`;
} else if (mapDrawing.element instanceof EllipseElement) {
elem = `<ellipse fill=\"${mapDrawing.element.fill}\" fill-opacity=\"${mapDrawing.element.fill_opacity}\" cx=\"${mapDrawing.element.cx}\" cy=\"${mapDrawing.element.cy}\" rx=\"${mapDrawing.element.rx}\" ry=\"${mapDrawing.element.ry}\" stroke=\"${mapDrawing.element.stroke}\" stroke-width=\"${mapDrawing.element.stroke_width}\" />`;
elem = `${mapDrawing.element.stroke_dasharray == '' ? `<ellipse fill=\"${mapDrawing.element.fill}\" fill-opacity=\"${mapDrawing.element.fill_opacity}\" cx=\"${mapDrawing.element.cx}\" cy=\"${mapDrawing.element.cy}\" rx=\"${mapDrawing.element.rx}\" ry=\"${mapDrawing.element.ry}\"/>` :`<ellipse fill=\"${mapDrawing.element.fill}\" fill-opacity=\"${mapDrawing.element.fill_opacity}\" cx=\"${mapDrawing.element.cx}\" cy=\"${mapDrawing.element.cy}\" rx=\"${mapDrawing.element.rx}\" ry=\"${mapDrawing.element.ry}\" stroke=\"${mapDrawing.element.stroke}\" stroke-width=\"${mapDrawing.element.stroke_width}\" stroke-dasharray=\"${mapDrawing.element.stroke_dasharray}\" />`}`;
} else if (mapDrawing.element instanceof LineElement) {
elem = `<line stroke=\"${mapDrawing.element.stroke}\" stroke-width=\"${mapDrawing.element.stroke_width}\" x1=\"${mapDrawing.element.x1}\" x2=\"${mapDrawing.element.x2}\" y1=\"${mapDrawing.element.y1}\" y2=\"${mapDrawing.element.y2}\" />`;
elem = `<line stroke=\"${mapDrawing.element.stroke}\" stroke-width=\"${mapDrawing.element.stroke_width}\" x1=\"${mapDrawing.element.x1}\" x2=\"${mapDrawing.element.x2}\" y1=\"${mapDrawing.element.y1}\" y2=\"${mapDrawing.element.y2}\" stroke-dasharray=\"${mapDrawing.element.stroke_dasharray ?? 'none'}\" />`;
} else if (mapDrawing.element instanceof TextElement) {
elem = `<text fill=\"${mapDrawing.element.fill}\" fill-opacity=\"1.0\" font-family=\"${mapDrawing.element.font_family}\" font-size=\"${mapDrawing.element.font_size}\" font-weight=\"${mapDrawing.element.font_weight}\">${mapDrawing.element.text}</text>`;
} else return '';

View File

@ -16,6 +16,7 @@ export class MapLinkToLinkConverter implements Converter<MapLink, Link> {
link.capturing = mapLink.capturing;
link.filters = mapLink.filters;
link.link_type = mapLink.linkType;
link.link_style = mapLink.link_style;
link.nodes = mapLink.nodes.map((mapLinkNode) => this.mapLinkNodeToMapLinkNode.convert(mapLinkNode));
link.project_id = mapLink.projectId;
link.suspend = mapLink.suspend;

View File

@ -1,5 +1,5 @@
import { Component } from '@angular/core';
import { async, ComponentFixture, fakeAsync, TestBed, tick } from '@angular/core/testing';
import { ComponentFixture, fakeAsync, TestBed, tick } from '@angular/core/testing';
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
import { MovingEventSource } from '../events/moving-event-source';
import { Context } from '../models/context';
@ -19,8 +19,8 @@ describe('MovingCanvasDirective', () => {
let fixture: ComponentFixture<DummyComponent>;
let movingEventSource = new MovingEventSource();
beforeEach(async(() => {
TestBed.configureTestingModule({
beforeEach(async() => {
await TestBed.configureTestingModule({
imports: [NoopAnimationsModule],
providers: [
{ provide: MovingEventSource, useValue: movingEventSource },
@ -28,7 +28,7 @@ describe('MovingCanvasDirective', () => {
],
declarations: [DummyComponent, MovingCanvasDirective],
}).compileComponents();
}));
});
beforeEach(() => {
fixture = TestBed.createComponent(DummyComponent);

View File

@ -1,5 +1,5 @@
import { Component } from '@angular/core';
import { async, ComponentFixture, fakeAsync, TestBed, tick } from '@angular/core/testing';
import { ComponentFixture, fakeAsync, TestBed, tick } from '@angular/core/testing';
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
import { MapScaleService } from '../../services/mapScale.service';
import { MovingEventSource } from '../events/moving-event-source';
@ -20,8 +20,8 @@ describe('ZoomingCanvasDirective', () => {
let fixture: ComponentFixture<DummyComponent>;
let movingEventSource = new MovingEventSource();
beforeEach(async(() => {
TestBed.configureTestingModule({
beforeEach(async() => {
await TestBed.configureTestingModule({
imports: [NoopAnimationsModule],
providers: [
{ provide: MovingEventSource, useValue: movingEventSource },
@ -30,7 +30,7 @@ describe('ZoomingCanvasDirective', () => {
],
declarations: [DummyComponent, ZoomingCanvasDirective],
}).compileComponents();
}));
});
beforeEach(() => {
fixture = TestBed.createComponent(DummyComponent);

View File

@ -1,4 +1,5 @@
import { EventEmitter, Injectable } from '@angular/core';
import { MapLink } from '../models/map/map-link';
import { MapLinkNode } from '../models/map/map-link-node';
import { DraggedDataEvent } from './event-source';
import { MapLinkCreated } from './links';
@ -6,5 +7,6 @@ import { MapLinkCreated } from './links';
@Injectable()
export class LinksEventSource {
public created = new EventEmitter<MapLinkCreated>();
public edited = new EventEmitter<MapLink>();
public interfaceDragged = new EventEmitter<DraggedDataEvent<MapLinkNode>>();
}

View File

@ -8,43 +8,47 @@ describe('FontFixer', () => {
fixer = new FontFixer();
});
it('should fix TypeWriter font and 10px size', () => {
it("should fix TypeWriter font and 10px size", () => {
const font: Font = {
font_family: 'TypeWriter',
font_family: "TypeWriter",
font_size: 10,
font_weight: 'bold',
font_weight: "bold",
};
expect(fixer.fix(font)).toEqual({
font_family: 'Arial',
font_size: 12,
font_weight: 'bold',
font_family: "Noto Sans",
font_size: 11,
font_weight: "bold",
});
});
it('should not fix other fonts', () => {
it("should not fix other fonts", () => {
const font: Font = {
font_family: 'OtherFont',
font_family: "OtherFont",
font_size: 11,
font_weight: 'bold',
font_weight: "bold",
};
expect(fixer.fix(font)).toEqual({
font_family: 'OtherFont',
font_family: "OtherFont",
font_size: 11,
font_weight: 'bold',
font_weight: "bold",
});
});
it('should fix TypeWriter font and 10px size in styles', () => {
const styles = 'font-family: TypeWriter; font-size: 10px; font-weight: bold';
let typeWriter = "TypeWriter";
let notoSans = "Noto Sans";
const styles = `font-family:${typeWriter} ; font-size: 10px; font-weight: bold`;
expect(fixer.fixStyles(styles)).toEqual('font-family:Arial;font-size:12px;font-weight:bold');
expect(fixer.fixStyles(styles)).toEqual(`font-family:${notoSans};font-size:11px;font-weight:bold`);
});
it('should fix TypeWriter font and 10px size in styles with quotes', () => {
const styles = 'font-family: "TypeWriter"; font-size: 10px; font-weight: bold';
it("should fix TypeWriter font and 10px size in styles with quotes", () => {
let typeWriter = "TypeWriter";
let notoSans = "Noto Sans";
const styles = `font-family:${typeWriter}; font-size: 10px; font-weight: bold`;
expect(fixer.fixStyles(styles)).toEqual('font-family:Arial;font-size:12px;font-weight:bold');
expect(fixer.fixStyles(styles)).toEqual(`font-family:${notoSans};font-size:11px;font-weight:bold`);
});
});

View File

@ -9,8 +9,8 @@ import { Font } from '../models/font';
export class FontFixer {
static DEFAULT_FONT = 'TypeWriter';
static DEFAULT_SIZE = 10;
static REPLACE_BY_FONT = 'Arial';
static REPLACE_BY_SIZE = 12;
static REPLACE_BY_FONT = 'Noto Sans';
static REPLACE_BY_SIZE = 11;
public fix(font: Font): Font {
if (font.font_family === FontFixer.DEFAULT_FONT && font.font_size === FontFixer.DEFAULT_SIZE) {

View File

@ -7,16 +7,18 @@ import { Injectable } from '@angular/core';
@Injectable()
export class QtDasharrayFixer {
static MAPPING = {
'25, 25': '10, 2',
'5, 25': '4, 2',
'5, 25, 25': '5, 5, 1, 5',
'25, 25, 5, 25, 5': '5, 2, 5, 2, 5',
'25, 25': '10, 2', // Dash
'5, 25': '4, 2', // Dot
'5, 25, 25': '12, 3, 5, 3', // Dash Dot
'25, 25, 5, 25, 5': '12, 3, 5, 3, 5, 3', // Dash Dot Dot
};
public fix(dasharray: string): string {
if(dasharray || dasharray == '' ){
if (dasharray in QtDasharrayFixer.MAPPING) {
return QtDasharrayFixer.MAPPING[dasharray];
}
return dasharray;
}
}
}

View File

@ -45,6 +45,7 @@ export class GraphDataManager {
public setLinks(links: Link[]) {
if (links) {
console.log("from set links");
const mapLinks = links.map((l) => this.linkToMapLink.convert(l));
this.mapLinksDataSource.set(mapLinks);
@ -88,6 +89,7 @@ export class GraphDataManager {
private onDataUpdate() {
this.layersManager.clear();
this.layersManager.setNodes(this.getNodes());
console.log(this.getLinks());
this.layersManager.setLinks(this.getLinks());
this.layersManager.setDrawings(this.getDrawings());
}

View File

@ -38,6 +38,7 @@ export class LayersManager {
}
public setLinks(links: MapLink[]) {
console.log('from set links 2');
links
.filter((link: MapLink) => link.source && link.target)
.forEach((link: MapLink) => {

View File

@ -2,6 +2,7 @@ import { Filter } from '../../../models/filter';
import { Indexed } from '../../datasources/map-datasource';
import { MapLinkNode } from './map-link-node';
import { MapNode } from './map-node';
import { LinkStyle } from '../../../models/link-style';
export class MapLink implements Indexed {
id: string;
@ -13,14 +14,15 @@ export class MapLink implements Indexed {
nodes: MapLinkNode[];
projectId: string;
suspend: boolean;
link_style?: LinkStyle;
distance: number; // this is not from server
length: number; // this is not from server
source: MapNode; // this is not from server
target: MapNode; // this is not from server
distance: number; // this is not from controller
length: number; // this is not from controller
source: MapNode; // this is not from controller
target: MapNode; // this is not from controller
isSelected = false; // this is not from server
isMultiplied = false; // this is not from server
x: number; // this is not from server
y: number; // this is not from server
isSelected = false; // this is not from controller
isMultiplied = false; // this is not from controller
x: number; // this is not from controller
y: number; // this is not from controller
}

View File

@ -14,7 +14,6 @@ export class Properties {
headless: boolean;
linked_clone: boolean;
on_close: string;
aux: number;
ram: number;
nvram: number;
usage: string;
@ -46,7 +45,6 @@ export class Properties {
kernel_command_line: string;
kernel_image: string;
kernel_image_md5sum?: any;
legacy_networking: boolean;
mac_address: string;
options: string;
platform: string;
@ -54,8 +52,8 @@ export class Properties {
qemu_path: string;
environment: string;
extra_hosts: string;
extra_volumes: string[];
replicate_network_connection_state: boolean;
memory: number;
tpm: boolean;
uefi: boolean;
}

View File

@ -7,6 +7,7 @@ export class MapChangeDetectorRef {
public hasBeenDrawn = false;
public detectChanges() {
console.log('from map change detector');
this.changesDetected.emit(true);
}
}

View File

@ -42,7 +42,7 @@ describe('TextDrawingWidget', () => {
const text_element = drew.nodes()[0];
expect(text_element.innerHTML).toEqual('<tspan xml:space="preserve" x="0" dy="0em">THIS IS TEXT</tspan>');
expect(text_element.getAttribute('fill')).toEqual('#000000');
expect(text_element.getAttribute('style')).toEqual('font-family: "Arial"; font-size: 12pt; font-weight: bold');
expect(text_element.getAttribute('style')).toEqual('font-family: "Noto Sans"; font-size: 11pt; font-weight: bold');
expect(text_element.getAttribute('text-decoration')).toEqual('line-through');
});

View File

@ -52,13 +52,13 @@ export class InterfaceStatusWidget implements Widget {
new LinkStatus(
start_point.x,
start_point.y,
l.capturing && l.suspend ? 'suspended' : l.source.status,
(( !l.capturing && l.suspend) || ( l.capturing && l.suspend)) ? 'suspended' : l.source.status,
sourcePort
),
new LinkStatus(
end_point.x,
end_point.y,
l.capturing && l.suspend ? 'suspended' : l.target.status,
(( !l.capturing && l.suspend) || ( l.capturing && l.suspend)) ? 'suspended' : l.target.status,
destinationPort
),
];
@ -90,16 +90,16 @@ export class InterfaceStatusWidget implements Widget {
.merge(status_started_enter)
.attr('class', 'status_started')
.attr('width', (ls: LinkStatus) => {
return ls.port.length * 10 + 5;
return ls.port.length * 8 + 10;
})
.attr('height', 20)
.attr('x', (ls: LinkStatus) => ls.x - 30)
.attr('y', (ls: LinkStatus) => ls.y - 10)
.attr('rx', 8)
.attr('ry', 8)
.style('fill', '#c7ffdf')
.style('fill', 'white')
.attr('stroke', '#2ecc71')
.attr('stroke-width', 2);
.attr('stroke-width', 3);
status_started.exit().remove();
const status_started_label = link_group
.selectAll<SVGTextElement, LinkStatus>('text.status_started_label')
@ -111,7 +111,7 @@ export class InterfaceStatusWidget implements Widget {
.text((ls: LinkStatus) => ls.port)
.attr('x', (ls: LinkStatus) => ls.x - 25)
.attr('y', (ls: LinkStatus) => ls.y + 5)
.attr('fill', `#0e9647`);
.attr('fill', `black`);
status_started_label.exit().remove();
const status_stopped = link_group
@ -122,16 +122,16 @@ export class InterfaceStatusWidget implements Widget {
.merge(status_stopped_enter)
.attr('class', 'status_stopped')
.attr('width', (ls: LinkStatus) => {
return ls.port.length * 10 + 5;
return ls.port.length * 8 + 10;
})
.attr('height', 20)
.attr('x', (ls: LinkStatus) => ls.x - 30)
.attr('y', (ls: LinkStatus) => ls.y - 10)
.attr('rx', 8)
.attr('ry', 8)
.style('fill', '#ffe3e3')
.style('fill', 'white')
.attr('stroke', 'red')
.attr('stroke-width', 2);
.attr('stroke-width', 3);
status_stopped.exit().remove();
const status_stopped_label = link_group
.selectAll<SVGTextElement, LinkStatus>('text.status_stopped_label')
@ -143,7 +143,7 @@ export class InterfaceStatusWidget implements Widget {
.text((ls: LinkStatus) => ls.port)
.attr('x', (ls: LinkStatus) => ls.x - 25)
.attr('y', (ls: LinkStatus) => ls.y + 5)
.attr('fill', `red`);
.attr('fill', `black`);
status_stopped_label.exit().remove();
const status_suspended = link_group
@ -154,7 +154,7 @@ export class InterfaceStatusWidget implements Widget {
.merge(status_suspended_enter)
.attr('class', 'status_suspended')
.attr('width', (ls: LinkStatus) => {
return ls.port.length * 10 + 5;
return ls.port.length * 8 + 10;
})
.attr('height', 20)
.attr('x', (ls: LinkStatus) => ls.x - 30)
@ -162,8 +162,8 @@ export class InterfaceStatusWidget implements Widget {
.attr('rx', 8)
.attr('ry', 8)
.style('fill', 'white')
.attr('stroke', '#fffbc3')
.attr('stroke-width', 2);
.attr('stroke', '#FFFF00')
.attr('stroke-width', 3);
status_suspended.exit().remove();
const status_suspended_label = link_group
.selectAll<SVGTextElement, LinkStatus>('text.status_suspended_label')
@ -175,7 +175,7 @@ export class InterfaceStatusWidget implements Widget {
.text((ls: LinkStatus) => ls.port)
.attr('x', (ls: LinkStatus) => ls.x - 25)
.attr('y', (ls: LinkStatus) => ls.y + 5)
.attr('fill', `#6b5633`);
.attr('fill', `black`);
status_suspended_label.exit().remove();
} else {
const status_started = link_group

View File

@ -22,14 +22,15 @@ export class LinkWidget implements Widget {
private selectionManager: SelectionManager,
private ethernetLinkWidget: EthernetLinkWidget,
private serialLinkWidget: SerialLinkWidget
) {}
) { }
public draw(view: SVGSelection) {
const link_body = view.selectAll<SVGGElement, MapLink>('g.link_body').data((l) => [l]);
const link_body_enter = link_body.enter().append<SVGGElement>('g').attr('class', 'link_body');
const link_body_merge = link_body.merge(link_body_enter).attr('transform', (link) => {
const link_body_merge = link_body.merge(link_body_enter)
.attr('transform', (link) => {
const translation = this.multiLinkCalculatorHelper.linkTranslation(link.distance, link.source, link.target);
return `translate (${translation.dx}, ${translation.dy})`;
});
@ -50,9 +51,8 @@ export class LinkWidget implements Widget {
})
.attr('class', 'capture-icon')
.attr('transform', (link) => {
return `translate (${(link.source.x + link.target.x) / 2 + 24}, ${
(link.source.y + link.target.y) / 2 + 24
}) scale(0.5)`;
return `translate (${(link.source.x + link.target.x) / 2 + 24}, ${(link.source.y + link.target.y) / 2 + 24
}) scale(0.5)`;
})
.attr('viewBox', '0 0 20 20')
.append<SVGImageElement>('image')
@ -74,9 +74,8 @@ export class LinkWidget implements Widget {
})
.attr('class', 'filter-capture-icon')
.attr('transform', (link) => {
return `translate (${(link.source.x + link.target.x) / 2 + 24}, ${
(link.source.y + link.target.y) / 2 + 24
}) scale(0.5)`;
return `translate (${(link.source.x + link.target.x) / 2 + 24}, ${(link.source.y + link.target.y) / 2 + 24
}) scale(0.5)`;
})
.attr('viewBox', '0 0 20 20')
.append<SVGImageElement>('image')
@ -100,9 +99,8 @@ export class LinkWidget implements Widget {
.attr('width', '48px')
.attr('height', '48px')
.attr('transform', (link) => {
return `translate (${(link.source.x + link.target.x) / 2 + 24}, ${
(link.source.y + link.target.y) / 2 + 24
}) scale(0.5)`;
return `translate (${(link.source.x + link.target.x) / 2 + 24}, ${(link.source.y + link.target.y) / 2 + 24
}) scale(0.5)`;
})
.attr('viewBox', '0 0 20 20')
.append<SVGImageElement>('image')
@ -124,9 +122,8 @@ export class LinkWidget implements Widget {
})
.attr('class', 'pause-icon')
.attr('transform', (link) => {
return `translate (${(link.source.x + link.target.x) / 2 + 24}, ${
(link.source.y + link.target.y) / 2 + 24
}) scale(0.5)`;
return `translate (${(link.source.x + link.target.x) / 2 + 24}, ${(link.source.y + link.target.y) / 2 + 24
}) scale(0.5)`;
})
.attr('viewBox', '0 0 20 20')
.append<SVGImageElement>('image')

View File

@ -11,6 +11,7 @@ export class LinksWidget implements Widget {
constructor(private multiLinkCalculatorHelper: MultiLinkCalculatorHelper, private linkWidget: LinkWidget) {}
public redrawLink(view: SVGSelection, link: MapLink) {
console.log('redraw called');
this.linkWidget.draw(this.selectLink(view, link));
}

View File

@ -4,21 +4,29 @@ import { LinkContextMenu } from '../../events/event-source';
import { MapLink } from '../../models/map/map-link';
import { SVGSelection } from '../../models/types';
import { Widget } from '../widget';
import { LinkStyle } from '../../../models/link-style';
import { StyleTranslator} from './style-translator';
class EthernetLinkPath {
constructor(public source: [number, number], public target: [number, number]) {}
constructor(public source: [number, number], public target: [number, number], public style: LinkStyle) {}
}
@Injectable()
export class EthernetLinkWidget implements Widget {
public onContextMenu = new EventEmitter<LinkContextMenu>();
private defaultEthernetLinkStyle : LinkStyle = {
color: "#000",
width: 2,
type: 0
};
constructor() {}
private linktoEthernetLink(link: MapLink) {
return new EthernetLinkPath(
[link.source.x + link.source.width / 2, link.source.y + link.source.height / 2],
[link.target.x + link.target.width / 2, link.target.y + link.target.height / 2]
[link.target.x + link.target.width / 2, link.target.y + link.target.height / 2],
link.link_style.color ? link.link_style : this.defaultEthernetLinkStyle
);
}
@ -38,15 +46,15 @@ export class EthernetLinkWidget implements Widget {
let link: MapLink = (datum as unknown) as MapLink;
const evt = event;
this.onContextMenu.emit(new LinkContextMenu(evt, link));
});
link_enter
.attr('stroke', '#000')
.attr('stroke-width', '2')
.on('contextmenu', (datum) => {
let link: MapLink = (datum as unknown) as MapLink;
const evt = event;
this.onContextMenu.emit(new LinkContextMenu(evt, link));
})
.attr('stroke', (datum) => {
return datum.style.color;
})
.attr('stroke-width', (datum) => {
return datum.style.width;
})
.attr('stroke-dasharray', (datum) => {
return StyleTranslator.getLinkStyle(datum.style);
});
const link_merge = link.merge(link_enter);

View File

@ -4,19 +4,27 @@ import { LinkContextMenu } from '../../events/event-source';
import { MapLink } from '../../models/map/map-link';
import { SVGSelection } from '../../models/types';
import { Widget } from '../widget';
import { LinkStyle } from '../../../models/link-style';
import { StyleTranslator} from './style-translator';
class SerialLinkPath {
constructor(
public source: [number, number],
public source_angle: [number, number],
public target_angle: [number, number],
public target: [number, number]
public target: [number, number],
public style: LinkStyle
) {}
}
@Injectable()
export class SerialLinkWidget implements Widget {
public onContextMenu = new EventEmitter<LinkContextMenu>();
private defaultSerialLinkStyle : LinkStyle = {
color: "#B22222",
width: 2,
type: 0
};
constructor() {}
@ -47,7 +55,12 @@ export class SerialLinkWidget implements Widget {
target.y - dy / 2.0 - 15 * vect_rot[1],
];
return new SerialLinkPath([source.x, source.y], angle_source, angle_target, [target.x, target.y]);
return new SerialLinkPath(
[source.x, source.y],
angle_source,
angle_target,
[target.x, target.y],
link.link_style.color ? link.link_style : this.defaultSerialLinkStyle);
}
public draw(view: SVGSelection) {
@ -68,7 +81,16 @@ export class SerialLinkWidget implements Widget {
this.onContextMenu.emit(new LinkContextMenu(evt, link));
});
link_enter.attr('stroke', '#B22222').attr('fill', 'none').attr('stroke-width', '2');
link_enter
.attr('stroke', (datum) => {
return datum.style.color;
})
.attr('stroke-width', (datum) => {
return datum.style.width;
})
.attr('stroke-dasharray', (datum) => {
return StyleTranslator.getLinkStyle(datum.style);
});
const link_merge = link.merge(link_enter);

View File

@ -0,0 +1,16 @@
import { LinkStyle } from '../../../models/link-style';
export class StyleTranslator {
static getLinkStyle(linkStyle: LinkStyle) {
if (linkStyle.type == 1) {
return `10, 10`
}
if (linkStyle.type == 2) {
return `${linkStyle.width}, ${linkStyle.width}`
}
if (linkStyle.type == 3) {
return `20, 10, ${linkStyle.width}, ${linkStyle.width}, ${linkStyle.width}, 10`
}
return `0, 0`
}
}

View File

@ -31,19 +31,21 @@ describe('NodesWidget', () => {
const drew = svg.canvas.selectAll<SVGGElement, MapNode>('g.node');
const drewNode = drew.nodes()[0];
drewNode.dispatchEvent(
new MouseEvent('mousedown', {
clientX: 150,
clientY: 250,
relatedTarget: drewNode,
screenY: 1024,
screenX: 1024,
view: window,
})
);
if (drewNode != undefined && drewNode != null) {
drewNode.dispatchEvent(
new MouseEvent('mousedown', {
clientX: 150,
clientY: 250,
relatedTarget: drewNode,
screenY: 1024,
screenX: 1024,
view: window,
})
);
window.dispatchEvent(new MouseEvent('mousemove', { clientX: 300, clientY: 300 }));
window.dispatchEvent(new MouseEvent('mouseup', { clientX: 300, clientY: 300, view: window }));
window.dispatchEvent(new MouseEvent('mousemove', { clientX: 300, clientY: 300 }));
window.dispatchEvent(new MouseEvent('mouseup', { clientX: 300, clientY: 300, view: window }));
}
};
beforeEach(() => {
@ -54,6 +56,9 @@ describe('NodesWidget', () => {
node.height = 100;
node.label = new MapLabel();
});
it('draggable behaviour', () => {
tryToDrag()
})
// it('should be draggable when enabled', () => {
// widget.setDraggingEnabled(true);

View File

@ -4,7 +4,6 @@ import { MapSettingsService } from '../../services/mapsettings.service';
import { ClickedDataEvent } from '../events/event-source';
import { NodeClicked, NodeContextMenu } from '../events/nodes';
import { NodesEventSource } from '../events/nodes-event-source';
import { GraphDataManager } from '../managers/graph-data-manager';
import { SelectionManager } from '../managers/selection-manager';
import { MapNode } from '../models/map/map-node';
import { SVGSelection } from '../models/types';
@ -18,7 +17,6 @@ export class NodeWidget implements Widget {
public onNodeClicked = new EventEmitter<NodeClicked>();
constructor(
private graphDataManager: GraphDataManager,
private selectionManager: SelectionManager,
private labelWidget: LabelWidget,
private nodesEventSource: NodesEventSource,

View File

@ -14,8 +14,12 @@ describe('NodesWidget', () => {
nodeWidget = instance(mock(NodeWidget));
widget = new NodesWidget(nodeWidget, new MapSettingsManager());
});
it('draggable behaviour', () => {
})
afterEach(() => {
svg.destroy();
});
});

View File

@ -18,8 +18,8 @@ describe('ToasterErrorHandler', () => {
let toasterService: MockedToasterService;
let settingsService: SettingsService;
beforeEach(() => {
TestBed.configureTestingModule({
beforeEach(async() => {
await TestBed.configureTestingModule({
providers: [
{ provide: ToasterService, useClass: MockedToasterService },
{ provide: SettingsService},

View File

@ -1,15 +1,31 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { MatCheckboxModule } from '@angular/material/checkbox';
import { MatDialogModule, MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
import { MatIconModule } from '@angular/material/icon';
import { MatMenuModule } from '@angular/material/menu';
import { MatToolbarModule } from '@angular/material/toolbar';
import { ProgressDialogComponent } from './progress-dialog.component';
describe('ProgressDialogComponent', () => {
let component: ProgressDialogComponent;
let fixture: ComponentFixture<ProgressDialogComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
beforeEach(async() => {
await TestBed.configureTestingModule({
declarations: [ProgressDialogComponent],
imports:[
MatIconModule,
MatToolbarModule,
MatMenuModule,
MatCheckboxModule,
MatDialogModule
],
providers:[
{ provide: MatDialogRef, useValue: {}},
{ provide: MAT_DIALOG_DATA, useValue: {}},
]
}).compileComponents();
}));
});
beforeEach(() => {
fixture = TestBed.createComponent(ProgressDialogComponent);
@ -17,7 +33,7 @@ describe('ProgressDialogComponent', () => {
fixture.detectChanges();
});
// it('should create', () => {
// expect(component).toBeTruthy();
// });
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -1,14 +1,21 @@
import { TestBed } from '@angular/core/testing';
import { inject, TestBed } from '@angular/core/testing';
import { MatDialog } from '@angular/material/dialog';
import { MockedProgressService } from 'app/components/project-map/project-map.component.spec';
import { ProgressDialogService } from './progress-dialog.service';
describe('ProgressDialogService', () => {
let mockedProgressService : MockedProgressService
beforeEach(() => {
TestBed.configureTestingModule({
providers: [ProgressDialogService],
// imports:[ProgressDialogService],
providers: [
{ provide: MatDialog, useValue: {} },
{ provide: ProgressDialogService, useClass:MockedProgressService },
],
});
});
// it('should be created', inject([ProgressDialogService], (service: ProgressDialogService) => {
// expect(service).toBeTruthy();
// }));
it('should be created', inject([ProgressDialogService], (service: ProgressDialogService) => {
expect(service).toBeTruthy();
}));
});

View File

@ -1,4 +1,4 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { MatIconModule } from '@angular/material/icon';
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
import { Router } from '@angular/router';
@ -23,8 +23,8 @@ describe('ProgressComponent', () => {
let progressService: ProgressService;
let router: MockedRouter = new MockedRouter();
beforeEach(async(() => {
TestBed.configureTestingModule({
beforeEach(async() => {
await TestBed.configureTestingModule({
imports: [RouterTestingModule, MatProgressSpinnerModule, MatIconModule],
providers: [ProgressService, { provide: Router, useValue: router }],
declarations: [ProgressComponent],
@ -32,7 +32,7 @@ describe('ProgressComponent', () => {
progressService = TestBed.get(ProgressService);
router = TestBed.get(Router);
}));
});
beforeEach(() => {
fixture = TestBed.createComponent(ProgressComponent);

View File

@ -0,0 +1,16 @@
import { TestBed } from '@angular/core/testing';
import { UploadServiceService } from './upload-service.service';
describe('UploadServiceService', () => {
let service: UploadServiceService;
beforeEach(() => {
TestBed.configureTestingModule({});
service = TestBed.inject(UploadServiceService);
});
it('should be created', () => {
expect(service).toBeTruthy();
});
});

View File

@ -0,0 +1,23 @@
import { Injectable } from '@angular/core';
import { BehaviorSubject, Subject } from 'rxjs';
@Injectable({
providedIn: 'root'
})
export class UploadServiceService {
private countSource = new Subject();
currentCount = this.countSource.asObservable();
private cancelItem = new Subject();
currentCancelItemDetails = this.cancelItem.asObservable();
constructor() { }
processBarCount(processCount:number) {
this.countSource.next(processCount)
}
cancelFileUploading(isCancel){
this.cancelItem.next(isCancel)
}
}

View File

@ -0,0 +1,10 @@
<p>{{upload_file_type}} Uploading please wait .... {{uploadProgress}}%</p>
<div class="row proccessBar-row ">
<div class="col-md-9 proccessBar-col">
<mat-progress-bar mode="determinate" [value]="uploadProgress" aria-valuemin="0" aria-valuemax="100">
</mat-progress-bar>
</div>
<div class="col-md-3 proccessBar-col">
<button mat-button color="primary" (click)="cancelItem()" class="file-button">Cancel</button>
</div>
</div>

View File

@ -0,0 +1,11 @@
.mat-snack-bar-container{
min-width: 450px !important;
}
.proccessBar-row{
display: flex;
}
.proccessBar-col{
margin: auto;
}

View File

@ -0,0 +1,34 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { MatSnackBarModule, MatSnackBarRef, MAT_SNACK_BAR_DATA } from '@angular/material/snack-bar';
import { UploadServiceService } from './upload-service.service';
import { UploadingProcessbarComponent } from './uploading-processbar.component';
describe('UploadingProcessbarComponent', () => {
let component: UploadingProcessbarComponent;
let fixture: ComponentFixture<UploadingProcessbarComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [UploadingProcessbarComponent],
imports:[MatSnackBarModule],
providers: [
{ provide: MAT_SNACK_BAR_DATA, useValue: {} },
{ provide: MatSnackBarRef, useValue: {} },
{ provide: UploadServiceService, useClass: UploadServiceService },
]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(UploadingProcessbarComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -0,0 +1,45 @@
import { Component, Inject, OnInit, Renderer2, ViewEncapsulation } from '@angular/core';
import { MatSnackBarRef, MAT_SNACK_BAR_DATA } from '@angular/material/snack-bar';
import { Subscription } from 'rxjs';
import { UploadServiceService } from './upload-service.service';
@Component({
selector: 'app-uploading-processbar',
templateUrl: './uploading-processbar.component.html',
styleUrls: ['./uploading-processbar.component.scss'],
encapsulation: ViewEncapsulation.None,
})
export class UploadingProcessbarComponent implements OnInit {
uploadProgress: number = 0
subscription: Subscription;
upload_file_type:string
constructor(
@Inject(MAT_SNACK_BAR_DATA) public data,
private _snackRef: MatSnackBarRef<UploadingProcessbarComponent>,
private _US: UploadServiceService
) { }
ngOnInit() {
this.upload_file_type = this.data.upload_file_type
this.subscription = this._US.currentCount.subscribe((count:number) => {
this.uploadProgress = count;
if (this.uploadProgress === 100 || this.uploadProgress == null ) {
this.dismiss()
}
})
}
dismiss() {
this._snackRef.dismiss();
}
cancelItem() {
this._US.cancelFileUploading(true)
}
ngOnDestroy() {
this.subscription.unsubscribe();
}
}

View File

@ -0,0 +1,98 @@
<div class="content" *ngIf="isReady; else loading">
<div class="default-header">
<div class="row">
<h1 class="col">Access Control List (ACL)</h1>
<button class="col" mat-raised-button color="primary" (click)="deleteMultiple()" class="add-ace-button" [disabled]="selection.selected.length == 0">
Delete selected ACEs
</button>
<button class="col" mat-raised-button color="primary" (click)="addACE()" class="add-ace-button">
Add ACE
</button>
</div>
</div>
<form>
<mat-form-field class="full-width">
<input matInput placeholder="Search by path, user/group or role" [(ngModel)]="searchText"
[ngModelOptions]="{ standalone: true }"/>
</mat-form-field>
</form>
<div class="default-content">
<table mat-table [dataSource]="dataSource | aceFilter: searchText:endpoints " class="mat-elevation-z8" matSort #acesSort="matSort">
<ng-container matColumnDef="select" >
<th mat-header-cell *matHeaderCellDef class="small-col">
<mat-checkbox (change)="$event ? masterToggle() : null"
[checked]="selection.hasValue() && isAllSelected()"
[indeterminate]="selection.hasValue() && !isAllSelected()">
</mat-checkbox>
</th>
<td mat-cell *matCellDef="let row" class="small-col">
<mat-checkbox (click)="$event.stopPropagation()"
(change)="$event ? selection.toggle(row) : null"
[checked]="selection.isSelected(row)">
</mat-checkbox>
</td>
</ng-container>
<ng-container matColumnDef="path">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Path</th>
<td mat-cell *matCellDef="let element"> {{getNameByUuidFromEndpoint(element.path)}} </td>
</ng-container>
<ng-container matColumnDef="user/group">
<th mat-header-cell *matHeaderCellDef mat-sort-header>User/Group</th>
<td mat-cell *matCellDef="let element">
<div *ngIf="element.ace_type === 'user' else groupId">{{getNameByUuidFromEndpoint(element.user_id)}}</div>
<ng-template #groupId>{{getNameByUuidFromEndpoint(element.group_id)}}</ng-template>
</td>
</ng-container>
<ng-container matColumnDef="role">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Role</th>
<td mat-cell *matCellDef="let element"> {{getNameByUuidFromEndpoint(element.role_id)}} </td>
</ng-container>
<ng-container matColumnDef="propagate">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Propagate</th>
<td mat-cell *matCellDef="let element"> {{element.propagate}} </td>
</ng-container>
<ng-container matColumnDef="allowed">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Allowed</th>
<td mat-cell *matCellDef="let element"> {{element.allowed}} </td>
</ng-container>
<ng-container matColumnDef="created_at">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Created</th>
<td mat-cell *matCellDef="let element"> {{element.created_at}} </td>
</ng-container>
<ng-container matColumnDef="updated_at">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Last update</th>
<td mat-cell *matCellDef="let element"> {{element.updated_at}} </td>
</ng-container>
<ng-container matColumnDef="delete">
<th mat-header-cell *matHeaderCellDef> </th>
<td mat-cell *matCellDef="let element"><button mat-button (click)="onDelete(element)"><mat-icon>delete</mat-icon></button></td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
</table>
<mat-paginator #acesPaginator="matPaginator"
[pageSizeOptions]="[5, 10, 20]"
showFirstLastButtons
aria-label="Select page">
</mat-paginator>
</div>
</div>
<ng-template #loading>
<div>
<mat-spinner class="loader"></mat-spinner>
</div>
</ng-template>

View File

@ -0,0 +1,26 @@
table {
width: 100%;
}
.full-width {
width: 940px;
margin-left: -470px;
left: 50%;
}
.add-ace-button {
height: 40px;
width: 160px;
margin: 20px;
}
.loader {
position: absolute;
margin: auto;
height: 175px;
bottom: 0;
left: 0;
right: 0;
top: 0;
width: 175px;
}

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