From c15df303f03eb540a2b595b8f7a3db692d96604b Mon Sep 17 00:00:00 2001 From: "leon.hoppe" Date: Sat, 22 Apr 2023 14:12:20 +0200 Subject: [PATCH] added mails page + reworked button placement --- .../BetterIServ.Backend.csproj | 1 + .../Controllers/MailController.cs | 105 +++++++++++++++++ BetterIServ.Backend/Entities/Credentials.cs | 9 +- BetterIServ.Backend/Entities/MailContent.cs | 13 +++ BetterIServ.Backend/Entities/MailData.cs | 9 ++ BetterIServ.Backend/Entities/SingleResult.cs | 5 + BetterIServ.Mobile/angular.json | 3 +- BetterIServ.Mobile/package-lock.json | 19 +++ BetterIServ.Mobile/package.json | 6 +- .../src/app/api/mail.service.ts | 50 ++++++++ BetterIServ.Mobile/src/app/app.component.ts | 2 +- BetterIServ.Mobile/src/app/app.routes.ts | 4 + BetterIServ.Mobile/src/app/entities/mail.ts | 28 +++++ .../src/app/pages/files/files.page.html | 67 +++++------ .../src/app/pages/files/files.page.ts | 29 ++++- .../src/app/pages/mails/mails.page.html | 96 +++++++++++++++ .../src/app/pages/mails/mails.page.scss | 51 ++++++++ .../src/app/pages/mails/mails.page.ts | 109 ++++++++++++++++++ BetterIServ.Mobile/src/global.scss | 4 + 19 files changed, 560 insertions(+), 50 deletions(-) create mode 100644 BetterIServ.Backend/Controllers/MailController.cs create mode 100644 BetterIServ.Backend/Entities/MailContent.cs create mode 100644 BetterIServ.Backend/Entities/MailData.cs create mode 100644 BetterIServ.Backend/Entities/SingleResult.cs create mode 100644 BetterIServ.Mobile/src/app/api/mail.service.ts create mode 100644 BetterIServ.Mobile/src/app/entities/mail.ts create mode 100644 BetterIServ.Mobile/src/app/pages/mails/mails.page.html create mode 100644 BetterIServ.Mobile/src/app/pages/mails/mails.page.scss create mode 100644 BetterIServ.Mobile/src/app/pages/mails/mails.page.ts diff --git a/BetterIServ.Backend/BetterIServ.Backend.csproj b/BetterIServ.Backend/BetterIServ.Backend.csproj index 01b1bff..c275bf3 100644 --- a/BetterIServ.Backend/BetterIServ.Backend.csproj +++ b/BetterIServ.Backend/BetterIServ.Backend.csproj @@ -8,6 +8,7 @@ + diff --git a/BetterIServ.Backend/Controllers/MailController.cs b/BetterIServ.Backend/Controllers/MailController.cs new file mode 100644 index 0000000..ff967ba --- /dev/null +++ b/BetterIServ.Backend/Controllers/MailController.cs @@ -0,0 +1,105 @@ +using System.Net; +using System.Net.Mail; +using System.Text; +using Aspose.Email.Clients.Imap; +using BetterIServ.Backend.Entities; +using Microsoft.AspNetCore.Mvc; + +namespace BetterIServ.Backend.Controllers; + +[ApiController] +[Route("mail")] +public class MailController : ControllerBase { + + [HttpPost("send")] + public async Task SendMail([FromBody] MailData data) { + using var client = new SmtpClient($"smpt.{data.Domain}"); + var sender = new MailAddress($"{data.Username}@{data.Domain}", data.Username); + var reciever = new MailAddress(data.Receiver ?? $"{data.Username}@{data.Domain}"); + + using var message = new MailMessage(sender, reciever); + message.Body = data.MailBody; + message.Subject = data.Subject; + message.BodyEncoding = Encoding.UTF8; + message.SubjectEncoding = Encoding.UTF8; + + var result = new TaskCompletionSource(); + client.SendCompleted += (o, args) => { + if (args is { Cancelled: false, Error: null }) + result.SetResult(Ok()); + else result.SetResult(BadRequest(args.Error?.Message)); + }; + + client.Credentials = new NetworkCredential(data.Username, data.Password); + client.EnableSsl = true; + await client.SendMailAsync(message); + return await result.Task; + } + + [HttpPost("list/{page}")] + public async Task> GetMails([FromBody] Credentials credentials, [FromQuery] string folder, [FromRoute] int page) { + using var client = new ImapClient($"imap.{credentials.Domain}", credentials.Username, credentials.Password); + await client.SelectFolderAsync(folder); + + var messages = await client.ListMessagesByPageAsync(20, page, new PageSettingsAsync()); + var contents = new List(); + foreach (var message in messages.Items) { + var content = new MailContent { + Id = message.SequenceNumber, + Sender = message.Sender, + Subject = message.Subject, + Time = message.Date, + Read = message.IsRead + }; + contents.Add(content); + } + + return contents.ToArray(); + } + + [HttpPost("content/{id}")] + public async Task> GetMail([FromBody] Credentials credentials, [FromRoute] int id) { + using var client = new ImapClient($"imap.{credentials.Domain}", credentials.Username, credentials.Password); + var message = await client.FetchMessageAsync(id); + + var content = new MailContent { + Id = id, + Sender = message.Sender, + Subject = message.Subject.Replace("(Aspose.Email Evaluation)", ""), + Time = message.Date, + Read = true, + Message = message.Body.Replace("EVALUATION ONLY. CREATED WITH ASPOSE.EMAIL FOR .NET. COPYRIGHT 2002-2022 ASPOSE PTY LTD. \r\n http://www.aspose.com/corporate/purchase/end-user-license-agreement.aspx: View EULA Online\r\n", ""), + Attachments = message.Attachments.Select(a => a.Name).ToArray() + }; + + return content; + } + + [HttpPost("folder")] + public async Task>> GetFolder([FromBody] Credentials credentials) { + using var client = new ImapClient($"imap.{credentials.Domain}", credentials.Username, credentials.Password); + var folders = await client.ListFoldersAsync(); + var results = new List(); + + foreach (var folder in folders) { + results.Add(folder); + if (folder.HasChildren) { + var children = await client.ListFoldersAsync(folder.Name); + results.AddRange(children); + } + } + + return new SingleResult { Value = results.ToArray() }; + } + + [HttpPost("download/{id}/{attachment}")] + public async Task DownloadAttachment([FromBody] Credentials credentials, [FromRoute] int id, [FromRoute] string attachment) { + using var client = new ImapClient($"imap.{credentials.Domain}", credentials.Username, credentials.Password); + var data = await client.FetchAttachmentAsync(id, attachment); + + return new FileStreamResult(data.ContentStream, "application/octet-stream") { + FileDownloadName = attachment + }; + } + +} \ No newline at end of file diff --git a/BetterIServ.Backend/Entities/Credentials.cs b/BetterIServ.Backend/Entities/Credentials.cs index d8458bc..a561950 100644 --- a/BetterIServ.Backend/Entities/Credentials.cs +++ b/BetterIServ.Backend/Entities/Credentials.cs @@ -1,7 +1,8 @@ namespace BetterIServ.Backend.Entities; -public struct Credentials { - public string Domain { get; set; } - public string Username { get; set; } - public string Password { get; set; } +public class Credentials { + public string? Domain { get; set; } + public string? Username { get; set; } + public string? Password { get; set; } + public string? Token { get; set; } } \ No newline at end of file diff --git a/BetterIServ.Backend/Entities/MailContent.cs b/BetterIServ.Backend/Entities/MailContent.cs new file mode 100644 index 0000000..8a11f93 --- /dev/null +++ b/BetterIServ.Backend/Entities/MailContent.cs @@ -0,0 +1,13 @@ +using Aspose.Email; + +namespace BetterIServ.Backend.Entities; + +public struct MailContent { + public int Id { get; set; } + public MailAddress Sender { get; set; } + public string Subject { get; set; } + public string Message { get; set; } + public DateTime Time { get; set; } + public bool Read { get; set; } + public string[] Attachments { get; set; } +} \ No newline at end of file diff --git a/BetterIServ.Backend/Entities/MailData.cs b/BetterIServ.Backend/Entities/MailData.cs new file mode 100644 index 0000000..e174518 --- /dev/null +++ b/BetterIServ.Backend/Entities/MailData.cs @@ -0,0 +1,9 @@ +namespace BetterIServ.Backend.Entities; + +public sealed class MailData : Credentials { + + public string? MailBody { get; set; } + public string? Receiver { get; set; } + public string? Subject { get; set; } + +} \ No newline at end of file diff --git a/BetterIServ.Backend/Entities/SingleResult.cs b/BetterIServ.Backend/Entities/SingleResult.cs new file mode 100644 index 0000000..8f8a384 --- /dev/null +++ b/BetterIServ.Backend/Entities/SingleResult.cs @@ -0,0 +1,5 @@ +namespace BetterIServ.Backend.Entities; + +public class SingleResult { + public TValue? Value { get; set; } +} \ No newline at end of file diff --git a/BetterIServ.Mobile/angular.json b/BetterIServ.Mobile/angular.json index 6e857f5..78e95e9 100644 --- a/BetterIServ.Mobile/angular.json +++ b/BetterIServ.Mobile/angular.json @@ -37,7 +37,8 @@ } ], "styles": ["src/theme/variables.scss", "src/global.scss"], - "scripts": [] + "scripts": [], + "allowedCommonJsDependencies": ["file-saver"] }, "configurations": { "production": { diff --git a/BetterIServ.Mobile/package-lock.json b/BetterIServ.Mobile/package-lock.json index 9e28e3c..17790a6 100644 --- a/BetterIServ.Mobile/package-lock.json +++ b/BetterIServ.Mobile/package-lock.json @@ -23,6 +23,7 @@ "@ionic/angular": "^7.0.0", "file-saver": "^2.0.5", "ionicons": "^7.0.0", + "marked": "^4.3.0", "rxjs": "~7.5.0", "tslib": "^2.3.0", "zone.js": "~0.11.4" @@ -42,6 +43,7 @@ "@ionic/angular-toolkit": "^9.0.0", "@types/file-saver": "^2.0.5", "@types/jasmine": "~4.0.0", + "@types/marked": "^4.0.8", "@types/node": "^12.11.1", "@typescript-eslint/eslint-plugin": "5.3.0", "@typescript-eslint/parser": "5.3.0", @@ -3730,6 +3732,12 @@ "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", "dev": true }, + "node_modules/@types/marked": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/@types/marked/-/marked-4.0.8.tgz", + "integrity": "sha512-HVNzMT5QlWCOdeuBsgXP8EZzKUf0+AXzN+sLmjvaB3ZlLqO+e4u0uXrdw9ub69wBKFs+c6/pA4r9sy6cCDvImw==", + "dev": true + }, "node_modules/@types/mime": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/@types/mime/-/mime-3.0.1.tgz", @@ -9998,6 +10006,17 @@ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "dev": true }, + "node_modules/marked": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/marked/-/marked-4.3.0.tgz", + "integrity": "sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A==", + "bin": { + "marked": "bin/marked.js" + }, + "engines": { + "node": ">= 12" + } + }, "node_modules/media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", diff --git a/BetterIServ.Mobile/package.json b/BetterIServ.Mobile/package.json index ba798ad..6a06441 100644 --- a/BetterIServ.Mobile/package.json +++ b/BetterIServ.Mobile/package.json @@ -29,6 +29,7 @@ "@ionic/angular": "^7.0.0", "file-saver": "^2.0.5", "ionicons": "^7.0.0", + "marked": "^4.3.0", "rxjs": "~7.5.0", "tslib": "^2.3.0", "zone.js": "~0.11.4" @@ -46,9 +47,10 @@ "@angular/language-service": "^15.0.0", "@capacitor/cli": "4.7.3", "@ionic/angular-toolkit": "^9.0.0", - "@types/jasmine": "~4.0.0", - "@types/node": "^12.11.1", "@types/file-saver": "^2.0.5", + "@types/jasmine": "~4.0.0", + "@types/marked": "^4.0.8", + "@types/node": "^12.11.1", "@typescript-eslint/eslint-plugin": "5.3.0", "@typescript-eslint/parser": "5.3.0", "eslint": "^7.6.0", diff --git a/BetterIServ.Mobile/src/app/api/mail.service.ts b/BetterIServ.Mobile/src/app/api/mail.service.ts new file mode 100644 index 0000000..49e71be --- /dev/null +++ b/BetterIServ.Mobile/src/app/api/mail.service.ts @@ -0,0 +1,50 @@ +import { Injectable } from '@angular/core'; +import {IServService} from "./iserv.service"; +import {HttpClient, HttpEvent} from "@angular/common/http"; +import {MailContent, MailData, MailFolder} from "../entities/mail"; +import {firstValueFrom, Observable} from "rxjs"; + +@Injectable({ + providedIn: 'root' +}) +export class MailService { + + constructor(private iserv: IServService, private client: HttpClient) { } + + public async getMails(folder: string, page: number): Promise { + const mails = await firstValueFrom(this.client.post(this.iserv.backend + `/mail/list/${page}?folder=${folder}`, this.iserv.userdata)); + + for (let mail of mails) { + mail.time = new Date(mail.time); + } + + return mails; + } + + public async getMail(id: number): Promise { + const mail = await firstValueFrom(this.client.post(this.iserv.backend + "/mail/content/" + id, this.iserv.userdata)); + + mail.time = new Date(mail.time); + return mail; + } + + public async getFolders(): Promise { + return (await firstValueFrom(this.client.post<{value: MailFolder[]}>(this.iserv.backend + "/mail/folder", this.iserv.userdata))).value; + } + + public async sendMail(subject: string, receiver: string, mailBody: string) { + const data: MailData = { + domain: this.iserv.userdata.domain, + username: this.iserv.userdata.username, + password: this.iserv.userdata.password, + token: this.iserv.userdata.token, + subject, receiver, mailBody + }; + await firstValueFrom(this.client.post(this.iserv.backend + "/mail/send", data)); + } + + public downloadAttachment(mailId: number, attachment: string): Observable> { + return this.client.post(this.iserv.backend + `/mail/download/${mailId}/${attachment}`, this.iserv.userdata, {responseType: "blob", reportProgress: true, observe: "events"}); + } + +} diff --git a/BetterIServ.Mobile/src/app/app.component.ts b/BetterIServ.Mobile/src/app/app.component.ts index 41e1008..1223413 100644 --- a/BetterIServ.Mobile/src/app/app.component.ts +++ b/BetterIServ.Mobile/src/app/app.component.ts @@ -14,7 +14,7 @@ export class AppComponent { public appPages = [ { title: 'Übersicht', url: '/home', icon: 'home' }, - { title: 'E-Mail', url: '/email', icon: 'mail' }, + { title: 'E-Mail', url: '/mails', icon: 'mail' }, { title: 'Dateien', url: '/files', icon: 'folder' }, { title: 'Aufgaben', url: '/tasks', icon: 'clipboard' }, { title: 'Stundenplan', url: '/schedule', icon: 'grid' }, diff --git a/BetterIServ.Mobile/src/app/app.routes.ts b/BetterIServ.Mobile/src/app/app.routes.ts index bca29f3..6c5d835 100644 --- a/BetterIServ.Mobile/src/app/app.routes.ts +++ b/BetterIServ.Mobile/src/app/app.routes.ts @@ -18,4 +18,8 @@ export const routes: Routes = [ path: 'files', loadComponent: () => import('./pages/files/files.page').then( m => m.FilesPage) }, + { + path: 'mails', + loadComponent: () => import('./pages/mails/mails.page').then( m => m.MailsPage) + }, ]; diff --git a/BetterIServ.Mobile/src/app/entities/mail.ts b/BetterIServ.Mobile/src/app/entities/mail.ts new file mode 100644 index 0000000..465d6d9 --- /dev/null +++ b/BetterIServ.Mobile/src/app/entities/mail.ts @@ -0,0 +1,28 @@ +import {Userdata} from "./userdata"; + +export interface MailFolder { + name: string; + newMessageCount: number; +} + +export interface MailData extends Userdata { + mailBody: string; + receiver: string; + subject: string; +} + +export interface MailAddress { + displayName: string; + user: string; + address: string; +} + +export interface MailContent { + id: number; + sender: MailAddress; + subject: string; + message: string; + time: Date; + read: boolean; + attachments: string[]; +} diff --git a/BetterIServ.Mobile/src/app/pages/files/files.page.html b/BetterIServ.Mobile/src/app/pages/files/files.page.html index 27a0bb8..ea6a3ce 100644 --- a/BetterIServ.Mobile/src/app/pages/files/files.page.html +++ b/BetterIServ.Mobile/src/app/pages/files/files.page.html @@ -4,6 +4,36 @@ Dateien + + + + +
+ +
+ + + + + + + Abbrechen + + Neuer Ordner + + Erstellen + + + + + + Name + + + + + +
@@ -16,43 +46,6 @@ - - - - - -
- -
- - - - - - - Abbrechen - - Neuer Ordner - - Erstellen - - - - - - Name - - - - - -
- - Verschieben - -
-
-
{{currentDirectory}} diff --git a/BetterIServ.Mobile/src/app/pages/files/files.page.ts b/BetterIServ.Mobile/src/app/pages/files/files.page.ts index 62ba3c8..9e1b3e5 100644 --- a/BetterIServ.Mobile/src/app/pages/files/files.page.ts +++ b/BetterIServ.Mobile/src/app/pages/files/files.page.ts @@ -1,7 +1,7 @@ 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 {ActionSheetController, AlertController, IonicModule, Platform, ToastController} from '@ionic/angular'; import {WebdavService} from "../../api/webdav.service"; import {DirectoryContent} from "../../entities/directoryContent"; import {File} from "@awesome-cordova-plugins/file/ngx"; @@ -24,7 +24,7 @@ export class FilesPage implements OnInit { public progress: number = -1; - constructor(private webdav: WebdavService, private platform: Platform, private menus: ActionSheetController, private alerts: AlertController) { } + constructor(private webdav: WebdavService, private platform: Platform, private menus: ActionSheetController, private alerts: AlertController, private toasts: ToastController) { } async ngOnInit() { this.directoryContent = await this.webdav.getDirectory(this.currentDirectory); @@ -122,9 +122,10 @@ export class FilesPage implements OnInit { await this.switchDirectory(this.currentDirectory); this.loading = false; - await (await this.alerts.create({ - header: "Element gelöscht!", - buttons: ["Ok"] + await (await this.toasts.create({ + message: "Element gelöscht!", + position: "bottom", + duration: 2000 })).present(); } } @@ -152,6 +153,12 @@ export class FilesPage implements OnInit { await this.switchDirectory(this.currentDirectory); this.loading = false; form.reset(); + + await (await this.toasts.create({ + message: "Element hochgeladen!", + position: "bottom", + duration: 2000 + })).present(); } public async createFolder(event: any) { @@ -160,6 +167,12 @@ export class FilesPage implements OnInit { await this.webdav.createFolder(this.currentDirectory + event.detail.data); await this.switchDirectory(this.currentDirectory); this.loading = false; + + await (await this.toasts.create({ + message: "Ordner erstellt!", + position: "bottom", + duration: 2000 + })).present(); } public async onMove() { @@ -168,6 +181,12 @@ export class FilesPage implements OnInit { await this.switchDirectory(this.currentDirectory); this.loading = false; delete this.clipboard; + + await (await this.toasts.create({ + message: "Element verschoben!", + position: "bottom", + duration: 2000 + })).present(); } } diff --git a/BetterIServ.Mobile/src/app/pages/mails/mails.page.html b/BetterIServ.Mobile/src/app/pages/mails/mails.page.html new file mode 100644 index 0000000..fa38ca1 --- /dev/null +++ b/BetterIServ.Mobile/src/app/pages/mails/mails.page.html @@ -0,0 +1,96 @@ + + + + + + E-Mails + + + + + + + + + + Zurück + + Neue E-Mail + + Senden + + + + + +
+ + + + +
+
+
+
+ + +
+
+ + + + + E-Mails + + + + + + {{folder.name}} + + + + + +
+
+ + {{message.sender.displayName}} + {{message.time.toLocaleDateString()}} +
+ {{message.subject}} +
+
+
+ + + + + + + + + + Zurück + + {{currentMail?.sender.displayName}} + + + + +
+ {{currentMail?.subject}} + {{currentMail?.time.toLocaleDateString()}} + + + {{attachment}} + + +
+ +
+
+
+
+ +
diff --git a/BetterIServ.Mobile/src/app/pages/mails/mails.page.scss b/BetterIServ.Mobile/src/app/pages/mails/mails.page.scss new file mode 100644 index 0000000..5fb1bd7 --- /dev/null +++ b/BetterIServ.Mobile/src/app/pages/mails/mails.page.scss @@ -0,0 +1,51 @@ +ion-select { + padding-inline: 15px; +} + +.mail > div { + display: flex; + flex-direction: column; + gap: 7px; + margin-block: 15px; + width: 100%; + + .subject, .date { + font-size: 15px; + } + + & > div { + display: flex; + + ion-icon { + margin-right: 5px; + color: var(--ion-color-primary); + } + + .date { + margin-left: auto; + } + } +} + +.current-mail { + .header { + display: flex; + flex-direction: column; + gap: 10px; + + .subject { + font-weight: bold; + } + + .time { + font-size: 15px; + } + } +} + +.new-email { + display: flex; + flex-direction: column; + gap: 15px; + height: 100%; +} diff --git a/BetterIServ.Mobile/src/app/pages/mails/mails.page.ts b/BetterIServ.Mobile/src/app/pages/mails/mails.page.ts new file mode 100644 index 0000000..5bc1dff --- /dev/null +++ b/BetterIServ.Mobile/src/app/pages/mails/mails.page.ts @@ -0,0 +1,109 @@ +import {Component, OnInit} from '@angular/core'; +import {CommonModule} from '@angular/common'; +import {FormsModule} from '@angular/forms'; +import {InfiniteScrollCustomEvent, IonicModule, IonModal, Platform, ToastController} from '@ionic/angular'; +import {MailService} from "../../api/mail.service"; +import {MailContent, MailFolder} from "../../entities/mail"; +import {marked} from "marked"; +import {HttpDownloadProgressEvent, HttpEventType} from "@angular/common/http"; +import {File} from "@awesome-cordova-plugins/file/ngx"; +import {saveAs} from "file-saver"; + +@Component({ + selector: 'app-mails', + templateUrl: './mails.page.html', + styleUrls: ['./mails.page.scss'], + standalone: true, + imports: [IonicModule, CommonModule, FormsModule] +}) +export class MailsPage implements OnInit { + + public showLoading = false; + public mails: MailContent[] = []; + public folders: MailFolder[] = []; + public currentMail: MailContent; + private currentPage = 0; + private currentFolder: MailFolder; + + constructor(private mail: MailService, private platform: Platform, private toasts: ToastController) { } + + async ngOnInit() { + this.showLoading = true; + const folderResponse = this.mail.getFolders(); + const mailResponse = this.mail.getMails("INBOX", this.currentPage); + await Promise.all([mailResponse, folderResponse]); + + this.folders = await folderResponse; + this.mails = await mailResponse; + + this.currentFolder = this.folders.filter(folder => folder.name == "INBOX")[0]; + this.showLoading = false; + } + + public async changeFolder(folder: MailFolder) { + this.showLoading = true; + this.currentFolder = folder; + this.currentPage = 0; + this.mails = await this.mail.getMails(this.currentFolder.name, this.currentPage); + this.showLoading = false; + } + + public async loadMore(event: any) { + this.showLoading = true; + this.currentPage++; + const newMails = await this.mail.getMails(this.currentFolder.name, this.currentPage); + this.mails.push(...newMails); + this.showLoading = false; + await event.target.complete(); + } + + public async selectMail(message: MailContent, modal: IonModal) { + this.showLoading = true; + message.read = true; + this.currentMail = message; + + const body = await this.mail.getMail(message.id); + this.currentMail.message = marked(body.message); + this.currentMail.attachments = body.attachments; + + this.showLoading = false; + await modal.present(); + } + + public async downloadAttachment(attachment: string, mailId: number) { + this.showLoading = true; + this.mail.downloadAttachment(mailId, attachment).subscribe(async event => { + if (event.type == HttpEventType.Response) { + const blob = event.body; + const file = new File(); + + if (this.platform.is('desktop')) { + saveAs(blob, attachment); + this.showLoading = false; + return; + } + + const downloadPath = ( + this.platform.is('android') + ) ? file.externalDataDirectory : file.documentsDirectory; + await file.writeFile(downloadPath, attachment, blob, {replace: true}); + this.showLoading = false; + } + }) + } + + public async sendMail(receiver: string, subject: string, message: string, modal: IonModal) { + this.showLoading = true; + await this.mail.sendMail(subject, receiver, message); + await modal.dismiss(); + this.showLoading = false; + + const toast = await this.toasts.create({ + message: "E-Mail gesendet!", + duration: 2000, + position: "bottom" + }); + await toast.present(); + } + +} diff --git a/BetterIServ.Mobile/src/global.scss b/BetterIServ.Mobile/src/global.scss index ba50f1f..1e0fb47 100644 --- a/BetterIServ.Mobile/src/global.scss +++ b/BetterIServ.Mobile/src/global.scss @@ -28,3 +28,7 @@ ion-menu-button { color: var(--ion-color-primary); } + +.pointer { + cursor: pointer; +}