mirror of
https://github.com/GNS3/gns3-web-ui.git
synced 2025-01-18 02:39:50 +00:00
Merge pull request #95 from GNS3/sentry
Connect crash analytics service, Fixes: #13
This commit is contained in:
commit
01f2518323
@ -14,13 +14,11 @@ jobs:
|
|||||||
sudo systemsetup -settimezone Europe/Warsaw
|
sudo systemsetup -settimezone Europe/Warsaw
|
||||||
echo "Today is $(date +"%Y-%m-%d %T")"
|
echo "Today is $(date +"%Y-%m-%d %T")"
|
||||||
|
|
||||||
- restore_cache:
|
# - restore_cache:
|
||||||
name: Restore Yarn Package Cache
|
# name: Restore Yarn Package Cache
|
||||||
keys:
|
# keys:
|
||||||
- yarn-packages-{{ .Branch }}-{{ checksum "yarn.lock" }}
|
# - dependency-cache-{{ checksum "yarn.lock" }}
|
||||||
- yarn-packages-{{ .Branch }}
|
# - dependency-cache-
|
||||||
- yarn-packages-master
|
|
||||||
- yarn-packages-
|
|
||||||
|
|
||||||
- run:
|
- run:
|
||||||
name: Install project
|
name: Install project
|
||||||
@ -30,11 +28,11 @@ jobs:
|
|||||||
yarn || true
|
yarn || true
|
||||||
yarn || true
|
yarn || true
|
||||||
|
|
||||||
- save_cache:
|
# - save_cache:
|
||||||
name: Save Yarn Package Cache
|
# name: Save Yarn Package Cache
|
||||||
key: yarn-packages-{{ .Branch }}-{{ checksum "yarn.lock" }}
|
# key: dependency-cache-{{ checksum "yarn.lock" }}
|
||||||
paths:
|
# paths:
|
||||||
- node_modules/
|
# - ./node_modules
|
||||||
|
|
||||||
- run:
|
- run:
|
||||||
name: Building WebUI for distribution
|
name: Building WebUI for distribution
|
||||||
|
58
main.js
58
main.js
@ -1,22 +1,39 @@
|
|||||||
const electron = require('electron');
|
const electron = require('electron');
|
||||||
var fs = require('fs');
|
const fs = require('fs');
|
||||||
// Module to control application life.
|
|
||||||
const app = electron.app;
|
const app = electron.app;
|
||||||
// Module to create native browser window.
|
|
||||||
const BrowserWindow = electron.BrowserWindow;
|
const BrowserWindow = electron.BrowserWindow;
|
||||||
|
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
const url = require('url');
|
const url = require('url');
|
||||||
|
const yargs = require('yargs');
|
||||||
|
|
||||||
|
require('./sentry');
|
||||||
|
|
||||||
// Keep a global reference of the window object, if you don't, the window will
|
// Keep a global reference of the window object, if you don't, the window will
|
||||||
// be closed automatically when the JavaScript object is garbage collected.
|
// be closed automatically when the JavaScript object is garbage collected.
|
||||||
let mainWindow;
|
let mainWindow;
|
||||||
|
|
||||||
let serverProc = null;
|
let serverProc = null;
|
||||||
|
|
||||||
let isWin = /^win/.test(process.platform);
|
let isWin = /^win/.test(process.platform);
|
||||||
|
let isDev = false;
|
||||||
|
|
||||||
|
const argv = yargs
|
||||||
|
.describe('m', 'Maximizes window on startup.')
|
||||||
|
.boolean('m')
|
||||||
|
.describe('e', 'Environment, `dev` for developer mode and when not specified then production mode. ')
|
||||||
|
.choices('e', ['dev', null])
|
||||||
|
.argv;
|
||||||
|
|
||||||
|
if (argv.e == 'dev') {
|
||||||
|
isDev = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
const createServerProc = () => {
|
const createServerProc = () => {
|
||||||
|
const directory = path.join(__dirname, 'dist');
|
||||||
|
|
||||||
|
if (!fs.existsSync(directory)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
fs.readdir(path.join(__dirname, 'dist'), (err, files) => {
|
fs.readdir(path.join(__dirname, 'dist'), (err, files) => {
|
||||||
var serverPath = null;
|
var serverPath = null;
|
||||||
|
|
||||||
@ -43,8 +60,10 @@ const createServerProc = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const exitServerProc = () => {
|
const exitServerProc = () => {
|
||||||
serverProc.kill();
|
if(serverProc) {
|
||||||
serverProc = null;
|
serverProc.kill();
|
||||||
|
serverProc = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -53,15 +72,26 @@ function createWindow () {
|
|||||||
mainWindow = new BrowserWindow({width: 800, height: 600});
|
mainWindow = new BrowserWindow({width: 800, height: 600});
|
||||||
|
|
||||||
// and load the index.html of the app.
|
// and load the index.html of the app.
|
||||||
mainWindow.loadURL(url.format({
|
|
||||||
pathname: path.join(__dirname, 'dist/index.html'),
|
if(isDev) {
|
||||||
protocol: 'file:',
|
mainWindow.loadURL('http://localhost:4200/');
|
||||||
slashes: true
|
mainWindow.webContents.openDevTools();
|
||||||
}));
|
}
|
||||||
|
else {
|
||||||
|
mainWindow.loadURL(url.format({
|
||||||
|
pathname: path.join(__dirname, 'dist/index.html'),
|
||||||
|
protocol: 'file:',
|
||||||
|
slashes: true
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
// Open the DevTools.
|
// Open the DevTools.
|
||||||
// mainWindow.webContents.openDevTools();
|
// mainWindow.webContents.openDevTools();
|
||||||
|
|
||||||
|
if(argv.m) {
|
||||||
|
mainWindow.maximize();
|
||||||
|
}
|
||||||
|
|
||||||
// Emitted when the window is closed.
|
// Emitted when the window is closed.
|
||||||
mainWindow.on('closed', function () {
|
mainWindow.on('closed', function () {
|
||||||
// Dereference the window object, usually you would store windows
|
// Dereference the window object, usually you would store windows
|
||||||
@ -98,3 +128,5 @@ app.on('activate', function () {
|
|||||||
|
|
||||||
// In this file you can include the rest of your app's specific main process
|
// In this file you can include the rest of your app's specific main process
|
||||||
// code. You can also put them in separate files and require them here.
|
// code. You can also put them in separate files and require them here.
|
||||||
|
|
||||||
|
|
||||||
|
@ -16,7 +16,8 @@
|
|||||||
"test": "ng test",
|
"test": "ng test",
|
||||||
"lint": "ng lint",
|
"lint": "ng lint",
|
||||||
"e2e": "ng e2e",
|
"e2e": "ng e2e",
|
||||||
"electrondev": "concurrently -k \"yarn startforelectron\" \"electron .\"",
|
"electron": "electron .",
|
||||||
|
"electrondev": "concurrently -k \"yarn startforelectron\" \"electron . -e dev\"",
|
||||||
"distlinux": "yarn buildforelectron && electron-builder --linux --x64",
|
"distlinux": "yarn buildforelectron && electron-builder --linux --x64",
|
||||||
"distwin": "yarn buildforelectron && electron-builder --win --x64",
|
"distwin": "yarn buildforelectron && electron-builder --win --x64",
|
||||||
"distmac": "yarn buildforelectron && electron-builder --mac --x64",
|
"distmac": "yarn buildforelectron && electron-builder --mac --x64",
|
||||||
@ -36,20 +37,25 @@
|
|||||||
"@angular/platform-browser-dynamic": "^5.2.1",
|
"@angular/platform-browser-dynamic": "^5.2.1",
|
||||||
"@angular/router": "^5.2.1",
|
"@angular/router": "^5.2.1",
|
||||||
"@ng-bootstrap/ng-bootstrap": "^1.0.0-beta.9",
|
"@ng-bootstrap/ng-bootstrap": "^1.0.0-beta.9",
|
||||||
|
"angular-persistence": "^1.0.1",
|
||||||
"angular2-hotkeys": "^2.0.4",
|
"angular2-hotkeys": "^2.0.4",
|
||||||
"angular2-indexeddb": "^1.2.2",
|
"angular2-indexeddb": "^1.2.2",
|
||||||
"bootstrap": "4.0.0",
|
"bootstrap": "4.0.0",
|
||||||
"core-js": "^2.4.1",
|
"core-js": "^2.4.1",
|
||||||
"d3-ng2-service": "^1.23.3",
|
"d3-ng2-service": "^1.23.3",
|
||||||
|
"electron-settings": "^3.1.4",
|
||||||
|
"ngx-electron": "^1.0.4",
|
||||||
"npm-check-updates": "^2.13.0",
|
"npm-check-updates": "^2.13.0",
|
||||||
"raven-js": "^3.24.0",
|
"raven-js": "^3.24.0",
|
||||||
"rxjs": "^5.4.1",
|
"rxjs": "^5.4.1",
|
||||||
|
"yargs": "^11.0.0",
|
||||||
"zone.js": "^0.8.20"
|
"zone.js": "^0.8.20"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@angular/cli": "^6.0.0-beta.5",
|
"@angular/cli": "^6.0.0-beta.5",
|
||||||
"@angular/compiler-cli": "^5.2.1",
|
"@angular/compiler-cli": "^5.2.1",
|
||||||
"@angular/language-service": "^5.2.1",
|
"@angular/language-service": "^5.2.1",
|
||||||
|
"@sentry/electron": "^0.4.2",
|
||||||
"@types/jasmine": "~2.8.5",
|
"@types/jasmine": "~2.8.5",
|
||||||
"@types/jasminewd2": "~2.0.2",
|
"@types/jasminewd2": "~2.0.2",
|
||||||
"@types/node": "~9.6.0",
|
"@types/node": "~9.6.0",
|
||||||
|
26
sentry.js
Normal file
26
sentry.js
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
const { SentryClient } = require('@sentry/electron');
|
||||||
|
const fs = require('fs');
|
||||||
|
const { ipcMain } = require('electron');
|
||||||
|
|
||||||
|
let crashReportsEnabled = true;
|
||||||
|
const DSN =
|
||||||
|
'https://cb7b474b2e874afb8e400c47d1452ecc:7876224cbff543d992cb0ac4021962f8@sentry.io/1040940';
|
||||||
|
|
||||||
|
const isDev = () => {
|
||||||
|
return fs.existsSync('.git');
|
||||||
|
};
|
||||||
|
|
||||||
|
const shouldSendCallback = () => {
|
||||||
|
return !isDev() && crashReportsEnabled;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
ipcMain.on('settings.changed', function (event, settings) {
|
||||||
|
crashReportsEnabled = settings.crash_reports;
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
SentryClient.create({
|
||||||
|
dsn: DSN,
|
||||||
|
shouldSendCallback: shouldSendCallback
|
||||||
|
});
|
@ -7,6 +7,7 @@ import { ProjectMapComponent } from './project-map/project-map.component';
|
|||||||
import { ServersComponent } from "./servers/servers.component";
|
import { ServersComponent } from "./servers/servers.component";
|
||||||
import { ProjectsComponent } from "./projects/projects.component";
|
import { ProjectsComponent } from "./projects/projects.component";
|
||||||
import { DefaultLayoutComponent } from "./default-layout/default-layout.component";
|
import { DefaultLayoutComponent } from "./default-layout/default-layout.component";
|
||||||
|
import { SettingsComponent } from "./settings/settings.component";
|
||||||
|
|
||||||
|
|
||||||
const routes: Routes = [
|
const routes: Routes = [
|
||||||
@ -14,7 +15,8 @@ const routes: Routes = [
|
|||||||
children: [
|
children: [
|
||||||
{ path: '', redirectTo: 'servers', pathMatch: 'full'},
|
{ path: '', redirectTo: 'servers', pathMatch: 'full'},
|
||||||
{ path: 'servers', component: ServersComponent },
|
{ path: 'servers', component: ServersComponent },
|
||||||
{ path: 'server/:server_id/projects', component: ProjectsComponent }
|
{ path: 'server/:server_id/projects', component: ProjectsComponent },
|
||||||
|
{ path: 'settings', component: SettingsComponent },
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{ path: 'server/:server_id/project/:project_id', component: ProjectMapComponent },
|
{ path: 'server/:server_id/project/:project_id', component: ProjectMapComponent },
|
||||||
|
@ -1,30 +1,74 @@
|
|||||||
import { TestBed, async } from '@angular/core/testing';
|
import { TestBed, async, ComponentFixture } from '@angular/core/testing';
|
||||||
import { RouterTestingModule } from '@angular/router/testing';
|
import { RouterTestingModule } from '@angular/router/testing';
|
||||||
|
|
||||||
import { AppComponent } from './app.component';
|
import { AppComponent } from './app.component';
|
||||||
|
import { MatIconModule } from "@angular/material";
|
||||||
|
import { SettingsService } from "./shared/services/settings.service";
|
||||||
|
import { PersistenceService } from "angular-persistence";
|
||||||
|
import { ElectronService, NgxElectronModule } from "ngx-electron";
|
||||||
|
import createSpyObj = jasmine.createSpyObj;
|
||||||
|
|
||||||
|
|
||||||
describe('AppComponent', () => {
|
describe('AppComponent', () => {
|
||||||
|
let component: AppComponent;
|
||||||
|
let fixture: ComponentFixture<AppComponent>;
|
||||||
|
let electronService: ElectronService;
|
||||||
|
let settingsService: SettingsService;
|
||||||
|
|
||||||
beforeEach(async(() => {
|
beforeEach(async(() => {
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
declarations: [
|
declarations: [
|
||||||
AppComponent
|
AppComponent
|
||||||
],
|
],
|
||||||
imports: [
|
imports: [
|
||||||
RouterTestingModule
|
RouterTestingModule,
|
||||||
|
MatIconModule,
|
||||||
|
NgxElectronModule
|
||||||
|
],
|
||||||
|
providers: [
|
||||||
|
SettingsService,
|
||||||
|
PersistenceService,
|
||||||
]
|
]
|
||||||
}).compileComponents();
|
}).compileComponents();
|
||||||
|
|
||||||
|
electronService = TestBed.get(ElectronService);
|
||||||
|
settingsService = TestBed.get(SettingsService);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
// it('should create the app', async(() => {
|
beforeEach(() => {
|
||||||
// const fixture = TestBed.createComponent(AppComponent);
|
fixture = TestBed.createComponent(AppComponent);
|
||||||
// const app = fixture.debugElement.componentInstance;
|
component = fixture.componentInstance;
|
||||||
// expect(app).toBeTruthy();
|
fixture.detectChanges();
|
||||||
// }));
|
});
|
||||||
|
|
||||||
// it('should have footer', async(() => {
|
it('should create the app', async(() => {
|
||||||
// const fixture = TestBed.createComponent(AppComponent);
|
const app = fixture.debugElement.componentInstance;
|
||||||
// fixture.detectChanges();
|
expect(app).toBeTruthy();
|
||||||
// const compiled = fixture.debugElement.nativeElement;
|
}));
|
||||||
// expect(compiled.querySelector('.text-muted').textContent).toContain('GNS3 Web UI demo');
|
|
||||||
// }));
|
it('should have footer', async(() => {
|
||||||
|
const compiled = fixture.debugElement.nativeElement;
|
||||||
|
expect(compiled.querySelector('router-outlet').textContent).toEqual('');
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should receive changed settings and forward to electron', async(() => {
|
||||||
|
const spy = createSpyObj('Electron.IpcRenderer', ['send']);
|
||||||
|
spyOnProperty(electronService, 'isElectronApp').and.returnValue(true);
|
||||||
|
spyOnProperty(electronService, 'ipcRenderer').and.returnValue(spy);
|
||||||
|
settingsService.set('crash_reports', true);
|
||||||
|
component.ngOnInit();
|
||||||
|
settingsService.set('crash_reports', false);
|
||||||
|
expect(spy.send).toHaveBeenCalled();
|
||||||
|
expect(spy.send.calls.mostRecent().args[0]).toEqual('settings.changed');
|
||||||
|
expect(spy.send.calls.mostRecent().args[1].crash_reports).toEqual(false);
|
||||||
|
}));
|
||||||
|
|
||||||
|
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.set('crash_reports', true);
|
||||||
|
component.ngOnInit();
|
||||||
|
settingsService.set('crash_reports', false);
|
||||||
|
expect(spy.send).not.toHaveBeenCalled();
|
||||||
|
}));
|
||||||
});
|
});
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
import { Component, OnInit } from '@angular/core';
|
import { Component, OnInit } from '@angular/core';
|
||||||
import {Http} from "@angular/http";
|
import { MatIconRegistry } from "@angular/material";
|
||||||
import {MatIconRegistry} from "@angular/material";
|
import { DomSanitizer } from "@angular/platform-browser";
|
||||||
import {DomSanitizer} from "@angular/platform-browser";
|
import { ElectronService } from "ngx-electron";
|
||||||
|
import { SettingsService } from "./shared/services/settings.service";
|
||||||
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-root',
|
selector: 'app-root',
|
||||||
@ -11,10 +13,20 @@ import {DomSanitizer} from "@angular/platform-browser";
|
|||||||
]
|
]
|
||||||
})
|
})
|
||||||
export class AppComponent implements OnInit {
|
export class AppComponent implements OnInit {
|
||||||
constructor(http: Http, iconReg: MatIconRegistry, sanitizer: DomSanitizer) {
|
constructor(
|
||||||
|
iconReg: MatIconRegistry,
|
||||||
|
sanitizer: DomSanitizer,
|
||||||
|
private settingsService: SettingsService,
|
||||||
|
private electronService: ElectronService) {
|
||||||
|
|
||||||
iconReg.addSvgIcon('gns3', sanitizer.bypassSecurityTrustResourceUrl('./assets/gns3_icon.svg'));
|
iconReg.addSvgIcon('gns3', sanitizer.bypassSecurityTrustResourceUrl('./assets/gns3_icon.svg'));
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
|
if (this.electronService.isElectronApp) {
|
||||||
|
this.settingsService.subscribe((settings) => {
|
||||||
|
this.electronService.ipcRenderer.send('settings.changed', settings);
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import * as Raven from 'raven-js';
|
import * as Raven from 'raven-js';
|
||||||
import { BrowserModule } from '@angular/platform-browser';
|
import { BrowserModule } from '@angular/platform-browser';
|
||||||
import { NgModule, ErrorHandler } from '@angular/core';
|
import { NgModule, ErrorHandler } from '@angular/core';
|
||||||
import { HttpModule } from '@angular/http';
|
|
||||||
import { FormsModule } from '@angular/forms';
|
import { FormsModule } from '@angular/forms';
|
||||||
import { CdkTableModule } from "@angular/cdk/table";
|
import { CdkTableModule } from "@angular/cdk/table";
|
||||||
import { HttpClientModule } from '@angular/common/http';
|
import { HttpClientModule } from '@angular/common/http';
|
||||||
@ -19,13 +18,17 @@ import {
|
|||||||
MatDialogModule,
|
MatDialogModule,
|
||||||
MatProgressBarModule,
|
MatProgressBarModule,
|
||||||
MatProgressSpinnerModule,
|
MatProgressSpinnerModule,
|
||||||
MatSnackBarModule
|
MatSnackBarModule,
|
||||||
|
MatCheckboxModule,
|
||||||
|
MatListModule,
|
||||||
|
MatExpansionModule,
|
||||||
} from '@angular/material';
|
} from '@angular/material';
|
||||||
|
|
||||||
import { D3Service } from 'd3-ng2-service';
|
import { D3Service } from 'd3-ng2-service';
|
||||||
import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
|
import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
|
||||||
|
|
||||||
import { HotkeyModule } from 'angular2-hotkeys';
|
import { HotkeyModule } from 'angular2-hotkeys';
|
||||||
|
import { PersistenceModule } from 'angular-persistence';
|
||||||
|
import { NgxElectronModule } from 'ngx-electron';
|
||||||
|
|
||||||
import { AppRoutingModule } from './app-routing.module';
|
import { AppRoutingModule } from './app-routing.module';
|
||||||
|
|
||||||
@ -66,21 +69,15 @@ import { DrawingsDataSource } from "./cartography/shared/datasources/drawings-da
|
|||||||
import { MoveLayerDownActionComponent } from './shared/node-context-menu/actions/move-layer-down-action/move-layer-down-action.component';
|
import { MoveLayerDownActionComponent } from './shared/node-context-menu/actions/move-layer-down-action/move-layer-down-action.component';
|
||||||
import { MoveLayerUpActionComponent } from './shared/node-context-menu/actions/move-layer-up-action/move-layer-up-action.component';
|
import { MoveLayerUpActionComponent } from './shared/node-context-menu/actions/move-layer-up-action/move-layer-up-action.component';
|
||||||
import { ProjectMapShortcutsComponent } from './project-map/project-map-shortcuts/project-map-shortcuts.component';
|
import { ProjectMapShortcutsComponent } from './project-map/project-map-shortcuts/project-map-shortcuts.component';
|
||||||
|
import { SettingsComponent } from './settings/settings.component';
|
||||||
|
import { SettingsService } from "./shared/services/settings.service";
|
||||||
|
|
||||||
import { environment } from "../environments/environment";
|
import { RavenErrorHandler } from "./raven-error-handler";
|
||||||
|
|
||||||
Raven
|
Raven
|
||||||
.config('https://b2b1cfd9b043491eb6b566fd8acee358@sentry.io/842726')
|
.config('https://b2b1cfd9b043491eb6b566fd8acee358@sentry.io/842726')
|
||||||
.install();
|
.install();
|
||||||
|
|
||||||
export class RavenErrorHandler implements ErrorHandler {
|
|
||||||
handleError(err:any) : void {
|
|
||||||
console.error(err.originalError || err);
|
|
||||||
if (environment.production) {
|
|
||||||
Raven.captureException(err.originalError || err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
@ -102,11 +99,11 @@ export class RavenErrorHandler implements ErrorHandler {
|
|||||||
MoveLayerDownActionComponent,
|
MoveLayerDownActionComponent,
|
||||||
MoveLayerUpActionComponent,
|
MoveLayerUpActionComponent,
|
||||||
ProjectMapShortcutsComponent,
|
ProjectMapShortcutsComponent,
|
||||||
|
SettingsComponent,
|
||||||
],
|
],
|
||||||
imports: [
|
imports: [
|
||||||
NgbModule.forRoot(),
|
NgbModule.forRoot(),
|
||||||
BrowserModule,
|
BrowserModule,
|
||||||
HttpModule,
|
|
||||||
HttpClientModule,
|
HttpClientModule,
|
||||||
AppRoutingModule,
|
AppRoutingModule,
|
||||||
FormsModule,
|
FormsModule,
|
||||||
@ -123,11 +120,17 @@ export class RavenErrorHandler implements ErrorHandler {
|
|||||||
MatProgressBarModule,
|
MatProgressBarModule,
|
||||||
MatProgressSpinnerModule,
|
MatProgressSpinnerModule,
|
||||||
MatSnackBarModule,
|
MatSnackBarModule,
|
||||||
|
MatCheckboxModule,
|
||||||
|
MatListModule,
|
||||||
|
MatExpansionModule,
|
||||||
CdkTableModule,
|
CdkTableModule,
|
||||||
CartographyModule,
|
CartographyModule,
|
||||||
HotkeyModule.forRoot()
|
HotkeyModule.forRoot(),
|
||||||
|
PersistenceModule,
|
||||||
|
NgxElectronModule
|
||||||
],
|
],
|
||||||
providers: [
|
providers: [
|
||||||
|
SettingsService,
|
||||||
{ provide: ErrorHandler, useClass: RavenErrorHandler },
|
{ provide: ErrorHandler, useClass: RavenErrorHandler },
|
||||||
D3Service,
|
D3Service,
|
||||||
VersionService,
|
VersionService,
|
||||||
|
@ -58,3 +58,10 @@ main {
|
|||||||
text-align: right;
|
text-align: right;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.fill-space {
|
||||||
|
flex: 1 1 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.example-container > * {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
@ -5,6 +5,12 @@
|
|||||||
</button>
|
</button>
|
||||||
|
|
||||||
<button mat-button routerLink="/servers" >Servers</button>
|
<button mat-button routerLink="/servers" >Servers</button>
|
||||||
|
|
||||||
|
<span class="fill-space"></span>
|
||||||
|
|
||||||
|
<button mat-button routerLink="/settings" >
|
||||||
|
<mat-icon>settings</mat-icon>
|
||||||
|
</button>
|
||||||
</mat-toolbar>
|
</mat-toolbar>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
@ -13,6 +19,6 @@
|
|||||||
</main>
|
</main>
|
||||||
|
|
||||||
<footer class="footer mat-app-background">
|
<footer class="footer mat-app-background">
|
||||||
GNS3 Web UI demo © 2017
|
GNS3 Web UI demo © 2018
|
||||||
</footer>
|
</footer>
|
||||||
|
|
||||||
|
48
src/app/raven-error-handler.spec.ts
Normal file
48
src/app/raven-error-handler.spec.ts
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
import { TestBed } from '@angular/core/testing';
|
||||||
|
import { PersistenceService } from "angular-persistence";
|
||||||
|
|
||||||
|
import * as Raven from 'raven-js';
|
||||||
|
|
||||||
|
import { SettingsService } from "./shared/services/settings.service";
|
||||||
|
import { RavenErrorHandler } from "./raven-error-handler";
|
||||||
|
import { environment } from "../environments/environment";
|
||||||
|
|
||||||
|
|
||||||
|
describe('RavenErrorHandler', () => {
|
||||||
|
let handler: RavenErrorHandler;
|
||||||
|
let settingsService: SettingsService;
|
||||||
|
const inProductionOriginal = environment.production;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
providers: [SettingsService, PersistenceService, RavenErrorHandler]
|
||||||
|
});
|
||||||
|
|
||||||
|
settingsService = TestBed.get(SettingsService);
|
||||||
|
handler = TestBed.get(RavenErrorHandler);
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
environment.production = inProductionOriginal;
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(handler).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should handle error', () => {
|
||||||
|
settingsService.set('crash_reports', true);
|
||||||
|
const error = new Error("My error");
|
||||||
|
const captureException = spyOn(Raven, 'captureException');
|
||||||
|
environment.production = true;
|
||||||
|
handler.handleError(error);
|
||||||
|
expect(captureException).toHaveBeenCalledWith(error);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not handle when not in production', () => {
|
||||||
|
const captureException = spyOn(Raven, 'captureException');
|
||||||
|
environment.production = false;
|
||||||
|
handler.handleError(new Error("My error"));
|
||||||
|
expect(captureException).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
});
|
20
src/app/raven-error-handler.ts
Normal file
20
src/app/raven-error-handler.ts
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
import * as Raven from 'raven-js';
|
||||||
|
|
||||||
|
import { ErrorHandler, Inject, Injector } from "@angular/core";
|
||||||
|
|
||||||
|
import { SettingsService } from "./shared/services/settings.service";
|
||||||
|
import { environment } from "../environments/environment";
|
||||||
|
|
||||||
|
|
||||||
|
export class RavenErrorHandler implements ErrorHandler {
|
||||||
|
constructor(@Inject(Injector) private injector: Injector) {}
|
||||||
|
|
||||||
|
handleError(err: any): void {
|
||||||
|
const settingsService: SettingsService = this.injector.get(SettingsService);
|
||||||
|
console.error(err.originalError || err);
|
||||||
|
|
||||||
|
if (environment.production && settingsService.get('crash_reports')) {
|
||||||
|
Raven.captureException(err.originalError || err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
28
src/app/settings/settings.component.html
Normal file
28
src/app/settings/settings.component.html
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
<div class="content">
|
||||||
|
<div class="default-header">
|
||||||
|
<h1>Settings</h1>
|
||||||
|
</div>
|
||||||
|
<div class="default-content">
|
||||||
|
<div class="example-container mat-elevation-z8">
|
||||||
|
<mat-accordion>
|
||||||
|
<mat-expansion-panel>
|
||||||
|
<mat-expansion-panel-header>
|
||||||
|
<mat-panel-title>
|
||||||
|
Local settings
|
||||||
|
</mat-panel-title>
|
||||||
|
<mat-panel-description>
|
||||||
|
Customize your local settings
|
||||||
|
</mat-panel-description>
|
||||||
|
</mat-expansion-panel-header>
|
||||||
|
|
||||||
|
<mat-checkbox class="example-margin" [(ngModel)]="settings.crash_reports">Send anonymous crash reports</mat-checkbox>
|
||||||
|
|
||||||
|
</mat-expansion-panel>
|
||||||
|
</mat-accordion>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="buttons-bar">
|
||||||
|
<button mat-raised-button color="primary" (click)="save()">Save settings</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
0
src/app/settings/settings.component.scss
Normal file
0
src/app/settings/settings.component.scss
Normal file
53
src/app/settings/settings.component.spec.ts
Normal file
53
src/app/settings/settings.component.spec.ts
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { SettingsComponent } from './settings.component';
|
||||||
|
import { MatCheckboxModule, MatExpansionModule } from "@angular/material";
|
||||||
|
import { FormsModule } from "@angular/forms";
|
||||||
|
import { SettingsService } from "../shared/services/settings.service";
|
||||||
|
import { PersistenceModule } from "angular-persistence";
|
||||||
|
import { BrowserAnimationsModule } from "@angular/platform-browser/animations";
|
||||||
|
|
||||||
|
describe('SettingsComponent', () => {
|
||||||
|
let component: SettingsComponent;
|
||||||
|
let fixture: ComponentFixture<SettingsComponent>;
|
||||||
|
let settingsService: SettingsService;
|
||||||
|
|
||||||
|
beforeEach(async(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
imports: [
|
||||||
|
MatExpansionModule, MatCheckboxModule, FormsModule,
|
||||||
|
PersistenceModule, BrowserAnimationsModule ],
|
||||||
|
providers: [ SettingsService ],
|
||||||
|
declarations: [ SettingsComponent ]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
|
||||||
|
settingsService = TestBed.get(SettingsService);
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(SettingsComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should get and save new settings', () => {
|
||||||
|
const settings = {
|
||||||
|
'crash_reports': true
|
||||||
|
};
|
||||||
|
const getAll = spyOn(settingsService, 'getAll').and.returnValue(settings);
|
||||||
|
const setAll = spyOn(settingsService, 'setAll');
|
||||||
|
component.ngOnInit();
|
||||||
|
expect(getAll).toHaveBeenCalled();
|
||||||
|
expect(component.settings).toEqual(settings);
|
||||||
|
component.settings.crash_reports = false;
|
||||||
|
component.save();
|
||||||
|
expect(setAll).toHaveBeenCalledWith(settings);
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
});
|
21
src/app/settings/settings.component.ts
Normal file
21
src/app/settings/settings.component.ts
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
import { Component, OnInit } from '@angular/core';
|
||||||
|
import { SettingsService } from "../shared/services/settings.service";
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-settings',
|
||||||
|
templateUrl: './settings.component.html',
|
||||||
|
styleUrls: ['./settings.component.scss']
|
||||||
|
})
|
||||||
|
export class SettingsComponent implements OnInit {
|
||||||
|
settings = { ...SettingsService.DEFAULTS };
|
||||||
|
|
||||||
|
constructor(private settingsService: SettingsService) { }
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
this.settings = this.settingsService.getAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
save() {
|
||||||
|
this.settingsService.setAll(this.settings);
|
||||||
|
}
|
||||||
|
}
|
73
src/app/shared/services/settings.service.spec.ts
Normal file
73
src/app/shared/services/settings.service.spec.ts
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
import { TestBed, inject } from '@angular/core/testing';
|
||||||
|
import { PersistenceService, StorageType } from "angular-persistence";
|
||||||
|
|
||||||
|
import { Settings, SettingsService } from './settings.service';
|
||||||
|
import createSpyObj = jasmine.createSpyObj;
|
||||||
|
|
||||||
|
|
||||||
|
describe('SettingsService', () => {
|
||||||
|
let persistenceService: PersistenceService;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
providers: [SettingsService, PersistenceService]
|
||||||
|
});
|
||||||
|
|
||||||
|
persistenceService = TestBed.get(PersistenceService);
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
persistenceService.removeAll(StorageType.LOCAL);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be created', inject([SettingsService], (service: SettingsService) => {
|
||||||
|
expect(service).toBeTruthy();
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should set value', inject([SettingsService], (service: SettingsService) => {
|
||||||
|
service.set('crash_reports', false);
|
||||||
|
expect(service.get('crash_reports')).toEqual(false);
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should get default value', inject([SettingsService], (service: SettingsService) => {
|
||||||
|
expect(service.get('crash_reports')).toEqual(true);
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should throw error when setting value with wrong key',
|
||||||
|
inject([SettingsService], (service: SettingsService) => {
|
||||||
|
expect(() => service.set('test', false)).toThrowError("Key 'test' doesn't exist in settings");
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should throw error when getting value with wrong key',
|
||||||
|
inject([SettingsService], (service: SettingsService) => {
|
||||||
|
expect(() => service.get('test')).toThrowError("Key 'test' doesn't exist in settings");
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should get all values', inject([SettingsService], (service: SettingsService) => {
|
||||||
|
expect(service.getAll()).toEqual({
|
||||||
|
'crash_reports': true
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should set all values', inject([SettingsService], (service: SettingsService) => {
|
||||||
|
const settings = {
|
||||||
|
'crash_reports': false
|
||||||
|
};
|
||||||
|
service.setAll(settings)
|
||||||
|
|
||||||
|
expect(service.getAll()).toEqual({
|
||||||
|
'crash_reports': false
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should execute subscriber', inject([SettingsService], (service: SettingsService) => {
|
||||||
|
let changedSettings: Settings;
|
||||||
|
|
||||||
|
service.set('crash_reports', true);
|
||||||
|
service.subscribe(settings => changedSettings = settings);
|
||||||
|
service.set('crash_reports', false);
|
||||||
|
|
||||||
|
expect(changedSettings.crash_reports).toEqual(false);
|
||||||
|
}));
|
||||||
|
|
||||||
|
});
|
60
src/app/shared/services/settings.service.ts
Normal file
60
src/app/shared/services/settings.service.ts
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import { PersistenceService, StorageType } from "angular-persistence";
|
||||||
|
import { Subject } from "rxjs/Subject";
|
||||||
|
import { BehaviorSubject } from "rxjs/BehaviorSubject";
|
||||||
|
|
||||||
|
|
||||||
|
export interface Settings {
|
||||||
|
crash_reports: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class SettingsService {
|
||||||
|
static DEFAULTS: Settings = {
|
||||||
|
'crash_reports': true
|
||||||
|
};
|
||||||
|
|
||||||
|
private settingsSubject: BehaviorSubject<Settings>;
|
||||||
|
|
||||||
|
constructor(private persistenceService: PersistenceService) {
|
||||||
|
this.settingsSubject = new BehaviorSubject<Settings>(this.getAll());
|
||||||
|
}
|
||||||
|
|
||||||
|
get<T>(key: string) {
|
||||||
|
if (!(key in SettingsService.DEFAULTS)) {
|
||||||
|
throw Error(`Key '${key}' doesn't exist in settings`);
|
||||||
|
}
|
||||||
|
const value = this.persistenceService.get(key, StorageType.LOCAL) as T;
|
||||||
|
if (typeof value === 'undefined') {
|
||||||
|
return SettingsService.DEFAULTS[key];
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
set<T>(key: string, value: T): void {
|
||||||
|
if (!(key in SettingsService.DEFAULTS)) {
|
||||||
|
throw Error(`Key '${key}' doesn't exist in settings`);
|
||||||
|
}
|
||||||
|
this.persistenceService.set(key, value, { type: StorageType.LOCAL });
|
||||||
|
this.settingsSubject.next(this.getAll());
|
||||||
|
}
|
||||||
|
|
||||||
|
getAll() {
|
||||||
|
const settings = { ...SettingsService.DEFAULTS };
|
||||||
|
Object.keys(SettingsService.DEFAULTS).forEach((key) => {
|
||||||
|
settings[key] = this.get(key);
|
||||||
|
});
|
||||||
|
return settings;
|
||||||
|
}
|
||||||
|
|
||||||
|
setAll(settings) {
|
||||||
|
Object.keys(settings).forEach((key) => {
|
||||||
|
this.set(key, settings[key]);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
subscribe(subscriber: ((settings: Settings) => void)) {
|
||||||
|
return this.settingsSubject.subscribe(subscriber);
|
||||||
|
}
|
||||||
|
}
|
139
yarn.lock
139
yarn.lock
@ -227,6 +227,42 @@
|
|||||||
semver "^5.3.0"
|
semver "^5.3.0"
|
||||||
semver-intersect "^1.1.2"
|
semver-intersect "^1.1.2"
|
||||||
|
|
||||||
|
"@sentry/browser@0.4.2":
|
||||||
|
version "0.4.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/@sentry/browser/-/browser-0.4.2.tgz#bd91752558d2e92adbd1f4b1dcd78efd92c7d2ed"
|
||||||
|
dependencies:
|
||||||
|
"@sentry/core" "0.4.2"
|
||||||
|
"@sentry/utils" "0.4.2"
|
||||||
|
raven-js "^3.23.1"
|
||||||
|
|
||||||
|
"@sentry/core@0.4.2":
|
||||||
|
version "0.4.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/@sentry/core/-/core-0.4.2.tgz#3922c61b42519d9b67cd49da39f214a1d92b7f84"
|
||||||
|
|
||||||
|
"@sentry/electron@^0.4.2":
|
||||||
|
version "0.4.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/@sentry/electron/-/electron-0.4.2.tgz#47c15672470d3fd850096d8786b6738e250eea61"
|
||||||
|
dependencies:
|
||||||
|
"@sentry/browser" "0.4.2"
|
||||||
|
"@sentry/core" "0.4.2"
|
||||||
|
"@sentry/node" "0.4.2"
|
||||||
|
"@sentry/utils" "0.4.2"
|
||||||
|
form-data "^2.3.2"
|
||||||
|
node-fetch "^2.1.1"
|
||||||
|
util.promisify "^1.0.0"
|
||||||
|
|
||||||
|
"@sentry/node@0.4.2":
|
||||||
|
version "0.4.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/@sentry/node/-/node-0.4.2.tgz#3fcc890cdff157fbb488a130ba83b7f68b57aacd"
|
||||||
|
dependencies:
|
||||||
|
"@sentry/core" "0.4.2"
|
||||||
|
"@sentry/utils" "0.4.2"
|
||||||
|
raven "^2.4.2"
|
||||||
|
|
||||||
|
"@sentry/utils@0.4.2":
|
||||||
|
version "0.4.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/@sentry/utils/-/utils-0.4.2.tgz#1a951ceee448f0fd2dc146798ee9b93f39c058cf"
|
||||||
|
|
||||||
"@types/d3-array@1.2":
|
"@types/d3-array@1.2":
|
||||||
version "1.2.1"
|
version "1.2.1"
|
||||||
resolved "https://registry.yarnpkg.com/@types/d3-array/-/d3-array-1.2.1.tgz#e489605208d46a1c9d980d2e5772fa9c75d9ec65"
|
resolved "https://registry.yarnpkg.com/@types/d3-array/-/d3-array-1.2.1.tgz#e489605208d46a1c9d980d2e5772fa9c75d9ec65"
|
||||||
@ -535,6 +571,10 @@ amqplib@^0.5.2:
|
|||||||
readable-stream "1.x >=1.1.9"
|
readable-stream "1.x >=1.1.9"
|
||||||
safe-buffer "^5.0.1"
|
safe-buffer "^5.0.1"
|
||||||
|
|
||||||
|
angular-persistence@^1.0.1:
|
||||||
|
version "1.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/angular-persistence/-/angular-persistence-1.0.1.tgz#79ffe7317f1f7aed88e69f07705f0ac32ccdb9da"
|
||||||
|
|
||||||
angular2-hotkeys@^2.0.4:
|
angular2-hotkeys@^2.0.4:
|
||||||
version "2.0.4"
|
version "2.0.4"
|
||||||
resolved "https://registry.yarnpkg.com/angular2-hotkeys/-/angular2-hotkeys-2.0.4.tgz#83355f0a65fe484bfdd3d238b6ee96d63526eb91"
|
resolved "https://registry.yarnpkg.com/angular2-hotkeys/-/angular2-hotkeys-2.0.4.tgz#83355f0a65fe484bfdd3d238b6ee96d63526eb91"
|
||||||
@ -1538,6 +1578,10 @@ chalk@~2.2.0:
|
|||||||
escape-string-regexp "^1.0.5"
|
escape-string-regexp "^1.0.5"
|
||||||
supports-color "^4.0.0"
|
supports-color "^4.0.0"
|
||||||
|
|
||||||
|
charenc@~0.0.1:
|
||||||
|
version "0.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/charenc/-/charenc-0.0.2.tgz#c0a1d2f3a7092e03774bfa83f14c0fc5790a8667"
|
||||||
|
|
||||||
chokidar@^1.4.1, chokidar@^1.4.2, chokidar@^1.7.0:
|
chokidar@^1.4.1, chokidar@^1.4.2, chokidar@^1.7.0:
|
||||||
version "1.7.0"
|
version "1.7.0"
|
||||||
resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-1.7.0.tgz#798e689778151c8076b4b360e5edd28cda2bb468"
|
resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-1.7.0.tgz#798e689778151c8076b4b360e5edd28cda2bb468"
|
||||||
@ -1791,6 +1835,12 @@ combine-source-map@~0.8.0:
|
|||||||
lodash.memoize "~3.0.3"
|
lodash.memoize "~3.0.3"
|
||||||
source-map "~0.5.3"
|
source-map "~0.5.3"
|
||||||
|
|
||||||
|
combined-stream@1.0.6:
|
||||||
|
version "1.0.6"
|
||||||
|
resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.6.tgz#723e7df6e801ac5613113a7e445a9b69cb632818"
|
||||||
|
dependencies:
|
||||||
|
delayed-stream "~1.0.0"
|
||||||
|
|
||||||
combined-stream@^1.0.5, combined-stream@~1.0.5:
|
combined-stream@^1.0.5, combined-stream@~1.0.5:
|
||||||
version "1.0.5"
|
version "1.0.5"
|
||||||
resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.5.tgz#938370a57b4a51dea2c77c15d5c5fdf895164009"
|
resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.5.tgz#938370a57b4a51dea2c77c15d5c5fdf895164009"
|
||||||
@ -2071,6 +2121,10 @@ cross-spawn@^5.0.1:
|
|||||||
shebang-command "^1.2.0"
|
shebang-command "^1.2.0"
|
||||||
which "^1.2.9"
|
which "^1.2.9"
|
||||||
|
|
||||||
|
crypt@~0.0.1:
|
||||||
|
version "0.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/crypt/-/crypt-0.0.2.tgz#88d7ff7ec0dfb86f713dc87bbb42d044d3e6c41b"
|
||||||
|
|
||||||
cryptiles@2.x.x:
|
cryptiles@2.x.x:
|
||||||
version "2.0.5"
|
version "2.0.5"
|
||||||
resolved "https://registry.yarnpkg.com/cryptiles/-/cryptiles-2.0.5.tgz#3bdfecdc608147c1c67202fa291e7dca59eaa3b8"
|
resolved "https://registry.yarnpkg.com/cryptiles/-/cryptiles-2.0.5.tgz#3bdfecdc608147c1c67202fa291e7dca59eaa3b8"
|
||||||
@ -2862,6 +2916,13 @@ electron-publish@20.0.2:
|
|||||||
fs-extra-p "^4.5.0"
|
fs-extra-p "^4.5.0"
|
||||||
mime "^2.2.0"
|
mime "^2.2.0"
|
||||||
|
|
||||||
|
electron-settings@^3.1.4:
|
||||||
|
version "3.1.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/electron-settings/-/electron-settings-3.1.4.tgz#1b670837fd00626395714210291fb4af8ff52880"
|
||||||
|
dependencies:
|
||||||
|
clone "^2.1.1"
|
||||||
|
jsonfile "^4.0.0"
|
||||||
|
|
||||||
electron-to-chromium@^1.3.30:
|
electron-to-chromium@^1.3.30:
|
||||||
version "1.3.31"
|
version "1.3.31"
|
||||||
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.31.tgz#00d832cba9fe2358652b0c48a8816c8e3a037e9f"
|
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.31.tgz#00d832cba9fe2358652b0c48a8816c8e3a037e9f"
|
||||||
@ -2979,6 +3040,16 @@ error-ex@^1.2.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
is-arrayish "^0.2.1"
|
is-arrayish "^0.2.1"
|
||||||
|
|
||||||
|
es-abstract@^1.5.1:
|
||||||
|
version "1.11.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.11.0.tgz#cce87d518f0496893b1a30cd8461835535480681"
|
||||||
|
dependencies:
|
||||||
|
es-to-primitive "^1.1.1"
|
||||||
|
function-bind "^1.1.1"
|
||||||
|
has "^1.0.1"
|
||||||
|
is-callable "^1.1.3"
|
||||||
|
is-regex "^1.0.4"
|
||||||
|
|
||||||
es-abstract@^1.7.0:
|
es-abstract@^1.7.0:
|
||||||
version "1.10.0"
|
version "1.10.0"
|
||||||
resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.10.0.tgz#1ecb36c197842a00d8ee4c2dfd8646bb97d60864"
|
resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.10.0.tgz#1ecb36c197842a00d8ee4c2dfd8646bb97d60864"
|
||||||
@ -3437,6 +3508,14 @@ forever-agent@~0.6.1:
|
|||||||
version "0.6.1"
|
version "0.6.1"
|
||||||
resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91"
|
resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91"
|
||||||
|
|
||||||
|
form-data@^2.3.2:
|
||||||
|
version "2.3.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.2.tgz#4970498be604c20c005d4f5c23aecd21d6b49099"
|
||||||
|
dependencies:
|
||||||
|
asynckit "^0.4.0"
|
||||||
|
combined-stream "1.0.6"
|
||||||
|
mime-types "^2.1.12"
|
||||||
|
|
||||||
form-data@~2.0.0:
|
form-data@~2.0.0:
|
||||||
version "2.0.0"
|
version "2.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.0.0.tgz#6f0aebadcc5da16c13e1ecc11137d85f9b883b25"
|
resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.0.0.tgz#6f0aebadcc5da16c13e1ecc11137d85f9b883b25"
|
||||||
@ -4342,7 +4421,7 @@ is-binary-path@^1.0.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
binary-extensions "^1.0.0"
|
binary-extensions "^1.0.0"
|
||||||
|
|
||||||
is-buffer@^1.0.2, is-buffer@^1.1.0, is-buffer@^1.1.5:
|
is-buffer@^1.0.2, is-buffer@^1.1.0, is-buffer@^1.1.5, is-buffer@~1.1.1:
|
||||||
version "1.1.6"
|
version "1.1.6"
|
||||||
resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be"
|
resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be"
|
||||||
|
|
||||||
@ -5308,6 +5387,14 @@ md5.js@^1.3.4:
|
|||||||
hash-base "^3.0.0"
|
hash-base "^3.0.0"
|
||||||
inherits "^2.0.1"
|
inherits "^2.0.1"
|
||||||
|
|
||||||
|
md5@^2.2.1:
|
||||||
|
version "2.2.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/md5/-/md5-2.2.1.tgz#53ab38d5fe3c8891ba465329ea23fac0540126f9"
|
||||||
|
dependencies:
|
||||||
|
charenc "~0.0.1"
|
||||||
|
crypt "~0.0.1"
|
||||||
|
is-buffer "~1.1.1"
|
||||||
|
|
||||||
media-typer@0.3.0:
|
media-typer@0.3.0:
|
||||||
version "0.3.0"
|
version "0.3.0"
|
||||||
resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748"
|
resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748"
|
||||||
@ -5650,6 +5737,10 @@ netmask@~1.0.4:
|
|||||||
version "1.0.6"
|
version "1.0.6"
|
||||||
resolved "https://registry.yarnpkg.com/netmask/-/netmask-1.0.6.tgz#20297e89d86f6f6400f250d9f4f6b4c1945fcd35"
|
resolved "https://registry.yarnpkg.com/netmask/-/netmask-1.0.6.tgz#20297e89d86f6f6400f250d9f4f6b4c1945fcd35"
|
||||||
|
|
||||||
|
ngx-electron@^1.0.4:
|
||||||
|
version "1.0.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/ngx-electron/-/ngx-electron-1.0.4.tgz#2d80b25d74ae4d6226ad8b3bc4ecfa611e48fdca"
|
||||||
|
|
||||||
no-case@^2.2.0:
|
no-case@^2.2.0:
|
||||||
version "2.3.2"
|
version "2.3.2"
|
||||||
resolved "https://registry.yarnpkg.com/no-case/-/no-case-2.3.2.tgz#60b813396be39b3f1288a4c1ed5d1e7d28b464ac"
|
resolved "https://registry.yarnpkg.com/no-case/-/no-case-2.3.2.tgz#60b813396be39b3f1288a4c1ed5d1e7d28b464ac"
|
||||||
@ -5663,6 +5754,10 @@ node-alias@^1.0.4:
|
|||||||
chalk "^1.1.1"
|
chalk "^1.1.1"
|
||||||
lodash "^4.2.0"
|
lodash "^4.2.0"
|
||||||
|
|
||||||
|
node-fetch@^2.1.1:
|
||||||
|
version "2.1.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.1.2.tgz#ab884e8e7e57e38a944753cec706f788d1768bb5"
|
||||||
|
|
||||||
node-forge@0.6.33:
|
node-forge@0.6.33:
|
||||||
version "0.6.33"
|
version "0.6.33"
|
||||||
resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-0.6.33.tgz#463811879f573d45155ad6a9f43dc296e8e85ebc"
|
resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-0.6.33.tgz#463811879f573d45155ad6a9f43dc296e8e85ebc"
|
||||||
@ -6132,6 +6227,13 @@ object-visit@^1.0.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
isobject "^3.0.0"
|
isobject "^3.0.0"
|
||||||
|
|
||||||
|
object.getownpropertydescriptors@^2.0.3:
|
||||||
|
version "2.0.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz#8758c846f5b407adab0f236e0986f14b051caa16"
|
||||||
|
dependencies:
|
||||||
|
define-properties "^1.1.2"
|
||||||
|
es-abstract "^1.5.1"
|
||||||
|
|
||||||
object.omit@^2.0.0:
|
object.omit@^2.0.0:
|
||||||
version "2.0.1"
|
version "2.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/object.omit/-/object.omit-2.0.1.tgz#1a9c744829f39dbb858c76ca3579ae2a54ebd1fa"
|
resolved "https://registry.yarnpkg.com/object.omit/-/object.omit-2.0.1.tgz#1a9c744829f39dbb858c76ca3579ae2a54ebd1fa"
|
||||||
@ -6851,10 +6953,20 @@ range-parser@^1.0.3, range-parser@^1.2.0, range-parser@~1.2.0:
|
|||||||
version "1.2.0"
|
version "1.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.0.tgz#f49be6b487894ddc40dcc94a322f611092e00d5e"
|
resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.0.tgz#f49be6b487894ddc40dcc94a322f611092e00d5e"
|
||||||
|
|
||||||
raven-js@^3.24.0:
|
raven-js@^3.23.1, raven-js@^3.24.0:
|
||||||
version "3.24.0"
|
version "3.24.0"
|
||||||
resolved "https://registry.yarnpkg.com/raven-js/-/raven-js-3.24.0.tgz#59464d8bc4b3812ae87a282e9bb98ecad5b4b047"
|
resolved "https://registry.yarnpkg.com/raven-js/-/raven-js-3.24.0.tgz#59464d8bc4b3812ae87a282e9bb98ecad5b4b047"
|
||||||
|
|
||||||
|
raven@^2.4.2:
|
||||||
|
version "2.4.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/raven/-/raven-2.4.2.tgz#0129e2adc30788646fd530b67d08a8ce25d4f6dc"
|
||||||
|
dependencies:
|
||||||
|
cookie "0.3.1"
|
||||||
|
md5 "^2.2.1"
|
||||||
|
stack-trace "0.0.9"
|
||||||
|
timed-out "4.0.1"
|
||||||
|
uuid "3.0.0"
|
||||||
|
|
||||||
raw-body@2, raw-body@2.3.2:
|
raw-body@2, raw-body@2.3.2:
|
||||||
version "2.3.2"
|
version "2.3.2"
|
||||||
resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.3.2.tgz#bcd60c77d3eb93cde0050295c3f379389bc88f89"
|
resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.3.2.tgz#bcd60c77d3eb93cde0050295c3f379389bc88f89"
|
||||||
@ -8148,6 +8260,10 @@ ssri@^5.0.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
safe-buffer "^5.1.0"
|
safe-buffer "^5.1.0"
|
||||||
|
|
||||||
|
stack-trace@0.0.9:
|
||||||
|
version "0.0.9"
|
||||||
|
resolved "https://registry.yarnpkg.com/stack-trace/-/stack-trace-0.0.9.tgz#a8f6eaeca90674c333e7c43953f275b451510695"
|
||||||
|
|
||||||
stat-mode@^0.2.2:
|
stat-mode@^0.2.2:
|
||||||
version "0.2.2"
|
version "0.2.2"
|
||||||
resolved "https://registry.yarnpkg.com/stat-mode/-/stat-mode-0.2.2.tgz#e6c80b623123d7d80cf132ce538f346289072502"
|
resolved "https://registry.yarnpkg.com/stat-mode/-/stat-mode-0.2.2.tgz#e6c80b623123d7d80cf132ce538f346289072502"
|
||||||
@ -8465,6 +8581,10 @@ thunky@^0.1.0:
|
|||||||
version "0.1.0"
|
version "0.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/thunky/-/thunky-0.1.0.tgz#bf30146824e2b6e67b0f2d7a4ac8beb26908684e"
|
resolved "https://registry.yarnpkg.com/thunky/-/thunky-0.1.0.tgz#bf30146824e2b6e67b0f2d7a4ac8beb26908684e"
|
||||||
|
|
||||||
|
timed-out@4.0.1, timed-out@^4.0.0:
|
||||||
|
version "4.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/timed-out/-/timed-out-4.0.1.tgz#f32eacac5a175bea25d7fab565ab3ed8741ef56f"
|
||||||
|
|
||||||
timed-out@^2.0.0:
|
timed-out@^2.0.0:
|
||||||
version "2.0.0"
|
version "2.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/timed-out/-/timed-out-2.0.0.tgz#f38b0ae81d3747d628001f41dafc652ace671c0a"
|
resolved "https://registry.yarnpkg.com/timed-out/-/timed-out-2.0.0.tgz#f38b0ae81d3747d628001f41dafc652ace671c0a"
|
||||||
@ -8473,10 +8593,6 @@ timed-out@^3.0.0:
|
|||||||
version "3.1.3"
|
version "3.1.3"
|
||||||
resolved "https://registry.yarnpkg.com/timed-out/-/timed-out-3.1.3.tgz#95860bfcc5c76c277f8f8326fd0f5b2e20eba217"
|
resolved "https://registry.yarnpkg.com/timed-out/-/timed-out-3.1.3.tgz#95860bfcc5c76c277f8f8326fd0f5b2e20eba217"
|
||||||
|
|
||||||
timed-out@^4.0.0:
|
|
||||||
version "4.0.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/timed-out/-/timed-out-4.0.1.tgz#f32eacac5a175bea25d7fab565ab3ed8741ef56f"
|
|
||||||
|
|
||||||
timers-browserify@^1.0.1:
|
timers-browserify@^1.0.1:
|
||||||
version "1.4.2"
|
version "1.4.2"
|
||||||
resolved "https://registry.yarnpkg.com/timers-browserify/-/timers-browserify-1.4.2.tgz#c9c58b575be8407375cb5e2462dacee74359f41d"
|
resolved "https://registry.yarnpkg.com/timers-browserify/-/timers-browserify-1.4.2.tgz#c9c58b575be8407375cb5e2462dacee74359f41d"
|
||||||
@ -8919,6 +9035,13 @@ util-extend@^1.0.1:
|
|||||||
version "1.0.3"
|
version "1.0.3"
|
||||||
resolved "https://registry.yarnpkg.com/util-extend/-/util-extend-1.0.3.tgz#a7c216d267545169637b3b6edc6ca9119e2ff93f"
|
resolved "https://registry.yarnpkg.com/util-extend/-/util-extend-1.0.3.tgz#a7c216d267545169637b3b6edc6ca9119e2ff93f"
|
||||||
|
|
||||||
|
util.promisify@^1.0.0:
|
||||||
|
version "1.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/util.promisify/-/util.promisify-1.0.0.tgz#440f7165a459c9a16dc145eb8e72f35687097030"
|
||||||
|
dependencies:
|
||||||
|
define-properties "^1.1.2"
|
||||||
|
object.getownpropertydescriptors "^2.0.3"
|
||||||
|
|
||||||
util@0.10.3, util@^0.10.3, util@~0.10.1:
|
util@0.10.3, util@^0.10.3, util@~0.10.1:
|
||||||
version "0.10.3"
|
version "0.10.3"
|
||||||
resolved "https://registry.yarnpkg.com/util/-/util-0.10.3.tgz#7afb1afe50805246489e3db7fe0ed379336ac0f9"
|
resolved "https://registry.yarnpkg.com/util/-/util-0.10.3.tgz#7afb1afe50805246489e3db7fe0ed379336ac0f9"
|
||||||
@ -8937,6 +9060,10 @@ utils-merge@1.0.1:
|
|||||||
version "1.0.1"
|
version "1.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713"
|
resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713"
|
||||||
|
|
||||||
|
uuid@3.0.0:
|
||||||
|
version "3.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.0.0.tgz#6728fc0459c450d796a99c31837569bdf672d728"
|
||||||
|
|
||||||
uuid@^2.0.1:
|
uuid@^2.0.1:
|
||||||
version "2.0.3"
|
version "2.0.3"
|
||||||
resolved "https://registry.yarnpkg.com/uuid/-/uuid-2.0.3.tgz#67e2e863797215530dff318e5bf9dcebfd47b21a"
|
resolved "https://registry.yarnpkg.com/uuid/-/uuid-2.0.3.tgz#67e2e863797215530dff318e5bf9dcebfd47b21a"
|
||||||
|
Loading…
Reference in New Issue
Block a user