Skip to content
Snippets Groups Projects
Commit eceb6574 authored by Chris Hines's avatar Chris Hines
Browse files

improve error handleing and notifying the user of various exceptions

parent 6ff7eeee
No related branches found
No related tags found
No related merge requests found
Pipeline #131299 failed
Showing
with 0 additions and 483 deletions
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
@NgModule({
declarations: [],
imports: [
CommonModule
]
})
export class CoreModule { }
import { TestBed } from '@angular/core/testing';
import { ElectronService } from './electron.service';
describe('ElectronService', () => {
beforeEach(() => TestBed.configureTestingModule({}));
it('should be created', () => {
const service: ElectronService = TestBed.get(ElectronService);
expect(service).toBeTruthy();
});
});
import { Injectable } from '@angular/core';
// If you import a module but never use any of the imported values other than as TypeScript types,
// the resulting javascript file will look as if you never imported the module at all.
import { ipcRenderer, webFrame, remote } from 'electron';
import * as childProcess from 'child_process';
import * as fs from 'fs';
@Injectable({
providedIn: 'root'
})
export class ElectronService {
ipcRenderer: typeof ipcRenderer;
webFrame: typeof webFrame;
remote: typeof remote;
childProcess: typeof childProcess;
fs: typeof fs;
get isElectron(): boolean {
return !!(window && window.process && window.process.type);
}
constructor() {
// Conditional imports
if (this.isElectron) {
this.ipcRenderer = window.require('electron').ipcRenderer;
this.webFrame = window.require('electron').webFrame;
// If you wan to use remote object, pleanse set enableRemoteModule to true in main.ts
// this.remote = window.require('electron').remote;
this.childProcess = window.require('child_process');
this.fs = window.require('fs');
}
}
}
export * from './electron/electron.service';
With credit to https://github.com/LukasMarx/angular-file-manager
/*:host {
height: 100%;
display: flex;
flex-direction: column;
-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}*/
/*.file-or-folder {
padding: 8px;
overflow: hidden;
}
.file-or-folder-icon {
width: 50px;
height: 50px;
font-size: 50px;
}
.pointer {
cursor: pointer;
}
.spacer {
flex: 1 1 auto;
}
.file-table {
height: 400px;
}
.basic-container {
height: 400px;
}*/
<!--
<mat-toolbar>
<mat-icon *ngIf="canNavigateUp" class="pointer" (click)="navigateUp()">arrow_upwards</mat-icon>
<span style="margin-left: 8px">{{path || 'Files'}}</span>
<span class="spacer"></span>
</mat-toolbar> -->
<!-- <div class="container" fxFlex fxLayout="row" fxLayoutAlign="space-between stretch"> -->
<!-- <div class="content" fxFlex fxLayout="row"> -->
<!-- <mat-grid-list cols="4" rowHeight="100px" fxFlex>
<mat-grid-tile *ngFor="let element of fileElements" class=file-or-folder>
<span [matMenuTriggerFor]="rootMenu" [matMenuTriggerData]="{element: element}" #menuTrigger="matMenuTrigger"></span>
<div fxLayout="column" fxLayoutAlign="space-between center" (click)="navigate(element)" (contextmenu)="openMenu($event, menuTrigger)">
<mat-icon color="primary" class="file-or-folder-icon pointer" *ngIf="element.isFolder">folder</mat-icon>
<mat-icon color="primary" class="file-or-folder-icon pointer" *ngIf="!element.isFolder">insert_drive_file</mat-icon>
<span>{{element.name}}</span>
</div>
</mat-grid-tile>
</mat-grid-list> -->
<!-- <cdk-virtual-scroll-viewport itemSize="50px" style="height: 400px"> -->
<!-- <cdk-virtual-scroll-viewport itemSize="50px">
<div *cdkVirtualFor="let element of fileElements">
<div fxFlex="row">
<div fxFlex="10%">
<mat-icon *ngIf="element.isFolder">folder</mat-icon>
<mat-icon *ngIf="!element.isFolder">insert_drive_file</mat-icon>
</div>
<div fxFlex>
{{ element.name }}
</div>
<div fxFlex="10%">
{{ element.size }}
</div>
</div>
</div>
</cdk-virtual-scroll-viewport> -->
<table mat-table [dataSource]="fileElements" style="width: 100%; height: 100%; overflow-y: scroll">
<ng-container matColumnDef="icon">
<th mat-header-cell *matHeaderCellDef></th>
<td mat-cell *matCellDef="let element" (contextmenu)="onContextMenu($event, element)">
<mat-icon *ngIf="element.isFolder">folder</mat-icon>
<mat-icon *ngIf="!element.isFolder">insert_drive_file</mat-icon>
<div style="position: fixed"
[style.left]="contextMenuPosition.x"
[style.top]="contextMenuPosition.y"
[matMenuTriggerFor]="contextMenu"
[matMenuTriggerData]="{element: element}">
</div>
</td>
</ng-container>
<ng-container matColumnDef="name">
<th mat-header-cell *matHeaderCellDef>Name</th>
<td mat-cell *matCellDef="let element" (contextmenu)="onContextMenu($event, element)">
{{ element.name }}
<div style="position: fixed"
[style.left]="contextMenuPosition.x"
[style.top]="contextMenuPosition.y"
[matMenuTriggerFor]="contextMenu"
[matMenuTriggerData]="{element: element}">
</div>
</td>
</ng-container>
<ng-container matColumnDef="size">
<th mat-header-cell *matHeaderCellDef>Size</th>
<td mat-cell *matCellDef="let element" (contextmenu)="onContextMenu($event, element)">
{{ element.size }}
<div style="position: fixed"
[style.left]="contextMenuPosition.x"
[style.top]="contextMenuPosition.y"
[matMenuTriggerFor]="contextMenu"
[matMenuTriggerData]="{element: element}">
</div>
</td>
</ng-container>
<ng-container matColumnDef="online">
<th mat-header-cell *matHeaderCellDef>Online</th>
<td mat-cell *matCellDef="let element" (contextmenu)="onContextMenu($event, element)">
<div *ngIf="element.online !== undefined">
<mat-icon *ngIf="element.online">check</mat-icon>
<mat-icon *ngIf="!element.online">close</mat-icon>
</div>
<div style="position: fixed"
[style.left]="contextMenuPosition.x"
[style.top]="contextMenuPosition.y"
[matMenuTriggerFor]="contextMenu"
[matMenuTriggerData]="{element: element}">
</div>
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumns; sticky: true"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;" (click)="navigate(row)"></tr>
<mat-menu #contextMenu="matMenu" [overlapTrigger]="false">
<ng-template matMenuContent let-element="element">
<!-- <button mat-menu-item [matMenuTriggerFor]="moveToMenu" [matMenuTriggerData]="{self: element}">
<mat-icon>open_with</mat-icon>
<span>Move To</span>
</button> -->
<button mat-menu-item (click)="emitSendFile(element)">
<mat-icon>send</mat-icon>
<span>Send file</span>
</button>
<button mat-menu-item (click)="openNewFolderDialog()">
<mat-icon>send</mat-icon>
<span>New directory</span>
</button>
</ng-template>
</mat-menu>
</table>
<!-- <mat-list>
<mat-list-item *ngFor="let element of fileElements" class=file-or-folder>
<span [matMenuTriggerFor]="rootMenu" [matMenuTriggerData]="{element: element}" #menuTrigger="matMenuTrigger"></span>
<div fxFlex="100%">
<div fxLayout="row" fxLayoutAlign="start none" (click)="navigate(element)" (contextmenu)="openMenu($event, menuTrigger)">
<div>
<mat-icon color="primary" class="file-or-folder-icon pointer" *ngIf="element.isFolder">folder</mat-icon>
<mat-icon color="primary" class="file-or-folder-icon pointer" *ngIf="!element.isFolder">insert_drive_file</mat-icon>
</div>
<span fxFlex>{{element.name}}</span>
<span>{{element.size}}</span>
</div>
</div>
</mat-list-item>
</mat-list> -->
<!-- </div> -->
<!-- </div> -->
import { Component, Input, Output, EventEmitter, ViewChild } from '@angular/core';
import { FileElement } from './model/element';
import { MatMenu, MatMenuTrigger } from '@angular/material/menu';
import { Observable } from 'rxjs/Observable';
import { MatDialog } from '@angular/material/dialog';
import { NewFolderDialogComponent } from './modals/newFolderDialog/newFolderDialog.component';
import { RenameDialogComponent } from './modals/renameDialog/renameDialog.component';
@Component({
selector: 'file-explorer',
templateUrl: './file-explorer.component.html',
styleUrls: ['./file-explorer.component.css']
})
export class FileExplorerComponent {
constructor(public dialog: MatDialog) {}
@ViewChild(MatMenuTrigger) contextMenu: MatMenuTrigger;
contextMenuPosition = { x: '0px', y: '0px' };
@Input() fileElements: FileElement[];
@Input() canNavigateUp: string;
@Input() path: string;
@Input() disableSend: Boolean;
@Input() identities: any;
@Output() folderAdded = new EventEmitter<{ name: string }>();
@Output() elementRemoved = new EventEmitter<FileElement>();
@Output() elementRenamed = new EventEmitter<FileElement>();
@Output() elementMoved = new EventEmitter<{ element: FileElement; moveTo: FileElement }>();
@Output() navigatedDown = new EventEmitter<FileElement>();
@Output() navigatedUp = new EventEmitter();
@Output() sendFile = new EventEmitter<FileElement>();
@Output() idSelected = new EventEmitter<any>();
displayedColumns: string[] = ['icon','name','size','online'];
fixedSizeData = Array(10000).fill(30);
onContextMenu(event: MouseEvent, element: any) {
event.preventDefault();
console.log('called onContextMenu with element',element);
this.contextMenuPosition.x = event.clientX + 'px';
this.contextMenuPosition.y = event.clientY + 'px';
this.contextMenu.menuData = { 'element': element };
this.contextMenu.openMenu();
}
deleteElement(element: FileElement) {
this.elementRemoved.emit(element);
}
navigate(element: FileElement) {
console.log('attempting navigate down');
if (element.isFolder) {
console.log('attempting navigate down',element.name);
this.navigatedDown.emit(element);
}
}
navigateUp() {
console.log('attempting navigate up');
this.navigatedUp.emit();
console.log('emitted navigateUp');
}
moveElement(element: FileElement, moveTo: FileElement) {
this.elementMoved.emit({ element: element, moveTo: moveTo });
}
rowClicked(row) {
console.log('row clicked',row);
}
openNewFolderDialog() {
let dialogRef = this.dialog.open(NewFolderDialogComponent);
dialogRef.afterClosed().subscribe(res => {
if (res) {
this.folderAdded.emit({ name: res });
}
});
}
openRenameDialog(element: FileElement) {
let dialogRef = this.dialog.open(RenameDialogComponent);
dialogRef.afterClosed().subscribe(res => {
if (res) {
element.name = res;
this.elementRenamed.emit(element);
}
});
}
emitSendFile(element: FileElement) {
console.log('called emitSendFile with element',element);
this.sendFile.emit(element);
}
emitIdSelected(id: any) {
console.log('Im going to emit',id);
this.idSelected.emit(id);
}
openMenu(event: MouseEvent, viewChild: MatMenuTrigger) {
event.preventDefault();
viewChild.openMenu();
}
}
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { MatToolbarModule } from '@angular/material/toolbar';
import { MatIconModule } from '@angular/material/icon';
import { MatGridListModule } from '@angular/material/grid-list';
import { MatListModule } from '@angular/material/list';
import { MatMenuModule } from '@angular/material/menu';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { MatDialogModule } from '@angular/material/dialog';
import { MatInputModule } from '@angular/material/input';
import { NewFolderDialogComponent } from './modals/newFolderDialog/newFolderDialog.component';
import { MatButtonModule } from '@angular/material/button';
import { FormsModule } from '@angular/forms';
import { RenameDialogComponent } from './modals/renameDialog/renameDialog.component';
import { FileExplorerComponent } from './file-explorer.component';
import {MatTableModule} from '@angular/material/table';
import {ScrollingModule} from '@angular/cdk/scrolling';
import {MatSidenavModule} from '@angular/material/sidenav'
import { MatSelectModule } from '@angular/material/select';
// import {cdkScrollable} from '@angular/'
@NgModule({
imports: [
CommonModule,
MatToolbarModule,
FlexLayoutModule,
MatIconModule,
MatGridListModule,
MatListModule,
MatMenuModule,
BrowserAnimationsModule,
MatDialogModule,
MatInputModule,
FormsModule,
MatButtonModule,
MatTableModule,
ScrollingModule,
MatSidenavModule,
MatSelectModule,
],
declarations: [FileExplorerComponent, NewFolderDialogComponent, RenameDialogComponent],
exports: [FileExplorerComponent],
entryComponents: [NewFolderDialogComponent, RenameDialogComponent]
})
export class FileExplorerModule {}
<h1 mat-dialog-title>Create a new folder</h1>
<mat-dialog-content>
<mat-form-field class="example-full-width">
<input matInput placeholder="Folder Name" [(ngModel)]="folderName">
</mat-form-field>
</mat-dialog-content>
<mat-dialog-actions>
<button mat-raised-button mat-dialog-close>Cancel</button>
<button mat-raised-button [mat-dialog-close]="folderName" color="primary">OK</button>
</mat-dialog-actions>
\ No newline at end of file
/* tslint:disable:no-unused-variable */
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { DebugElement } from '@angular/core';
import { NewFolderDialogComponent } from './newFolderDialog.component';
describe('NewFolderDialogComponent', () => {
let component: NewFolderDialogComponent;
let fixture: ComponentFixture<NewFolderDialogComponent>;
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
declarations: [ NewFolderDialogComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(NewFolderDialogComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
import { Component, OnInit } from '@angular/core';
import { MatDialogRef } from '@angular/material/dialog';
@Component({
selector: 'app-newFolderDialog',
templateUrl: './newFolderDialog.component.html',
styleUrls: ['./newFolderDialog.component.css']
})
export class NewFolderDialogComponent implements OnInit {
constructor(public dialogRef: MatDialogRef<NewFolderDialogComponent>) {}
folderName: string;
ngOnInit() {}
}
<h1 mat-dialog-title>Rename Element</h1>
<mat-dialog-content>
<mat-form-field class="example-full-width">
<input matInput placeholder="Folder Name" [(ngModel)]="folderName">
</mat-form-field>
</mat-dialog-content>
<mat-dialog-actions>
<button mat-raised-button mat-dialog-close>Cancel</button>
<button mat-raised-button [mat-dialog-close]="folderName" color="primary">OK</button>
</mat-dialog-actions>
\ No newline at end of file
import { Component, OnInit } from '@angular/core';
import { MatDialogRef } from '@angular/material/dialog';
@Component({
selector: 'app-renameDialog',
templateUrl: './renameDialog.component.html',
styleUrls: ['./renameDialog.component.css']
})
export class RenameDialogComponent implements OnInit {
constructor(public dialogRef: MatDialogRef<RenameDialogComponent>) {}
folderName: string;
ngOnInit() {}
}
export class FileElement {
isFolder: boolean;
name: string;
size: number;
online: boolean;
}
export * from './page-not-found/page-not-found.component';
<p>
page-not-found works!
</p>
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment