mirror of
https://github.com/GNS3/gns3-web-ui.git
synced 2025-02-06 11:10:16 +00:00
Merge remote-tracking branch 'origin/master' into master-3.0
# Conflicts: # angular.json # package.json # src/ReleaseNotes.txt # src/app/cartography/helpers/font-fixer.spec.ts # src/app/cartography/models/node.ts # src/app/components/preferences/qemu/add-qemu-vm-template/add-qemu-vm-template.component.html # src/app/components/preferences/qemu/add-qemu-vm-template/add-qemu-vm-template.component.ts # src/app/components/project-map/node-editors/configurator/docker/configurator-docker.component.ts # src/app/components/project-map/project-map-menu/project-map-menu.component.ts # src/app/components/project-map/project-map.component.html # src/app/components/project-map/project-map.component.ts # src/app/components/projects/projects.component.html # src/app/components/settings/settings.component.html # src/app/components/settings/settings.component.spec.ts # src/app/components/template/template-list-dialog/template-list-dialog.component.html # src/app/components/template/template.component.html # src/app/components/template/template.component.ts # src/app/services/link.service.ts # yarn.lock
This commit is contained in:
commit
7ac3a628a4
1
.angular/cache/babel-webpack/d6a73bccc4e531ea9b921fbd7f814650.json
vendored
Normal file
1
.angular/cache/babel-webpack/d6a73bccc4e531ea9b921fbd7f814650.json
vendored
Normal file
File diff suppressed because one or more lines are too long
16
.github/workflows/add-new-issues-to-project.yml
vendored
Normal file
16
.github/workflows/add-new-issues-to-project.yml
vendored
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
name: Add new issues to GNS3 project
|
||||||
|
|
||||||
|
on:
|
||||||
|
issues:
|
||||||
|
types:
|
||||||
|
- opened
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
add-to-project:
|
||||||
|
name: Add issue to project
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/add-to-project@v0.4.0
|
||||||
|
with:
|
||||||
|
project-url: https://github.com/orgs/GNS3/projects/3
|
||||||
|
github-token: ${{ secrets.ADD_NEW_ISSUES_TO_PROJECT }}
|
76
.github/workflows/codeql.yml
vendored
Normal file
76
.github/workflows/codeql.yml
vendored
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
# For most projects, this workflow file will not need changing; you simply need
|
||||||
|
# to commit it to your repository.
|
||||||
|
#
|
||||||
|
# You may wish to alter this file to override the set of languages analyzed,
|
||||||
|
# or to provide custom queries or build logic.
|
||||||
|
#
|
||||||
|
# ******** NOTE ********
|
||||||
|
# We have attempted to detect the languages in your repository. Please check
|
||||||
|
# the `language` matrix defined below to confirm you have the correct set of
|
||||||
|
# supported CodeQL languages.
|
||||||
|
#
|
||||||
|
name: "CodeQL"
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [ "master-3.0" ]
|
||||||
|
pull_request:
|
||||||
|
# The branches below must be a subset of the branches above
|
||||||
|
branches: [ "master-3.0" ]
|
||||||
|
schedule:
|
||||||
|
- cron: '38 18 * * 6'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
analyze:
|
||||||
|
name: Analyze
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
actions: read
|
||||||
|
contents: read
|
||||||
|
security-events: write
|
||||||
|
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
language: [ 'javascript', 'python' ]
|
||||||
|
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
|
||||||
|
# Use only 'java' to analyze code written in Java, Kotlin or both
|
||||||
|
# Use only 'javascript' to analyze code written in JavaScript, TypeScript or both
|
||||||
|
# Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
|
# Initializes the CodeQL tools for scanning.
|
||||||
|
- name: Initialize CodeQL
|
||||||
|
uses: github/codeql-action/init@v2
|
||||||
|
with:
|
||||||
|
languages: ${{ matrix.language }}
|
||||||
|
# If you wish to specify custom queries, you can do so here or in a config file.
|
||||||
|
# By default, queries listed here will override any specified in a config file.
|
||||||
|
# Prefix the list here with "+" to use these queries and those in the config file.
|
||||||
|
|
||||||
|
# Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
|
||||||
|
# queries: security-extended,security-and-quality
|
||||||
|
|
||||||
|
|
||||||
|
# Autobuild attempts to build any compiled languages (C/C++, C#, Go, or Java).
|
||||||
|
# If this step fails, then you should remove it and run the build manually (see below)
|
||||||
|
- name: Autobuild
|
||||||
|
uses: github/codeql-action/autobuild@v2
|
||||||
|
|
||||||
|
# ℹ️ Command-line programs to run using the OS shell.
|
||||||
|
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
|
||||||
|
|
||||||
|
# If the Autobuild fails above, remove it and uncomment the following three lines.
|
||||||
|
# modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance.
|
||||||
|
|
||||||
|
# - run: |
|
||||||
|
# echo "Run, Build Application using script"
|
||||||
|
# ./location_of_script_within_repo/buildscript.sh
|
||||||
|
|
||||||
|
- name: Perform CodeQL Analysis
|
||||||
|
uses: github/codeql-action/analyze@v2
|
||||||
|
with:
|
||||||
|
category: "/language:${{matrix.language}}"
|
@ -2,7 +2,8 @@
|
|||||||
"scanSettings": {
|
"scanSettings": {
|
||||||
"configMode": "AUTO",
|
"configMode": "AUTO",
|
||||||
"configExternalURL": "",
|
"configExternalURL": "",
|
||||||
"projectToken" : ""
|
"projectToken" : "",
|
||||||
|
"baseBranches": ["master", "master-3.0"]
|
||||||
},
|
},
|
||||||
"checkRunSettings": {
|
"checkRunSettings": {
|
||||||
"vulnerableCheckRunConclusionLevel": "failure"
|
"vulnerableCheckRunConclusionLevel": "failure"
|
||||||
@ -10,4 +11,4 @@
|
|||||||
"issueSettings": {
|
"issueSettings": {
|
||||||
"minSeverityLevel": "LOW"
|
"minSeverityLevel": "LOW"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
5
SECURITY.md
Normal file
5
SECURITY.md
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
# Security Policy
|
||||||
|
|
||||||
|
## Reporting a Vulnerability
|
||||||
|
|
||||||
|
Please use GitHub's report a vulnerability feature. More information can be found in https://docs.github.com/en/code-security/security-advisories/guidance-on-reporting-and-writing/privately-reporting-a-security-vulnerability
|
@ -228,4 +228,4 @@
|
|||||||
"cli": {
|
"cli": {
|
||||||
"analytics": false
|
"analytics": false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,7 +25,7 @@ module.exports = function (config) {
|
|||||||
colors: true,
|
colors: true,
|
||||||
logLevel: config.LOG_INFO,
|
logLevel: config.LOG_INFO,
|
||||||
autoWatch: true,
|
autoWatch: true,
|
||||||
browsers: ['ChromeHeadless'],
|
browsers: ['Chrome'],
|
||||||
singleRun: true
|
singleRun: true
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
"start": "ng serve",
|
"start": "ng serve",
|
||||||
"startforelectron": "ng serve --configuration=electronDev",
|
"startforelectron": "ng serve --configuration=electronDev",
|
||||||
"build": "ng build",
|
"build": "ng build",
|
||||||
"buildforproduction": "ng build --source-map=false --configuration=production --base-href /static/web-ui/",
|
"buildforproduction": "ng build --source-map=false --build-optimizer --configuration=production --base-href /static/web-ui/",
|
||||||
"buildforelectron": "ng build --configuration=electronProd",
|
"buildforelectron": "ng build --configuration=electronProd",
|
||||||
"buildforgithub": "ng build --configuration=githubProd",
|
"buildforgithub": "ng build --configuration=githubProd",
|
||||||
"test": "ng test",
|
"test": "ng test",
|
||||||
|
@ -9,8 +9,8 @@ import { Font } from '../models/font';
|
|||||||
export class FontFixer {
|
export class FontFixer {
|
||||||
static DEFAULT_FONT = 'TypeWriter';
|
static DEFAULT_FONT = 'TypeWriter';
|
||||||
static DEFAULT_SIZE = 10;
|
static DEFAULT_SIZE = 10;
|
||||||
static REPLACE_BY_FONT = 'Noto Sans';
|
static REPLACE_BY_FONT = 'Arial';
|
||||||
static REPLACE_BY_SIZE = 11;
|
static REPLACE_BY_SIZE = 12;
|
||||||
|
|
||||||
public fix(font: Font): Font {
|
public fix(font: Font): Font {
|
||||||
if (font.font_family === FontFixer.DEFAULT_FONT && font.font_size === FontFixer.DEFAULT_SIZE) {
|
if (font.font_family === FontFixer.DEFAULT_FONT && font.font_size === FontFixer.DEFAULT_SIZE) {
|
||||||
|
@ -42,7 +42,7 @@ describe('TextDrawingWidget', () => {
|
|||||||
const text_element = drew.nodes()[0];
|
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.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('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');
|
expect(text_element.getAttribute('text-decoration')).toEqual('line-through');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -97,9 +97,9 @@ export class InterfaceStatusWidget implements Widget {
|
|||||||
.attr('y', (ls: LinkStatus) => ls.y - 10)
|
.attr('y', (ls: LinkStatus) => ls.y - 10)
|
||||||
.attr('rx', 8)
|
.attr('rx', 8)
|
||||||
.attr('ry', 8)
|
.attr('ry', 8)
|
||||||
.style('fill', 'white')
|
.style('fill', '#c7ffdf')
|
||||||
.attr('stroke', '#2ecc71')
|
.attr('stroke', '#2ecc71')
|
||||||
.attr('stroke-width', 3);
|
.attr('stroke-width', 2);
|
||||||
status_started.exit().remove();
|
status_started.exit().remove();
|
||||||
const status_started_label = link_group
|
const status_started_label = link_group
|
||||||
.selectAll<SVGTextElement, LinkStatus>('text.status_started_label')
|
.selectAll<SVGTextElement, LinkStatus>('text.status_started_label')
|
||||||
@ -111,7 +111,7 @@ export class InterfaceStatusWidget implements Widget {
|
|||||||
.text((ls: LinkStatus) => ls.port)
|
.text((ls: LinkStatus) => ls.port)
|
||||||
.attr('x', (ls: LinkStatus) => ls.x - 25)
|
.attr('x', (ls: LinkStatus) => ls.x - 25)
|
||||||
.attr('y', (ls: LinkStatus) => ls.y + 5)
|
.attr('y', (ls: LinkStatus) => ls.y + 5)
|
||||||
.attr('fill', `black`);
|
.attr('fill', `#0e9647`);
|
||||||
status_started_label.exit().remove();
|
status_started_label.exit().remove();
|
||||||
|
|
||||||
const status_stopped = link_group
|
const status_stopped = link_group
|
||||||
@ -129,9 +129,9 @@ export class InterfaceStatusWidget implements Widget {
|
|||||||
.attr('y', (ls: LinkStatus) => ls.y - 10)
|
.attr('y', (ls: LinkStatus) => ls.y - 10)
|
||||||
.attr('rx', 8)
|
.attr('rx', 8)
|
||||||
.attr('ry', 8)
|
.attr('ry', 8)
|
||||||
.style('fill', 'white')
|
.style('fill', '#ffe3e3')
|
||||||
.attr('stroke', 'red')
|
.attr('stroke', 'red')
|
||||||
.attr('stroke-width', 3);
|
.attr('stroke-width', 2);
|
||||||
status_stopped.exit().remove();
|
status_stopped.exit().remove();
|
||||||
const status_stopped_label = link_group
|
const status_stopped_label = link_group
|
||||||
.selectAll<SVGTextElement, LinkStatus>('text.status_stopped_label')
|
.selectAll<SVGTextElement, LinkStatus>('text.status_stopped_label')
|
||||||
@ -143,7 +143,7 @@ export class InterfaceStatusWidget implements Widget {
|
|||||||
.text((ls: LinkStatus) => ls.port)
|
.text((ls: LinkStatus) => ls.port)
|
||||||
.attr('x', (ls: LinkStatus) => ls.x - 25)
|
.attr('x', (ls: LinkStatus) => ls.x - 25)
|
||||||
.attr('y', (ls: LinkStatus) => ls.y + 5)
|
.attr('y', (ls: LinkStatus) => ls.y + 5)
|
||||||
.attr('fill', `black`);
|
.attr('fill', `red`);
|
||||||
status_stopped_label.exit().remove();
|
status_stopped_label.exit().remove();
|
||||||
|
|
||||||
const status_suspended = link_group
|
const status_suspended = link_group
|
||||||
@ -162,8 +162,8 @@ export class InterfaceStatusWidget implements Widget {
|
|||||||
.attr('rx', 8)
|
.attr('rx', 8)
|
||||||
.attr('ry', 8)
|
.attr('ry', 8)
|
||||||
.style('fill', 'white')
|
.style('fill', 'white')
|
||||||
.attr('stroke', '#FFFF00')
|
.attr('stroke', '#fffbc3')
|
||||||
.attr('stroke-width', 3);
|
.attr('stroke-width', 2);
|
||||||
status_suspended.exit().remove();
|
status_suspended.exit().remove();
|
||||||
const status_suspended_label = link_group
|
const status_suspended_label = link_group
|
||||||
.selectAll<SVGTextElement, LinkStatus>('text.status_suspended_label')
|
.selectAll<SVGTextElement, LinkStatus>('text.status_suspended_label')
|
||||||
@ -175,7 +175,7 @@ export class InterfaceStatusWidget implements Widget {
|
|||||||
.text((ls: LinkStatus) => ls.port)
|
.text((ls: LinkStatus) => ls.port)
|
||||||
.attr('x', (ls: LinkStatus) => ls.x - 25)
|
.attr('x', (ls: LinkStatus) => ls.x - 25)
|
||||||
.attr('y', (ls: LinkStatus) => ls.y + 5)
|
.attr('y', (ls: LinkStatus) => ls.y + 5)
|
||||||
.attr('fill', `black`);
|
.attr('fill', `#6b5633`);
|
||||||
status_suspended_label.exit().remove();
|
status_suspended_label.exit().remove();
|
||||||
} else {
|
} else {
|
||||||
const status_started = link_group
|
const status_started = link_group
|
||||||
|
@ -106,7 +106,6 @@
|
|||||||
placeholder="Please enter name"
|
placeholder="Please enter name"
|
||||||
/>
|
/>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
<!-- here removed the processbar and common processbar -->
|
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</mat-step>
|
</mat-step>
|
||||||
|
@ -29,7 +29,7 @@ export class ConsoleDeviceActionComponent implements OnInit {
|
|||||||
let consoleCommand = this.settingsService.getConsoleSettings()
|
let consoleCommand = this.settingsService.getConsoleSettings()
|
||||||
? this.settingsService.getConsoleSettings()
|
? this.settingsService.getConsoleSettings()
|
||||||
: this.nodeService.getDefaultCommand();
|
: this.nodeService.getDefaultCommand();
|
||||||
const startedNodes = this.nodes.filter((node) => node.status === 'started');
|
const startedNodes = this.nodes.filter((node) => node.status === 'started' && node.console_type !== 'none');
|
||||||
|
|
||||||
if (startedNodes.length === 0) {
|
if (startedNodes.length === 0) {
|
||||||
this.toasterService.error('Device needs to be started in order to console to it.');
|
this.toasterService.error('Device needs to be started in order to console to it.');
|
||||||
@ -37,7 +37,7 @@ export class ConsoleDeviceActionComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (var node of this.nodes) {
|
for (var node of this.nodes) {
|
||||||
if (node.status !== 'started') {
|
if (node.status !== 'started' && node.console_type !== 'none') {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -232,12 +232,12 @@ export class LogConsoleComponent implements OnInit, AfterViewInit, OnDestroy {
|
|||||||
location.assign(
|
location.assign(
|
||||||
`gns3+vnc://${node.console_host}:${node.console}?name=${node.name}&project_id=${node.project_id}&node_id=${node.node_id}`
|
`gns3+vnc://${node.console_host}:${node.console}?name=${node.name}&project_id=${node.project_id}&node_id=${node.node_id}`
|
||||||
);
|
);
|
||||||
} else if (node.console_type === 'spice') {
|
} else if (node.console_type.startsWith('spice')) {
|
||||||
location.assign(
|
location.assign(
|
||||||
`gns3+spice://${node.console_host}:${node.console}?name=${node.name}&project_id=${node.project_id}&node_id=${node.node_id}`
|
`gns3+spice://${node.console_host}:${node.console}?name=${node.name}&project_id=${node.project_id}&node_id=${node.node_id}`
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
this.showCommand('Supported console types: telnet, vnc, spice.');
|
this.showCommand('Supported console types are: telnet, vnc, spice and spice+agent');
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
this.showCommand(`This node must be started before a console can be opened.`);
|
this.showCommand(`This node must be started before a console can be opened.`);
|
||||||
|
@ -110,7 +110,7 @@
|
|||||||
|
|
||||||
<h6>Additional directories</h6>
|
<h6>Additional directories</h6>
|
||||||
<mat-form-field class="form-field">
|
<mat-form-field class="form-field">
|
||||||
<textarea matInput type="text" [(ngModel)]="node.properties.extra_volumes"></textarea>
|
<textarea matInput type="text" [(ngModel)]="additionalDirectories"></textarea>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
</mat-tab>
|
</mat-tab>
|
||||||
|
|
||||||
|
@ -56,7 +56,7 @@ export class StartCaptureDialogComponent implements OnInit {
|
|||||||
const sourcePort = sourceNode.ports[this.link.nodes[0].port_number];
|
const sourcePort = sourceNode.ports[this.link.nodes[0].port_number];
|
||||||
const targetPort = targetNode.ports[this.link.nodes[1].port_number];
|
const targetPort = targetNode.ports[this.link.nodes[1].port_number];
|
||||||
this.inputForm.controls['fileName'].setValue(
|
this.inputForm.controls['fileName'].setValue(
|
||||||
`${sourceNode.name}_${sourcePort.name}_to_${targetNode.name}_${targetPort.name}`
|
`${sourceNode.name}_${sourcePort.name}_to_${targetNode.name}_${targetPort.name}`.replace(new RegExp('[^0-9A-Za-z_-]', 'g'), '')
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -207,7 +207,7 @@ export class ProjectMapMenuComponent implements OnInit, OnDestroy {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public changeLockValue() {
|
public changeLockValue() {
|
||||||
this.isLocked = !this.isLocked;
|
this.isLocked = !this.isLocked;
|
||||||
this.mapSettingsService.changeMapLockValue(this.isLocked);
|
this.mapSettingsService.changeMapLockValue(this.isLocked);
|
||||||
@ -269,7 +269,7 @@ export class ProjectMapMenuComponent implements OnInit, OnDestroy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private createSvgFileForImage(image: string | ArrayBuffer, imageToUpload: HTMLImageElement) {
|
private createSvgFileForImage(image: string | ArrayBuffer, imageToUpload: HTMLImageElement) {
|
||||||
return `<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" height=\"${imageToUpload.height}\"
|
return `<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" height=\"${imageToUpload.height}\"
|
||||||
width=\"${imageToUpload.width}\">\n<image height=\"${imageToUpload.height}\" width=\"${imageToUpload.width}\" xlink:href=\"${image}\"/>\n</svg>`;
|
width=\"${imageToUpload.width}\">\n<image height=\"${imageToUpload.height}\" width=\"${imageToUpload.width}\" xlink:href=\"${image}\"/>\n</svg>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -91,7 +91,7 @@
|
|||||||
<mat-icon>work</mat-icon>
|
<mat-icon>work</mat-icon>
|
||||||
<span>Projects</span>
|
<span>Projects</span>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<button mat-menu-item routerLink="/controller/{{ controller.id }}/preferences">
|
<button mat-menu-item routerLink="/controller/{{ controller.id }}/preferences">
|
||||||
<mat-icon>settings_applications</mat-icon>
|
<mat-icon>settings_applications</mat-icon>
|
||||||
<span>Template preferences</span>
|
<span>Template preferences</span>
|
||||||
|
@ -73,6 +73,10 @@ g.node:hover {
|
|||||||
font-size: 28px !important;
|
font-size: 28px !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.map-settings-button mat-icon {
|
||||||
|
font-size: 22px !important;
|
||||||
|
}
|
||||||
|
|
||||||
.selected {
|
.selected {
|
||||||
background: rgba(0, 151, 167, 0.1);
|
background: rgba(0, 151, 167, 0.1);
|
||||||
|
|
||||||
|
@ -998,7 +998,7 @@ export class ProjectMapComponent implements OnInit, OnDestroy {
|
|||||||
this.exportPortableProjectDialog();
|
this.exportPortableProjectDialog();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
exportPortableProjectDialog() {
|
exportPortableProjectDialog() {
|
||||||
const dialogRef = this.dialog.open(ExportPortableProjectComponent, {
|
const dialogRef = this.dialog.open(ExportPortableProjectComponent, {
|
||||||
width: '700px',
|
width: '700px',
|
||||||
|
@ -77,17 +77,17 @@
|
|||||||
matTooltip="Export project"
|
matTooltip="Export project"
|
||||||
matTooltipClass="custom-tooltip"
|
matTooltipClass="custom-tooltip"
|
||||||
(click)="exportSelectProject(row)"
|
(click)="exportSelectProject(row)"
|
||||||
|
|
||||||
>
|
>
|
||||||
<mat-icon aria-label="Export project">arrow_downward</mat-icon>
|
<mat-icon aria-label="Export project">arrow_downward</mat-icon>
|
||||||
|
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
</mat-cell>
|
</mat-cell>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<ng-container matColumnDef="delete" >
|
<ng-container matColumnDef="delete" >
|
||||||
<mat-header-cell *matHeaderCellDef class="action">
|
<mat-header-cell *matHeaderCellDef class="action">
|
||||||
<button mat-button matTooltip="Delete all projects" matTooltipClass="custom-tooltip"*ngIf="(selection.hasValue() && isAllSelected()) || selection.selected.length > 1" (click)="deleteAllFiles()" aria-label="Example icon button with a delete icon">
|
<button mat-button matTooltip="Delete all projects" matTooltipClass="custom-tooltip"*ngIf="(selection.hasValue() && isAllSelected()) || selection.selected.length > 1" (click)="deleteAllFiles()" aria-label="Example icon button with a delete icon">
|
||||||
<mat-icon>delete</mat-icon>
|
<mat-icon>delete</mat-icon>
|
||||||
</button>
|
</button>
|
||||||
|
@ -69,6 +69,12 @@ export class ProjectsComponent implements OnInit {
|
|||||||
this.projectService.projectListSubject.subscribe(() => this.refresh());
|
this.projectService.projectListSubject.subscribe(() => this.refresh());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
goToSystemStatus() {
|
||||||
|
this.router
|
||||||
|
.navigate(['/server', this.server.id, 'systemstatus'])
|
||||||
|
.catch((error) => this.toasterService.error('Cannot navigate to the system status'));
|
||||||
|
}
|
||||||
|
|
||||||
refresh() {
|
refresh() {
|
||||||
this.projectService.list(this.controller).subscribe(
|
this.projectService.list(this.controller).subscribe(
|
||||||
(projects: Project[]) => {
|
(projects: Project[]) => {
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
::ng-deep .mat-menu-panel {
|
::ng-deep .mat-menu-panel {
|
||||||
max-width: 400px;
|
max-width: 400px;
|
||||||
max-height: 500px;
|
max-height: 640px;
|
||||||
|
border-radius: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.menu {
|
.menu {
|
||||||
@ -8,6 +9,26 @@
|
|||||||
overflow-y: scroll;
|
overflow-y: scroll;
|
||||||
scrollbar-color: darkgrey #263238;
|
scrollbar-color: darkgrey #263238;
|
||||||
scrollbar-width: thin;
|
scrollbar-width: thin;
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.templateMenuHeader {
|
||||||
|
border-bottom: 1px solid rgba(255,255,255,0.05);
|
||||||
|
}
|
||||||
|
|
||||||
|
.templateFilterBar {
|
||||||
|
padding: 10px 2%;
|
||||||
|
background-color: rgba(0,0,0,0.2);
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.templateFilterBar > .form-field {
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.templateFilterBar .searchIcon {
|
||||||
|
position: relative;
|
||||||
|
top: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
::-webkit-scrollbar {
|
::-webkit-scrollbar {
|
||||||
@ -24,20 +45,22 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.form-field {
|
.form-field {
|
||||||
width: 90%;
|
width: 44%;
|
||||||
margin-left: 5%;
|
margin-left: 3%;
|
||||||
margin-right: 5%;
|
margin-right: 3%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.image {
|
.image {
|
||||||
width: 65px;
|
display: inline-block;
|
||||||
height: 65px;
|
width: 55px;
|
||||||
|
height: 55px;
|
||||||
filter: invert(0);
|
filter: invert(0);
|
||||||
--webkit-filter: invert(0) !important;
|
--webkit-filter: invert(0) !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.templateList {
|
.templateList {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
padding: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.templateRow {
|
.templateRow {
|
||||||
@ -55,6 +78,23 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.templateIcon {
|
.templateIcon {
|
||||||
width: 80px !important;
|
width: 90px !important;
|
||||||
padding: 10px;
|
padding: 2px 5px;
|
||||||
|
text-align: center;
|
||||||
|
margin: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.templateIcon > .iconContainer {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
width: 70px;
|
||||||
|
height: 70px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
border-radius: 50%;
|
||||||
|
cursor: move;
|
||||||
|
}
|
||||||
|
|
||||||
|
.templateIcon > .iconContainer:hover {
|
||||||
|
background-color: rgba(237, 246, 231, 0.08);
|
||||||
}
|
}
|
||||||
|
@ -57,7 +57,7 @@ export class TemplateComponent implements OnInit, OnDestroy {
|
|||||||
private symbolService: SymbolService,
|
private symbolService: SymbolService,
|
||||||
private domSanitizer: DomSanitizer,
|
private domSanitizer: DomSanitizer,
|
||||||
private themeService: ThemeService,
|
private themeService: ThemeService,
|
||||||
private overlayContainer: OverlayContainer,
|
private overlayContainer: OverlayContainer,
|
||||||
) {
|
) {
|
||||||
this.overlay = overlayContainer.getContainerElement();
|
this.overlay = overlayContainer.getContainerElement();
|
||||||
}
|
}
|
||||||
|
@ -79,13 +79,15 @@ export class NodeConsoleService {
|
|||||||
let nodesToStart = 'Please start the following nodes if you want to open consoles for them: ';
|
let nodesToStart = 'Please start the following nodes if you want to open consoles for them: ';
|
||||||
let nodesToStartCounter = 0;
|
let nodesToStartCounter = 0;
|
||||||
nodes.forEach((n) => {
|
nodes.forEach((n) => {
|
||||||
if (n.status === 'started') {
|
if (n.console_type !== "none") {
|
||||||
this.mapSettingsService.logConsoleSubject.next(true);
|
if (n.status === 'started') {
|
||||||
// this timeout is required due to xterm.js implementation
|
this.mapSettingsService.logConsoleSubject.next(true);
|
||||||
setTimeout(() => { this.openConsoleForNode(n); }, 500);
|
// this timeout is required due to xterm.js implementation
|
||||||
} else {
|
setTimeout(() => { this.openConsoleForNode(n); }, 500);
|
||||||
nodesToStartCounter++;
|
} else {
|
||||||
nodesToStart += n.name + ' '
|
nodesToStartCounter++;
|
||||||
|
nodesToStart += n.name + ' '
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
if (nodesToStartCounter > 0) {
|
if (nodesToStartCounter > 0) {
|
||||||
@ -94,16 +96,19 @@ export class NodeConsoleService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
openConsolesForAllNodesInNewTabs(nodes: Node[]) {
|
openConsolesForAllNodesInNewTabs(nodes: Node[]) {
|
||||||
let nodesToStart = 'Please start the following nodes if you want to open consoles for them: ';
|
let nodesToStart = 'Please start the following nodes if you want to open consoles in tabs for them: ';
|
||||||
let nodesToStartCounter = 0;
|
let nodesToStartCounter = 0;
|
||||||
nodes.forEach((n) => {
|
nodes.forEach((n) => {
|
||||||
if (n.status === 'started') {
|
// opening a console in tab is only supported for telnet type
|
||||||
let url = this.router.url.split('/');
|
if (n.console_type === "telnet") {
|
||||||
let urlString = `/static/web-ui/${url[1]}/${url[2]}/${url[3]}/${url[4]}/nodes/${n.node_id}`;
|
if (n.status === 'started') {
|
||||||
window.open(urlString);
|
let url = this.router.url.split('/');
|
||||||
} else {
|
let urlString = `/static/web-ui/${url[1]}/${url[2]}/${url[3]}/${url[4]}/nodes/${n.node_id}`;
|
||||||
nodesToStartCounter++;
|
window.open(urlString);
|
||||||
nodesToStart += n.name + ' '
|
} else {
|
||||||
|
nodesToStartCounter++;
|
||||||
|
nodesToStart += n.name + ' '
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
if (nodesToStartCounter > 0) {
|
if (nodesToStartCounter > 0) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user