generated from corrad-software/corrad-af-2024
Linked navigation pane to API
The navigation pane now matches the document structure from database, but breadcrumbs bar became broken, not yet fixed. Added check to folder creation so that subfolders cannot be created in parent folders that don't exist.
This commit is contained in:
parent
384d571997
commit
274b1cf693
23
dms-api.md
23
dms-api.md
@ -10,7 +10,7 @@
|
||||
```json
|
||||
{
|
||||
"status": 200,
|
||||
"message": "Hello from the backend",
|
||||
"message": "Backend data sent successfully",
|
||||
"folders": [...]
|
||||
}
|
||||
```
|
||||
@ -30,6 +30,8 @@
|
||||
}
|
||||
```
|
||||
- **Required Fields**: cabinet_name, cabinet_sector
|
||||
- **Validation**:
|
||||
- Parent folder must exist (cabinet_parent_id must be valid)
|
||||
- **Response Example**:
|
||||
```json
|
||||
{
|
||||
@ -38,6 +40,25 @@
|
||||
"folder": {...}
|
||||
}
|
||||
```
|
||||
- **Error Responses**:
|
||||
```json
|
||||
{
|
||||
"status": 400,
|
||||
"message": "cabinet_name and cabinet_sector are required"
|
||||
}
|
||||
```
|
||||
```json
|
||||
{
|
||||
"status": 400,
|
||||
"message": "Parent folder does not exist"
|
||||
}
|
||||
```
|
||||
```json
|
||||
{
|
||||
"status": 400,
|
||||
"message": "Body was not received"
|
||||
}
|
||||
```
|
||||
|
||||
### PATCH /api/dms/folder
|
||||
- **Description**: Updates an existing folder (rename or move)
|
||||
|
@ -100,128 +100,128 @@ const dropTarget = ref(null);
|
||||
|
||||
// Enhanced hierarchical structure (Cabinet > Drawer > Folder structure)
|
||||
const documentStructure = ref([
|
||||
{
|
||||
id: 'cabinet-1',
|
||||
name: 'JKR Document Cabinet',
|
||||
type: 'cabinet',
|
||||
path: '/jkr-cabinet',
|
||||
accessLevel: 'department',
|
||||
itemCount: 234,
|
||||
children: [
|
||||
{
|
||||
id: 'drawer-1-1',
|
||||
name: 'Administrative Drawer',
|
||||
type: 'drawer',
|
||||
path: '/jkr-cabinet/administrative',
|
||||
accessLevel: 'department',
|
||||
itemCount: 89,
|
||||
children: [
|
||||
{
|
||||
id: 'folder-1-1-1',
|
||||
name: 'Personnel Files',
|
||||
type: 'folder',
|
||||
path: '/jkr-cabinet/administrative/personnel',
|
||||
accessLevel: 'private',
|
||||
itemCount: 45,
|
||||
children: []
|
||||
},
|
||||
{
|
||||
id: 'folder-1-1-2',
|
||||
name: 'Budget Reports',
|
||||
type: 'folder',
|
||||
path: '/jkr-cabinet/administrative/budget',
|
||||
accessLevel: 'department',
|
||||
itemCount: 23,
|
||||
children: []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 'drawer-1-2',
|
||||
name: 'Project Drawer',
|
||||
type: 'drawer',
|
||||
path: '/jkr-cabinet/projects',
|
||||
accessLevel: 'department',
|
||||
itemCount: 145,
|
||||
children: [
|
||||
{
|
||||
id: 'folder-1-2-1',
|
||||
name: 'Highway Projects',
|
||||
type: 'folder',
|
||||
path: '/jkr-cabinet/projects/highway',
|
||||
accessLevel: 'department',
|
||||
itemCount: 67,
|
||||
children: []
|
||||
},
|
||||
{
|
||||
id: 'folder-1-2-2',
|
||||
name: 'Building Projects',
|
||||
type: 'folder',
|
||||
path: '/jkr-cabinet/projects/building',
|
||||
accessLevel: 'department',
|
||||
itemCount: 78,
|
||||
children: []
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 'cabinet-2',
|
||||
name: 'Public Documents Cabinet',
|
||||
type: 'cabinet',
|
||||
path: '/public-cabinet',
|
||||
accessLevel: 'public',
|
||||
itemCount: 156,
|
||||
children: [
|
||||
{
|
||||
id: 'drawer-2-1',
|
||||
name: 'Forms & Applications',
|
||||
type: 'drawer',
|
||||
path: '/public-cabinet/forms',
|
||||
accessLevel: 'public',
|
||||
itemCount: 89,
|
||||
children: []
|
||||
},
|
||||
{
|
||||
id: 'drawer-2-2',
|
||||
name: 'Public Announcements',
|
||||
type: 'drawer',
|
||||
path: '/public-cabinet/announcements',
|
||||
accessLevel: 'public',
|
||||
itemCount: 67,
|
||||
children: []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 'cabinet-3',
|
||||
name: 'Personal Documents',
|
||||
type: 'cabinet',
|
||||
path: '/personal-cabinet',
|
||||
accessLevel: 'personal',
|
||||
itemCount: 45,
|
||||
children: [
|
||||
{
|
||||
id: 'drawer-3-1',
|
||||
name: 'My Documents',
|
||||
type: 'drawer',
|
||||
path: '/personal-cabinet/my-docs',
|
||||
accessLevel: 'personal',
|
||||
itemCount: 25,
|
||||
children: []
|
||||
},
|
||||
{
|
||||
id: 'drawer-3-2',
|
||||
name: 'Private Files',
|
||||
type: 'drawer',
|
||||
path: '/personal-cabinet/private',
|
||||
accessLevel: 'private',
|
||||
itemCount: 20,
|
||||
children: []
|
||||
}
|
||||
]
|
||||
}
|
||||
// {
|
||||
// id: 'cabinet-1',
|
||||
// name: 'JKR Document Cabinet',
|
||||
// type: 'cabinet',
|
||||
// path: '/jkr-cabinet',
|
||||
// accessLevel: 'department',
|
||||
// itemCount: 234,
|
||||
// children: [
|
||||
// {
|
||||
// id: 'drawer-1-1',
|
||||
// name: 'Administrative Drawer',
|
||||
// type: 'drawer',
|
||||
// path: '/jkr-cabinet/administrative',
|
||||
// accessLevel: 'department',
|
||||
// itemCount: 89,
|
||||
// children: [
|
||||
// {
|
||||
// id: 'folder-1-1-1',
|
||||
// name: 'Personnel Files',
|
||||
// type: 'folder',
|
||||
// path: '/jkr-cabinet/administrative/personnel',
|
||||
// accessLevel: 'private',
|
||||
// itemCount: 45,
|
||||
// children: []
|
||||
// },
|
||||
// {
|
||||
// id: 'folder-1-1-2',
|
||||
// name: 'Budget Reports',
|
||||
// type: 'folder',
|
||||
// path: '/jkr-cabinet/administrative/budget',
|
||||
// accessLevel: 'department',
|
||||
// itemCount: 23,
|
||||
// children: []
|
||||
// }
|
||||
// ]
|
||||
// },
|
||||
// {
|
||||
// id: 'drawer-1-2',
|
||||
// name: 'Project Drawer',
|
||||
// type: 'drawer',
|
||||
// path: '/jkr-cabinet/projects',
|
||||
// accessLevel: 'department',
|
||||
// itemCount: 145,
|
||||
// children: [
|
||||
// {
|
||||
// id: 'folder-1-2-1',
|
||||
// name: 'Highway Projects',
|
||||
// type: 'folder',
|
||||
// path: '/jkr-cabinet/projects/highway',
|
||||
// accessLevel: 'department',
|
||||
// itemCount: 67,
|
||||
// children: []
|
||||
// },
|
||||
// {
|
||||
// id: 'folder-1-2-2',
|
||||
// name: 'Building Projects',
|
||||
// type: 'folder',
|
||||
// path: '/jkr-cabinet/projects/building',
|
||||
// accessLevel: 'department',
|
||||
// itemCount: 78,
|
||||
// children: []
|
||||
// }
|
||||
// ]
|
||||
// }
|
||||
// ]
|
||||
// },
|
||||
// {
|
||||
// id: 'cabinet-2',
|
||||
// name: 'Public Documents Cabinet',
|
||||
// type: 'cabinet',
|
||||
// path: '/public-cabinet',
|
||||
// accessLevel: 'public',
|
||||
// itemCount: 156,
|
||||
// children: [
|
||||
// {
|
||||
// id: 'drawer-2-1',
|
||||
// name: 'Forms & Applications',
|
||||
// type: 'drawer',
|
||||
// path: '/public-cabinet/forms',
|
||||
// accessLevel: 'public',
|
||||
// itemCount: 89,
|
||||
// children: []
|
||||
// },
|
||||
// {
|
||||
// id: 'drawer-2-2',
|
||||
// name: 'Public Announcements',
|
||||
// type: 'drawer',
|
||||
// path: '/public-cabinet/announcements',
|
||||
// accessLevel: 'public',
|
||||
// itemCount: 67,
|
||||
// children: []
|
||||
// }
|
||||
// ]
|
||||
// },
|
||||
// {
|
||||
// id: 'cabinet-3',
|
||||
// name: 'Personal Documents',
|
||||
// type: 'cabinet',
|
||||
// path: '/personal-cabinet',
|
||||
// accessLevel: 'personal',
|
||||
// itemCount: 45,
|
||||
// children: [
|
||||
// {
|
||||
// id: 'drawer-3-1',
|
||||
// name: 'My Documents',
|
||||
// type: 'drawer',
|
||||
// path: '/personal-cabinet/my-docs',
|
||||
// accessLevel: 'personal',
|
||||
// itemCount: 25,
|
||||
// children: []
|
||||
// },
|
||||
// {
|
||||
// id: 'drawer-3-2',
|
||||
// name: 'Private Files',
|
||||
// type: 'drawer',
|
||||
// path: '/personal-cabinet/private',
|
||||
// accessLevel: 'private',
|
||||
// itemCount: 20,
|
||||
// children: []
|
||||
// }
|
||||
// ]
|
||||
// }
|
||||
]);
|
||||
|
||||
// Current folder contents (what's displayed in the main view)
|
||||
@ -322,25 +322,85 @@ const getFileTypeColor = (fileName) => {
|
||||
return colorMap[extension] || colorMap.default;
|
||||
};
|
||||
|
||||
const mapAPIToDocumentStructure = async () => {
|
||||
const response = await fetch('/api/dms/folder');
|
||||
const APIData = await response.json();
|
||||
// Function to build path from parent_id chain
|
||||
const buildPathFromParentId = (item, allItems) => {
|
||||
const pathSegments = [];
|
||||
let currentItem = item;
|
||||
|
||||
// const documentStructure.value = APIData.map(obj => {
|
||||
// id: obj.cb_id,
|
||||
// name: obj.cb_name,
|
||||
// type: obj.cb_type || "folder",
|
||||
// parent_id: obj.cb_parent_id,
|
||||
// access_level: obj.cb_access_level || "public",
|
||||
// itemCount: null,
|
||||
// children: obj.children_count || null
|
||||
// })
|
||||
// Traverse up the parent chain until we reach a root item (null parent_id)
|
||||
while (currentItem) {
|
||||
// Add the current item's name to the start of the path
|
||||
pathSegments.unshift(currentItem.name.toLowerCase().replace(/\s+/g, '-'));
|
||||
|
||||
return documentStructure.value;
|
||||
// If we've reached a root item (null parent_id), break the loop
|
||||
if (!currentItem.parent_id) break;
|
||||
|
||||
// Find the parent item
|
||||
currentItem = allItems.find(i => i.id === currentItem.parent_id);
|
||||
|
||||
// Break if we can't find the parent (shouldn't happen in a valid tree)
|
||||
if (!currentItem) break;
|
||||
}
|
||||
|
||||
// Construct the final path with leading slash
|
||||
return '/' + pathSegments.join('/');
|
||||
};
|
||||
|
||||
// Function to convert database records to frontend structure
|
||||
const convertDbToFrontendStructure = (dbRecords) => {
|
||||
// First pass: Create a map of all items with their paths
|
||||
const itemsWithPaths = dbRecords.folders.map(record => ({
|
||||
id: record.cb_id,
|
||||
name: record.cb_name,
|
||||
type: record.cb_type || 'folder',
|
||||
parent_id: record.cb_parent_id,
|
||||
accessLevel: record.cb_access_level || 'public',
|
||||
itemCount: record.item_count || 0,
|
||||
children: [],
|
||||
path: '' // Will be populated in the next step
|
||||
}));
|
||||
|
||||
// Second pass: Build paths for all items
|
||||
itemsWithPaths.forEach(item => {
|
||||
item.path = buildPathFromParentId(item, itemsWithPaths);
|
||||
});
|
||||
|
||||
// Third pass: Build the tree structure
|
||||
const rootItems = itemsWithPaths.filter(item => !item.parent_id);
|
||||
|
||||
// Recursive function to build the tree
|
||||
const buildTree = (items) => {
|
||||
return items.map(item => {
|
||||
const children = itemsWithPaths.filter(child => child.parent_id === item.id);
|
||||
return {
|
||||
...item,
|
||||
children: children.length > 0 ? buildTree(children) : []
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
return buildTree(rootItems);
|
||||
};
|
||||
|
||||
const mapAPIToDocumentStructure = async () => {
|
||||
try {
|
||||
const response = await fetch('/api/dms/folder');
|
||||
const dbRecords = await response.json();
|
||||
|
||||
console.log(dbRecords);
|
||||
|
||||
// Convert database records to frontend structure
|
||||
documentStructure.value = convertDbToFrontendStructure(dbRecords);
|
||||
|
||||
return documentStructure.value;
|
||||
} catch (error) {
|
||||
console.error('Error mapping API data:', error);
|
||||
return [];
|
||||
}
|
||||
};
|
||||
|
||||
// Navigation functions
|
||||
const buildBreadcrumbs = (path) => {
|
||||
const buildBreadcrumbs = async (path) => {
|
||||
if (path === '/') {
|
||||
return [{ name: 'Root', path: '/', type: 'root' }];
|
||||
}
|
||||
@ -348,8 +408,10 @@ const buildBreadcrumbs = (path) => {
|
||||
const crumbs = [{ name: 'Root', path: '/', type: 'root' }];
|
||||
const segments = path.split('/').filter(Boolean);
|
||||
|
||||
// const documentStructure.value = await mapAPIToDocumentStructure();
|
||||
documentStructure.value = await mapAPIToDocumentStructure();
|
||||
console.log(documentStructure.value);
|
||||
let itemsToSearch = documentStructure.value;
|
||||
console.log(itemsToSearch);
|
||||
let currentPath = '';
|
||||
|
||||
for (const segment of segments) {
|
||||
@ -456,7 +518,7 @@ const loadFolderContents = async (path) => {
|
||||
try {
|
||||
await new Promise(resolve => setTimeout(resolve, 200));
|
||||
|
||||
const item = findItemByPath(path);
|
||||
const item = findItemByPath(path, documentStructure.value);
|
||||
if (item && item.children) {
|
||||
currentFolderContents.value = item.children.map(child => ({
|
||||
...child,
|
||||
@ -1031,7 +1093,7 @@ const getTabIconClasses = (tab) => {
|
||||
};
|
||||
|
||||
// Lifecycle hooks
|
||||
onMounted(() => {
|
||||
onMounted(async () => {
|
||||
checkMobileView();
|
||||
|
||||
// Add event listeners
|
||||
@ -1040,6 +1102,9 @@ onMounted(() => {
|
||||
document.addEventListener('click', handleGlobalClick);
|
||||
document.addEventListener('contextmenu', handleGlobalContextMenu);
|
||||
|
||||
// Populate document structure
|
||||
await mapAPIToDocumentStructure();
|
||||
|
||||
// Initialize navigation
|
||||
navigateToPath('/', false);
|
||||
|
||||
|
@ -3,9 +3,9 @@ import { PrismaClient } from "@prisma/client";
|
||||
const prisma = new PrismaClient();
|
||||
|
||||
export default defineEventHandler( async (event) => {
|
||||
console.log("This is a test for a GET request to the backend");
|
||||
console.log("GET request sent received from backend.");
|
||||
|
||||
const successMsg = "Hello from the backend";
|
||||
const successMsg = "Backend data sent successfully";
|
||||
|
||||
const folders = await prisma.cabinets.findMany();
|
||||
|
||||
|
@ -3,7 +3,7 @@ import { PrismaClient } from "@prisma/client";
|
||||
const prisma = new PrismaClient();
|
||||
|
||||
export default defineEventHandler( async (event) => {
|
||||
console.log("This is a test for a POST request to the backend");
|
||||
console.log("POST request received by backend.");
|
||||
|
||||
// const successMsg = "Hello from the backend";
|
||||
|
||||
@ -39,6 +39,19 @@ export default defineEventHandler( async (event) => {
|
||||
};
|
||||
};
|
||||
|
||||
const parentExists = await prisma.cabinets.findUnique({
|
||||
where: {
|
||||
cb_id: body.cabinet_parent_id
|
||||
}
|
||||
});
|
||||
|
||||
if (!parentExists) {
|
||||
return {
|
||||
status: 400,
|
||||
message: "Parent folder does not exist"
|
||||
}
|
||||
}
|
||||
|
||||
// Checked body data.
|
||||
const folderData = {
|
||||
cb_name: body.cabinet_name,
|
||||
|
Loading…
x
Reference in New Issue
Block a user