feat: add default label template setting and apply it to print dialog selection
Build and Push Multi-Platform Images / build-and-push (push) Successful in 35s

This commit is contained in:
2026-05-09 12:41:05 +02:00
parent e4f765fcfd
commit 0318fe8e7a
5 changed files with 82 additions and 5 deletions
@@ -28,4 +28,7 @@ export class UserSettings {
@Column({ type: 'text', nullable: true })
MailSignatureHtml!: string | null;
@Column({ type: 'int', nullable: true })
DefaultLabelTemplateId!: number | null;
}
@@ -17,6 +17,7 @@ export interface UserSettingsDto {
smtpFrom: string | null;
smtpFromName: string | null;
mailSignatureHtml: string | null;
defaultLabelTemplateId: number | null;
}
@Injectable()
@@ -78,6 +79,7 @@ export class UserSettingsService {
smtpFrom?: string | null;
smtpFromName?: string | null;
mailSignatureHtml?: string | null;
defaultLabelTemplateId?: number | null;
},
): Promise<UserSettingsDto> {
let entity = await this.repo.findOne({ where: { UserId: userId } });
@@ -95,6 +97,7 @@ export class UserSettingsService {
if (data.smtpFrom !== undefined) entity.SmtpFrom = data.smtpFrom;
if (data.smtpFromName !== undefined) entity.SmtpFromName = data.smtpFromName;
if (data.mailSignatureHtml !== undefined) entity.MailSignatureHtml = data.mailSignatureHtml;
if (data.defaultLabelTemplateId !== undefined) entity.DefaultLabelTemplateId = data.defaultLabelTemplateId;
await this.repo.save(entity);
return this.toDto(entity);
@@ -164,6 +167,7 @@ export class UserSettingsService {
smtpFrom: entity?.SmtpFrom ?? null,
smtpFromName: entity?.SmtpFromName ?? null,
mailSignatureHtml: entity?.MailSignatureHtml ?? null,
defaultLabelTemplateId: entity?.DefaultLabelTemplateId ?? null,
};
}
}
@@ -9,6 +9,7 @@ export interface UserSettingsData {
smtpFrom: string | null;
smtpFromName: string | null;
mailSignatureHtml: string | null;
defaultLabelTemplateId: number | null;
}
export interface SenderOption {
+13 -4
View File
@@ -36,6 +36,7 @@ import type { ColumnsType } from 'antd/es/table';
import { inboxApi, type InboxBarcode, type InboxFile } from '../api/inbox';
import { barcodeTemplatesApi, type BarcodeTemplate } from '../api/barcode-templates';
import { labelPrintAgentApi } from '../api/labelPrintAgent';
import { userSettingsApi } from '../api/userSettings';
const { Title } = Typography;
@@ -150,14 +151,22 @@ export default function InboxPage() {
const openPrintDialog = async () => {
try {
const all = await barcodeTemplatesApi.list();
setLabelTemplates(all.filter((t) => t.LabelEnabled));
const [all, settings] = await Promise.all([
barcodeTemplatesApi.list(),
userSettingsApi.get(),
]);
const enabled = all.filter((t) => t.LabelEnabled);
setLabelTemplates(enabled);
const defaultId = settings.defaultLabelTemplateId;
const defaultTemplate = defaultId != null
? (enabled.find((t) => t.Id === defaultId) ?? null)
: null;
setSelectedTemplate(defaultTemplate);
setFieldValues(buildInitialFieldValues(defaultTemplate));
} catch {
message.error('Vorlagen konnten nicht geladen werden');
return;
}
setSelectedTemplate(null);
setFieldValues({});
setLabelCount(1);
setPrintDialogOpen(true);
};
@@ -1,11 +1,66 @@
import { useEffect, useRef, useState } from 'react';
import { Button, Card, Form, Input, InputNumber, Space, Switch, Tabs, Typography, message } from 'antd';
import { Button, Card, Form, Input, InputNumber, Select, Space, Switch, Tabs, Typography, message } from 'antd';
import { CheckCircleOutlined, CloseCircleOutlined, LoadingOutlined } from '@ant-design/icons';
import { WysiwygEditor, type WysiwygEditorHandle } from '../components/WysiwygEditor';
import { userSettingsApi } from '../api/userSettings';
import { barcodeTemplatesApi, type BarcodeTemplate } from '../api/barcode-templates';
const { Title } = Typography;
function LabelSettingsTab() {
const [templates, setTemplates] = useState<BarcodeTemplate[]>([]);
const [selectedId, setSelectedId] = useState<number | null>(null);
const [loading, setLoading] = useState(true);
const [saving, setSaving] = useState(false);
useEffect(() => {
Promise.all([userSettingsApi.get(), barcodeTemplatesApi.list()])
.then(([settings, all]) => {
setTemplates(all.filter((t) => t.LabelEnabled));
setSelectedId(settings.defaultLabelTemplateId);
})
.catch(() => message.error('Einstellungen konnten nicht geladen werden'))
.finally(() => setLoading(false));
}, []);
const handleSave = async () => {
setSaving(true);
try {
await userSettingsApi.update({ defaultLabelTemplateId: selectedId });
message.success('Einstellungen gespeichert');
} catch {
message.error('Speichern fehlgeschlagen');
} finally {
setSaving(false);
}
};
if (loading) return null;
return (
<Form layout="vertical" style={{ maxWidth: 600 }}>
<Form.Item
label="Standard-Etikettenvorlage"
extra="Diese Vorlage wird beim Öffnen des Etikett-drucken-Dialogs vorausgewählt."
>
<Select
placeholder="Keine Standardvorlage"
allowClear
options={templates.map((t) => ({ value: t.Id, label: t.Name }))}
value={selectedId ?? undefined}
onChange={(v: number | undefined) => setSelectedId(v ?? null)}
style={{ width: '100%' }}
/>
</Form.Item>
<Form.Item>
<Button type="primary" loading={saving} onClick={handleSave}>
Speichern
</Button>
</Form.Item>
</Form>
);
}
function MailSettingsTab() {
const [form] = Form.useForm();
const [loading, setLoading] = useState(true);
@@ -155,6 +210,11 @@ export default function UserSettingsPage() {
label: 'Maileinstellungen',
children: <MailSettingsTab />,
},
{
key: 'label',
label: 'Etikettendruck',
children: <LabelSettingsTab />,
},
]}
/>
</Card>