Compare commits

..

59 Commits

Author SHA1 Message Date
7c7e20d95f Release v3.0.2
Some checks failed
CodeQL / Analyze (javascript) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Build / Node ${{ matrix.node }} (14) (push) Has been cancelled
Build / Node ${{ matrix.node }} (16) (push) Has been cancelled
Build / Node ${{ matrix.node }} (18) (push) Has been cancelled
2025-01-03 21:36:27 +07:00
e959a947cc Use correct image upload endpoint
Some checks failed
CodeQL / Analyze (javascript) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Build / Node ${{ matrix.node }} (14) (push) Has been cancelled
Build / Node ${{ matrix.node }} (16) (push) Has been cancelled
Build / Node ${{ matrix.node }} (18) (push) Has been cancelled
2024-12-31 18:57:36 +07:00
7b633c29dd Allow ':' in project names. Fixes https://github.com/GNS3/gns3-gui/issues/3686
Some checks failed
CodeQL / Analyze (javascript) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Build / Node ${{ matrix.node }} (14) (push) Has been cancelled
Build / Node ${{ matrix.node }} (16) (push) Has been cancelled
Build / Node ${{ matrix.node }} (18) (push) Has been cancelled
2024-12-30 16:26:51 +07:00
c24517d1f0 Release v3.0.1
Some checks failed
CodeQL / Analyze (javascript) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Build / Node ${{ matrix.node }} (14) (push) Has been cancelled
Build / Node ${{ matrix.node }} (16) (push) Has been cancelled
Build / Node ${{ matrix.node }} (18) (push) Has been cancelled
2024-12-27 20:58:03 +07:00
9043c5b97c Use template image name when uploading to controller 2024-12-27 20:57:23 +07:00
2227d11932 Handle normal user cannot access user management page. Fixes https://github.com/GNS3/gns3-server/issues/2460
Some checks are pending
CodeQL / Analyze (javascript) (push) Waiting to run
CodeQL / Analyze (python) (push) Waiting to run
Build / Node ${{ matrix.node }} (14) (push) Waiting to run
Build / Node ${{ matrix.node }} (16) (push) Waiting to run
Build / Node ${{ matrix.node }} (18) (push) Waiting to run
2024-12-26 17:21:37 +07:00
2e581c4495 Merge pull request #1533 from GNS3/bugfix/1436
Some checks failed
CodeQL / Analyze (javascript) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Build / Node ${{ matrix.node }} (14) (push) Has been cancelled
Build / Node ${{ matrix.node }} (16) (push) Has been cancelled
Build / Node ${{ matrix.node }} (18) (push) Has been cancelled
Fix error 404 when editing a project
2024-12-23 17:27:07 +07:00
cddce63e2b Fix error 404 when editing a project 2024-12-23 15:44:43 +07:00
180c65351b Merge pull request #1532 from GNS3/bugfix/1435
Fix interface labels are not persistant
2024-12-23 15:13:50 +07:00
27eb8eb9c3 Fix interface labels are not persistant 2024-12-23 15:07:09 +07:00
ab84d1eea6 Development on 3.1.0.dev1
Some checks failed
CodeQL / Analyze (javascript) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Build / Node ${{ matrix.node }} (14) (push) Has been cancelled
Build / Node ${{ matrix.node }} (16) (push) Has been cancelled
Build / Node ${{ matrix.node }} (18) (push) Has been cancelled
2024-12-20 18:11:44 +07:00
89a7588612 Release v3.0.0
Some checks are pending
CodeQL / Analyze (javascript) (push) Waiting to run
CodeQL / Analyze (python) (push) Waiting to run
Build / Node ${{ matrix.node }} (14) (push) Waiting to run
Build / Node ${{ matrix.node }} (16) (push) Waiting to run
Build / Node ${{ matrix.node }} (18) (push) Waiting to run
2024-12-19 19:46:49 +07:00
ab5d298d7b Merge branch '2.2' into master-3.0
# Conflicts:
#	package.json
2024-12-19 18:17:25 +07:00
608fcfd04e Fix unable to configure Ethernet Switch. Fixes #1530
Some checks failed
Build / build (push) Has been cancelled
2024-12-19 18:16:41 +07:00
99c6502a65 Development on 2.2.53.dev1 2024-12-02 11:27:15 +10:00
28d27194be Release v2.2.52 2024-12-02 11:05:45 +10:00
bbb7f08925 Add .iol extension filter to image dialog. Ref https://github.com/GNS3/gns3-gui/issues/3664 2024-11-25 11:03:44 +10:00
c1fa038f27 Merge branch '2.2' into master-3.0 2024-11-25 11:03:29 +10:00
52f772676b Add .iol extension filter. Ref https://github.com/GNS3/gns3-gui/issues/3664 2024-11-25 11:02:49 +10:00
e424a7f410 Release v3.0.0rc2 2024-11-20 13:46:43 +10:00
27eecf2ec9 Merge branch '2.2' into master-3.0
# Conflicts:
#	package.json
#	src/app/models/templates/docker-template.ts
#	src/app/services/template-mocks.service.ts
#	yarn.lock
2024-11-20 12:37:26 +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
9d0d88337a Release v3.0.0rc1 2024-08-11 11:00:56 -06:00
5283d074e7 Merge remote-tracking branch 'origin/2.2' into master-3.0
# Conflicts:
#	package.json
2024-08-11 10:53:25 -06: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
9cb21c7dd1 Merge remote-tracking branch 'origin/2.2' into master-3.0
# Conflicts:
#	package.json
#	src/app/layouts/default-layout/default-layout.component.html
#	src/app/layouts/default-layout/default-layout.component.ts
#	yarn.lock
2024-07-22 19:16:37 +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
f3b3f35d58 Development on 3.0.0.dev14 2024-05-19 20:55:35 +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
23 changed files with 66 additions and 38 deletions

