- V1__init.sql: синхронизированы таблицы с Java моделями (users, folders, messages, contacts) - docker-compose.yml: обновлён контекст сборки, переменные R2DBC/Flyway, порты (5433, 3026, 1443) - backend/Dockerfile: обновлены пути COPY для нового контекста сборки - settings.gradle: удалён frontend проект из Gradle - contacts.component.html: исправлен ternary оператор с HTML на Angular @if/@else - Фронтенд компоненты: обновления compose, inbox, layout, login, message-detail, register - index.html, styles.css: обновления стилей и мета-данных Co-authored-by: Junie <junie@jetbrains.com>
122 lines
5.0 KiB
TypeScript
122 lines
5.0 KiB
TypeScript
import { Component, inject } from '@angular/core';
|
|
import { RouterLink } from '@angular/router';
|
|
import { FormsModule } from '@angular/forms';
|
|
import { MailService } from '../../services/mail.service';
|
|
import { Router, ActivatedRoute } from '@angular/router';
|
|
|
|
@Component({
|
|
selector: 'app-compose',
|
|
standalone: true,
|
|
imports: [RouterLink, FormsModule],
|
|
providers: [MailService],
|
|
template: `
|
|
<div class="glass-panel p-6">
|
|
<h2 class="text-lg font-orbitron font-bold text-cyan-500 mb-6 flex items-center gap-2">
|
|
<i class="fa-solid fa-pen-to-square text-pink-500"></i> COMPOSE MESSAGE
|
|
</h2>
|
|
|
|
@if (success) {
|
|
<div class="mb-4 p-3 rounded-lg bg-cyan-500/20 border border-cyan-500/40 text-cyan-500 text-sm font-mono">
|
|
Message sent successfully!
|
|
</div>
|
|
}
|
|
|
|
<form (ngSubmit)="onSend()" class="space-y-4">
|
|
<div>
|
|
<label for="to" class="block text-xs font-mono text-cyan-500 mb-1">TO</label>
|
|
<input id="to" type="email" [(ngModel)]="to" name="to" required
|
|
class="w-full bg-slate-950/80 border border-cyan-500/40 rounded-xl px-4 py-3 text-sm text-slate-200 font-mono focus:outline-none focus:ring-2 focus:ring-pink-500 focus:border-cyan-500 transition-all"
|
|
placeholder="recipient@example.com">
|
|
</div>
|
|
|
|
<div>
|
|
<label for="subject" class="block text-xs font-mono text-cyan-500 mb-1">SUBJECT</label>
|
|
<input id="subject" type="text" [(ngModel)]="subject" name="subject" required
|
|
class="w-full bg-slate-950/80 border border-cyan-500/40 rounded-xl px-4 py-3 text-sm text-slate-200 font-mono focus:outline-none focus:ring-2 focus:ring-pink-500 focus:border-cyan-500 transition-all"
|
|
placeholder="Enter subject...">
|
|
</div>
|
|
|
|
<div>
|
|
<div class="flex items-center justify-between mb-1">
|
|
<label for="body" class="text-xs font-mono text-cyan-500">BODY</label>
|
|
<label class="flex items-center gap-2 cursor-pointer">
|
|
<span class="text-xs font-mono text-slate-400">HTML</span>
|
|
<input type="checkbox" [(ngModel)]="isHtml" name="isHtml" class="sr-only">
|
|
<span class="w-10 h-5 rounded-full bg-slate-900/50 border border-cyan-500/30 relative transition-all"
|
|
[class.bg-cyan-500/30]="isHtml" [class.border-cyan-500]="isHtml">
|
|
<span class="absolute top-0.5 left-0.5 w-3.5 h-3.5 rounded-full bg-cyan-500 transition-all"
|
|
[class.translate-x-5]="isHtml"></span>
|
|
</span>
|
|
</label>
|
|
</div>
|
|
<textarea id="body" [(ngModel)]="body" name="body" rows="10" required
|
|
class="w-full bg-slate-950/80 border border-cyan-500/40 rounded-xl px-4 py-3 text-sm text-slate-200 font-mono focus:outline-none focus:ring-2 focus:ring-pink-500 focus:border-cyan-500 transition-all resize-none"
|
|
[placeholder]="isHtml ? 'Write HTML or Markdown...' : 'Write your message...'"></textarea>
|
|
@if (isHtml) {
|
|
<p class="text-xs text-slate-500 font-mono mt-1"><i class="fa-solid fa-lightbulb mr-1"></i>Supports Markdown: **bold**, *italic*, - lists, code </p>
|
|
}
|
|
</div>
|
|
|
|
<div class="flex gap-3 pt-4">
|
|
<button type="submit" [disabled]="sending"
|
|
class="cyber-btn px-8 py-3 rounded-xl text-sm font-bold">
|
|
<i class="fa-solid fa-paper-plane mr-1"></i> {{ sending ? 'SENDING...' : 'SEND' }}
|
|
</button>
|
|
<a routerLink="/inbox" class="px-6 py-3 rounded-xl text-xs font-mono text-slate-400 border border-slate-600 hover:text-slate-200 hover:border-slate-400 transition-all text-center">
|
|
CANCEL
|
|
</a>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
`,
|
|
styles: ``
|
|
})
|
|
export default class ComposeComponent {
|
|
private mailService = inject(MailService);
|
|
private router = inject(Router);
|
|
private route = inject(ActivatedRoute);
|
|
|
|
to = '';
|
|
subject = '';
|
|
body = '';
|
|
isHtml = false;
|
|
sending = false;
|
|
success = false;
|
|
|
|
constructor() {
|
|
// Поддержка Reply и Forward через queryParams
|
|
this.route.queryParams.subscribe(params => {
|
|
if (params['replyTo']) {
|
|
this.to = params['replyTo'];
|
|
}
|
|
if (params['subject']) {
|
|
this.subject = params['subject'];
|
|
}
|
|
if (params['forwardSubject']) {
|
|
this.subject = params['forwardSubject'];
|
|
}
|
|
if (params['forwardBody']) {
|
|
this.body = '\n\n--- Forwarded message ---\n' + params['forwardBody'];
|
|
}
|
|
});
|
|
}
|
|
|
|
onSend(): void {
|
|
this.sending = true;
|
|
this.mailService.send({ to: this.to, subject: this.subject, body: this.body, html: this.isHtml }).subscribe({
|
|
next: () => {
|
|
this.success = true;
|
|
this.sending = false;
|
|
this.to = '';
|
|
this.subject = '';
|
|
this.body = '';
|
|
this.isHtml = false;
|
|
setTimeout(() => this.router.navigate(['/inbox']), 1500);
|
|
},
|
|
error: () => {
|
|
this.sending = false;
|
|
}
|
|
});
|
|
}
|
|
}
|