chore: estructura inicial del MVP
Backend (Express + MariaDB) y frontend (React + Vite, identidad Fluent/Windows) con el nucleo funcional: seguridad, organizacion, proyectos, actividades, subtareas, dependencias, dashboard, calendario, gantt, comentarios, adjuntos, notificaciones in-app y catalogos. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,30 @@
|
||||
import { api } from './api.js';
|
||||
|
||||
export const listAttachments = (entityType, entityId) => api.get(`/attachments?entityType=${entityType}&entityId=${entityId}`);
|
||||
|
||||
export async function uploadAttachment(entityType, entityId, file) {
|
||||
const form = new FormData();
|
||||
form.append('entityType', entityType);
|
||||
form.append('entityId', entityId);
|
||||
form.append('file', file);
|
||||
return api.postForm('/attachments', form);
|
||||
}
|
||||
|
||||
export const deleteAttachment = (id) => api.delete(`/attachments/${id}`);
|
||||
|
||||
export async function downloadAttachment(id, filename) {
|
||||
const token = localStorage.getItem('plc_token');
|
||||
const res = await fetch(api.downloadUrl(`/attachments/${id}/download`), {
|
||||
headers: token ? { Authorization: `Bearer ${token}` } : {},
|
||||
});
|
||||
if (!res.ok) throw new Error('No se pudo descargar el archivo');
|
||||
const blob = await res.blob();
|
||||
const url = URL.createObjectURL(blob);
|
||||
const a = document.createElement('a');
|
||||
a.href = url;
|
||||
a.download = filename;
|
||||
document.body.appendChild(a);
|
||||
a.click();
|
||||
a.remove();
|
||||
URL.revokeObjectURL(url);
|
||||
}
|
||||
Reference in New Issue
Block a user