View File

@ -1,6 +1,6 @@
{
"name": "gns3-web-ui",
"version": "3.0.0b3",
"version": "3.0.2",
"author": {
"name": "GNS3 Technology Inc.",
"email": "developers@gns3.com"

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

View File

@ -90,7 +90,7 @@ 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)
@ -122,7 +122,7 @@ 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)
@ -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)

View File

@ -39,7 +39,7 @@
<div class="col-md-4 txt-align" *ngIf="uploaderImage.queue.length <= 0">
<input
type="file"
accept=".bin,.image,.qcow2,.vmdk"
accept=".bin,.image,.iol,.qcow2,.vmdk"
multiple
#file
class="non-visible"

View File

@ -30,6 +30,7 @@ export class PortsComponent implements OnInit {
}
onAdd() {
this.newPort.name = "Ethernet" + this.newPort.port_number;
this.ethernetPorts.push(this.newPort);
this.newPort = {

View File

@ -66,6 +66,15 @@
placeholder="Start command"
/>
</mat-form-field>
<mat-form-field class="form-field">
<input
matInput
type="text"
[ngModelOptions]="{ standalone: true }"
[(ngModel)]="dockerTemplate.mac_address"
placeholder="Base MAC"
/>
</mat-form-field>
<mat-form-field class="form-field">
<input
formControlName="adapter"

View File

@ -67,7 +67,7 @@
<div *ngIf="newImageSelected">
<input
type="file"
accept=".bin"
accept=".bin, .image, .iol"
#file
class="nonvisible"
(change)="uploadImageFile($event)"

View File

@ -61,7 +61,7 @@
</mat-form-field>
<input
type="file"
accept=".bin"
accept=".bin, .image, .iol"
#file
class="nonvisible"
(change)="uploadImageFile($event)"

View File

@ -142,7 +142,7 @@ export class ImportApplianceComponent implements OnInit {
}
this.template = template;
const url = this.getUploadPath(this.controller, template.template_type, name);
const url = this.getUploadPath(this.controller, name);
this.uploader.queue.forEach((elem) => (elem.url = url));
const itemToUpload = this.uploader.queue[0];
this.uploader.uploadItem(itemToUpload);
@ -150,7 +150,7 @@ export class ImportApplianceComponent implements OnInit {
fileReader.readAsText(file);
}
private getUploadPath(controller:Controller , emulator: string, filename: string) {
return `${controller.protocol}//${controller.host}:${controller.port}/${environment.current_version}/${emulator}/images/${filename}`;
private getUploadPath(controller:Controller , filename: string) {
return `${controller.protocol}//${controller.host}:${controller.port}/${environment.current_version}/images/upload/${filename}`;
}
}

View File

@ -266,7 +266,7 @@ export class NewTemplateDialogComponent implements OnInit {
if (appliance.iou) emulator = 'iou';
if (appliance.qemu) emulator = 'qemu';
const url = this.applianceService.getUploadPath(this.controller, emulator, fileName);
const url = this.applianceService.getUploadPath(this.controller, fileName);
this.uploader.queue.forEach((elem) => (elem.url = url));
const itemToUpload = this.uploader.queue[0];
@ -341,8 +341,6 @@ export class NewTemplateDialogComponent implements OnInit {
dialogRef.componentInstance.appliance = object;
}
importImage(event, imageName) {
this.computeChecksumMd5(event.target.files[0], false).then((output) => {
let imageToInstall = this.applianceToInstall.images.filter((n) => n.filename === imageName)[0];
@ -359,22 +357,21 @@ export class NewTemplateDialogComponent implements OnInit {
The MD5 sum is ${output} and should be ${imageToInstall.md5sum}. Do you want to accept it at your own risks?`;
dialogRef.afterClosed().subscribe((answer: boolean) => {
if (answer) {
this.importImageFile(event);
this.importImageFile(event, imageName);
this.openSnackBar()
} else {
this.uploaderImage.clearQueue();
}
});
} else {
this.importImageFile(event);
this.importImageFile(event, imageName);
this.openSnackBar()
}
});
}
importImageFile(event) {
importImageFile(event, imageName) {
let name = event.target.files[0].name.split('-')[0];
let fileName = event.target.files[0].name;
let file = event.target.files[0];
let fileReader: FileReader = new FileReader();
let emulator;
@ -384,7 +381,7 @@ export class NewTemplateDialogComponent implements OnInit {
if (this.applianceToInstall.dynamips) emulator = 'dynamips';
if (this.applianceToInstall.iou) emulator = 'iou';
const url = this.applianceService.getUploadPath(this.controller, emulator, fileName);
const url = this.applianceService.getUploadPath(this.controller, imageName);
this.uploaderImage.queue.forEach((elem) => (elem.url = url));
const itemToUpload = this.uploaderImage.queue[0];

View File

@ -21,8 +21,18 @@ export class ReadmeEditorComponent implements OnInit {
) {}
ngOnInit() {
this.projectService.getReadmeFile(this.controller, this.project.project_id).subscribe(file => {
if (file) this.markdown = file;
this.projectService.getReadmeFile(this.controller, this.project.project_id).subscribe({
next: (file) => {
if (file) {
this.markdown = file;
}
},
error: (err) => {
if (err.status === 404) {
// File doesn't exist yet, which is fine
this.markdown = '';
}
}
});
}
}

View File

@ -3,7 +3,7 @@ import { Injectable } from '@angular/core';
@Injectable()
export class ProjectNameValidator {
get(projectName) {
var pattern = new RegExp(/[~`!#$%\^&*+=\[\]\\';,/{}|\\":<>\?]/);
var pattern = new RegExp(/[~`!#$%\^&*+=\[\]\\';,/{}|\\"<>\?]/);
if (!pattern.test(projectName.value)) {
return null;

View File

@ -11,6 +11,7 @@
* Author: Sylvain MATHIEU, Elise LEBEAU
*/
import {Component, OnInit, QueryList, ViewChild, ViewChildren} from '@angular/core';
import {Location} from '@angular/common';
import {ActivatedRoute, Router} from "@angular/router";
import {Controller} from "@models/controller";
import {MatSort} from "@angular/material/sort";
@ -49,7 +50,8 @@ export class UserManagementComponent implements OnInit {
private progressService: ProgressService,
private controllerService: ControllerService,
public dialog: MatDialog,
private toasterService: ToasterService) { }
private toasterService: ToasterService,
private location: Location) { }
ngOnInit() {
const controllerId = this.route.parent.snapshot.paramMap.get('controller_id');
@ -88,6 +90,8 @@ export class UserManagementComponent implements OnInit {
},
(error) => {
this.progressService.setError(error);
this.toasterService.error(`Cannot open the user management page`);
this.location.back();
}
);
}

View File

@ -90,4 +90,4 @@
<app-progress></app-progress>
<footer class="footer mat-app-background">GNS3 Web UI &copy; 2022 - v{{ uiVersion }}</footer>
<footer class="footer mat-app-background">GNS3 Web-UI &copy;2018-{{ currentYear }} v{{ uiVersion }}</footer>

View File

@ -25,6 +25,7 @@ export class DefaultLayoutComponent implements OnInit, OnDestroy {
public uiVersion = version;
public isLoginPage = false;
public routeSubscription;
public currentYear = new Date().getFullYear();
controllerStatusSubscription: Subscription;
shouldStopControllersOnClosing = true;

View File

@ -11,6 +11,7 @@ export class DockerTemplate {
console_resolution: string;
console_type: string;
aux_type: string;
mac_address: string;
custom_adapters: CustomAdapter[];
default_name_format: string;
environment: string;

View File

@ -17,8 +17,8 @@ export class ApplianceService {
return this.httpController.get<Appliance>(controller, url) as Observable<Appliance>;
}
getUploadPath(controller:Controller , emulator: string, filename: string) {
return `${controller.protocol}//${controller.host}:${controller.port}/${environment.current_version}/images/upload/${filename}?allow_raw_image=true`;
getUploadPath(controller:Controller, filename: string) {
return `${controller.protocol}//${controller.host}:${controller.port}/${environment.current_version}/images/upload/${filename}`;
}
updateAppliances(controller:Controller ): Observable<Appliance[]> {

View File

@ -14,10 +14,6 @@ export class ComputeService {
return this.httpController.get<Compute[]>(controller, '/computes') as Observable<Compute[]>;
}
getUploadPath(controller:Controller , emulator: string, filename: string) {
return `${controller.protocol}//${controller.host}:${controller.port}/${environment.current_version}/${emulator}/images/${filename}`;
}
getStatistics(controller:Controller ): Observable<ComputeStatistics[]> {
return this.httpController.get(controller, `/statistics`);
}

View File

@ -20,10 +20,6 @@ export class ImageManagerService {
return `${controller.protocol}//${controller.host}:${controller.port}/${environment.current_version}/images/upload/${image_path}?install_appliances=${install_appliance}`;
}
getUploadPath(controller:Controller , emulator: string, filename: string) {
return `${controller.protocol}//${controller.host}:${controller.port}/${environment.current_version}/images/upload/${filename}`;
}
uploadedImage(controller :Controller, install_appliance, image_path, flie){
return this.httpController.post<Image[]>(controller, `/images/upload/${image_path}?install_appliances=${install_appliance}`,flie) as Observable<Image[]>;
}

View File

@ -37,6 +37,12 @@ export class MapSettingsService {
} else {
localStorage.setItem('openReadme', 'false');
}
if (localStorage.getItem('showInterfaceLabels')) {
this.showInterfaceLabels = localStorage.getItem('showInterfaceLabels') === 'true' ? true : false;
} else {
localStorage.setItem('showInterfaceLabels', 'true');
}
}
public getSymbolScaling(): boolean {
@ -78,6 +84,12 @@ export class MapSettingsService {
toggleShowInterfaceLabels(value: boolean) {
this.showInterfaceLabels = value;
localStorage.removeItem('showInterfaceLabels');
if (value) {
localStorage.setItem('showInterfaceLabels', 'true');
} else {
localStorage.setItem('showInterfaceLabels', 'false');
}
}
toggleIntegrateInterfaceLabels(value: boolean) {

View File

@ -242,6 +242,7 @@ export class TemplateMocksService {
console_resolution: '1024x768',
console_type: 'telnet',
aux_type: 'none',
mac_address: '',
custom_adapters: [],
default_name_format: '{name}-{0}',
environment: '',

View File

@ -38,7 +38,7 @@
<body class="mat-app-background" oncontextmenu="return false;">
<app-root></app-root>
<!-- Global site tag (gtag.js) - Google Analytics -->
<script async src="https://www.googletagmanager.com/gtag/js?id=G-5D6FZL9923"></script>
<script async src="https://www.googletagmanager.com/gtag/js?id=G-0BT7QQV1W1"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag() {
@ -46,7 +46,7 @@
}
gtag('js', new Date());
gtag('config', 'G-5D6FZL9923');
gtag('config', 'G-0BT7QQV1W1');
</script>
</body>
</html>