Compare commits

..

96 Commits

Author SHA1 Message Date
28d27194be Release v2.2.52 2024-12-02 11:05:45 +10:00
52f772676b Add .iol extension filter. Ref https://github.com/GNS3/gns3-gui/issues/3664 2024-11-25 11:02:49 +10:00
8068751032 Development on 2.2.51.dev1 2024-10-21 13:25:06 +10:00
28f8de0da1 Release v2.2.50 2024-10-21 12:02:41 +10:00
8cc4fb6f75 Merge remote-tracking branch 'origin/master' into 2.2 2024-10-21 11:56:21 +10:00
1196742e3b Merge pull request #1525 from GNS3/dependabot/npm_and_yarn/body-parser-1.20.3
Bump body-parser from 1.20.1 to 1.20.3
2024-09-21 16:54:09 +07:00
d398efe229 Bump body-parser from 1.20.1 to 1.20.3
Bumps [body-parser](https://github.com/expressjs/body-parser) from 1.20.1 to 1.20.3.
- [Release notes](https://github.com/expressjs/body-parser/releases)
- [Changelog](https://github.com/expressjs/body-parser/blob/master/HISTORY.md)
- [Commits](https://github.com/expressjs/body-parser/compare/1.20.1...1.20.3)

---
updated-dependencies:
- dependency-name: body-parser
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-09-21 09:40:03 +00:00
33e8fa7f5f Merge pull request #1524 from GNS3/dependabot/npm_and_yarn/express-4.21.0
Bump express from 4.19.2 to 4.21.0
2024-09-21 16:38:57 +07:00
b9833aa00b Bump express from 4.19.2 to 4.21.0
Bumps [express](https://github.com/expressjs/express) from 4.19.2 to 4.21.0.
- [Release notes](https://github.com/expressjs/express/releases)
- [Changelog](https://github.com/expressjs/express/blob/4.21.0/History.md)
- [Commits](https://github.com/expressjs/express/compare/4.19.2...4.21.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-09-21 08:22:26 +00:00
fc66124ea9 Add configure base mac address for Docker templates 2024-09-18 17:09:25 +07:00
3f74a916d4 Merge pull request #1522 from GNS3/2.2
Release v2.2.49
2024-08-06 20:44:59 +02:00
ff78754fd5 Merge branch 'master' into 2.2 2024-08-06 20:26:35 +02:00
323255286b Development on 2.2.50.dev1 2024-08-06 20:25:51 +02:00
a9314b65f8 Release v2.2.49 2024-08-06 12:36:04 +02:00
e5b3a101b8 Fix CVE-2024-6345 and CVE-2024-39689. Fixes #1521 #1520 2024-07-22 19:13:46 +02:00
8b2d20e8e9 Merge pull request #1519 from GNS3/dependabot/pip/scripts/setuptools-70.0.0
Bump setuptools from 65.5.1 to 70.0.0 in /scripts
2024-07-15 20:44:13 +02:00
26023fe884 Bump setuptools from 65.5.1 to 70.0.0 in /scripts
Bumps [setuptools](https://github.com/pypa/setuptools) from 65.5.1 to 70.0.0.
- [Release notes](https://github.com/pypa/setuptools/releases)
- [Changelog](https://github.com/pypa/setuptools/blob/main/NEWS.rst)
- [Commits](https://github.com/pypa/setuptools/compare/v65.5.1...v70.0.0)

---
updated-dependencies:
- dependency-name: setuptools
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-07-15 17:29:28 +00:00
9a2e06471c Development on 2.2.49.dev1 2024-07-13 16:33:10 +02:00
98f4ec1ce0 Merge pull request #1518 from GNS3/release/2.2.48.1
Release v2.2.48.1
2024-07-13 14:43:03 +02:00
4d695274bb Release v2.2.48.1 2024-07-11 23:40:15 +02:00
e5af89821d Show current year in default-layout.component.html 2024-07-11 23:39:53 +02:00
78b910504d Fix syntax error in index.html. Ref https://github.com/GNS3/gns3-server/issues/2399 2024-07-11 23:21:44 +02:00
93aabe0cbc Merge pull request #1515 from GNS3/2.2
Release v2.2.48
2024-07-09 00:31:25 +02:00
27446f8d14 Development on 2.2.49.dev1 2024-07-09 00:20:28 +02:00
a026374e75 Release v2.2.48 2024-07-08 18:21:21 +02:00
4f303921c6 Merge branch 'master' into 2.2 2024-07-08 18:19:14 +02:00
dea6a5021d Merge pull request #1511 from GNS3/dependabot/npm_and_yarn/socket.io-4.7.5
Bump socket.io from 4.4.1 to 4.7.5
2024-06-19 19:02:52 +02:00
46c7c58402 Bump socket.io from 4.4.1 to 4.7.5
Bumps [socket.io](https://github.com/socketio/socket.io) from 4.4.1 to 4.7.5.
- [Release notes](https://github.com/socketio/socket.io/releases)
- [Changelog](https://github.com/socketio/socket.io/blob/main/CHANGELOG.md)
- [Commits](https://github.com/socketio/socket.io/compare/4.4.1...4.7.5)

---
updated-dependencies:
- dependency-name: socket.io
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-06-19 16:25:06 +00:00
0df3525bbf Merge pull request #1509 from GNS3/dependabot/npm_and_yarn/ws-6.2.3
Bump ws from 6.2.2 to 6.2.3
2024-06-18 20:06:15 +02:00
9667e2363c Bump ws from 6.2.2 to 6.2.3
Bumps [ws](https://github.com/websockets/ws) from 6.2.2 to 6.2.3.
- [Release notes](https://github.com/websockets/ws/releases)
- [Commits](https://github.com/websockets/ws/compare/6.2.2...6.2.3)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-06-18 16:17:11 +00:00
24ec96a2dd Change interface label to fit in the SVG rect. Ref #1504 2024-06-17 17:37:07 +02:00
9844a2f88f Disable AdButler 2024-06-17 17:16:33 +02:00
0cdbeb98a2 Update Google Analytics ID 2024-06-17 16:18:14 +02:00
dc40d3be6e Merge pull request #1502 from GNS3/dependabot/pip/scripts/requests-2.32.0
Bump requests from 2.31.0 to 2.32.0 in /scripts
2024-05-21 13:46:33 +07:00
2015917767 ---
updated-dependencies:
- dependency-name: requests
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-05-21 05:25:06 +00:00
360d77d2ef Add Qemu for auxiliary console support. 2024-05-16 17:14:13 +07:00
75c3d8ed97 Merge pull request #1500 from GNS3/release/v2.2.47
Release v2.2.47
2024-05-15 16:44:26 +07:00
f94d59206e Development on 2.2.48.dev1 2024-05-15 16:28:14 +07:00
5b41f9789a Release v2.2.47 2024-05-15 11:51:18 +07:00
ac84106dbc Merge pull request #1499 from GNS3/feature/aux-console
Auxiliary console support
2024-05-14 22:17:16 +07:00
21f2267960 Merge remote-tracking branch 'origin/feature/aux-console' into feature/aux-console 2024-05-14 22:12:01 +07:00
a9781943d5 Check auxiliary console port is defined 2024-05-14 22:11:38 +07:00
6fc2f6f964 Merge branch '2.2' into feature/aux-console 2024-05-14 20:19:59 +07:00
cd5773e58a Merge branch 'master' into 2.2 2024-05-14 20:18:30 +07:00
f4bcb844dc Merge pull request #1494
Bump @angular/core from 9.0.0 to 12.2.17
2024-05-14 20:18:10 +07:00
24cf0f5623 Merge pull request #1489 from GNS3/dependabot/npm_and_yarn/follow-redirects-1.15.6
Bump follow-redirects from 1.15.4 to 1.15.6
2024-05-14 20:10:14 +07:00
5e02a3d757 Merge pull request #1490 from GNS3/dependabot/npm_and_yarn/express-4.19.2
Bump express from 4.18.2 to 4.19.2
2024-05-14 20:09:48 +07:00
42599dafb5 Auxiliary console support 2024-05-14 20:07:30 +07:00
9c754f3444 Merge remote-tracking branch 'origin/2.2' into 2.2 2024-05-14 17:43:48 +07:00
6772f0cb16 Merge pull request #1498 from GNS3/feature/protocol-handler-service
Create protocol handler service
2024-05-14 17:43:33 +07:00
2730ee6f6e Merge branch 'master' into 2.2 2024-05-14 17:25:07 +07:00
de058e175b Fix tests 2024-05-14 17:15:29 +07:00
e9487c5ada Create protocol handler service 2024-05-14 15:18:59 +07:00
035c846f85 Merge pull request #1495 from GNS3/dependabot/npm_and_yarn/ejs-3.1.10
Bump ejs from 3.1.8 to 3.1.10
2024-05-02 08:54:27 +07:00
80239229aa Bump ejs from 3.1.8 to 3.1.10
Bumps [ejs](https://github.com/mde/ejs) from 3.1.8 to 3.1.10.
- [Release notes](https://github.com/mde/ejs/releases)
- [Commits](https://github.com/mde/ejs/compare/v3.1.8...v3.1.10)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-05-02 01:29:26 +00:00
c12a7acb2c Bump @angular/core from 9.0.0 to 12.2.17
Bumps [@angular/core](https://github.com/angular/angular/tree/HEAD/packages/core) from 9.0.0 to 12.2.17.
- [Release notes](https://github.com/angular/angular/releases)
- [Changelog](https://github.com/angular/angular/blob/main/CHANGELOG.md)
- [Commits](https://github.com/angular/angular/commits/12.2.17/packages/core)

---
updated-dependencies:
- dependency-name: "@angular/core"
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-04-11 07:52:40 +00:00
23bf5ad2f3 Merge pull request #1493 from GNS3/dependabot/npm_and_yarn/tar-6.2.1
Bump tar from 6.1.11 to 6.2.1
2024-04-11 14:51:41 +07:00
bed98624cc Bump tar from 6.1.11 to 6.2.1
Bumps [tar](https://github.com/isaacs/node-tar) from 6.1.11 to 6.2.1.
- [Release notes](https://github.com/isaacs/node-tar/releases)
- [Changelog](https://github.com/isaacs/node-tar/blob/main/CHANGELOG.md)
- [Commits](https://github.com/isaacs/node-tar/compare/v6.1.11...v6.2.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-04-10 21:17:40 +00:00
383c26dcef Merge branch 'master' into 2.2 2024-04-03 17:54:45 +07:00
f505c101f7 Merge pull request #1491 from qmwd2006/patch-1
web browser out ouf memory when upload large image file
2024-04-03 17:53:57 +07:00
ca071f79c2 web browser out ouf memory when upload large image file 2024-03-31 07:18:10 +08:00
20be9027fd Bump express from 4.18.2 to 4.19.2
Bumps [express](https://github.com/expressjs/express) from 4.18.2 to 4.19.2.
- [Release notes](https://github.com/expressjs/express/releases)
- [Changelog](https://github.com/expressjs/express/blob/master/History.md)
- [Commits](https://github.com/expressjs/express/compare/4.18.2...4.19.2)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-03-28 17:27:08 +00:00
63389812b5 Bump follow-redirects from 1.15.4 to 1.15.6
Bumps [follow-redirects](https://github.com/follow-redirects/follow-redirects) from 1.15.4 to 1.15.6.
- [Release notes](https://github.com/follow-redirects/follow-redirects/releases)
- [Commits](https://github.com/follow-redirects/follow-redirects/compare/v1.15.4...v1.15.6)

---
updated-dependencies:
- dependency-name: follow-redirects
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-03-16 23:09:05 +00:00
6873432833 Merge pull request #1488 from GNS3/release/v2.2.46
Release v2.2.46
2024-02-26 17:53:06 +08:00
a7e3c24a27 Development on 2.2.47.dev1 2024-02-26 17:36:11 +08:00
358f50596c Release v2.2.46 2024-02-26 16:29:45 +08:00
b61f5803fd Merge branch 'master' into 2.2 2024-02-26 16:26:56 +08:00
c27f4aee57 Merge pull request #1486 from GNS3/dependabot/npm_and_yarn/ip-1.1.9
Bump ip from 1.1.5 to 1.1.9
2024-02-21 10:53:45 +08:00
5aa00a9f77 Bump ip from 1.1.5 to 1.1.9
Bumps [ip](https://github.com/indutny/node-ip) from 1.1.5 to 1.1.9.
- [Commits](https://github.com/indutny/node-ip/compare/v1.1.5...v1.1.9)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-02-20 21:27:19 +00:00
91075a60b1 Release v2.2.45 2024-01-12 21:18:37 +11:00
57e590a704 Merge branch 'master' into 2.2 2024-01-12 21:16:07 +11:00
8d3e571aa4 Merge pull request #1485 from GNS3/dependabot/npm_and_yarn/follow-redirects-1.15.4
Bump follow-redirects from 1.14.8 to 1.15.4
2024-01-12 12:21:20 +11:00
af5917b6e4 Bump follow-redirects from 1.14.8 to 1.15.4
Bumps [follow-redirects](https://github.com/follow-redirects/follow-redirects) from 1.14.8 to 1.15.4.
- [Release notes](https://github.com/follow-redirects/follow-redirects/releases)
- [Commits](https://github.com/follow-redirects/follow-redirects/compare/v1.14.8...v1.15.4)

---
updated-dependencies:
- dependency-name: follow-redirects
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-01-09 17:38:04 +00:00
21ed977a55 Add ipaddr.js to "allowedCommonJsDependencies" 2023-12-06 22:34:22 +10:00
f861364727 Fix console launch with protocol handler for IPv6 addresses 2023-12-06 15:10:12 +10:00
0ff4d534f4 Development on 2.2.45.dev1 2023-11-06 16:28:27 +10:00
ca408663a5 Merge pull request #1478 from GNS3/release-v2.2.44
Release v2.2.44
2023-11-06 16:27:49 +10:00
c96d66b34a Release v2.2.44 2023-11-06 15:52:05 +10:00
896ca927f3 Add correct protocol when capturing with protocol handler 2023-11-03 14:44:41 +10:00
8253f8da38 Add server protocol to gns3+pcap 2023-11-02 17:36:41 +10:00
cbb1c9ecfc Add project name in gns3+pcap protocol handler URL 2023-10-31 16:45:17 +10:00
1e8b6261dc Merge branch 'master' into 2.2 2023-10-31 16:16:22 +10:00
f3b8a42d89 Merge pull request #1476 from GNS3/console-ipv6
Support IPv6 for external consoles
2023-10-29 15:50:45 +10:00
7812ff38cc Development on 3.0.0.dev10 2023-10-29 15:36:53 +10:00
d725363fe5 Allow edit height and width for rectangles and ellipses 2023-10-24 18:23:55 +10:00
58d42558f7 Merge pull request #1467 from GNS3/dependabot/npm_and_yarn/babel/traverse-7.23.2
Bump @babel/traverse from 7.16.0 to 7.23.2
2023-10-24 18:08:43 +10:00
aecbe32c6c Merge branch 'master' into dependabot/npm_and_yarn/babel/traverse-7.23.2 2023-10-24 17:47:26 +10:00
35193043a2 Merge pull request #1469 from ventaquil/feature/add-qemu-igb-nic
Add Qemu IGB network device
2023-10-24 17:13:59 +10:00
7a229d8e3e Add Qemu IGB network device 2023-10-19 11:23:55 +02:00
ba1180786f Bump @babel/traverse from 7.16.0 to 7.23.2
Bumps [@babel/traverse](https://github.com/babel/babel/tree/HEAD/packages/babel-traverse) from 7.16.0 to 7.23.2.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.23.2/packages/babel-traverse)

---
updated-dependencies:
- dependency-name: "@babel/traverse"
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-17 09:34:36 +00:00
535649f0a9 Merge pull request #1458 from GNS3/release-v2.2.42
Release v2.2.42
2023-08-09 22:18:36 +10:00
a4f7db62ba Development on v2.2.43.dev1 2023-08-09 22:14:16 +10:00
662aba4ec8 Release v2.2.42 2023-08-09 20:55:57 +10:00
de07558349 Merge pull request #1455 from GNS3/release-v2.2.41
Release v2.2.41
2023-07-12 17:10:55 +10:00
b8253d365d Merge pull request #1454 from GNS3/dependabot/npm_and_yarn/semver-5.7.2
Bump semver from 5.7.1 to 5.7.2
2023-07-11 11:09:22 +10:00
05685af5c4 Bump semver from 5.7.1 to 5.7.2
Bumps [semver](https://github.com/npm/node-semver) from 5.7.1 to 5.7.2.
- [Release notes](https://github.com/npm/node-semver/releases)
- [Changelog](https://github.com/npm/node-semver/blob/v5.7.2/CHANGELOG.md)
- [Commits](https://github.com/npm/node-semver/compare/v5.7.1...v5.7.2)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-07-10 23:33:31 +00:00
774 changed files with 13958 additions and 22551 deletions

View File

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

1
.gitignore vendored
View File

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

View File

@ -1,3 +0,0 @@
{
"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,234 +1,247 @@
{
"$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
}
"$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
}
}

View File

@ -1,43 +0,0 @@
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 ControllersPage {
export class ServersPage {
helper = new TestHelper();
maximizeWindow() {
browser.driver.manage().window().maximize();
}
navigateToControllersPage() {
return browser.get('/controllers');
navigateToServersPage() {
return browser.get('/servers');
}
getAddControllerNotificationText() {
getAddServerNotificationText() {
return browser.driver.findElement(by.className('mat-card-content')).getText();
}
async clickAddController() {
let controllerTable = await this.checkControllersTable();
if (controllerTable.length === 0) {
async clickAddServer() {
let serversTable = await this.checkServersTable();
if (serversTable.length === 0) {
let buttons = await browser.driver.findElements(by.className('mat-button mat-button-base'));
await buttons[3].click();
}
}
checkControllersTable() {
checkServersTable() {
return browser.driver.findElements(by.css('mat-cell'));
}
async navigateToControllerProjects() {
async navigateToServerProjects() {
this.helper.sleep(2000);
let hyperlinks = await browser.driver.findElements(by.css('a.table-link'));
let controllerLink;
let serverLink;
await this.helper.asyncForEach(hyperlinks, async (element) => {
let text = await element.getText();
if (text === '127.0.0.1') controllerLink = element;
if (text === '127.0.0.1') serverLink = element;
});
await controllerLink.click();
await serverLink.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 { ControllersPage } from './helpers/controller.po';
import { ServersPage } from './helpers/server.po';
describe('Project map page', () => {
let controllersPage: ControllersPage;
let serversPage: ServersPage;
let projectsPage: ProjectsPage;
let projectMapPage: ProjectMapPage;
let helper: TestHelper;
beforeEach(async () => {
controllersPage = new ControllersPage();
serversPage = new ServersPage();
projectsPage = new ProjectsPage();
projectMapPage = new ProjectMapPage();
helper = new TestHelper();
controllersPage.maximizeWindow();
await controllersPage.navigateToControllersPage();
await controllersPage.clickAddController();
await controllersPage.navigateToControllerProjects();
serversPage.maximizeWindow();
await serversPage.navigateToServersPage();
await serversPage.clickAddServer();
await serversPage.navigateToServerProjects();
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 { ControllersPage } from './helpers/controller.po';
import { ServersPage } from './helpers/server.po';
describe('Projects page', () => {
let controllersPage: ControllersPage;
let serversPage: ServersPage;
let projectsPage: ProjectsPage;
let helper: TestHelper;
beforeEach(() => {
controllersPage = new ControllersPage();
serversPage = new ServersPage();
projectsPage = new ProjectsPage();
helper = new TestHelper();
});
it('user should have possibility to create new project', async () => {
// arrange
controllersPage.maximizeWindow();
await controllersPage.navigateToControllersPage();
await controllersPage.clickAddController();
await controllersPage.navigateToControllerProjects();
serversPage.maximizeWindow();
await serversPage.navigateToServersPage();
await serversPage.clickAddServer();
await serversPage.navigateToServerProjects();
helper.sleep(2000);
//act
@ -28,6 +28,6 @@ describe('Projects page', () => {
helper.sleep(2000);
//assert
expect(helper.getCurrentUrl()).toMatch('controller/1/project/');
expect(helper.getCurrentUrl()).toMatch('server/1/project/');
});
});

43
e2e/servers.e2e-spec.ts Normal file
View File

@ -0,0 +1,43 @@
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-controller.js
- local-server.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: ['ChromeHeadless'],
browsers: ['Chrome'],
singleRun: true
});
};

View File

@ -8,9 +8,9 @@ const { app } = require('electron')
const isWin = /^win/.test(process.platform);
let runningControllers = {};
let runningServers = {};
exports.getLocalControllerPath = async () => {
exports.getLocalServerPath = async () => {
let binary = isWin ? 'gns3server.exe': 'gns3server';
return findBinary('exe.', binary);
}
@ -20,27 +20,27 @@ exports.getUbridgePath = async () => {
return findBinary('ubridge', binary);
}
exports.startLocalController = async (controller) => {
return await run(controller, {
exports.startLocalServer = async (server) => {
return await run(server, {
logStdout: true
});
}
exports.stopLocalController = async (controller) => {
return await stop(controller.name);
exports.stopLocalServer = async (server) => {
return await stop(server.name);
}
exports.getRunningControllers = () => {
return Object.keys(runningControllers);
exports.getRunningServers = () => {
return Object.keys(runningServers);
}
exports.stopAllLocalControllers = async () => {
exports.stopAllLocalServers = 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 getControllerArguments(controller, overrides, configPath) {
let controllerArguments = [];
if(controller.host) {
controllerArguments.push('--host');
controllerArguments.push(controller.host);
function getServerArguments(server, overrides, configPath) {
let serverArguments = [];
if(server.host) {
serverArguments.push('--host');
serverArguments.push(server.host);
}
if(controller.port) {
controllerArguments.push('--port');
controllerArguments.push(controller.port);
if(server.port) {
serverArguments.push('--port');
serverArguments.push(server.port);
}
controllerArguments.push('--local');
serverArguments.push('--local');
if(configPath) {
controllerArguments.push('--config');
controllerArguments.push(configPath);
serverArguments.push('--config');
serverArguments.push(configPath);
}
return controllerArguments;
return serverArguments;
}
function getChannelForController(controller) {
return `local-controller-run-${controller.name}`;
function getChannelForServer(server) {
return `local-server-run-${server.name}`;
}
function notifyStatus(status) {
ipcMain.emit('local-controller-status-events', status);
ipcMain.emit('local-server-status-events', status);
}
function filterOutput(line) {
@ -120,44 +120,44 @@ function filterOutput(line) {
}
async function stopAll() {
for(var controllerName in runningControllers) {
let result, error = await stop(controllerName);
for(var serverName in runningServers) {
let result, error = await stop(serverName);
}
console.log(`Stopped all controllers`);
console.log(`Stopped all servers`);
}
async function stop(controllerName) {
async function stop(serverName) {
let pid = undefined;
const runningController = runningControllers[controllerName];
const runningServer = runningServers[serverName];
if(runningController !== undefined && runningController.process) {
pid = runningController.process.pid;
if(runningServer !== undefined && runningServer.process) {
pid = runningServer.process.pid;
}
console.log(`Stopping '${controllerName}' with PID='${pid}'`);
console.log(`Stopping '${serverName}' with PID='${pid}'`);
const stopped = new Promise((resolve, reject) => {
if(pid === undefined) {
resolve(`Controller '${controllerName} is already stopped`);
delete runningControllers[controllerName];
resolve(`Server '${serverName} is already stopped`);
delete runningServers[serverName];
return;
}
kill(pid, (error) => {
if(error) {
console.error(`Error occured during stopping '${controllerName}' with PID='${pid}'`);
console.error(`Error occured during stopping '${serverName}' with PID='${pid}'`);
reject(error);
}
else {
delete runningControllers[controllerName];
console.log(`Stopped '${controllerName}' with PID='${pid}'`);
resolve(`Stopped '${controllerName}' with PID='${pid}'`);
delete runningServers[serverName];
console.log(`Stopped '${serverName}' with PID='${pid}'`);
resolve(`Stopped '${serverName}' with PID='${pid}'`);
notifyStatus({
controllerName: controllerName,
serverName: serverName,
status: 'stopped',
message: `Controller '${controllerName}' stopped'`
message: `Server '${serverName}' stopped'`
});
}
});
@ -166,11 +166,11 @@ async function stop(controllerName) {
return stopped;
}
async function getIniFile(controller) {
return path.join(app.getPath('userData'), `gns3_controller_${controller.id}.ini`);
async function getIniFile(server) {
return path.join(app.getPath('userData'), `gns3_server_${server.id}.ini`);
}
async function configure(configPath, controller) {
async function configure(configPath, server) {
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, controller) {
var config = ini.parse(fs.readFileSync(configPath, 'utf-8'));
if(controller.path) {
config.path = controller.path;
if(server.path) {
config.path = server.path;
}
if(controller.host) {
config.host = controller.host;
if(server.host) {
config.host = server.host;
}
if(controller.port) {
config.port = controller.port;
if(server.port) {
config.port = server.port;
}
if(controller.ubridge_path) {
config.ubridge_path = controller.ubridge_path;
if(server.ubridge_path) {
config.ubridge_path = server.ubridge_path;
}
fs.writeFileSync(configPath, ini.stringify(config, { section: 'Controller' }));
fs.writeFileSync(configPath, ini.stringify(config, { section: 'Server' }));
}
async function setPATHEnv() {
@ -216,7 +216,7 @@ async function setPATHEnv() {
process.env.PATH = extra.join(";");
}
async function run(controller, options) {
async function run(server, options) {
if(!options) {
options = {};
}
@ -226,34 +226,34 @@ async function run(controller, options) {
console.log(`Configuring`);
const configPath = await getIniFile(controller);
await configure(configPath, controller);
const configPath = await getIniFile(server);
await configure(configPath, server);
console.log(`Setting up PATH`);
await setPATHEnv();
console.log(`Running '${controller.path}'`);
console.log(`Running '${server.path}'`);
let controllerProcess = spawn(controller.path, getControllerArguments(controller, {}, configPath));
let serverProcess = spawn(server.path, getServerArguments(server, {}, configPath));
notifyStatus({
controllerName: controller.name,
serverName: server.name,
status: 'started',
message: `Controller '${controller.name}' started'`
message: `Server '${server.name}' started'`
});
runningControllers[controller.name] = {
process: controllerProcess
runningServers[server.name] = {
process: serverProcess
};
controllerProcess.stdout.on('data', function(data) {
serverProcess.stdout.on('data', function(data) {
const line = data.toString();
const { isCritical, errorMessage } = filterOutput(line);
if(isCritical) {
notifyStatus({
controllerName: controller.name,
serverName: server.name,
status: 'stderr',
message: `Controller reported error: '${errorMessage}`
message: `Server reported error: '${errorMessage}`
});
}
@ -262,25 +262,25 @@ async function run(controller, options) {
}
});
controllerProcess.stderr.on('data', function(data) {
serverProcess.stderr.on('data', function(data) {
if(logSterr) {
console.log(data.toString());
}
});
controllerProcess.on('exit', (code, signal) => {
serverProcess.on('exit', (code, signal) => {
notifyStatus({
controllerName: controller.name,
serverName: server.name,
status: 'errored',
message: `controller '${controller.name}' has exited with status='${code}'`
message: `Server '${server.name}' has exited with status='${code}'`
});
});
controllerProcess.on('error', (err) => {
serverProcess.on('error', (err) => {
notifyStatus({
controllerName: controller.name,
serverName: server.name,
status: 'errored',
message: `Controller errored: '${err}`
message: `Server errored: '${err}`
});
});
@ -297,9 +297,9 @@ async function main() {
}
if(ipcMain) {
ipcMain.on('local-controller-run', async function (event, controller) {
const responseChannel = getChannelForController();
await run(controller);
ipcMain.on('local-server-run', async function (event, server) {
const responseChannel = getChannelForServer();
await run(server);
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": "3.0.0.dev7",
"version": "2.2.52",
"author": {
"name": "GNS3 Technology Inc.",
"email": "developers@gns3.com"
@ -36,100 +36,98 @@
"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 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",
"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",
"prepare": "yarn run snyk-protect"
},
"private": true,
"dependencies": {
"@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",
"@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",
"@sentry/browser": "^6.14.1",
"@snyk/protect": "^1.972.0",
"@types/jest": "^27.0.2",
"@types/mocha": "^9.1.1",
"@types/mocha": "^9.0.0",
"@types/react": "^17.0.34",
"@types/react-dom": "^17.0.11",
"angular-draggable-droppable": "^6.1.0",
"angular-draggable-droppable": "^5.0.0",
"angular-resizable-element": "^3.4.0",
"autoprefixer": "10.4.5",
"bootstrap": "^5.1.3",
"command-exists": "^1.2.9",
"core-js": "^3.22.3",
"css-tree": "^2.1.0",
"core-js": "^3.19.1",
"css-tree": "^1.1.3",
"d3-ng2-service": "^2.2.0",
"eev": "^0.1.5",
"ini": "^3.0.0",
"marked": "^4.0.14",
"ini": "^2.0.0",
"ipaddr.js": "^2.1.0",
"material-design-icons": "^3.0.1",
"mousetrap": "^1.6.5",
"ng-circle-progress": "^1.6.0",
"ng2-file-upload": "^3.0.0",
"ng2-file-upload": "^1.4.0",
"ngx-childprocess": "^0.0.6",
"ngx-device-detector": "4.0.1",
"ngx-device-detector": "^2.1.1",
"ngx-electron": "^2.2.0",
"node-fetch": "^3.2.10",
"notosans-fontface": "^1.3.0",
"postcss-loader": "^6.2.1",
"notosans-fontface": "1.2.2",
"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.4.0",
"tslib": "^2.3.1",
"typeface-roboto": "^1.1.13",
"xterm": "^4.18.0",
"xterm": "^4.15.0",
"xterm-addon-attach": "^0.6.0",
"xterm-addon-fit": "^0.5.0",
"yargs": "^17.4.1",
"zone.js": "^0.11.5"
"yargs": "^17.2.1",
"zone.js": "~0.11.4"
},
"devDependencies": {
"@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",
"@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",
"@types/jasminewd2": "^2.0.10",
"@types/node": "^17.0.31",
"codelyzer": "^0.0.28",
"electron": "13.6.6",
"electron-builder": "^23.0.3",
"@types/node": "16.11.6",
"codelyzer": "^6.0.2",
"electron": "^13.6.6",
"electron-builder": "^22.9.1",
"file-loader": "^6.2.0",
"jasmine-core": "^4.1.0",
"jasmine-spec-reporter": "^7.0.0",
"jasmine-core": "~3.10.1",
"jasmine-spec-reporter": "~7.0.0",
"jquery": "^3.6.0",
"karma": "^6.3.19",
"karma-chrome-launcher": "^3.1.1",
"karma": "^6.3.16",
"karma-chrome-launcher": "~3.1.0",
"karma-cli": "^2.0.0",
"karma-coverage-istanbul-reporter": "^3.0.3",
"karma-jasmine": "^5.0.0",
"karma-coverage-istanbul-reporter": "~3.0.3",
"karma-jasmine": "~4.0.1",
"karma-jasmine-html-reporter": "^1.7.0",
"license-checker": "^25.0.1",
"popper.js": "^1.16.1",
"prettier": "^2.6.2",
"prettier": "^2.4.1",
"protractor": "^7.0.0",
"replace": "^1.2.1",
"rxjs-tslint": "^0.1.8",
"ts-mockito": "^2.6.1",
"ts-node": "^10.7.0",
"ts-node": "~10.4.0",
"tslint": "^6.1.3",
"tslint-config-prettier": "^1.18.0",
"typescript": "4.6.4",
"webpack": "^5.72.0",
"yarn-upgrade-all": "^0.7.1"
"typescript": "4.2.3",
"webpack": "5.76.0",
"yarn-upgrade-all": "^0.5.4"
},
"greenkeeper": {
"ignore": [
@ -137,4 +135,4 @@
]
},
"snyk": true
}
}

View File

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

View File

@ -1,9 +1,10 @@
GNS3 WebUI is web implementation of user interface for GNS3 software.
Current version: 2.2.24
Current version: 2.2.32
Bug Fixes & enhancements
- security fixes
- Fixed generated capture file is not valid
- Fixed Docker additional directories
Current version: 2020.4.0-beta.1
@ -67,7 +68,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
-Controller type in template preferences
- Server type in template preferences
- Error when selecting existing Docker image
- Default values in templates
- TypeError: Cannot read property 'message' of undefined

View File

@ -1,10 +1,9 @@
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { BundledControllerFinderComponent } from './components/bundled-controller-finder/bundled-controller-finder.component';
import { BundledServerFinderComponent } from './components/bundled-server-finder/bundled-server-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';
@ -24,6 +23,7 @@ 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,266 +44,157 @@ 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 { ControllersComponent } from './components/controllers/controllers.component';
import { ServersComponent } from './components/servers/servers.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 { 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 { PermissionResolver } from "./resolvers/permission.resolver";
import { UserGroupsResolver } from "./resolvers/user-groups.resolver";
import { UserPermissionsResolver } from "./resolvers/user-permissions.resolver";
import { GroupManagementComponent } from "./components/group-management/group-management.component";
import { RoleManagementComponent } from "./components/role-management/role-management.component";
import { PermissionsManagementComponent } from "./components/permissions-management/permissions-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 { RolePermissionsComponent } from "./components/role-management/role-detail/role-permissions/role-permissions.component";
import { UserPermissionsComponent } from "./components/user-management/user-detail/user-permissions/user-permissions.component";
import { ServerResolve } from './resolvers/server-resolve';
const routes: Routes = [
{
path: '',
component: DefaultLayoutComponent,
children: [
{ 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: '', redirectTo: 'servers', pathMatch: 'full' },
{ path: 'servers', component: ServersComponent },
{ path: 'bundled', component: BundledServerFinderComponent },
{
path: 'controller/:controller_id/projects',
path: 'server/:server_id/projects',
component: ProjectsComponent,
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,
permissions: UserPermissionsResolver,
controller: ControllerResolve},
resolve: { server: ServerResolve },
},
{ path: 'help', component: HelpComponent },
{ path: 'settings', component: SettingsComponent },
{ path: 'settings/console', component: ConsoleComponent },
{ path: 'installed-software', component: InstalledSoftwareComponent },
{ path: 'controller/:controller_id/systemstatus', component: SystemStatusComponent, canActivate: [LoginGuard] },
{ path: 'server/:server_id/systemstatus', component: SystemStatusComponent },
{ path: 'controller/:controller_ip/:controller_port/project/:project_id', component: DirectLinkComponent, canActivate: [LoginGuard] },
{ path: 'server/:server_ip/:server_port/project/:project_id', component: DirectLinkComponent },
{
path: 'controller/:controller_id/project/:project_id/snapshots',
path: 'server/:server_id/project/:project_id/snapshots',
component: ListOfSnapshotsComponent,
canActivate: [LoginGuard],
resolve: { controller: ControllerResolve },
resolve: { server: ServerResolve },
},
{ 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', 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/builtin/ethernet-hubs', component: EthernetHubsTemplatesComponent, canActivate: [LoginGuard] },
{ path: 'server/:server_id/preferences/builtin/ethernet-hubs', component: EthernetHubsTemplatesComponent },
{
path: 'controller/:controller_id/preferences/builtin/ethernet-hubs/addtemplate',
path: 'server/:server_id/preferences/builtin/ethernet-hubs/addtemplate',
component: EthernetHubsAddTemplateComponent,
canActivate: [LoginGuard]
},
{
path: 'controller/:controller_id/preferences/builtin/ethernet-hubs/:template_id',
path: 'server/:server_id/preferences/builtin/ethernet-hubs/:template_id',
component: EthernetHubsTemplateDetailsComponent,
canActivate: [LoginGuard]
},
{
path: 'controller/:controller_id/preferences/builtin/ethernet-switches',
path: 'server/:server_id/preferences/builtin/ethernet-switches',
component: EthernetSwitchesTemplatesComponent,
canActivate: [LoginGuard]
},
{
path: 'controller/:controller_id/preferences/builtin/ethernet-switches/addtemplate',
path: 'server/:server_id/preferences/builtin/ethernet-switches/addtemplate',
component: EthernetSwitchesAddTemplateComponent,
canActivate: [LoginGuard]
},
{
path: 'controller/:controller_id/preferences/builtin/ethernet-switches/:template_id',
path: 'server/:server_id/preferences/builtin/ethernet-switches/:template_id',
component: EthernetSwitchesTemplateDetailsComponent,
canActivate: [LoginGuard]
},
{ path: 'controller/:controller_id/preferences/builtin/cloud-nodes', component: CloudNodesTemplatesComponent, canActivate: [LoginGuard] },
{ path: 'server/:server_id/preferences/builtin/cloud-nodes', component: CloudNodesTemplatesComponent },
{
path: 'controller/:controller_id/preferences/builtin/cloud-nodes/addtemplate',
path: 'server/:server_id/preferences/builtin/cloud-nodes/addtemplate',
component: CloudNodesAddTemplateComponent,
canActivate: [LoginGuard]
},
{
path: 'controller/:controller_id/preferences/builtin/cloud-nodes/:template_id',
path: 'server/:server_id/preferences/builtin/cloud-nodes/:template_id',
component: CloudNodesTemplateDetailsComponent,
canActivate: [LoginGuard]
},
//{ 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', 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/templates/:template_id/copy',
path: 'server/:server_id/preferences/dynamips/templates/:template_id/copy',
component: CopyIosTemplateComponent,
canActivate: [LoginGuard]
},
// { 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', component: QemuPreferencesComponent },
{ path: 'server/:server_id/preferences/qemu/templates', component: QemuVmTemplatesComponent },
{
path: 'controller/:controller_id/preferences/qemu/templates/:template_id/copy',
path: 'server/:server_id/preferences/qemu/templates/:template_id/copy',
component: CopyQemuVmTemplateComponent,
canActivate: [LoginGuard]
},
{ 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/qemu/templates/:template_id', component: QemuVmTemplateDetailsComponent },
{ path: 'server/:server_id/preferences/qemu/addtemplate', component: AddQemuVmTemplateComponent },
// { 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/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/virtualbox', component: VirtualBoxPreferencesComponent },
{ path: 'controller/:controller_id/preferences/virtualbox/templates', component: VirtualBoxTemplatesComponent, 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/templates/:template_id',
path: 'server/:server_id/preferences/virtualbox/templates/:template_id',
component: VirtualBoxTemplateDetailsComponent,
canActivate: [LoginGuard]
},
{ path: 'controller/:controller_id/preferences/virtualbox/addtemplate', component: AddVirtualBoxTemplateComponent, canActivate: [LoginGuard] },
{ path: 'server/:server_id/preferences/virtualbox/addtemplate', component: AddVirtualBoxTemplateComponent },
// { 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', component: VmwarePreferencesComponent },
{ path: 'server/:server_id/preferences/vmware/templates', component: VmwareTemplatesComponent },
{
path: 'controller/:controller_id/preferences/vmware/templates/:template_id',
path: 'server/:server_id/preferences/vmware/templates/:template_id',
component: VmwareTemplateDetailsComponent,
canActivate: [LoginGuard]
},
{ path: 'controller/:controller_id/preferences/vmware/addtemplate', component: AddVmwareTemplateComponent, canActivate: [LoginGuard] },
{ path: 'server/:server_id/preferences/vmware/addtemplate', component: AddVmwareTemplateComponent },
{ path: 'controller/:controller_id/preferences/docker/templates', component: DockerTemplatesComponent, 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/:template_id',
path: 'server/:server_id/preferences/docker/templates/:template_id',
component: DockerTemplateDetailsComponent,
canActivate: [LoginGuard]
},
{
path: 'controller/:controller_id/preferences/docker/templates/:template_id/copy',
path: 'server/:server_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: 'permissions',
component: PermissionsManagementComponent
}
]
},
{
path: 'controller/:controller_id/management/groups/:user_group_id',
component: GroupDetailsComponent,
resolve: {
members: GroupMembersResolver,
controller: ControllerResolve,
group: GroupResolver,
roles: GroupRoleResolver
}
},
{
path: 'controller/:controller_id/management/roles/:role_id',
component: RoleDetailComponent,
resolve: {
role: RoleDetailResolver,
controller: ControllerResolve
}
},
{
path: 'controller/:controller_id/management/roles/:role_id/permissions',
component: RolePermissionsComponent,
resolve: {
role: RoleDetailResolver,
controller: ControllerResolve,
permissions: PermissionResolver
}
},
{
path: 'controller/:controller_id/management/users/:user_id/permissions',
component: UserPermissionsComponent,
resolve: {
user: UserDetailResolver,
userPermissions: UserPermissionsResolver,
controller: ControllerResolve,
permissions: PermissionResolver
}
}
{ 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: 'controller/:controller_id/project/:project_id',
path: 'server/:server_id/project/:project_id',
component: ProjectMapComponent,
canActivate: [LoginGuard],
canDeactivate: [ConsoleGuard],
},
{
path: 'controller/:controller_id/project/:project_id/nodes/:node_id',
path: 'server/:server_id/project/:project_id/nodes/:node_id',
component: WebConsoleFullWindowComponent,
canActivate: [LoginGuard]
},
{
path: 'static/web-ui/controller/:controller_id/project/:project_id/nodes/:node_id',
path: 'static/web-ui/server/:server_id/project/:project_id/nodes/:node_id',
component: WebConsoleFullWindowComponent,
canActivate: [LoginGuard]
},
{
path: '**',
component: PageNotFoundComponent,
}
},
];
@NgModule({
@ -316,5 +207,4 @@ 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 { ComponentFixture, TestBed } from '@angular/core/testing';
import { async, 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() => {
await TestBed.configureTestingModule({
beforeEach(async(() => {
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;
await expect(app).toBeTruthy();
});
expect(app).toBeTruthy();
}));
it('should have footer', async() => {
it('should have footer', async(() => {
const compiled = fixture.debugElement.nativeElement;
await expect(compiled.querySelector('router-outlet').textContent).toEqual('');
});
expect(compiled.querySelector('router-outlet').textContent).toEqual('');
}));
it('should receive changed settings and forward to electron', async() => {
await spyOnProperty(electronService, 'isElectronApp').and.returnValue(true);
it('should receive changed settings and forward to electron', async(() => {
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);
await expect(spy.send).not.toHaveBeenCalled();
});
expect(spy.send).not.toHaveBeenCalled();
}));
});

View File

@ -1,8 +1,7 @@
/* tslint:disable */
import { DragDropModule } from '@angular/cdk/drag-drop';
import { OverlayModule } from '@angular/cdk/overlay';
import { CdkTableModule } from '@angular/cdk/table';
import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http';
import { HttpClientModule } from '@angular/common/http';
import { ErrorHandler, NgModule } from '@angular/core';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { MatSidenavModule } from '@angular/material/sidenav';
@ -30,7 +29,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 { BundledControllerFinderComponent } from './components/bundled-controller-finder/bundled-controller-finder.component';
import { BundledServerFinderComponent } from './components/bundled-server-finder/bundled-server-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';
@ -75,6 +74,7 @@ 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,6 +85,10 @@ 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';
@ -113,7 +117,6 @@ 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';
@ -131,16 +134,13 @@ 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 { 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 { 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,6 +165,7 @@ 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';
@ -174,7 +175,6 @@ 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 { 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 { 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 { 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,19 +204,18 @@ 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 { ControllerResolve } from './resolvers/controller-resolve';
import { ServerResolve } from './resolvers/server-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';
@ -224,8 +223,9 @@ 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 { HttpController, ControllerErrorHandler } from './services/http-controller.service';
import { HttpServer, ServerErrorHandler } from './services/http-server.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 { 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 { 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 { SettingsService } from './services/settings.service';
import { ConsoleService } from './services/settings/console.service';
import { DefaultConsoleService } from './services/settings/default-console.service';
@ -258,6 +258,7 @@ 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';
@ -268,404 +269,337 @@ 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 { PermissionEditorComponent } from './components/role-management/role-detail/permission-editor/permission-editor.component';
import { EditablePermissionComponent } from './components/role-management/role-detail/permission-editor/editable-permission/editable-permission.component';
import { PermissionEditorValidateDialogComponent } from './components/role-management/role-detail/permission-editor/permission-editor-validate-dialog/permission-editor-validate-dialog.component';
import { PermissionsManagementComponent } from './components/permissions-management/permissions-management.component';
import { PermissionEditLineComponent } from '@components/permissions-management/permission-edit-line/permission-edit-line.component';
import {MatSlideToggleModule} from '@angular/material/slide-toggle';
import { UserPermissionsComponent } from './components/user-management/user-detail/user-permissions/user-permissions.component';
import {MatAutocompleteModule} from "@angular/material/autocomplete";
import {PathAutoCompleteComponent} from './components/permissions-management/add-permission-line/path-auto-complete/path-auto-complete.component';
import {FilterCompletePipe} from './components/permissions-management/add-permission-line/path-auto-complete/filter-complete.pipe';
import { AddPermissionLineComponent } from './components/permissions-management/add-permission-line/add-permission-line.component';
import { MethodButtonComponent } from './components/permissions-management/method-button/method-button.component';
import { ActionButtonComponent } from './components/permissions-management/action-button/action-button.component';
import { DeletePermissionDialogComponent } from './components/permissions-management/delete-permission-dialog/delete-permission-dialog.component';
import { AddRoleToGroupComponent } from './components/group-details/add-role-to-group/add-role-to-group.component';
import {MatFormFieldModule} from "@angular/material/form-field";
import { PermissionsFilterPipe } from './components/permissions-management/permissions-filter.pipe';
import { DisplayPathPipe } from './components/permissions-management/display-path.pipe';
import {RolePermissionsComponent} from "@components/role-management/role-detail/role-permissions/role-permissions.component";
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';
@NgModule({
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,
PermissionEditorComponent,
EditablePermissionComponent,
PermissionEditorValidateDialogComponent,
RemoveToGroupDialogComponent,
PermissionsManagementComponent,
AddRoleToGroupComponent,
PermissionEditLineComponent,
AddPermissionLineComponent,
MethodButtonComponent,
ActionButtonComponent,
DeletePermissionDialogComponent,
PathAutoCompleteComponent,
FilterCompletePipe,
UserPermissionsComponent,
PermissionsFilterPipe,
RolePermissionsComponent,
DisplayPathPipe,
ChangeUserPasswordComponent,
FilterCompletePipe,
DisplayPathPipe,
ChangeUserPasswordComponent,
ProjectReadmeComponent,
ImageManagerComponent,
AddImageDialogComponent,
DeleteAllImageFilesDialogComponent,
UploadingProcessbarComponent,
ExportPortableProjectComponent,
NodesMenuConfirmationDialogComponent,
ConfirmationDeleteAllProjectsComponent,
ProjectMapLockConfirmationDialogComponent,
],
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,
],
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]
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],
})
export class AppModule {
constructor(protected _googleAnalyticsService: GoogleAnalyticsService) {}

View File

@ -5,7 +5,6 @@ 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';
@ -74,7 +73,6 @@ import { SerialLinkWidget } from './widgets/links/serial-link';
SelectionControlComponent,
SelectionSelectComponent,
DraggableSelectionComponent,
LinkEditingComponent,
MovingCanvasDirective,
ZoomingCanvasDirective,
],

View File

@ -44,6 +44,5 @@
<app-drawing-resizing></app-drawing-resizing>
<app-selection-control></app-selection-control>
<app-selection-select></app-selection-select>
<app-text-editor #textEditor [controller]="controller" [svg]="svg"></app-text-editor>
<app-text-editor #textEditor [server]="server" [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,17 +1,23 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { D3MapComponent } from './d3-map.component';
describe('D3MapComponent', () => {
let component: D3MapComponent;
let fixture: ComponentFixture<D3MapComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [D3MapComponent],
}).compileComponents();
});
}));
it('should create', () => {
expect(component)
});
// beforeEach(() => {
// fixture = TestBed.createComponent(MapComponent);
// component = fixture.componentInstance;
// fixture.detectChanges();
// });
//
// it('should create', () => {
// expect(component).toBeTruthy();
// });
});

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 { Controller } from '../../../models/controller';
import { Server } from '../../../models/server';
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() controller: Controller;
@Input() server: Server;
@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: () => {} },
};
await TestBed.configureTestingModule({
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 { ComponentFixture, TestBed } from '@angular/core/testing';
import { async, 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() => {
await TestBed.configureTestingModule({
beforeEach(async(() => {
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 { ComponentFixture, TestBed } from '@angular/core/testing';
import { async, 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() => {
await TestBed.configureTestingModule({
beforeEach(async(() => {
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 { ComponentFixture, TestBed } from '@angular/core/testing';
import { async, 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: 573 B

After

Width:  |  Height:  |  Size: 563 B

View File

@ -1,18 +1,15 @@
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 { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { DrawingComponent } from './drawing.component';
describe('DrawingComponent', () => {
let component: DrawingComponent;
let fixture: ComponentFixture<DrawingComponent>;
beforeEach(async() => {
await TestBed.configureTestingModule({
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [DrawingComponent],
providers:[SvgToDrawingConverter,DrawingsEventSource]
}).compileComponents();
});
}));
beforeEach(() => {
fixture = TestBed.createComponent(DrawingComponent);
@ -20,7 +17,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 ? evt.x : '';
this.drawing.y = evt ? evt.y : '';
this.drawing.x = evt.x;
this.drawing.y = evt.y;
this.cd.detectChanges();
}
@ -64,8 +64,6 @@ export class DrawingComponent implements OnInit {
}
get transformation() {
if (this.drawing) {
return `translate(${this.drawing.x},${this.drawing.y}) rotate(${this.drawing.rotation})`;
}
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: 338 B

After

Width:  |  Height:  |  Size: 332 B

View File

@ -1,17 +1,15 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { QtDasharrayFixer } from 'app/cartography/helpers/qt-dasharray-fixer';
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { EllipseComponent } from './ellipse.component';
describe('EllipseComponent', () => {
let component: EllipseComponent;
let fixture: ComponentFixture<EllipseComponent>;
beforeEach(async() => {
await TestBed.configureTestingModule({
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [EllipseComponent],
providers:[QtDasharrayFixer]
}).compileComponents();
});
}));
beforeEach(() => {
fixture = TestBed.createComponent(EllipseComponent);
@ -19,7 +17,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 (this.ellipse && isFinite(this.ellipse.fill_opacity)) {
if (isFinite(this.ellipse.fill_opacity)) {
return this.ellipse.fill_opacity;
}
return null;
}
get stroke_width() {
if (this.ellipse && isFinite(this.ellipse.stroke_width)) {
if (isFinite(this.ellipse.stroke_width)) {
return this.ellipse.stroke_width;
}
return null;
}
get stroke_dasharray() {
if (this.ellipse && this.ellipse.stroke_dasharray) {
if (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: 143 B

After

Width:  |  Height:  |  Size: 140 B

View File

@ -1,15 +1,15 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ImageComponent } from './image.component';
describe('ImageComponent', () => {
let component: ImageComponent;
let fixture: ComponentFixture<ImageComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
beforeEach(async(() => {
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,7 +8,6 @@ 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: 256 B

After

Width:  |  Height:  |  Size: 245 B

View File

@ -1,17 +1,15 @@
import {ComponentFixture, TestBed } from '@angular/core/testing';
import { QtDasharrayFixer } from 'app/cartography/helpers/qt-dasharray-fixer';
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
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);
@ -19,7 +17,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 (this.line && isFinite(this.line.stroke_width)) {
if (isFinite(this.line.stroke_width)) {
return this.line.stroke_width;
}
return null;
}
get stroke_dasharray() {
if ( this.line && this.line.stroke_dasharray) {
if (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 ? fill_opacity : '' "
[attr.stroke]="rect?.stroke"
[attr.fill]="rect.fill"
[attr.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: 349 B

After

Width:  |  Height:  |  Size: 322 B

View File

@ -1,17 +1,15 @@
import {ComponentFixture, TestBed } from '@angular/core/testing';
import { QtDasharrayFixer } from 'app/cartography/helpers/qt-dasharray-fixer';
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { RectComponent } from './rect.component';
describe('RectComponent', () => {
let component: RectComponent;
let fixture: ComponentFixture<RectComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [RectComponent],
providers:[QtDasharrayFixer]
}).compileComponents();
});
}));
beforeEach(() => {
fixture = TestBed.createComponent(RectComponent);
@ -19,7 +17,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 (this.rect && isFinite(this.rect.fill_opacity)) {
return this.rect.fill_opacity ? this.rect.fill_opacity : null;
if (isFinite(this.rect.fill_opacity)) {
return this.rect.fill_opacity;
}
return null;
}
get stroke_width() {
if (this.rect && isFinite(this.rect.stroke_width)) {
return this.rect.stroke_width ? this.rect.stroke_width : null;
if (isFinite(this.rect.stroke_width)) {
return this.rect.stroke_width;
}
return null;
}
get stroke_dasharray() {
if (this.rect && this.rect.stroke_dasharray) {
if (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: 339 B

After

Width:  |  Height:  |  Size: 338 B

View File

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

View File

@ -19,12 +19,10 @@ export class TextComponent implements OnInit, DoCheck {
transformation = '';
constructor(private fontFixer: FontFixer, private sanitizer: DomSanitizer) { }
constructor(private fontFixer: FontFixer, private sanitizer: DomSanitizer) {}
ngOnInit() {
if (this.text) {
this.lines = this.getLines(this.text.text);
}
this.lines = this.getLines(this.text.text);
}
ngDoCheck() {
@ -32,38 +30,32 @@ export class TextComponent implements OnInit, DoCheck {
}
get style() {
if (this.text) {
const font = this.fontFixer.fix(this.text);
const font = this.fontFixer.fix(this.text);
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('; '));
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('; '));
}
get textDecoration() {
if (this.text) {
return this.text.text_decoration;
}
return this.text.text_decoration;
}
calculateTransformation() {
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 '';
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 '';
}
getLines(text: string) {

View File

@ -1,28 +1,15 @@
import { ChangeDetectorRef, ElementRef, Injectable } from '@angular/core';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { CssFixer } from 'app/cartography/helpers/css-fixer';
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { InterfaceLabelComponent } from './interface-label.component';
export class MockElementRef extends ElementRef {
constructor() { super(null || undefined); }
nativeElement={}
}
xdescribe('InterfaceLabelComponent', () => {
describe('InterfaceLabelComponent', () => {
let component: InterfaceLabelComponent;
let fixture: ComponentFixture<InterfaceLabelComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [InterfaceLabelComponent],
providers: [
CssFixer,
ChangeDetectorRef,
{ provide: ElementRef, useValue: new MockElementRef() },
]
}).compileComponents();
});
}));
beforeEach(() => {
fixture = TestBed.createComponent(InterfaceLabelComponent);
@ -30,7 +17,7 @@ xdescribe('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,11 +89,9 @@ export class InterfaceLabelComponent implements OnInit {
}
get transform() {
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})`;
}
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.3 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -1,18 +1,15 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { MultiLinkCalculatorHelper } from 'app/cartography/helpers/multi-link-calculator-helper';
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { LinkComponent } from './link.component';
describe('LinkComponent', () => {
let component: LinkComponent;
let fixture: ComponentFixture<LinkComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [LinkComponent],
providers: [
{ provide: MultiLinkCalculatorHelper, useValue: {} }
]
}).compileComponents();
});
}));
beforeEach(() => {
fixture = TestBed.createComponent(LinkComponent);
@ -20,7 +17,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,21 +49,19 @@ export class LinkComponent implements OnInit, OnDestroy {
}
get strategy(): LinkStrategy {
if (this.link && this.link != undefined && this.link.linkType === 'serial') {
if (this.link.linkType === 'serial') {
return this.serialLinkStrategy;
}
return this.ethernetLinkStrategy;
}
get transform() {
if (this.link) {
const translation = this.multiLinkCalculatorHelper.linkTranslation(
this.link.distance,
this.link.source,
this.link.target
);
return `translate (${translation.dx}, ${translation.dy})`;
}
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,9 +5,8 @@ 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: 490 B

After

Width:  |  Height:  |  Size: 484 B

View File

@ -1,23 +1,15 @@
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 { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { NodeComponent } from './node.component';
describe('NodeComponent', () => {
let component: NodeComponent;
let fixture: ComponentFixture<NodeComponent>;
beforeEach(async() => {
await TestBed.configureTestingModule({
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [NodeComponent],
providers:[
CssFixer,
FontFixer,
NodesEventSource,
]
}).compileComponents();
});
}));
beforeEach(() => {
fixture = TestBed.createComponent(NodeComponent);
@ -25,7 +17,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,52 +85,42 @@ export class NodeComponent implements OnInit, OnDestroy, OnChanges, AfterViewIni
}
get symbol(): string {
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';
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';
}
get label_style() {
if (this.node != undefined) {
let styles = this.cssFixer.fix(this.node.label.style);
styles = this.fontFixer.fixStyles(styles);
return this.sanitizer.bypassSecurityTrustStyle(styles);
}
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 != undefined) {
if (this.node.label.x === null) {
// center
const bbox = this.label.nativeElement.getBBox();
if (this.node.label.x === null) {
// center
const bbox = this.label.nativeElement.getBBox();
return -bbox.width / 2;
}
return this.node.label.x + NodeComponent.NODE_LABEL_MARGIN;
return -bbox.width / 2;
}
return this.node.label.x + NodeComponent.NODE_LABEL_MARGIN;
}
get label_y(): number {
this.labelHeight = this.getLabelHeight();
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;
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;
}
private getLabelHeight() {
if (this.label != undefined) {
const bbox = this.label.nativeElement.getBBox();
return bbox.height;
}
const bbox = this.label.nativeElement.getBBox();
return bbox.height;
}
}

View File

@ -1,24 +1,23 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { SelectionComponent } from './selection.component';
describe('SelectionComponent', () => {
let component: SelectionComponent;
let fixture: ComponentFixture<SelectionComponent>;
beforeEach(() => {
beforeEach(async(() => {
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,14 +28,15 @@ 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;
@ -50,7 +51,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
@ -75,11 +76,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 { ComponentFixture, TestBed } from '@angular/core/testing';
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { StatusComponent } from './status.component';
describe('StatusComponent', () => {
let component: StatusComponent;
let fixture: ComponentFixture<StatusComponent>;
beforeEach(async() => {
await TestBed.configureTestingModule({
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [StatusComponent],
}).compileComponents();
});
}));
beforeEach(() => {
fixture = TestBed.createComponent(StatusComponent);

View File

@ -1,31 +0,0 @@
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,18 +1,15 @@
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 { async, ComponentFixture, TestBed } from '@angular/core/testing';
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);
@ -20,7 +17,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 { ComponentFixture, TestBed } from '@angular/core/testing';
import { async, 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 { Controller } from '../../../models/controller';
import { Server } from '../../../models/server';
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('controller') controller: Controller;
@Input('server') server: Server;
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.controller, link).subscribe((link: Link) => {
this.linkService.updateLink(this.server, link).subscribe((link: Link) => {
rootElement
.selectAll<SVGTextElement, TextElement>('text.editingMode')
.attr('visibility', 'visible')

View File

@ -15,7 +15,6 @@ 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 = `${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}\" />`}`;
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}\" />`;
} else if (mapDrawing.element instanceof EllipseElement) {
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}\" />`}`;
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}\" />`;
} 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}\" stroke-dasharray=\"${mapDrawing.element.stroke_dasharray ?? 'none'}\" />`;
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}\" />`;
} 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,7 +16,6 @@ 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 { ComponentFixture, fakeAsync, TestBed, tick } from '@angular/core/testing';
import { async, 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() => {
await TestBed.configureTestingModule({
beforeEach(async(() => {
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 { ComponentFixture, fakeAsync, TestBed, tick } from '@angular/core/testing';
import { async, 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() => {
await TestBed.configureTestingModule({
beforeEach(async(() => {
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,5 +1,4 @@
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';
@ -7,6 +6,5 @@ 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,47 +8,43 @@ 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: "Noto Sans",
font_size: 11,
font_weight: "bold",
font_family: 'Arial',
font_size: 12,
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', () => {
let typeWriter = "TypeWriter";
let notoSans = "Noto Sans";
const styles = `font-family:${typeWriter} ; font-size: 10px; font-weight: bold`;
const styles = 'font-family: TypeWriter; font-size: 10px; font-weight: bold';
expect(fixer.fixStyles(styles)).toEqual(`font-family:${notoSans};font-size:11px;font-weight:bold`);
expect(fixer.fixStyles(styles)).toEqual('font-family:Arial;font-size:12px;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`;
it('should fix TypeWriter font and 10px size in styles with quotes', () => {
const styles = 'font-family: "TypeWriter"; font-size: 10px; font-weight: bold';
expect(fixer.fixStyles(styles)).toEqual(`font-family:${notoSans};font-size:11px;font-weight:bold`);
expect(fixer.fixStyles(styles)).toEqual('font-family:Arial;font-size:12px;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 = 'Noto Sans';
static REPLACE_BY_SIZE = 11;
static REPLACE_BY_FONT = 'Arial';
static REPLACE_BY_SIZE = 12;
public fix(font: Font): Font {
if (font.font_family === FontFixer.DEFAULT_FONT && font.font_size === FontFixer.DEFAULT_SIZE) {

View File

@ -7,18 +7,16 @@ import { Injectable } from '@angular/core';
@Injectable()
export class QtDasharrayFixer {
static MAPPING = {
'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
'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',
};
public fix(dasharray: string): string {
if(dasharray || dasharray == '' ){
if (dasharray in QtDasharrayFixer.MAPPING) {
return QtDasharrayFixer.MAPPING[dasharray];
}
return dasharray;
}
}
}

View File

@ -45,7 +45,6 @@ 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);
@ -89,7 +88,6 @@ 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,7 +38,6 @@ 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,7 +2,6 @@ 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;
@ -14,15 +13,14 @@ export class MapLink implements Indexed {
nodes: MapLinkNode[];
projectId: string;
suspend: boolean;
link_style?: LinkStyle;
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
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
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
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
}

View File

@ -14,6 +14,7 @@ export class Properties {
headless: boolean;
linked_clone: boolean;
on_close: string;
aux: number;
ram: number;
nvram: number;
usage: string;
@ -45,6 +46,7 @@ export class Properties {
kernel_command_line: string;
kernel_image: string;
kernel_image_md5sum?: any;
legacy_networking: boolean;
mac_address: string;
options: string;
platform: string;
@ -52,8 +54,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,7 +7,6 @@ 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: "Noto Sans"; font-size: 11pt; font-weight: bold');
expect(text_element.getAttribute('style')).toEqual('font-family: "Arial"; font-size: 12pt; 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) || ( l.capturing && l.suspend)) ? 'suspended' : l.source.status,
l.capturing && l.suspend ? 'suspended' : l.source.status,
sourcePort
),
new LinkStatus(
end_point.x,
end_point.y,
(( !l.capturing && l.suspend) || ( l.capturing && l.suspend)) ? 'suspended' : l.target.status,
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 * 8 + 10;
return ls.port.length * 10 + 5;
})
.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', 'white')
.style('fill', '#c7ffdf')
.attr('stroke', '#2ecc71')
.attr('stroke-width', 3);
.attr('stroke-width', 2);
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', `black`);
.attr('fill', `#0e9647`);
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 * 8 + 10;
return ls.port.length * 10 + 5;
})
.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', 'white')
.style('fill', '#ffe3e3')
.attr('stroke', 'red')
.attr('stroke-width', 3);
.attr('stroke-width', 2);
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', `black`);
.attr('fill', `red`);
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 * 8 + 10;
return ls.port.length * 10 + 5;
})
.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', '#FFFF00')
.attr('stroke-width', 3);
.attr('stroke', '#fffbc3')
.attr('stroke-width', 2);
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', `black`);
.attr('fill', `#6b5633`);
status_suspended_label.exit().remove();
} else {
const status_started = link_group

View File

@ -22,15 +22,14 @@ 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})`;
});
@ -51,8 +50,9 @@ 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,8 +74,9 @@ 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')
@ -99,8 +100,9 @@ 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')
@ -122,8 +124,9 @@ 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,7 +11,6 @@ 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,29 +4,21 @@ 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], public style: LinkStyle) {}
constructor(public source: [number, number], public target: [number, number]) {}
}
@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.link_style.color ? link.link_style : this.defaultEthernetLinkStyle
[link.target.x + link.target.width / 2, link.target.y + link.target.height / 2]
);
}
@ -46,15 +38,15 @@ export class EthernetLinkWidget implements Widget {
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);
});
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));
});
const link_merge = link.merge(link_enter);

View File

@ -4,27 +4,19 @@ 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 style: LinkStyle
public target: [number, number]
) {}
}
@Injectable()
export class SerialLinkWidget implements Widget {
public onContextMenu = new EventEmitter<LinkContextMenu>();
private defaultSerialLinkStyle : LinkStyle = {
color: "#B22222",
width: 2,
type: 0
};
constructor() {}
@ -55,12 +47,7 @@ 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],
link.link_style.color ? link.link_style : this.defaultSerialLinkStyle);
return new SerialLinkPath([source.x, source.y], angle_source, angle_target, [target.x, target.y]);
}
public draw(view: SVGSelection) {
@ -81,16 +68,7 @@ export class SerialLinkWidget implements Widget {
this.onContextMenu.emit(new LinkContextMenu(evt, link));
});
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);
});
link_enter.attr('stroke', '#B22222').attr('fill', 'none').attr('stroke-width', '2');
const link_merge = link.merge(link_enter);

View File

@ -1,16 +0,0 @@
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,21 +31,19 @@ describe('NodesWidget', () => {
const drew = svg.canvas.selectAll<SVGGElement, MapNode>('g.node');
const drewNode = drew.nodes()[0];
if (drewNode != undefined && drewNode != null) {
drewNode.dispatchEvent(
new MouseEvent('mousedown', {
clientX: 150,
clientY: 250,
relatedTarget: drewNode,
screenY: 1024,
screenX: 1024,
view: window,
})
);
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(() => {
@ -56,9 +54,6 @@ 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,6 +4,7 @@ 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';
@ -17,6 +18,7 @@ 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,12 +14,8 @@ 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(async() => {
await TestBed.configureTestingModule({
beforeEach(() => {
TestBed.configureTestingModule({
providers: [
{ provide: ToasterService, useClass: MockedToasterService },
{ provide: SettingsService},

View File

@ -1,31 +1,15 @@
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 { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ProgressDialogComponent } from './progress-dialog.component';
describe('ProgressDialogComponent', () => {
let component: ProgressDialogComponent;
let fixture: ComponentFixture<ProgressDialogComponent>;
beforeEach(async() => {
await TestBed.configureTestingModule({
beforeEach(async(() => {
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);
@ -33,7 +17,7 @@ describe('ProgressDialogComponent', () => {
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
// it('should create', () => {
// expect(component).toBeTruthy();
// });
});

View File

@ -1,21 +1,14 @@
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 { TestBed } from '@angular/core/testing';
import { ProgressDialogService } from './progress-dialog.service';
describe('ProgressDialogService', () => {
let mockedProgressService : MockedProgressService
beforeEach(() => {
TestBed.configureTestingModule({
// imports:[ProgressDialogService],
providers: [
{ provide: MatDialog, useValue: {} },
{ provide: ProgressDialogService, useClass:MockedProgressService },
],
providers: [ProgressDialogService],
});
});
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 { ComponentFixture, TestBed } from '@angular/core/testing';
import { async, 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() => {
await TestBed.configureTestingModule({
beforeEach(async(() => {
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

@ -1,16 +0,0 @@
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

@ -1,23 +0,0 @@
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

@ -1,10 +0,0 @@
<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

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

View File

@ -1,34 +0,0 @@
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

@ -1,45 +0,0 @@
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

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

View File

@ -1,64 +0,0 @@
import { NO_ERRORS_SCHEMA } from '@angular/core';
import { ComponentFixture, fakeAsync, TestBed, tick } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { Router } from '@angular/router';
import { RouterTestingModule } from '@angular/router/testing';
import { ProgressService } from '../../common/progress/progress.service';
import{ Controller } from '../../models/controller';
import { ControllerService } from '../../services/controller.service';
import { MockedControllerService } from '../../services/controller.service.spec';
import { MockedProgressService } from '../project-map/project-map.component.spec';
import { BundledControllerFinderComponent } from './bundled-controller-finder.component';
describe('BundledControllerFinderComponent', () => {
let component: BundledControllerFinderComponent;
let fixture: ComponentFixture<BundledControllerFinderComponent>;
let router: any;
let service: ControllerService;
let progressService: MockedProgressService = new MockedProgressService();
let controllerServiceMock: jasmine.SpyObj<ControllerService>;
beforeEach(async () => {
router = {
navigate: jasmine.createSpy('navigate'),
};
controllerServiceMock = jasmine.createSpyObj<ControllerService>([
"getLocalController"
]);
await TestBed.configureTestingModule({
providers: [
{ provide: Router, useValue: router },
{ provide: ControllerService, useValue: controllerServiceMock },
{ provide: ProgressService, useValue: progressService },
],
declarations: [BundledControllerFinderComponent],
schemas: [NO_ERRORS_SCHEMA],
}).compileComponents();
fixture = TestBed.createComponent(BundledControllerFinderComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create and redirect to controller', fakeAsync(() => {
const controller = new Controller ();
controller.id = 99;
controllerServiceMock.getLocalController.and.returnValue(
Promise.resolve(controller)
);
expect(component).toBeTruthy();
tick(101)
fixture.detectChanges()
fixture.whenStable().then(() => {
expect(controllerServiceMock.getLocalController).toHaveBeenCalledWith('vps3.gns3.net',3000);
expect(router.navigate).toHaveBeenCalledWith(['/controller', 99, 'projects']);
})
service = TestBed.inject(ControllerService);
}));
});

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