feat: add issue kanban/attachments/deadlines, dashboard widget DnD, and checklisten system

This commit is contained in:
Matthias Hochmeister
2026-03-28 15:19:41 +01:00
parent a1cda5be51
commit 0c2ea829aa
42 changed files with 4804 additions and 201 deletions

View File

@@ -94,4 +94,42 @@ const wartungOptions: any = {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export const uploadWartung: any = multer(wartungOptions);
export { UPLOAD_DIR, THUMBNAIL_DIR, WARTUNG_DIR };
// ── Issue uploads ────────────────────────────────────────────────────────────
const ISSUE_DIR = path.join(APP_ROOT, 'uploads', 'issues');
try {
if (!fs.existsSync(ISSUE_DIR)) {
fs.mkdirSync(ISSUE_DIR, { recursive: true });
}
} catch (err) {
logger.warn(`Could not create issue upload directory`, { err });
}
const issueStorage = multer.diskStorage({
destination(_req: any, _file: any, cb: any) {
cb(null, ISSUE_DIR);
},
filename(_req: any, file: any, cb: any) {
const uniqueSuffix = `${Date.now()}-${Math.round(Math.random() * 1e9)}`;
const ext = path.extname(file.originalname);
cb(null, `${uniqueSuffix}${ext}`);
},
});
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const issueOptions: any = {
storage: issueStorage,
fileFilter(_req: any, file: any, cb: any) {
if (ALLOWED_TYPES.includes(file.mimetype)) {
cb(null, true);
} else {
cb(new Error(`Dateityp ${file.mimetype} ist nicht erlaubt.`));
}
},
limits: { fileSize: 20 * 1024 * 1024 },
};
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export const uploadIssue: any = multer(issueOptions);
export { UPLOAD_DIR, THUMBNAIL_DIR, WARTUNG_DIR, ISSUE_DIR };