diff --git a/client/src/components/_custom/drp/DataFilesProjectPublish/DataFilesProjectPublishWizardSteps/ReviewProjectStructure.jsx b/client/src/components/_custom/drp/DataFilesProjectPublish/DataFilesProjectPublishWizardSteps/ReviewProjectStructure.jsx index 3e3a0e596..9cdb163fc 100644 --- a/client/src/components/_custom/drp/DataFilesProjectPublish/DataFilesProjectPublishWizardSteps/ReviewProjectStructure.jsx +++ b/client/src/components/_custom/drp/DataFilesProjectPublish/DataFilesProjectPublishWizardSteps/ReviewProjectStructure.jsx @@ -28,6 +28,12 @@ const ReviewProjectStructure = ({ projectTree }) => { const { params } = useFileListing('FilesListing'); + useEffect(() => { + if (projectTree && projectTree.length > 0) { + setExpandedNodes([projectTree[0].uuid]); + } + }, [projectTree]); + const handleNodeToggle = (event, nodeIds) => { // Update the list of expanded nodes setExpandedNodes(nodeIds); @@ -59,18 +65,13 @@ const ReviewProjectStructure = ({ projectTree }) => { const dataType = node.metadata.data_type; // reconstruct editFile to mimic SelectedFile object const editFile = { - format: 'folder', - id: node.path, + id: node.uuid, + uuid: node.uuid, metadata: node.metadata, name: node.metadata.name, system: params.system, - path: node.path.split('/').slice(1).join('/'), type: 'dir', - _links: { - self: { - href: 'tapis://' + node.path, - }, - }, + }; switch (dataType) { case 'sample': @@ -92,10 +93,10 @@ const ReviewProjectStructure = ({ projectTree }) => { api: params.api, scheme: params.scheme, system: params.system, - path: node.path.split('/').slice(1).join('/'), + path: node.path, name: node.name, - href: 'tapis://' + node.path, - length: node.metadata.length, + href: `tapis://${params.system}/${node.path}`, + length: node.length, metadata: node.metadata, useReloadCallback: false, }, @@ -112,7 +113,8 @@ const ReviewProjectStructure = ({ projectTree }) => { .map(word => word.charAt(0).toUpperCase() + word.slice(1)) .join(' '); - const renderTree = (node) => ( + const renderTree = (node) => { + return ( <>
{ >
- {node.name} - - {formatDatatype(node.metadata.data_type)} + {node.label ?? node.name} + {node.metadata.data_type && ( + + {formatDatatype(node.metadata.data_type)} + )}
} classes={{ @@ -135,7 +139,7 @@ const ReviewProjectStructure = ({ projectTree }) => { }} onLabelClick={() => handleNodeToggle} > - {expandedNodes.includes(node.id) && ( + {expandedNodes.includes(node.uuid) && node.id !== 'NODE_ROOT' && (
{(canEdit || node.metadata.data_type === 'file') && (
)} + {Array.isArray(node.fileObjs) && + node.fileObjs.map((fileObj) => renderTree(fileObj))} {Array.isArray(node.children) && node.children.map((child) => renderTree(child))}
- ); - - const getAllNodeIds = (nodes) => { - const ids = []; - nodes.forEach((node) => { - ids.push(node.id); - if (Array.isArray(node.children)) { - ids.push(...getAllNodeIds(node.children)); - } - }); - return ids; - }; + )}; return ( { } defaultExpandIcon={} - // expanded={getAllNodeIds(tree)} + expanded={expandedNodes} onNodeToggle={handleNodeToggle} > {projectTree.map((node) => renderTree(node))} diff --git a/server/portal/apps/_custom/drp/views.py b/server/portal/apps/_custom/drp/views.py index ffd35f520..8cb223e88 100644 --- a/server/portal/apps/_custom/drp/views.py +++ b/server/portal/apps/_custom/drp/views.py @@ -5,7 +5,7 @@ from portal.apps.datafiles.models import DataFilesMetadata from portal.apps.projects.models.project_metadata import ProjectMetadata from portal.apps._custom.drp import constants - +import networkx as nx class DigitalRocksSampleView(BaseApiView): def get(self, request): @@ -48,6 +48,10 @@ def construct_tree(records, parent_id=None): } tree.append(node_dict) return tree + + @staticmethod + def _get_entity(uuid): + return ProjectMetadata.objects.get(uuid=uuid) def get(self, request): @@ -56,11 +60,36 @@ def get(self, request): project_id = request.GET.get('project_id') full_project_id = f'{settings.PORTAL_PROJECTS_SYSTEM_PREFIX}.{project_id}' - records = DataFilesMetadata.objects.filter( - project_id=full_project_id, - metadata__data_type__in=metadata_data_types - ).order_by('created_at') + graph_model = ProjectMetadata.objects.get( + name=constants.PROJECT_GRAPH, base_project__value__projectId=full_project_id + ) + + graph = nx.node_link_graph(graph_model.value) + + for node in graph.nodes: + node_uuid = graph.nodes[node].get("uuid") + + entity = self._get_entity(node_uuid) + metadata = entity.ordered_value - tree = self.construct_tree(records) + file_objs = entity.value.get('fileObjs', []) + + file_objs_dict = [] + + for file_obj in file_objs: + file_obj_entity = self._get_entity(file_obj.get('uuid')) + file_obj_metadata = file_obj_entity.ordered_value + + file_objs_dict.append({ + **file_obj, + 'metadata': file_obj_metadata + }) + + graph.nodes[node]['metadata'] = metadata + graph.nodes[node]['fileObjs'] = file_objs_dict + + tree = nx.tree_data(graph, "NODE_ROOT") + + return JsonResponse([tree], safe=False) + - return JsonResponse(tree, safe=False) \ No newline at end of file diff --git a/server/portal/apps/projects/workspace_operations/project_meta_operations.py b/server/portal/apps/projects/workspace_operations/project_meta_operations.py index 4f228f504..3fd46f7e6 100644 --- a/server/portal/apps/projects/workspace_operations/project_meta_operations.py +++ b/server/portal/apps/projects/workspace_operations/project_meta_operations.py @@ -86,7 +86,7 @@ def patch_entity(client, project_id, value, uuid=None, path=None, updated_path=N so that only fields in the payload are overwritten.""" node = get_node_from_path(project_id, path) if path else get_root_node(project_id) - entity = ProjectMetadata.objects.get(uuid=node['uuid']) + entity = ProjectMetadata.objects.get(uuid=uuid if uuid else node['uuid']) current_name = entity.value.get('name') current_path_full = path