feat: add Steuertags concept to separate workflow from content tags
Build and Push Multi-Platform Images / build-and-push (push) Successful in 38s
Build and Push Multi-Platform Images / build-and-push (push) Successful in 38s
- New steuertag_ids setting to mark tags as workflow-only (not editable) - DocumentEditModal shows only content tags (non-Steuertags) as editable chips - Backend preserves Steuertags when saving document tag changes - ManuellBearbeitenPage renders content tag chips under document title - New Steuertags settings tab with multi-select and color preview Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -29,6 +29,10 @@ import { Task } from '../database/entities/task.entity';
|
||||
import { Document } from '../database/entities/document.entity';
|
||||
import { DocumentField } from '../database/entities/document-field.entity';
|
||||
import { DocumentType } from '../database/entities/document-type.entity';
|
||||
import { Setting } from '../database/entities/setting.entity';
|
||||
|
||||
/** Setting.Tag-Schlüssel für die manuell gepflegte Steuertag-Liste */
|
||||
export const STEUERTAG_SETTING_KEY = 'steuertag_ids';
|
||||
|
||||
@Controller('api/paperless')
|
||||
export class PaperlessController {
|
||||
@@ -44,8 +48,26 @@ export class PaperlessController {
|
||||
private readonly documentFieldRepo: Repository<DocumentField>,
|
||||
@InjectRepository(DocumentType)
|
||||
private readonly documentTypeRepo: Repository<DocumentType>,
|
||||
@InjectRepository(Setting)
|
||||
private readonly settingRepo: Repository<Setting>,
|
||||
) {}
|
||||
|
||||
/** Liest die als Steuertags markierten Tag-IDs aus den Einstellungen. */
|
||||
private async getSteuertagIds(): Promise<number[]> {
|
||||
const setting = await this.settingRepo.findOneBy({
|
||||
Tag: STEUERTAG_SETTING_KEY,
|
||||
});
|
||||
return (setting?.Wert ?? '')
|
||||
.split(',')
|
||||
.map((s) => parseInt(s.trim(), 10))
|
||||
.filter((n) => !isNaN(n));
|
||||
}
|
||||
|
||||
@Get('steuertags')
|
||||
async getSteuertags() {
|
||||
return { ids: await this.getSteuertagIds() };
|
||||
}
|
||||
|
||||
@Post('checksum')
|
||||
async checksumExists(@Body('checksum') checksum: string) {
|
||||
const exists = await this.paperlessService.checksumExists(checksum);
|
||||
@@ -390,6 +412,19 @@ export class PaperlessController {
|
||||
|
||||
oldDocument.tags = oldDocument.tags || [];
|
||||
|
||||
// Im Modal bearbeitbare Inhaltstags übernehmen: Steuertags bleiben
|
||||
// unangetastet, die übrigen (Inhalts-)Tags werden durch die Auswahl ersetzt.
|
||||
if (Array.isArray(body.tags)) {
|
||||
const steuertagIds = new Set(await this.getSteuertagIds());
|
||||
const preserved = oldDocument.tags.filter((t: number) =>
|
||||
steuertagIds.has(t),
|
||||
);
|
||||
const selected = body.tags
|
||||
.map((t: any) => Number(t))
|
||||
.filter((t: number) => !isNaN(t) && !steuertagIds.has(t));
|
||||
oldDocument.tags = Array.from(new Set([...preserved, ...selected]));
|
||||
}
|
||||
|
||||
if (isReady) {
|
||||
oldDocument.tags = oldDocument.tags.filter((t: number) => t !== 1);
|
||||
if (docType?.TagNotReady)
|
||||
|
||||
@@ -9,6 +9,7 @@ import { DocumentField } from '../database/entities/document-field.entity';
|
||||
import { Task } from '../database/entities/task.entity';
|
||||
import { Document } from '../database/entities/document.entity';
|
||||
import { Attachment } from '../database/entities/attachment.entity';
|
||||
import { Setting } from '../database/entities/setting.entity';
|
||||
import { PostprocessingModule } from '../postprocessing/postprocessing.module';
|
||||
import { AuthModule } from '../auth/auth.module';
|
||||
|
||||
@@ -20,6 +21,7 @@ import { AuthModule } from '../auth/auth.module';
|
||||
Task,
|
||||
Document,
|
||||
Attachment,
|
||||
Setting,
|
||||
]),
|
||||
forwardRef(() => PostprocessingModule),
|
||||
AuthModule,
|
||||
|
||||
@@ -374,6 +374,36 @@ export class SettingsController {
|
||||
return this.settingRepo.findOneByOrFail({ ID: parseInt(id, 10) });
|
||||
}
|
||||
|
||||
// === Steuertags ===
|
||||
@Get('steuertags')
|
||||
async getSteuertags() {
|
||||
const setting = await this.settingRepo.findOneBy({ Tag: 'steuertag_ids' });
|
||||
const ids = (setting?.Wert ?? '')
|
||||
.split(',')
|
||||
.map((s) => parseInt(s.trim(), 10))
|
||||
.filter((n) => !isNaN(n));
|
||||
return { ids };
|
||||
}
|
||||
|
||||
@Put('steuertags')
|
||||
async updateSteuertags(@Body() body: { ids: number[] }) {
|
||||
const ids = (body.ids ?? [])
|
||||
.map((id) => Number(id))
|
||||
.filter((n) => !isNaN(n));
|
||||
let setting = await this.settingRepo.findOneBy({ Tag: 'steuertag_ids' });
|
||||
if (!setting) {
|
||||
setting = this.settingRepo.create({
|
||||
Typ: 0,
|
||||
Tag: 'steuertag_ids',
|
||||
Wert: ids.join(','),
|
||||
});
|
||||
} else {
|
||||
setting.Wert = ids.join(',');
|
||||
}
|
||||
await this.settingRepo.save(setting);
|
||||
return { ids };
|
||||
}
|
||||
|
||||
// === Korrespondenten ===
|
||||
@Get('correspondents')
|
||||
async getCorrespondents(
|
||||
|
||||
Reference in New Issue
Block a user