Archived
Private
Public Access
1
0

finished files page

This commit is contained in:
2023-04-16 14:28:34 +02:00
parent 72f08fc9cb
commit dfc405d799
26 changed files with 534 additions and 44 deletions

View File

@@ -9,7 +9,7 @@ import {firstValueFrom} from "rxjs";
export class IServService {
public userdata?: Userdata;
private backend: string = "http://localhost:5273";
public backend: string = "http://localhost:5273";
constructor(private client: HttpClient) {
const data = localStorage.getItem("userdata");

View File

@@ -0,0 +1,52 @@
import {Injectable} from '@angular/core';
import {IServService} from "./iserv.service";
import {HttpClient, HttpEvent} from "@angular/common/http";
import {DirectoryContent} from "../entities/directoryContent";
import {firstValueFrom, Observable} from "rxjs";
@Injectable({
providedIn: 'root'
})
export class WebdavService {
constructor(private iserv: IServService, private client: HttpClient) {}
public async getDirectory(path: string): Promise<DirectoryContent[]> {
const contents = await firstValueFrom(this.client.post<DirectoryContent[]>(this.iserv.backend + "/webdav/content?dir=" + path, this.iserv.userdata));
for (let content of contents) {
content.name = decodeURIComponent(content.name);
content.url = decodeURI(content.url);
content.lastModified = new Date(content.lastModified);
}
return contents;
}
public downloadFile(url: string): Observable<HttpEvent<Blob>> {
return this.client.post(this.iserv.backend + "/webdav/download?url=" + url, this.iserv.userdata, {responseType: "blob", reportProgress: true, observe: "events"});
}
public async delete(url: string) {
await firstValueFrom(this.client.post(this.iserv.backend + "/webdav/delete?url=" + url, this.iserv.userdata));
}
public uploadFile(url: string, file: File): Observable<HttpEvent<any>> {
const form = new FormData();
form.append('username', this.iserv.userdata.username);
form.append('password', this.iserv.userdata.password);
form.append('domain', this.iserv.userdata.domain);
form.append('file', file);
return this.client.post(this.iserv.backend + "/webdav/upload?url=" + url, form, {reportProgress: true, observe: "events"});
}
public async createFolder(url: string) {
await firstValueFrom(this.client.post(this.iserv.backend + "/webdav/create/?url=" + url, this.iserv.userdata));
}
public async moveElement(url: string, newUrl: string) {
await firstValueFrom(this.client.post(this.iserv.backend + `/webdav/move/?url=${url}&newUrl=${newUrl}`, this.iserv.userdata));
}
}

View File

@@ -1,6 +1,6 @@
<ion-app>
<ion-split-pane contentId="main-content">
<ion-menu contentId="main-content" type="overlay">
<ion-menu contentId="main-content" type="overlay" *ngIf="router.url != '/login'">
<ion-content>
<ion-list>
<ion-list-header>BetterIServ</ion-list-header>
@@ -14,7 +14,7 @@
</ion-menu-toggle>
<ion-menu-toggle auto-hide="false">
<ion-item lines="none" detail="false" (click)="logout()">
<ion-item lines="none" detail="false" routerDirection="root" routerLinkActive="selected" [routerLink]="'logout'" (click)="logout()">
<ion-icon aria-hidden="true" slot="start" ios="log-out-outline" md="log-out-sharp"></ion-icon>
<ion-label>Ausloggen</ion-label>
</ion-item>

View File

@@ -2,7 +2,7 @@ import { CommonModule } from '@angular/common';
import { Component } from '@angular/core';
import {Router, RouterLink, RouterLinkActive} from '@angular/router';
import { IonicModule } from '@ionic/angular';
import {IServService} from "./Api/iserv.service";
import {IServService} from "./api/iserv.service";
@Component({
selector: 'app-root',
templateUrl: 'app.component.html',
@@ -22,7 +22,7 @@ export class AppComponent {
];
public email = "leon.hoppe@hgbp.de";
constructor(private router: Router, public iserv: IServService) {
constructor(public router: Router, public iserv: IServService) {
if (localStorage.getItem("userdata") == null) {
this.router.navigate(["login"]);
}

View File

@@ -8,10 +8,14 @@ export const routes: Routes = [
},
{
path: 'home',
loadComponent: () => import('./home/home.page').then( m => m.HomePage)
loadComponent: () => import('./pages/home/home.page').then(m => m.HomePage)
},
{
path: 'login',
loadComponent: () => import('./login/login.page').then( m => m.LoginPage)
loadComponent: () => import('./pages/login/login.page').then(m => m.LoginPage)
},
{
path: 'files',
loadComponent: () => import('./pages/files/files.page').then( m => m.FilesPage)
},
];

View File

@@ -0,0 +1,7 @@
export interface DirectoryContent {
url: string,
name: string,
lastModified: Date,
type: string,
size: number
}

View File

@@ -1,28 +0,0 @@
ion-menu-button {
color: var(--ion-color-primary);
}
#container {
text-align: center;
position: absolute;
left: 0;
right: 0;
top: 50%;
transform: translateY(-50%);
}
#container strong {
font-size: 20px;
line-height: 26px;
}
#container p {
font-size: 16px;
line-height: 22px;
color: #8c8c8c;
margin: 0;
}
#container a {
text-decoration: none;
}

View File

@@ -0,0 +1,95 @@
<ion-header [translucent]="true">
<ion-toolbar>
<ion-buttons slot="start">
<ion-menu-button></ion-menu-button>
</ion-buttons>
<ion-title>Dateien</ion-title>
<ion-progress-bar type="indeterminate" *ngIf="loading" />
<ion-progress-bar [value]="progress" *ngIf="progress != -1" />
</ion-toolbar>
</ion-header>
<ion-content [fullscreen]="true">
<ion-header collapse="condense">
<ion-toolbar>
<ion-title size="large">Dateien</ion-title>
</ion-toolbar>
</ion-header>
<ion-grid>
<ion-row>
<ion-col>
<ion-button (click)="upload.click()"><ion-icon ios="arrow-up-circle-outline" md="arrow-up-circle-sharp" /></ion-button>
<ion-button id="create-folder"><ion-icon ios="add-circle-outline" md="add-circle-sharp" ></ion-icon></ion-button>
<form #uploadForm>
<input type="file" hidden="hidden" multiple (change)="onUpload(upload.files, uploadForm)" #upload>
</form>
<ion-modal trigger="create-folder" (willDismiss)="createFolder($event)" #modal>
<ng-template>
<ion-header>
<ion-toolbar>
<ion-buttons slot="start">
<ion-button (click)="modal.dismiss(null, 'cancel')">Abbrechen</ion-button>
</ion-buttons>
<ion-title>Neuer Ordner</ion-title>
<ion-buttons slot="end">
<ion-button (click)="modal.dismiss(newFolder.value, 'confirm')" [strong]="true">Erstellen</ion-button>
</ion-buttons>
</ion-toolbar>
</ion-header>
<ion-content class="ion-padding">
<ion-item>
<ion-label position="stacked">Name</ion-label>
<ion-input aria-label="Name" type="text" #newFolder/>
</ion-item>
</ion-content>
</ng-template>
</ion-modal>
</ion-col>
<ion-col *ngIf="clipboard">
<ion-button (click)="onMove()">Verschieben</ion-button>
</ion-col>
</ion-row>
</ion-grid>
<section class="container">
<ion-list>
<ion-list-header>{{currentDirectory}}</ion-list-header>
<ion-item *ngIf="currentDirectory != '/'">
<ion-icon ios="folder-outline" md="folder-sharp"></ion-icon>
<ion-label (click)="goUpFolder()">Übergeordnetes Verzeichnis</ion-label>
</ion-item>
<ion-item *ngFor="let item of directoryContent">
<ion-icon [ios]="(item.type == 'dir' ? 'folder' : 'document') + '-outline'" [md]="(item.type == 'dir' ? 'folder' : 'document') + '-sharp'" />
<ion-label (click)="interact(item)">{{item.name}}</ion-label>
<ion-button fill="none" (click)="openMenu(item)">
<ion-icon ios="ellipsis-vertical-outline" md="ellipsis-vertical-sharp" />
</ion-button>
</ion-item>
</ion-list>
</section>
</ion-content>
<ion-footer>
<ion-toolbar>
<ion-grid>
<ion-row>
<ion-col>
<ion-tab-button (click)="switchDirectory('/Files')" [ngClass]="{'active': currentDirectory.startsWith('/Files')}">
<ion-icon ios="folder-outline" md="folder-sharp" />
Eigene
</ion-tab-button>
</ion-col>
<ion-col>
<ion-tab-button (click)="switchDirectory('/Groups')" [ngClass]="{'active': currentDirectory.startsWith('/Groups')}">
<ion-icon ios="people-outline" md="people-sharp" />
Gruppen
</ion-tab-button>
</ion-col>
</ion-row>
</ion-grid>
</ion-toolbar>
</ion-footer>

View File

@@ -0,0 +1,8 @@
ion-label {
margin-left: 10px;
cursor: pointer;
}
.active {
color: var(--ion-color-primary);
}

View File

@@ -0,0 +1,173 @@
import {Component, OnInit} from '@angular/core';
import {CommonModule} from '@angular/common';
import {FormsModule} from '@angular/forms';
import {ActionSheetController, AlertController, IonicModule, Platform} from '@ionic/angular';
import {WebdavService} from "../../api/webdav.service";
import {DirectoryContent} from "../../entities/directoryContent";
import {File} from "@awesome-cordova-plugins/file/ngx";
import {saveAs} from "file-saver";
import {HttpDownloadProgressEvent, HttpEventType} from "@angular/common/http";
@Component({
selector: 'app-files',
templateUrl: './files.page.html',
styleUrls: ['./files.page.scss'],
standalone: true,
imports: [IonicModule, CommonModule, FormsModule]
})
export class FilesPage implements OnInit {
public currentDirectory: string = "/Files/";
public directoryContent: DirectoryContent[];
public clipboard: DirectoryContent = undefined;
public loading: boolean = true;
public progress: number = -1;
constructor(private webdav: WebdavService, private platform: Platform, private menus: ActionSheetController, private alerts: AlertController) { }
async ngOnInit() {
this.directoryContent = await this.webdav.getDirectory(this.currentDirectory);
this.loading = false;
}
public async switchDirectory(dir: string) {
this.loading = true;
this.directoryContent = await this.webdav.getDirectory(dir);
this.currentDirectory = dir;
this.loading = false;
}
public async goUpFolder() {
const split = this.currentDirectory.split("/");
await this.switchDirectory(this.currentDirectory.replace(split[split.length - 2] + "/", ""));
}
public async interact(item: DirectoryContent) {
if (item.type == "dir") {
await this.switchDirectory(item.url);
}else {
this.webdav.downloadFile(item.url).subscribe(async event => {
if (event.type == HttpEventType.DownloadProgress) {
const e = event as HttpDownloadProgressEvent;
this.progress = e.loaded / e.total * 100;
}
if (event.type == HttpEventType.Response) {
const blob = event.body;
const file = new File();
if (this.platform.is('desktop')) {
saveAs(blob, item.name);
this.progress = -1;
return;
}
const downloadPath = (
this.platform.is('android')
) ? file.externalDataDirectory : file.documentsDirectory;
await file.writeFile(downloadPath, item.name, blob, {replace: true});
this.progress = -1;
}
})
}
}
public async openMenu(item: DirectoryContent) {
const menu = await this.menus.create({
header: item.name,
buttons: [
{
text: "Löschen",
role: "destructive",
data: {action: "delete"}
},
{
text: "Verschieben",
data: {action: "move"}
},
{
text: "Abbrechen",
role: "cancel",
data: {action: "cancel"}
}
]
});
await menu.present();
const result = await menu.onDidDismiss<{action: string}>();
if (result.data?.action == undefined) return;
if (result.data.action == "delete") {
const alert = await this.alerts.create({
subHeader: "Möchtest du dieses Element wirklich löschen?",
message: item.name,
buttons: [
{
text: "Abbrechen",
role: "cancel"
},
{
text: "Löschen",
role: "destructive"
},
]
});
await alert.present();
const result = await alert.onDidDismiss();
if (result.role == "destructive") {
this.loading = true;
await this.webdav.delete(item.url);
await this.switchDirectory(this.currentDirectory);
this.loading = false;
await (await this.alerts.create({
header: "Element gelöscht!",
buttons: ["Ok"]
})).present();
}
}
if (result.data.action == "move") {
this.clipboard = item;
}
}
public async onUpload(files: FileList, form: HTMLFormElement) {
this.loading = true;
const uploads: Promise<void>[] = [];
for (let i = 0; i < files.length; i++) {
const file = files.item(i);
uploads.push(new Promise<void>(resolve => {
this.webdav.uploadFile(this.currentDirectory + file.name, file).subscribe(event => {
if (event.type == HttpEventType.Response) {
resolve();
}
});
}))
}
await Promise.all(uploads);
await this.switchDirectory(this.currentDirectory);
this.loading = false;
form.reset();
}
public async createFolder(event: any) {
if (event.detail.data == null) return;
this.loading = true;
await this.webdav.createFolder(this.currentDirectory + event.detail.data);
await this.switchDirectory(this.currentDirectory);
this.loading = false;
}
public async onMove() {
this.loading = true;
await this.webdav.moveElement(this.clipboard.url, this.currentDirectory + this.clipboard.name);
await this.switchDirectory(this.currentDirectory);
this.loading = false;
delete this.clipboard;
}
}

View File

@@ -13,9 +13,4 @@
<ion-title size="large">Übersicht</ion-title>
</ion-toolbar>
</ion-header>
<div id="container">
<strong class="capitalize">Übersicht</strong>
<p>Explore <a target="_blank" rel="noopener noreferrer" href="https://ionicframework.com/docs/components">UI Components</a></p>
</div>
</ion-content>

View File

@@ -0,0 +1 @@

View File

@@ -2,7 +2,7 @@ import { Component, OnInit } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import {AlertController, IonicModule} from '@ionic/angular';
import {IServService} from "../Api/iserv.service";
import {IServService} from "../../api/iserv.service";
import {Router} from "@angular/router";
@Component({