poprawki
This commit is contained in:
@@ -4,6 +4,7 @@ import { FormBuilder, ReactiveFormsModule, Validators } from '@angular/forms';
|
||||
import { AdminService } from '../../core/services/admin.service';
|
||||
import { AppSettingsService } from '../../core/services/app-settings.service';
|
||||
import { ToastService } from '../../core/services/toast.service';
|
||||
import { UiService } from '../../core/services/ui.service';
|
||||
import type { AppSettings, User } from '../../shared/models';
|
||||
|
||||
@Component({
|
||||
@@ -14,8 +15,8 @@ import type { AppSettings, User } from '../../shared/models';
|
||||
<div class="page-header d-print-none mb-3 ec-page-header">
|
||||
<div class="row align-items-center g-3">
|
||||
<div class="col">
|
||||
<h2 class="page-title mb-1">Administracja</h2>
|
||||
<div class="text-secondary">Ustawienia aplikacji, SMTP oraz zarządzanie użytkownikami.</div>
|
||||
<h2 class="page-title mb-1">{{ ui.t('admin.title') }}</h2>
|
||||
<div class="text-secondary">{{ ui.t('admin.subtitle') }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -23,52 +24,52 @@ import type { AppSettings, User } from '../../shared/models';
|
||||
<div class="row row-cards align-items-start">
|
||||
<div class="col-xl-5">
|
||||
<div class="card pv-card overflow-hidden">
|
||||
<div class="card-header"><h3 class="card-title">Ustawienia aplikacji</h3></div>
|
||||
<div class="card-header"><h3 class="card-title">{{ ui.t('admin.settings') }}</h3></div>
|
||||
<div class="card-body">
|
||||
<form [formGroup]="form" (ngSubmit)="save()" class="d-grid gap-3">
|
||||
<div>
|
||||
<label class="form-label">Nazwa aplikacji</label>
|
||||
<label class="form-label">{{ ui.t('admin.appName') }}</label>
|
||||
<input class="form-control" formControlName="appName" />
|
||||
</div>
|
||||
|
||||
<div class="row g-3">
|
||||
<div class="col-md-6"><label class="form-label">Domyślna waluta</label><input class="form-control" formControlName="defaultCurrency" /></div>
|
||||
<div class="col-md-6"><label class="form-label">Typy potwierdzeń</label><input class="form-control" formControlName="allowedProofTypes" /></div>
|
||||
<div class="col-md-6"><label class="form-label">{{ ui.t('admin.defaultCurrency') }}</label><input class="form-control" formControlName="defaultCurrency" /></div>
|
||||
<div class="col-md-6"><label class="form-label">{{ ui.t('admin.allowedProofTypes') }}</label><input class="form-control" formControlName="allowedProofTypes" /></div>
|
||||
</div>
|
||||
|
||||
<label class="form-check">
|
||||
<input class="form-check-input" type="checkbox" formControlName="registrationEnabled" />
|
||||
<span class="form-check-label">Włącz rejestrację</span>
|
||||
<span class="form-check-label">{{ ui.t('admin.registration') }}</span>
|
||||
</label>
|
||||
|
||||
<hr class="my-2" />
|
||||
<div class="fw-semibold">SMTP</div>
|
||||
<div class="fw-semibold">{{ ui.t('admin.smtp') }}</div>
|
||||
|
||||
<label class="form-check">
|
||||
<input class="form-check-input" type="checkbox" formControlName="smtpEnabled" />
|
||||
<span class="form-check-label">Włącz SMTP</span>
|
||||
<span class="form-check-label">{{ ui.t('admin.smtpEnabled') }}</span>
|
||||
</label>
|
||||
|
||||
<div class="row g-3">
|
||||
<div class="col-md-7"><label class="form-label">Host</label><input class="form-control" formControlName="smtpHost" /></div>
|
||||
<div class="col-md-5"><label class="form-label">Port</label><input class="form-control" type="number" formControlName="smtpPort" /></div>
|
||||
<div class="col-md-6"><label class="form-label">Użytkownik</label><input class="form-control" formControlName="smtpUser" /></div>
|
||||
<div class="col-md-6"><label class="form-label">Hasło</label><input class="form-control" type="password" formControlName="smtpPassword" /></div>
|
||||
<div class="col-md-6"><label class="form-label">Nazwa nadawcy</label><input class="form-control" formControlName="smtpFromName" /></div>
|
||||
<div class="col-md-6"><label class="form-label">E-mail nadawcy</label><input class="form-control" formControlName="smtpFromEmail" /></div>
|
||||
<div class="col-md-7"><label class="form-label">{{ ui.t('admin.host') }}</label><input class="form-control" formControlName="smtpHost" /></div>
|
||||
<div class="col-md-5"><label class="form-label">{{ ui.t('admin.port') }}</label><input class="form-control" type="number" formControlName="smtpPort" /></div>
|
||||
<div class="col-md-6"><label class="form-label">{{ ui.t('admin.user') }}</label><input class="form-control" formControlName="smtpUser" /></div>
|
||||
<div class="col-md-6"><label class="form-label">{{ ui.t('admin.password') }}</label><input class="form-control" type="password" formControlName="smtpPassword" /></div>
|
||||
<div class="col-md-6"><label class="form-label">{{ ui.t('admin.fromName') }}</label><input class="form-control" formControlName="smtpFromName" /></div>
|
||||
<div class="col-md-6"><label class="form-label">{{ ui.t('admin.fromEmail') }}</label><input class="form-control" formControlName="smtpFromEmail" /></div>
|
||||
</div>
|
||||
|
||||
<label class="form-check">
|
||||
<input class="form-check-input" type="checkbox" formControlName="smtpSecure" />
|
||||
<span class="form-check-label">Bezpieczne połączenie</span>
|
||||
<span class="form-check-label">{{ ui.t('admin.secureConnection') }}</span>
|
||||
</label>
|
||||
|
||||
<div class="btn-list flex-wrap">
|
||||
<button class="btn btn-success d-inline-flex align-items-center gap-2" [disabled]="form.invalid || saving()">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="icon" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><path d="M5 12l5 5l10 -10"/></svg>
|
||||
<span>Zapisz</span>
|
||||
<span>{{ ui.t('action.save') }}</span>
|
||||
</button>
|
||||
<button class="btn btn-outline-info" type="button" (click)="sendTest()">Test SMTP</button>
|
||||
<button class="btn btn-outline-info" type="button" (click)="sendTest()">{{ ui.t('action.testSmtp') }}</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
@@ -78,12 +79,12 @@ import type { AppSettings, User } from '../../shared/models';
|
||||
<div class="col-xl-7">
|
||||
<div class="card pv-card overflow-hidden">
|
||||
<div class="card-header d-flex justify-content-between align-items-center">
|
||||
<h3 class="card-title">Użytkownicy</h3>
|
||||
<h3 class="card-title">{{ ui.t('admin.users') }}</h3>
|
||||
<span class="badge bg-dark-lt">{{ users().length }}</span>
|
||||
</div>
|
||||
<div class="table-responsive">
|
||||
<table class="table table-vcenter card-table mb-0">
|
||||
<thead><tr><th>Użytkownik</th><th>Rola</th><th>Status</th><th>Data</th><th class="w-1"></th></tr></thead>
|
||||
<thead><tr><th>{{ ui.t('admin.userLabel') }}</th><th>{{ ui.t('admin.role') }}</th><th>{{ ui.t('admin.status') }}</th><th>{{ ui.t('admin.date') }}</th><th class="w-1"></th></tr></thead>
|
||||
<tbody>
|
||||
@for (user of users(); track user.id) {
|
||||
<tr>
|
||||
@@ -94,23 +95,23 @@ import type { AppSettings, User } from '../../shared/models';
|
||||
<td>{{ user.role }}</td>
|
||||
<td>
|
||||
<span class="badge" [class.bg-success]="user.isActive" [class.bg-secondary]="!user.isActive">
|
||||
{{ user.isActive ? 'Aktywny' : 'Zablokowany' }}
|
||||
{{ user.isActive ? ui.t('common.active') : ui.t('common.blocked') }}
|
||||
</span>
|
||||
</td>
|
||||
<td>{{ user.createdAt | date:'short' }}</td>
|
||||
<td>
|
||||
<div class="btn-list flex-nowrap">
|
||||
<button class="btn btn-outline-warning btn-sm" type="button" (click)="toggleRole(user)">
|
||||
{{ user.role === 'ADMIN' ? 'Ustaw USER' : 'Ustaw ADMIN' }}
|
||||
{{ user.role === 'ADMIN' ? ui.t('action.setUser') : ui.t('action.setAdmin') }}
|
||||
</button>
|
||||
<button class="btn btn-sm" [class.btn-danger]="user.isActive" [class.btn-success]="!user.isActive" type="button" (click)="toggleActive(user)">
|
||||
{{ user.isActive ? 'Zablokuj' : 'Odblokuj' }}
|
||||
{{ user.isActive ? ui.t('action.block') : ui.t('action.unblock') }}
|
||||
</button>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
} @empty {
|
||||
<tr><td colspan="5" class="text-secondary">Brak użytkowników.</td></tr>
|
||||
<tr><td colspan="5" class="text-secondary">{{ ui.t('admin.noUsers') }}</td></tr>
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
@@ -121,6 +122,7 @@ import type { AppSettings, User } from '../../shared/models';
|
||||
`
|
||||
})
|
||||
export class AdminComponent implements OnInit {
|
||||
readonly ui = inject(UiService);
|
||||
private readonly fb = inject(FormBuilder);
|
||||
private readonly admin = inject(AdminService);
|
||||
private readonly appSettings = inject(AppSettingsService);
|
||||
@@ -199,11 +201,11 @@ export class AdminComponent implements OnInit {
|
||||
this.saving.set(false);
|
||||
this.settings.set(response.item);
|
||||
this.appSettings.applySettings(response.item);
|
||||
this.toast.success('Ustawienia zapisane.');
|
||||
this.toast.success(this.ui.t('admin.settingsSaved'));
|
||||
},
|
||||
error: (error) => {
|
||||
this.saving.set(false);
|
||||
this.toast.error(error.error?.message ?? 'Nie udało się zapisać ustawień.');
|
||||
this.toast.error(error.error?.message ?? this.ui.t('admin.settingsError'));
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -211,12 +213,12 @@ export class AdminComponent implements OnInit {
|
||||
sendTest() {
|
||||
const to = this.form.getRawValue().smtpFromEmail;
|
||||
if (!to) {
|
||||
this.toast.error('Uzupełnij e-mail nadawcy.');
|
||||
this.toast.error(this.ui.t('admin.missingFromEmail'));
|
||||
return;
|
||||
}
|
||||
this.admin.testSmtp(to).subscribe({
|
||||
next: () => this.toast.success('Wiadomość testowa została wysłana.'),
|
||||
error: (error) => this.toast.error(error.error?.message ?? 'Nie udało się wysłać testu SMTP.')
|
||||
next: () => this.toast.success(this.ui.t('admin.testSent')),
|
||||
error: (error) => this.toast.error(error.error?.message ?? this.ui.t('admin.testError'))
|
||||
});
|
||||
}
|
||||
|
||||
@@ -224,9 +226,9 @@ export class AdminComponent implements OnInit {
|
||||
this.admin.updateUser(user.id, { role: user.role === 'ADMIN' ? 'USER' : 'ADMIN' }).subscribe({
|
||||
next: (response) => {
|
||||
this.users.update((items) => items.map((item) => (item.id === user.id ? response.item : item)));
|
||||
this.toast.success('Rola została zaktualizowana.');
|
||||
this.toast.success(this.ui.t('admin.roleUpdated'));
|
||||
},
|
||||
error: (error) => this.toast.error(error.error?.message ?? 'Nie udało się zmienić roli.')
|
||||
error: (error) => this.toast.error(error.error?.message ?? this.ui.t('admin.roleError'))
|
||||
});
|
||||
}
|
||||
|
||||
@@ -234,9 +236,9 @@ export class AdminComponent implements OnInit {
|
||||
this.admin.updateUser(user.id, { isActive: !user.isActive }).subscribe({
|
||||
next: (response) => {
|
||||
this.users.update((items) => items.map((item) => (item.id === user.id ? response.item : item)));
|
||||
this.toast.success('Status konta został zaktualizowany.');
|
||||
this.toast.success(this.ui.t('admin.statusUpdated'));
|
||||
},
|
||||
error: (error) => this.toast.error(error.error?.message ?? 'Nie udało się zmienić statusu.')
|
||||
error: (error) => this.toast.error(error.error?.message ?? this.ui.t('admin.statusError'))
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user