zmiany cd
This commit is contained in:
@@ -5,7 +5,7 @@ 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';
|
||||
import type { AdminSystemInfo, AppSettings, User } from '../../shared/models';
|
||||
|
||||
@Component({
|
||||
selector: 'app-admin',
|
||||
@@ -21,6 +21,62 @@ import type { AppSettings, User } from '../../shared/models';
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@if (systemInfo()) {
|
||||
<div class="row row-cards mb-3">
|
||||
<div class="col-12">
|
||||
<div class="card pv-card overflow-hidden ec-accent-card ec-accent-card-info">
|
||||
<div class="card-header d-flex justify-content-between align-items-center flex-wrap gap-2">
|
||||
<div>
|
||||
<h3 class="card-title mb-1">{{ ui.t('admin.techTitle') }}</h3>
|
||||
<div class="text-secondary small">{{ ui.t('admin.techSubtitle') }}</div>
|
||||
</div>
|
||||
<span class="badge bg-info">{{ systemInfo()!.environment }}</span>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="row g-3 mb-3">
|
||||
<div class="col-sm-6 col-xl-3"><div class="ec-stat-tile"><div class="ec-stat-label">{{ ui.t('admin.appVersion') }}</div><div class="ec-stat-value">{{ systemInfo()!.suiteVersion }}</div></div></div>
|
||||
<div class="col-sm-6 col-xl-3"><div class="ec-stat-tile"><div class="ec-stat-label">API</div><div class="ec-stat-value">{{ systemInfo()!.apiVersion }}</div></div></div>
|
||||
<div class="col-sm-6 col-xl-3"><div class="ec-stat-tile"><div class="ec-stat-label">Web</div><div class="ec-stat-value">{{ systemInfo()!.webVersion }}</div></div></div>
|
||||
<div class="col-sm-6 col-xl-3"><div class="ec-stat-tile"><div class="ec-stat-label">Node.js</div><div class="ec-stat-value">{{ systemInfo()!.nodeVersion }}</div></div></div>
|
||||
</div>
|
||||
|
||||
<div class="row g-3">
|
||||
<div class="col-lg-7">
|
||||
<div class="table-responsive">
|
||||
<table class="table table-sm table-vcenter mb-0">
|
||||
<tbody>
|
||||
<tr><td class="text-secondary">{{ ui.t('admin.database') }}</td><td class="fw-semibold">{{ systemInfo()!.database }}</td></tr>
|
||||
<tr><td class="text-secondary">Upload dir</td><td class="fw-semibold text-break">{{ systemInfo()!.uploadDir }}</td></tr>
|
||||
<tr><td class="text-secondary">{{ ui.t('admin.registration') }}</td><td><span class="badge" [class.bg-success]="systemInfo()!.registrationEnabled" [class.bg-secondary]="!systemInfo()!.registrationEnabled">{{ systemInfo()!.registrationEnabled ? ui.t('common.active') : ui.t('common.blocked') }}</span></td></tr>
|
||||
<tr><td class="text-secondary">SMTP</td><td><span class="badge" [class.bg-success]="systemInfo()!.smtpConfigured" [class.bg-warning]="!systemInfo()!.smtpConfigured">{{ systemInfo()!.smtpConfigured ? ui.t('admin.smtpReady') : ui.t('admin.smtpNotReady') }}</span></td></tr>
|
||||
<tr><td class="text-secondary">API base</td><td class="fw-semibold">{{ systemInfo()!.sources.apiBasePath }}</td></tr>
|
||||
<tr><td class="text-secondary">{{ ui.t('table.date') }}</td><td class="fw-semibold">{{ systemInfo()!.checkedAt | date:'yyyy-MM-dd HH:mm:ss' }}</td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-5">
|
||||
<div class="row g-2">
|
||||
<div class="col-6"><div class="ec-mini-kpi"><span>{{ ui.t('admin.kpi.users') }}</span><strong>{{ systemInfo()!.counters.users }}</strong></div></div>
|
||||
<div class="col-6"><div class="ec-mini-kpi"><span>{{ ui.t('admin.kpi.expenses') }}</span><strong>{{ systemInfo()!.counters.expenses }}</strong></div></div>
|
||||
<div class="col-6"><div class="ec-mini-kpi"><span>{{ ui.t('admin.kpi.categories') }}</span><strong>{{ systemInfo()!.counters.categories }}</strong></div></div>
|
||||
<div class="col-6"><div class="ec-mini-kpi"><span>{{ ui.t('admin.kpi.merchants') }}</span><strong>{{ systemInfo()!.counters.merchants }}</strong></div></div>
|
||||
<div class="col-6"><div class="ec-mini-kpi"><span>{{ ui.t('admin.kpi.budgets') }}</span><strong>{{ systemInfo()!.counters.budgets }}</strong></div></div>
|
||||
<div class="col-6"><div class="ec-mini-kpi"><span>{{ ui.t('admin.kpi.recurring') }}</span><strong>{{ systemInfo()!.counters.recurring }}</strong></div></div>
|
||||
<div class="col-12"><div class="ec-mini-kpi"><span>{{ ui.t('admin.kpi.integrations') }}</span><strong>{{ systemInfo()!.counters.shoppingIntegrations }}</strong></div></div>
|
||||
</div>
|
||||
<div class="mt-3 d-flex gap-2 flex-wrap">
|
||||
<a class="btn btn-outline-primary btn-sm" href="https://git.linuxiarz.pl/gru/expense-control" target="_blank" rel="noreferrer">{{ ui.t('footer.source') }}</a>
|
||||
<a class="btn btn-outline-secondary btn-sm" href="https://git.linuxiarz.pl/gru/lista_zakupowa_live" target="_blank" rel="noreferrer">{{ ui.t('footer.shoppingSource') }}</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
<div class="row row-cards align-items-start">
|
||||
<div class="col-xl-5">
|
||||
<div class="card pv-card overflow-hidden">
|
||||
@@ -130,6 +186,7 @@ export class AdminComponent implements OnInit {
|
||||
|
||||
readonly users = signal<User[]>([]);
|
||||
readonly settings = signal<AppSettings | null>(null);
|
||||
readonly systemInfo = signal<AdminSystemInfo | null>(null);
|
||||
readonly saving = signal(false);
|
||||
|
||||
readonly form = this.fb.nonNullable.group({
|
||||
@@ -147,9 +204,7 @@ export class AdminComponent implements OnInit {
|
||||
smtpFromEmail: ['']
|
||||
});
|
||||
|
||||
ngOnInit() {
|
||||
this.load();
|
||||
}
|
||||
ngOnInit() { this.load(); }
|
||||
|
||||
load() {
|
||||
this.admin.getSettings().subscribe({
|
||||
@@ -174,40 +229,40 @@ export class AdminComponent implements OnInit {
|
||||
});
|
||||
|
||||
this.admin.listUsers().subscribe({ next: (response) => this.users.set(response.items) });
|
||||
this.admin.getSystemInfo().subscribe({ next: (response) => this.systemInfo.set(response.item) });
|
||||
}
|
||||
|
||||
save() {
|
||||
if (this.form.invalid) return;
|
||||
this.saving.set(true);
|
||||
const raw = this.form.getRawValue();
|
||||
this.admin
|
||||
.updateSettings({
|
||||
appName: raw.appName,
|
||||
defaultCurrency: raw.defaultCurrency,
|
||||
registrationEnabled: raw.registrationEnabled,
|
||||
allowedProofTypes: raw.allowedProofTypes.split(',').map((item) => item.trim()).filter(Boolean),
|
||||
uiPreferences: { theme: 'dark', density: 'comfortable', defaultStatsPeriod: 'month' },
|
||||
smtpEnabled: raw.smtpEnabled,
|
||||
smtpHost: raw.smtpHost || null,
|
||||
smtpPort: Number(raw.smtpPort),
|
||||
smtpSecure: raw.smtpSecure,
|
||||
smtpUser: raw.smtpUser || null,
|
||||
smtpPassword: raw.smtpPassword || null,
|
||||
smtpFromName: raw.smtpFromName || null,
|
||||
smtpFromEmail: raw.smtpFromEmail || null
|
||||
})
|
||||
.subscribe({
|
||||
next: (response) => {
|
||||
this.saving.set(false);
|
||||
this.settings.set(response.item);
|
||||
this.appSettings.applySettings(response.item);
|
||||
this.toast.success(this.ui.t('admin.settingsSaved'));
|
||||
},
|
||||
error: (error) => {
|
||||
this.saving.set(false);
|
||||
this.toast.error(error.error?.message ?? this.ui.t('admin.settingsError'));
|
||||
}
|
||||
});
|
||||
this.admin.updateSettings({
|
||||
appName: raw.appName,
|
||||
defaultCurrency: raw.defaultCurrency,
|
||||
registrationEnabled: raw.registrationEnabled,
|
||||
allowedProofTypes: raw.allowedProofTypes.split(',').map((item) => item.trim()).filter(Boolean),
|
||||
uiPreferences: { theme: 'dark', density: 'comfortable', defaultStatsPeriod: 'month' },
|
||||
smtpEnabled: raw.smtpEnabled,
|
||||
smtpHost: raw.smtpHost || null,
|
||||
smtpPort: Number(raw.smtpPort),
|
||||
smtpSecure: raw.smtpSecure,
|
||||
smtpUser: raw.smtpUser || null,
|
||||
smtpPassword: raw.smtpPassword || null,
|
||||
smtpFromName: raw.smtpFromName || null,
|
||||
smtpFromEmail: raw.smtpFromEmail || null
|
||||
}).subscribe({
|
||||
next: (response) => {
|
||||
this.saving.set(false);
|
||||
this.settings.set(response.item);
|
||||
this.appSettings.applySettings(response.item);
|
||||
this.toast.success(this.ui.t('admin.settingsSaved'));
|
||||
this.admin.getSystemInfo().subscribe({ next: (systemResponse) => this.systemInfo.set(systemResponse.item) });
|
||||
},
|
||||
error: (error) => {
|
||||
this.saving.set(false);
|
||||
this.toast.error(error.error?.message ?? this.ui.t('admin.settingsError'));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
sendTest() {
|
||||
|
||||
Reference in New Issue
Block a user