diff --git a/Makefile b/Makefile
index 4ac51b224..e45c6ba32 100644
--- a/Makefile
+++ b/Makefile
@@ -2,7 +2,11 @@ PROJECT_PATH = $(shell pwd)
ENV_FILE := .env
+# include .env files if they exist
+-include ${ENV_FILE}
+
NAME := mapping_workbench
+DOCKER_PROJECT := ${NAME}_${ENVIRONMENT}
BACKEND_INFRA_FOLDER := ${PROJECT_PATH}/${NAME}/backend
FRONTEND_HOME := ${NAME}/frontend
FRONTEND_INFRA_FOLDER := ${PROJECT_PATH}/${FRONTEND_HOME}
@@ -10,10 +14,6 @@ FRONTEND_INFRA_FOLDER := ${PROJECT_PATH}/${FRONTEND_HOME}
RML_MAPPER_PATH = ${PROJECT_PATH}/.rmlmapper/rmlmapper.jar
-# include .env files if they exist
--include ${ENV_FILE}
-
-
#-----------------------------------------------------------------------------
# INSTALLING
#----------------------------------------------------------------------
@@ -107,37 +107,37 @@ prod-dotenv-file:
build-backend:
@ echo "Building the BACKEND"
- @ docker-compose -p ${NAME} --file ./infra/backend/docker-compose.yml --env-file ${ENV_FILE} build --progress plain --no-cache --force-rm
- @ docker-compose -p ${NAME} --file ./infra/backend/docker-compose.yml --env-file ${ENV_FILE} up -d --force-recreate
+ @ docker-compose -p ${DOCKER_PROJECT} --file ./infra/backend/docker-compose.yml --env-file ${ENV_FILE} build --progress plain --no-cache --force-rm
+ @ docker-compose -p ${DOCKER_PROJECT} --file ./infra/backend/docker-compose.yml --env-file ${ENV_FILE} up -d --force-recreate
start-backend:
@ echo "Starting the BACKEND"
- @ docker-compose -p ${NAME} --file ./infra/backend/docker-compose.yml --env-file ${ENV_FILE} up -d
+ @ docker-compose -p ${DOCKER_PROJECT} --file ./infra/backend/docker-compose.yml --env-file ${ENV_FILE} up -d
stop-backend:
@ echo "Stopping the BACKEND"
- @ docker-compose -p ${NAME} --file ./infra/backend/docker-compose.yml --env-file ${ENV_FILE} down
+ @ docker-compose -p ${DOCKER_PROJECT} --file ./infra/backend/docker-compose.yml --env-file ${ENV_FILE} down
build-frontend:
@ echo "Building the FRONTEND"
- @ docker-compose -p ${NAME} --file ./infra/frontend/docker-compose.yml --env-file ${ENV_FILE} build --progress plain --no-cache --force-rm
- @ docker-compose -p ${NAME} --file ./infra/frontend/docker-compose.yml --env-file ${ENV_FILE} up -d --force-recreate
+ @ docker-compose -p ${DOCKER_PROJECT} --file ./infra/frontend/docker-compose.yml --env-file ${ENV_FILE} build --progress plain --no-cache --force-rm
+ @ docker-compose -p ${DOCKER_PROJECT} --file ./infra/frontend/docker-compose.yml --env-file ${ENV_FILE} up -d --force-recreate
start-frontend:
@ echo "Starting the FRONTEND"
- @ docker-compose -p ${NAME} --file ./infra/frontend/docker-compose.yml --env-file ${ENV_FILE} up -d
+ @ docker-compose -p ${DOCKER_PROJECT} --file ./infra/frontend/docker-compose.yml --env-file ${ENV_FILE} up -d
stop-frontend:
@ echo "Stopping the FRONTEND"
- @ docker-compose -p ${NAME} --file ./infra/frontend/docker-compose.yml --env-file ${ENV_FILE} down
+ @ docker-compose -p ${DOCKER_PROJECT} --file ./infra/frontend/docker-compose.yml --env-file ${ENV_FILE} down
start-mongo: build-externals
@ echo "Starting the Mongo services"
- @ docker-compose -p ${NAME} --file ./infra/mongodb/docker-compose.yml --env-file ${ENV_FILE} up -d
+ @ docker-compose -p ${DOCKER_PROJECT} --file ./infra/mongodb/docker-compose.yml --env-file ${ENV_FILE} up -d
stop-mongo:
@ echo "Stopping the Mongo services"
- @ docker-compose -p ${NAME} --file ./infra/mongodb/docker-compose.yml --env-file ${ENV_FILE} down
+ @ docker-compose -p ${DOCKER_PROJECT} --file ./infra/mongodb/docker-compose.yml --env-file ${ENV_FILE} down
#-----------------------------------------------------------------------------
@@ -146,29 +146,29 @@ stop-mongo:
build-backend-dev:
@ echo "Building the BACKEND"
- @ docker-compose -p ${NAME} --file ./infra/backend/docker-compose.dev.yml --env-file ${ENV_FILE} build --progress plain --no-cache --force-rm
- @ docker-compose -p ${NAME} --file ./infra/backend/docker-compose.dev.yml --env-file ${ENV_FILE} up -d --force-recreate
+ @ docker-compose -p ${DOCKER_PROJECT} --file ./infra/backend/docker-compose.dev.yml --env-file ${ENV_FILE} build --progress plain --no-cache --force-rm
+ @ docker-compose -p ${DOCKER_PROJECT} --file ./infra/backend/docker-compose.dev.yml --env-file ${ENV_FILE} up -d --force-recreate
start-backend-dev:
@ echo "Starting the BACKEND"
- @ docker-compose -p ${NAME} --file ./infra/backend/docker-compose.dev.yml --env-file ${ENV_FILE} up -d
+ @ docker-compose -p ${DOCKER_PROJECT} --file ./infra/backend/docker-compose.dev.yml --env-file ${ENV_FILE} up -d
stop-backend-dev:
@ echo "Stopping the BACKEND"
- @ docker-compose -p ${NAME} --file ./infra/backend/docker-compose.dev.yml --env-file ${ENV_FILE} down
+ @ docker-compose -p ${DOCKER_PROJECT} --file ./infra/backend/docker-compose.dev.yml --env-file ${ENV_FILE} down
build-frontend-dev:
@ echo "Building the FRONTEND"
- @ docker-compose -p ${NAME} --file ./infra/frontend/docker-compose.dev.yml --env-file ${ENV_FILE} build --progress plain --no-cache --force-rm
- @ docker-compose -p ${NAME} --file ./infra/frontend/docker-compose.dev.yml --env-file ${ENV_FILE} up -d --force-recreate
+ @ docker-compose -p ${DOCKER_PROJECT} --file ./infra/frontend/docker-compose.dev.yml --env-file ${ENV_FILE} build --progress plain --no-cache --force-rm
+ @ docker-compose -p ${DOCKER_PROJECT} --file ./infra/frontend/docker-compose.dev.yml --env-file ${ENV_FILE} up -d --force-recreate
start-frontend-dev:
@ echo "Starting the FRONTEND"
- @ docker-compose -p ${NAME} --file ./infra/frontend/docker-compose.dev.yml --env-file ${ENV_FILE} up -d
+ @ docker-compose -p ${DOCKER_PROJECT} --file ./infra/frontend/docker-compose.dev.yml --env-file ${ENV_FILE} up -d
stop-frontend-dev:
@ echo "Stopping the FRONTEND"
- @ docker-compose -p ${NAME} --file ./infra/frontend/docker-compose.dev.yml --env-file ${ENV_FILE} down
+ @ docker-compose -p ${DOCKER_PROJECT} --file ./infra/frontend/docker-compose.dev.yml --env-file ${ENV_FILE} down
clear-frontend:
@ cd ${FRONTEND_HOME} && rm -rf build && rm -rf node_modules && rm -f .env* && rm -f package-lock.json
@@ -185,11 +185,11 @@ start-mongo-console-mode:
start-mongo-dev: build-externals
@ echo "Starting the Mongo services"
- @ docker-compose -p ${NAME} --file ./infra/mongodb/docker-compose.dev.yml --env-file ${ENV_FILE} up -d
+ @ docker-compose -p ${DOCKER_PROJECT} --file ./infra/mongodb/docker-compose.dev.yml --env-file ${ENV_FILE} up -d
stop-mongo-dev:
@ echo "Stopping the Mongo services"
- @ docker-compose -p ${NAME} --file ./infra/mongodb/docker-compose.dev.yml --env-file ${ENV_FILE} down
+ @ docker-compose -p ${DOCKER_PROJECT} --file ./infra/mongodb/docker-compose.dev.yml --env-file ${ENV_FILE} down
#-----------------------------------------------------------------------------
# SERVER SERVICES
diff --git a/mapping_workbench/backend/core/entrypoints/api/main.py b/mapping_workbench/backend/core/entrypoints/api/main.py
index ad0eaa67e..a6e071be0 100755
--- a/mapping_workbench/backend/core/entrypoints/api/main.py
+++ b/mapping_workbench/backend/core/entrypoints/api/main.py
@@ -2,6 +2,7 @@
from fastapi.middleware.cors import CORSMiddleware
from httpx_oauth.clients.google import GoogleOAuth2
+from mapping_workbench.backend.fields_registry.entrypoints.api import routes as fields_registry
from mapping_workbench.backend.conceptual_mapping_rule.entrypoints.api import routes as conceptual_mapping_rule_routes
from mapping_workbench.backend.config import settings
from mapping_workbench.backend.config.entrypoints.api import routes as config_routes
@@ -77,7 +78,8 @@ async def on_startup():
generic_triple_map_fragment_routes.router,
config_routes.router,
ontology_routes.router,
- tasks_routes.router
+ tasks_routes.router,
+ fields_registry.router
]
for secured_router in secured_routers:
diff --git a/mapping_workbench/backend/mapping_package/models/entity.py b/mapping_workbench/backend/mapping_package/models/entity.py
index 09ccb78c7..a0612a826 100644
--- a/mapping_workbench/backend/mapping_package/models/entity.py
+++ b/mapping_workbench/backend/mapping_package/models/entity.py
@@ -13,7 +13,7 @@
BaseProjectResourceEntityInSchema, BaseProjectResourceEntityOutSchema
from mapping_workbench.backend.shacl_test_suite.models.entity import SHACLTestSuite
from mapping_workbench.backend.state_manager.models.state_object import ObjectState, StatefulObjectABC
-from mapping_workbench.backend.test_data_suite.models.entity import TestDataSuite, TestDataSuiteState
+#from mapping_workbench.backend.test_data_suite.models.entity import TestDataSuite, TestDataSuiteState
class MappingPackageException(Exception):
@@ -30,7 +30,7 @@ class MappingPackageIn(BaseProjectResourceEntityInSchema):
end_date: Optional[datetime] = None
min_xsd_version: Optional[str] = None
max_xsd_version: Optional[str] = None
- test_data_suites: Optional[List[Optional[Link[TestDataSuite]]]] = None
+ #test_data_suites: Optional[List[Optional[Link[TestDataSuite]]]] = None
shacl_test_suites: Optional[List[Optional[Link[SHACLTestSuite]]]] = None
@@ -56,7 +56,7 @@ class MappingPackageOut(BaseProjectResourceEntityOutSchema):
end_date: Optional[datetime] = None
min_xsd_version: Optional[str] = None
max_xsd_version: Optional[str] = None
- test_data_suites: Optional[List[Link[TestDataSuite]]] = None
+ #test_data_suites: Optional[List[Link[TestDataSuite]]] = None
shacl_test_suites: Optional[List[Link[SHACLTestSuite]]] = None
@@ -74,7 +74,7 @@ class MappingPackageState(ObjectState):
end_date: Optional[datetime] = None
min_xsd_version: Optional[str] = None
max_xsd_version: Optional[str] = None
- test_data_suites: List[TestDataSuiteState] = []
+ #test_data_suites: List[TestDataSuiteState] = []
shacl_test_suites: List[SHACLTestSuite] = []
conceptual_mapping_rule_states: List[ConceptualMappingRuleState] = []
@@ -89,7 +89,7 @@ class MappingPackage(BaseProjectResourceEntity, StatefulObjectABC):
end_date: Optional[datetime] = None
min_xsd_version: Optional[str] = None
max_xsd_version: Optional[str] = None
- test_data_suites: Optional[List[Link[TestDataSuite]]] = None
+ #test_data_suites: Optional[List[Link[TestDataSuite]]] = None
shacl_test_suites: Optional[List[Link[SHACLTestSuite]]] = None
async def get_conceptual_mapping_rules(self) -> List[ConceptualMappingRuleState]:
diff --git a/mapping_workbench/backend/ontology_file_collection/entrypoints/api/routes.py b/mapping_workbench/backend/ontology_file_collection/entrypoints/api/routes.py
index 51576c775..5d20dc27c 100644
--- a/mapping_workbench/backend/ontology_file_collection/entrypoints/api/routes.py
+++ b/mapping_workbench/backend/ontology_file_collection/entrypoints/api/routes.py
@@ -1,5 +1,3 @@
-from typing import List
-
from beanie import PydanticObjectId
from fastapi import APIRouter, status, Depends
from starlette.requests import Request
diff --git a/mapping_workbench/backend/resource_collection/entrypoints/api/routes.py b/mapping_workbench/backend/resource_collection/entrypoints/api/routes.py
index 4378aed04..39f5d89ee 100644
--- a/mapping_workbench/backend/resource_collection/entrypoints/api/routes.py
+++ b/mapping_workbench/backend/resource_collection/entrypoints/api/routes.py
@@ -47,13 +47,22 @@
response_model=APIListResourceCollectionsPaginatedResponse
)
async def route_list_resource_collections(
- project: PydanticObjectId = None
+ project: PydanticObjectId = None,
+ page: int = None,
+ limit: int = None,
+ q: str = None
):
filters: dict = {}
if project:
filters['project'] = Project.link_from_id(project)
- items: List[ResourceCollection] = await list_resource_collections(filters)
- return APIListResourceCollectionsPaginatedResponse(items=items, count=len(items))
+ if q is not None:
+ filters['q'] = q
+
+ items, total_count = await list_resource_collections(filters, page, limit)
+ return APIListResourceCollectionsPaginatedResponse(
+ items=items,
+ count=total_count
+ )
@router.post(
@@ -112,10 +121,24 @@ async def route_delete_resource_collection(resource_collection: ResourceCollecti
response_model=APIListResourceFilesPaginatedResponse
)
async def route_list_resource_collection_file_resources(
- id: PydanticObjectId = None
+ resource_collection: ResourceCollection = Depends(get_resource_collection),
+ project: PydanticObjectId = None,
+ page: int = None,
+ limit: int = None,
+ q: str = None
):
- items: List[ResourceFile] = await list_resource_collection_file_resources(id)
- return APIListResourceFilesPaginatedResponse(items=items, count=len(items))
+ filters: dict = {}
+ if project:
+ filters['project'] = Project.link_from_id(project)
+ if q is not None:
+ filters['q'] = q
+
+ items, total_count = \
+ await list_resource_collection_file_resources(resource_collection, filters, page, limit)
+ return APIListResourceFilesPaginatedResponse(
+ items=items,
+ count=total_count
+ )
@router.post(
diff --git a/mapping_workbench/backend/resource_collection/services/api.py b/mapping_workbench/backend/resource_collection/services/api.py
index 39fa01cdf..fd4d96afa 100644
--- a/mapping_workbench/backend/resource_collection/services/api.py
+++ b/mapping_workbench/backend/resource_collection/services/api.py
@@ -1,25 +1,34 @@
from typing import List
from beanie import PydanticObjectId
-from bson import DBRef
from mapping_workbench.backend.core.models.base_entity import BaseEntityFiltersSchema
from mapping_workbench.backend.core.services.exceptions import ResourceNotFoundException
from mapping_workbench.backend.core.services.request import request_update_data, api_entity_is_found, \
- request_create_data
+ request_create_data, prepare_search_param, pagination_params
from mapping_workbench.backend.resource_collection.models.entity import ResourceCollection, ResourceFile, \
ResourceFileUpdateIn, ResourceFileCreateIn
from mapping_workbench.backend.user.models.user import User
-async def list_resource_collections(filters=None) -> List[ResourceCollection]:
+async def list_resource_collections(filters: dict = None, page: int = None, limit: int = None) -> \
+ (List[ResourceCollection], int):
query_filters: dict = dict(filters or {}) | dict(BaseEntityFiltersSchema())
- return await ResourceCollection.find(
+
+ prepare_search_param(query_filters)
+ skip, limit = pagination_params(page, limit)
+
+ items: List[ResourceCollection] = await ResourceCollection.find(
query_filters,
projection_model=ResourceCollection,
- fetch_links=False
+ fetch_links=False,
+ skip=skip,
+ limit=limit
).to_list()
+ total_count: int = await ResourceCollection.find(query_filters).count()
+ return items, total_count
+
async def create_resource_collection(resource_collection: ResourceCollection, user: User) -> ResourceCollection:
resource_collection.on_create(user=user)
@@ -48,15 +57,23 @@ async def delete_resource_collection(resource_collection: ResourceCollection):
async def list_resource_collection_file_resources(
- id: PydanticObjectId = None,
- filters=None
-) -> List[ResourceFile]:
+ resource_collection: ResourceCollection,
+ filters=None, page: int = None, limit: int = None
+):
query_filters: dict = dict(filters or {}) | dict(BaseEntityFiltersSchema())
- return await ResourceFile.find(
- ResourceFile.resource_collection == ResourceCollection.link_from_id(id),
+ query_filters['resource_collection'] = ResourceCollection.link_from_id(resource_collection.id)
+
+ prepare_search_param(query_filters)
+ skip, limit = pagination_params(page, limit)
+
+ items: List[ResourceFile] = await ResourceFile.find(
query_filters,
- fetch_links=False
+ fetch_links=False,
+ skip=skip,
+ limit=limit
).to_list()
+ total_count: int = await ResourceFile.find(query_filters).count()
+ return items, total_count
async def create_resource_collection_file_resource(
diff --git a/mapping_workbench/backend/shacl_test_suite/entrypoints/api/routes.py b/mapping_workbench/backend/shacl_test_suite/entrypoints/api/routes.py
index fd4871f2f..ddbe562ad 100644
--- a/mapping_workbench/backend/shacl_test_suite/entrypoints/api/routes.py
+++ b/mapping_workbench/backend/shacl_test_suite/entrypoints/api/routes.py
@@ -48,15 +48,24 @@
)
async def route_list_shacl_test_suites(
project: PydanticObjectId = None,
- ids: Annotated[List[PydanticObjectId | str] | None, Query()] = None
+ ids: Annotated[List[PydanticObjectId | str] | None, Query()] = None,
+ page: int = None,
+ limit: int = None,
+ q: str = None
):
filters: dict = {}
if project:
filters['project'] = Project.link_from_id(project)
if ids is not None:
filters['_id'] = {"$in": ids}
- items: List[SHACLTestSuite] = await list_shacl_test_suites(filters)
- return APIListSHACLTestSuitesPaginatedResponse(items=items, count=len(items))
+ if q is not None:
+ filters['q'] = q
+
+ items, total_count = await list_shacl_test_suites(filters, page, limit)
+ return APIListSHACLTestSuitesPaginatedResponse(
+ items=items,
+ count=total_count
+ )
@router.post(
@@ -115,10 +124,25 @@ async def route_delete_shacl_test_suite(shacl_test_suite: SHACLTestSuite = Depen
response_model=APIListSHACLTestFileResourcesPaginatedResponse
)
async def route_list_shacl_test_suite_file_resources(
- id: PydanticObjectId = None
+ shacl_test_suite: SHACLTestSuite = Depends(get_shacl_test_suite),
+ project: PydanticObjectId = None,
+ page: int = None,
+ limit: int = None,
+ q: str = None
):
- items: List[SHACLTestFileResource] = await list_shacl_test_suite_file_resources(id)
- return APIListSHACLTestFileResourcesPaginatedResponse(items=items, count=len(items))
+
+ filters: dict = {}
+ if project:
+ filters['project'] = Project.link_from_id(project)
+ if q is not None:
+ filters['q'] = q
+
+ items, total_count = \
+ await list_shacl_test_suite_file_resources(shacl_test_suite, filters, page, limit)
+ return APIListSHACLTestFileResourcesPaginatedResponse(
+ items=items,
+ count=total_count
+ )
@router.post(
diff --git a/mapping_workbench/backend/shacl_test_suite/services/api.py b/mapping_workbench/backend/shacl_test_suite/services/api.py
index 66dbbb30e..b237b91e9 100644
--- a/mapping_workbench/backend/shacl_test_suite/services/api.py
+++ b/mapping_workbench/backend/shacl_test_suite/services/api.py
@@ -5,15 +5,29 @@
from mapping_workbench.backend.core.models.base_entity import BaseEntityFiltersSchema
from mapping_workbench.backend.core.services.exceptions import ResourceNotFoundException
from mapping_workbench.backend.core.services.request import request_update_data, api_entity_is_found, \
- request_create_data
-from mapping_workbench.backend.shacl_test_suite.models.entity import SHACLTestSuite, SHACLTestFileResource, \
- SHACLTestFileResourceCreateIn, SHACLTestFileResourceUpdateIn
+ request_create_data, prepare_search_param, pagination_params
+from mapping_workbench.backend.shacl_test_suite.models.entity import SHACLTestSuite, SHACLTestFileResource
+from mapping_workbench.backend.shacl_test_suite.models.entity_api_response import SHACLTestFileResourceCreateIn, \
+ SHACLTestFileResourceUpdateIn
from mapping_workbench.backend.user.models.user import User
-async def list_shacl_test_suites(filters=None) -> List[SHACLTestSuite]:
+async def list_shacl_test_suites(filters: dict = None, page: int = None, limit: int = None) -> \
+ (List[SHACLTestSuite], int):
query_filters: dict = dict(filters or {}) | dict(BaseEntityFiltersSchema())
- return await SHACLTestSuite.find(query_filters, projection_model=SHACLTestSuite, fetch_links=False).to_list()
+
+ prepare_search_param(query_filters)
+ skip, limit = pagination_params(page, limit)
+
+ items: List[SHACLTestSuite] = await SHACLTestSuite.find(
+ query_filters,
+ projection_model=SHACLTestSuite,
+ fetch_links=False,
+ skip=skip,
+ limit=limit
+ ).to_list()
+ total_count: int = await SHACLTestSuite.find(query_filters).count()
+ return items, total_count
async def create_shacl_test_suite(shacl_test_suite: SHACLTestSuite, user: User) -> SHACLTestSuite:
@@ -43,15 +57,23 @@ async def delete_shacl_test_suite(shacl_test_suite: SHACLTestSuite):
async def list_shacl_test_suite_file_resources(
- id: PydanticObjectId = None,
- filters = None
-) -> List[SHACLTestFileResource]:
+ shacl_test_suite: SHACLTestSuite,
+ filters=None, page: int = None, limit: int = None
+):
query_filters: dict = dict(filters or {}) | dict(BaseEntityFiltersSchema())
- return await SHACLTestFileResource.find(
- SHACLTestFileResource.shacl_test_suite == SHACLTestSuite.link_from_id(id),
+ query_filters['shacl_test_suite'] = SHACLTestSuite.link_from_id(shacl_test_suite.id)
+
+ prepare_search_param(query_filters)
+ skip, limit = pagination_params(page, limit)
+
+ items: List[SHACLTestFileResource] = await SHACLTestFileResource.find(
query_filters,
- fetch_links=False
+ fetch_links=False,
+ skip=skip,
+ limit=limit
).to_list()
+ total_count: int = await SHACLTestFileResource.find(query_filters).count()
+ return items, total_count
async def create_shacl_test_suite_file_resource(
diff --git a/mapping_workbench/backend/sparql_test_suite/entrypoints/api/routes.py b/mapping_workbench/backend/sparql_test_suite/entrypoints/api/routes.py
index c5adc228d..b60be636f 100644
--- a/mapping_workbench/backend/sparql_test_suite/entrypoints/api/routes.py
+++ b/mapping_workbench/backend/sparql_test_suite/entrypoints/api/routes.py
@@ -48,15 +48,24 @@
)
async def route_list_sparql_test_suites(
project: PydanticObjectId = None,
- ids: Annotated[List[PydanticObjectId | str] | None, Query()] = None
+ ids: Annotated[List[PydanticObjectId | str] | None, Query()] = None,
+ page: int = None,
+ limit: int = None,
+ q: str = None
):
filters: dict = {}
if project:
filters['project'] = Project.link_from_id(project)
if ids is not None:
filters['_id'] = {"$in": ids}
- items: List[SPARQLTestSuite] = await list_sparql_test_suites(filters)
- return APIListSPARQLTestSuitesPaginatedResponse(items=items, count=len(items))
+ if q is not None:
+ filters['q'] = q
+
+ items, total_count = await list_sparql_test_suites(filters, page, limit)
+ return APIListSPARQLTestSuitesPaginatedResponse(
+ items=items,
+ count=total_count
+ )
@router.post(
@@ -131,10 +140,25 @@ async def route_list_sparql_test_file_resources(
response_model=APIListSPARQLTestFileResourcesPaginatedResponse
)
async def route_list_sparql_test_suite_file_resources(
- id: PydanticObjectId = None
+ sparql_test_suite: SPARQLTestSuite = Depends(get_sparql_test_suite),
+ project: PydanticObjectId = None,
+ page: int = None,
+ limit: int = None,
+ q: str = None
):
- items: List[SPARQLTestFileResource] = await list_sparql_test_suite_file_resources(id)
- return APIListSPARQLTestFileResourcesPaginatedResponse(items=items, count=len(items))
+
+ filters: dict = {}
+ if project:
+ filters['project'] = Project.link_from_id(project)
+ if q is not None:
+ filters['q'] = q
+
+ items, total_count = \
+ await list_sparql_test_suite_file_resources(sparql_test_suite, filters, page, limit)
+ return APIListSPARQLTestFileResourcesPaginatedResponse(
+ items=items,
+ count=total_count
+ )
@router.post(
diff --git a/mapping_workbench/backend/sparql_test_suite/services/api.py b/mapping_workbench/backend/sparql_test_suite/services/api.py
index ac50890d8..c3fc6d3de 100644
--- a/mapping_workbench/backend/sparql_test_suite/services/api.py
+++ b/mapping_workbench/backend/sparql_test_suite/services/api.py
@@ -5,16 +5,29 @@
from mapping_workbench.backend.core.models.base_entity import BaseEntityFiltersSchema
from mapping_workbench.backend.core.services.exceptions import ResourceNotFoundException
from mapping_workbench.backend.core.services.request import request_update_data, api_entity_is_found, \
- request_create_data
+ request_create_data, prepare_search_param, pagination_params
from mapping_workbench.backend.project.models.entity import Project
from mapping_workbench.backend.sparql_test_suite.models.entity import SPARQLTestSuite, SPARQLTestFileResource, \
SPARQLTestFileResourceUpdateIn, SPARQLTestFileResourceCreateIn
from mapping_workbench.backend.user.models.user import User
-async def list_sparql_test_suites(filters=None) -> List[SPARQLTestSuite]:
+async def list_sparql_test_suites(filters: dict = None, page: int = None, limit: int = None) -> \
+ (List[SPARQLTestSuite], int):
query_filters: dict = dict(filters or {}) | dict(BaseEntityFiltersSchema())
- return await SPARQLTestSuite.find(query_filters, projection_model=SPARQLTestSuite, fetch_links=False).to_list()
+
+ prepare_search_param(query_filters)
+ skip, limit = pagination_params(page, limit)
+
+ items: List[SPARQLTestSuite] = await SPARQLTestSuite.find(
+ query_filters,
+ projection_model=SPARQLTestSuite,
+ fetch_links=False,
+ skip=skip,
+ limit=limit
+ ).to_list()
+ total_count: int = await SPARQLTestSuite.find(query_filters).count()
+ return items, total_count
async def create_sparql_test_suite(sparql_test_suite: SPARQLTestSuite, user: User) -> SPARQLTestSuite:
@@ -54,15 +67,23 @@ async def list_sparql_test_file_resources(
async def list_sparql_test_suite_file_resources(
- id: PydanticObjectId = None,
- filters=None
-) -> List[SPARQLTestFileResource]:
+ sparql_test_suite: SPARQLTestSuite,
+ filters=None, page: int = None, limit: int = None
+) -> (List[SPARQLTestFileResource], int):
query_filters: dict = dict(filters or {}) | dict(BaseEntityFiltersSchema())
- return await SPARQLTestFileResource.find(
- SPARQLTestFileResource.sparql_test_suite == SPARQLTestSuite.link_from_id(id),
+ query_filters['sparql_test_suite'] = SPARQLTestSuite.link_from_id(sparql_test_suite.id)
+
+ prepare_search_param(query_filters)
+ skip, limit = pagination_params(page, limit)
+
+ items: List[SPARQLTestFileResource] = await SPARQLTestFileResource.find(
query_filters,
- fetch_links=False
+ fetch_links=False,
+ skip=skip,
+ limit=limit
).to_list()
+ total_count: int = await SPARQLTestFileResource.find(query_filters).count()
+ return items, total_count
async def create_sparql_test_suite_file_resource(
diff --git a/mapping_workbench/backend/sparql_test_suite/services/sparql_validator.py b/mapping_workbench/backend/sparql_test_suite/services/sparql_validator.py
index ca22db7cc..9ddbdb304 100644
--- a/mapping_workbench/backend/sparql_test_suite/services/sparql_validator.py
+++ b/mapping_workbench/backend/sparql_test_suite/services/sparql_validator.py
@@ -1,14 +1,30 @@
from typing import List
-from beanie import WriteRules
+from beanie import WriteRules, PydanticObjectId
from mapping_workbench.backend.sparql_test_suite.adapters.validator import SPARQLValidator
from mapping_workbench.backend.sparql_test_suite.models.entity import SPARQLTestSuite, SPARQLTestFileResource
from mapping_workbench.backend.test_data_suite.models.entity import TestDataFileResource, TestDataException
+from mapping_workbench.backend.user.models.user import User
-async def validate_test_data_with_sparql_test_suite(test_data: TestDataFileResource,
- sparql_test_suite: SPARQLTestSuite) -> TestDataFileResource:
+async def test_data_sparql_validation_for_project(
+ project_id: PydanticObjectId,
+ user: User = None
+):
+ """
+
+ :param test_data:
+ :param sparql_test_suite:
+ :return:
+ """
+ pass
+
+
+async def validate_test_data_with_sparql_test_suite(
+ test_data: TestDataFileResource,
+ sparql_test_suite: SPARQLTestSuite
+) -> TestDataFileResource:
"""
"""
@@ -24,8 +40,10 @@ async def validate_test_data_with_sparql_test_suite(test_data: TestDataFileResou
return test_data
-async def validate_tests_data_with_shacl_tests(tests_data: List[TestDataFileResource],
- sparql_tests: List[SPARQLTestFileResource]) -> List[TestDataFileResource]:
+async def validate_tests_data_with_shacl_tests(
+ tests_data: List[TestDataFileResource],
+ sparql_tests: List[SPARQLTestFileResource]
+) -> List[TestDataFileResource]:
"""
"""
@@ -36,4 +54,4 @@ async def validate_tests_data_with_shacl_tests(tests_data: List[TestDataFileReso
raise TestDataException("Test data must have a rdf manifestation")
await validate_test_data_with_sparql_test_suite(test_data=test_data, sparql_test_suite=sparql_test_suite)
- return tests_data
\ No newline at end of file
+ return tests_data
diff --git a/mapping_workbench/backend/test_data_suite/entrypoints/api/routes.py b/mapping_workbench/backend/test_data_suite/entrypoints/api/routes.py
index 465a1dc25..afac07488 100644
--- a/mapping_workbench/backend/test_data_suite/entrypoints/api/routes.py
+++ b/mapping_workbench/backend/test_data_suite/entrypoints/api/routes.py
@@ -10,6 +10,8 @@
file_resource_data_from_form_request
from mapping_workbench.backend.project.models.entity import Project
from mapping_workbench.backend.security.services.user_manager import current_active_user
+from mapping_workbench.backend.sparql_test_suite.services.sparql_validator import \
+ test_data_sparql_validation_for_project
from mapping_workbench.backend.test_data_suite.models.entity import TestDataSuite, TestDataFileResource, \
TestDataFileResourceUpdateIn, TestDataFileResourceCreateIn
from mapping_workbench.backend.test_data_suite.models.entity_api_response import \
@@ -25,8 +27,7 @@
get_test_data_file_resource,
delete_test_data_file_resource, update_test_data_file_resource
)
-from mapping_workbench.backend.test_data_suite.services.transform_test_data import transform_test_data_file_resource, \
- transform_test_data_for_project
+from mapping_workbench.backend.test_data_suite.services.transform_test_data import transform_test_data_for_project
from mapping_workbench.backend.user.models.user import User
ROUTE_PREFIX = "/test_data_suites"
@@ -50,15 +51,24 @@
)
async def route_list_test_data_suites(
project: PydanticObjectId = None,
- ids: Annotated[List[PydanticObjectId | str] | None, Query()] = None
+ ids: Annotated[List[PydanticObjectId | str] | None, Query()] = None,
+ page: int = None,
+ limit: int = None,
+ q: str = None
):
filters: dict = {}
if project:
filters['project'] = Project.link_from_id(project)
if ids is not None:
filters['_id'] = {"$in": ids}
- items: List[TestDataSuite] = await list_test_data_suites(filters)
- return APIListTestDataSuitesPaginatedResponse(items=items, count=len(items))
+ if q is not None:
+ filters['q'] = q
+
+ items, total_count = await list_test_data_suites(filters, page, limit)
+ return APIListTestDataSuitesPaginatedResponse(
+ items=items,
+ count=total_count
+ )
@router.post(
@@ -117,10 +127,24 @@ async def route_delete_test_data_suite(test_data_suite: TestDataSuite = Depends(
response_model=APIListTestDataFileResourcesPaginatedResponse
)
async def route_list_test_data_suite_file_resources(
- id: PydanticObjectId = None
+ test_data_suite: TestDataSuite = Depends(get_test_data_suite),
+ project: PydanticObjectId = None,
+ page: int = None,
+ limit: int = None,
+ q: str = None
):
- items: List[TestDataFileResource] = await list_test_data_suite_file_resources(id)
- return APIListTestDataFileResourcesPaginatedResponse(items=items, count=len(items))
+ filters: dict = {}
+ if project:
+ filters['project'] = Project.link_from_id(project)
+ if q is not None:
+ filters['q'] = q
+
+ items, total_count = \
+ await list_test_data_suite_file_resources(test_data_suite, filters, page, limit)
+ return APIListTestDataFileResourcesPaginatedResponse(
+ items=items,
+ count=total_count
+ )
@router.post(
@@ -201,3 +225,15 @@ async def route_transform_test_data(
user: User = Depends(current_active_user)
):
return await transform_test_data_for_project(project_id=filters.project, user=user)
+
+
+@router.post(
+ "/tasks/sparql_validation",
+ description=f"Test Data SPARQL Validation",
+ name=f"transform_test_data"
+)
+async def route_test_data_sparql_validation(
+ filters: APIRequestWithProject,
+ user: User = Depends(current_active_user)
+):
+ return await test_data_sparql_validation_for_project(project_id=filters.project, user=user)
diff --git a/mapping_workbench/backend/test_data_suite/models/entity.py b/mapping_workbench/backend/test_data_suite/models/entity.py
index 4455d5599..29a61d304 100644
--- a/mapping_workbench/backend/test_data_suite/models/entity.py
+++ b/mapping_workbench/backend/test_data_suite/models/entity.py
@@ -2,12 +2,13 @@
from typing import Optional, List
import pymongo
-from beanie import Link
+from beanie import Link, PydanticObjectId
from pymongo import IndexModel
from mapping_workbench.backend.core.models.base_project_resource_entity import BaseProjectResourceEntity
from mapping_workbench.backend.file_resource.models.file_resource import FileResource, FileResourceCollection, \
FileResourceIn
+from mapping_workbench.backend.mapping_package.models.entity import MappingPackage
from mapping_workbench.backend.shacl_test_suite.models.validator import SHACLTestDataValidationResult
from mapping_workbench.backend.sparql_test_suite.models.validator import SPARQLTestDataValidationResult
from mapping_workbench.backend.state_manager.models.state_object import StatefulObjectABC, ObjectState
@@ -100,8 +101,12 @@ class TestDataSuiteState(ObjectState):
test_data_states: List[TestDataState]
-class TestDataSuite(FileResourceCollection, StatefulObjectABC):
+class TestDataSuite(
+ FileResourceCollection,
+ StatefulObjectABC
+):
file_resources: Optional[List[Link[TestDataFileResource]]] = []
+ mapping_package_id: Optional[PydanticObjectId] = None
async def get_state(self) -> TestDataSuiteState:
title = self.title
diff --git a/mapping_workbench/backend/test_data_suite/services/api.py b/mapping_workbench/backend/test_data_suite/services/api.py
index 534cdbe45..e73be4dee 100644
--- a/mapping_workbench/backend/test_data_suite/services/api.py
+++ b/mapping_workbench/backend/test_data_suite/services/api.py
@@ -5,16 +5,29 @@
from mapping_workbench.backend.core.models.base_entity import BaseEntityFiltersSchema
from mapping_workbench.backend.core.services.exceptions import ResourceNotFoundException
from mapping_workbench.backend.core.services.request import request_update_data, api_entity_is_found, \
- request_create_data
+ request_create_data, prepare_search_param, pagination_params
from mapping_workbench.backend.test_data_suite.models.entity import TestDataSuite, TestDataFileResource, \
TestDataFileResourceUpdateIn, TestDataFileResourceCreateIn
from mapping_workbench.backend.test_data_suite.services.transform_test_data import transform_test_data_file_resource
from mapping_workbench.backend.user.models.user import User
-async def list_test_data_suites(filters=None) -> List[TestDataSuite]:
+async def list_test_data_suites(filters: dict = None, page: int = None, limit: int = None) -> \
+ (List[TestDataSuite], int):
query_filters: dict = dict(filters or {}) | dict(BaseEntityFiltersSchema())
- return await TestDataSuite.find(query_filters, projection_model=TestDataSuite, fetch_links=False).to_list()
+
+ prepare_search_param(query_filters)
+ skip, limit = pagination_params(page, limit)
+
+ items: List[TestDataSuite] = await TestDataSuite.find(
+ query_filters,
+ projection_model=TestDataSuite,
+ fetch_links=False,
+ skip=skip,
+ limit=limit
+ ).to_list()
+ total_count: int = await TestDataSuite.find(query_filters).count()
+ return items, total_count
async def create_test_data_suite(test_data_suite: TestDataSuite, user: User) -> TestDataSuite:
@@ -44,15 +57,24 @@ async def delete_test_data_suite(test_data_suite: TestDataSuite):
async def list_test_data_suite_file_resources(
- id: PydanticObjectId = None,
- filters=None
-) -> List[TestDataFileResource]:
+ test_data_suite: TestDataSuite,
+ filters=None, page: int = None, limit: int = None
+) -> (List[TestDataFileResource], int):
query_filters: dict = dict(filters or {}) | dict(BaseEntityFiltersSchema())
- return await TestDataFileResource.find(
- TestDataFileResource.test_data_suite == TestDataSuite.link_from_id(id),
+ query_filters['test_data_suite'] = TestDataSuite.link_from_id(test_data_suite.id)
+
+ prepare_search_param(query_filters)
+ skip, limit = pagination_params(page, limit)
+ print("K :: ", test_data_suite.id, query_filters)
+
+ items: List[TestDataFileResource] = await TestDataFileResource.find(
query_filters,
- fetch_links=False
+ fetch_links=False,
+ skip=skip,
+ limit=limit
).to_list()
+ total_count: int = await TestDataFileResource.find(query_filters).count()
+ return items, total_count
async def create_test_data_suite_file_resource(
diff --git a/mapping_workbench/frontend/Makefile b/mapping_workbench/frontend/Makefile
index 326bbd9c3..ebaed6f41 100644
--- a/mapping_workbench/frontend/Makefile
+++ b/mapping_workbench/frontend/Makefile
@@ -9,7 +9,8 @@ start-staging-frontend:
start-prod-frontend:
@ echo "Starting PROD FRONTEND"
- @ serve -s build
+ @ npm run dev
+# @ serve -s build
install-dev-frontend:
@ echo "Installing DEV FRONTEND"
@@ -22,4 +23,5 @@ install-staging-frontend:
install-prod-frontend:
@ echo "Installing PROD FRONTEND"
- @ npm install && npm install -g serve && npm run build && rm -fr node_modules
+ @ npm install
+# @ npm install && npm install -g serve && npm run build && rm -fr node_modules
diff --git a/mapping_workbench/frontend/package.json b/mapping_workbench/frontend/package.json
index bcd893a9f..33a658aaf 100644
--- a/mapping_workbench/frontend/package.json
+++ b/mapping_workbench/frontend/package.json
@@ -44,6 +44,7 @@
"aws-amplify": "5.2.1",
"axios": "^1.4.0",
"date-fns": "2.30.0",
+ "dotenv": "^16.3.1",
"draft-js": "0.11.7",
"firebase": "9.22.0",
"formik": "2.2.9",
diff --git a/mapping_workbench/frontend/src/api/app/index.js b/mapping_workbench/frontend/src/api/app/index.js
index 798fc1ef2..4aaec873b 100644
--- a/mapping_workbench/frontend/src/api/app/index.js
+++ b/mapping_workbench/frontend/src/api/app/index.js
@@ -20,7 +20,6 @@ const METHOD = {
};
class AppApi {
-
constructor() {
this.config = apiConfig;
this.apiClient = this.getApiClient(this.config);
diff --git a/mapping_workbench/frontend/src/api/fields-registry/index.js b/mapping_workbench/frontend/src/api/fields-registry/index.js
new file mode 100644
index 000000000..3d57afc9a
--- /dev/null
+++ b/mapping_workbench/frontend/src/api/fields-registry/index.js
@@ -0,0 +1,17 @@
+import {SectionApi} from "../section";
+
+class FieldsRegistryApi extends SectionApi {
+ get SECTION_TITLE() {
+ return "Fields Registry";
+ }
+
+ get SECTION_ITEM_TITLE() {
+ return "Fields Registry";
+ }
+
+ constructor() {
+ super("fields_registry");
+ }
+}
+
+export const fieldsRegistryApi = new FieldsRegistryApi();
diff --git a/mapping_workbench/frontend/src/api/test-data-suites/index.js b/mapping_workbench/frontend/src/api/test-data-suites/index.js
index 91b8d0d2f..d47aa9998 100644
--- a/mapping_workbench/frontend/src/api/test-data-suites/index.js
+++ b/mapping_workbench/frontend/src/api/test-data-suites/index.js
@@ -14,6 +14,7 @@ class TestDataSuitesApi extends FileCollectionsApi {
constructor() {
super("test_data_suites");
this.isProjectResource = true;
+ this.hasMappingPackage = true;
}
async getValuesForSelector(request = {}) {
diff --git a/mapping_workbench/frontend/src/components/app/list/list-file-collection-actions.js b/mapping_workbench/frontend/src/components/app/list/list-file-collection-actions.js
index 1f49f11b7..27bd5b392 100644
--- a/mapping_workbench/frontend/src/components/app/list/list-file-collection-actions.js
+++ b/mapping_workbench/frontend/src/components/app/list/list-file-collection-actions.js
@@ -48,7 +48,10 @@ export const ListFileCollectionActions = (props) => {
return (
<>
-
+
{/*
{
path: paths.app.specific_triple_map_fragments.index
}
]
+ },
+ {
+ title: t(tokens.nav.fields_registry),
+ path: paths.app.fields_registry.index,
+ icon: (
+
+
+
+ ),
+ items: [
+ {
+ title: t(tokens.nav.list),
+ path: paths.app.fields_registry.index
+ },
+ {
+ title: t(tokens.nav.create),
+ path: paths.app.fields_registry.create
+ }
+ ]
});
}
items.resources.push(sections);
diff --git a/mapping_workbench/frontend/src/locales/tokens.js b/mapping_workbench/frontend/src/locales/tokens.js
index a90814c30..24a51d997 100644
--- a/mapping_workbench/frontend/src/locales/tokens.js
+++ b/mapping_workbench/frontend/src/locales/tokens.js
@@ -69,6 +69,7 @@ export const tokens = {
triple_map_fragments: 'nav.triple_map_fragments',
generic_triple_map_fragments: 'nav.generic_triple_map_fragments',
specific_triple_map_fragments: 'nav.specific_triple_map_fragments',
+ fields_registry: 'nav.fields_registry',
admin: 'nav.admin',
users: 'nav.users',
diff --git a/mapping_workbench/frontend/src/locales/translations/en.js b/mapping_workbench/frontend/src/locales/translations/en.js
index 32996a2a5..b5ff7cdee 100644
--- a/mapping_workbench/frontend/src/locales/translations/en.js
+++ b/mapping_workbench/frontend/src/locales/translations/en.js
@@ -69,6 +69,7 @@ export const en = {
[tokens.nav.triple_map_fragments]: 'Triple Maps',
[tokens.nav.specific_triple_map_fragments]: 'Specific Triple Maps',
[tokens.nav.generic_triple_map_fragments]: 'Generic Triple Maps',
+ [tokens.nav.fields_registry]: 'Fields Registry',
[tokens.nav.terms_validator]: 'Terms Validator',
[tokens.nav.tasks]: 'Tasks',
[tokens.nav.generate_cm_assertions_queries]: 'Generate CM Assertions Queries',
diff --git a/mapping_workbench/frontend/src/pages/app/fields-registry/[id]/edit.js b/mapping_workbench/frontend/src/pages/app/fields-registry/[id]/edit.js
new file mode 100644
index 000000000..daa2e1f0b
--- /dev/null
+++ b/mapping_workbench/frontend/src/pages/app/fields-registry/[id]/edit.js
@@ -0,0 +1,107 @@
+import ArrowLeftIcon from '@untitled-ui/icons-react/build/esm/ArrowLeft';
+import Chip from '@mui/material/Chip';
+import Link from '@mui/material/Link';
+import Stack from '@mui/material/Stack';
+import SvgIcon from '@mui/material/SvgIcon';
+import Typography from '@mui/material/Typography';
+
+import {fieldsRegistryApi as sectionApi} from 'src/api/fields-registry';
+import {RouterLink} from 'src/components/router-link';
+import {Seo} from 'src/components/seo';
+import {usePageView} from 'src/hooks/use-page-view';
+import {Layout as AppLayout} from 'src/layouts/app';
+import {paths} from 'src/paths';
+import {EditForm} from 'src/sections/app/fields-registry/edit-form';
+import {ForItemEditForm} from "src/contexts/app/section/for-item-form";
+import {useItem} from "src/contexts/app/section/for-item-data-state";
+import {useRouter} from "src/hooks/use-router";
+
+
+const Page = () => {
+ const router = useRouter();
+ if (!router.isReady) return;
+
+ const {id} = router.query;
+
+ if (!id) {
+ return;
+ }
+
+ const formState = useItem(sectionApi, id);
+ const item = formState.item;
+
+ usePageView();
+
+ if (!item) {
+ return;
+ }
+
+ return (
+ <>
+
+
+
+
+
+
+
+
+
+ {sectionApi.SECTION_TITLE}
+
+
+
+
+
+
+
+ {item.prefix}
+
+
+
+
+
+
+
+
+
+
+ >
+ );
+};
+
+Page.getLayout = (page) => (
+
+ {page}
+
+);
+
+export default Page;
diff --git a/mapping_workbench/frontend/src/pages/app/fields-registry/[id]/view.js b/mapping_workbench/frontend/src/pages/app/fields-registry/[id]/view.js
new file mode 100644
index 000000000..e4586f6ba
--- /dev/null
+++ b/mapping_workbench/frontend/src/pages/app/fields-registry/[id]/view.js
@@ -0,0 +1,160 @@
+import {useCallback, useState} from 'react';
+import ArrowLeftIcon from '@untitled-ui/icons-react/build/esm/ArrowLeft';
+import Box from '@mui/material/Box';
+import Chip from '@mui/material/Chip';
+import Container from '@mui/material/Container';
+import Divider from '@mui/material/Divider';
+import Grid from '@mui/material/Unstable_Grid2';
+import Link from '@mui/material/Link';
+import Stack from '@mui/material/Stack';
+import SvgIcon from '@mui/material/SvgIcon';
+import Tab from '@mui/material/Tab';
+import Tabs from '@mui/material/Tabs';
+import Typography from '@mui/material/Typography';
+
+import {fieldsRegistryApi as sectionApi} from 'src/api/fields-registry';
+import {RouterLink} from 'src/components/router-link';
+import {Seo} from 'src/components/seo';
+import {usePageView} from 'src/hooks/use-page-view';
+import {Layout as AppLayout} from 'src/layouts/app';
+import {paths} from 'src/paths';
+import {BasicDetails} from 'src/sections/app/fields-registry/basic-details';
+import {useRouter} from "src/hooks/use-router";
+import {useItem} from "src/contexts/app/section/for-item-data-state";
+
+const tabs = [
+ {label: 'Details', value: 'details'}
+];
+
+const Page = () => {
+ const router = useRouter();
+ if (!router.isReady) return;
+
+ const {id} = router.query;
+
+ if (!id) {
+ return;
+ }
+
+ const formState = useItem(sectionApi, id);
+ const item = formState.item;
+
+ usePageView();
+ const [currentTab, setCurrentTab] = useState('details');
+
+ const handleTabsChange = useCallback((event, value) => {
+ setCurrentTab(value);
+ }, []);
+
+ if (!item) {
+ return;
+ }
+
+ return (
+ <>
+
+
+
+
+
+
+
+
+
+ {sectionApi.SECTION_TITLE}
+
+
+
+
+
+
+
+ {item.prefix}
+
+
+
+
+
+
+
+
+
+ {tabs.map((tab) => (
+
+ ))}
+
+
+
+
+ {currentTab === 'details' && (
+
+
+
+
+
+
+
+ )}
+
+ >
+ )
+};
+
+Page.getLayout = (page) => (
+
+ {page}
+
+);
+
+export default Page;
diff --git a/mapping_workbench/frontend/src/pages/app/fields-registry/create.js b/mapping_workbench/frontend/src/pages/app/fields-registry/create.js
new file mode 100644
index 000000000..4612e6aa3
--- /dev/null
+++ b/mapping_workbench/frontend/src/pages/app/fields-registry/create.js
@@ -0,0 +1,61 @@
+import ArrowLeftIcon from '@untitled-ui/icons-react/build/esm/ArrowLeft';
+import Box from '@mui/material/Box';
+import Container from '@mui/material/Container';
+import Link from '@mui/material/Link';
+import Stack from '@mui/material/Stack';
+import SvgIcon from '@mui/material/SvgIcon';
+import Typography from '@mui/material/Typography';
+
+import {fieldsRegistryApi as sectionApi} from 'src/api/fields-registry';
+import {RouterLink} from 'src/components/router-link';
+import {Seo} from 'src/components/seo';
+import {usePageView} from 'src/hooks/use-page-view';
+import {Layout as AppLayout} from 'src/layouts/app';
+import {paths} from 'src/paths';
+import {EditForm} from 'src/sections/app/fields-registry/edit-form';
+import {ForItemCreateForm} from "src/contexts/app/section/for-item-form";
+
+
+const Page = () => {
+ let item = {};
+
+ usePageView();
+
+ return (
+ <>
+
+
+
+
+
+
+
+
+
+ {sectionApi.SECTION_TITLE}
+
+
+
+
+
+
+ >
+ );
+};
+
+Page.getLayout = (page) => (
+
+ {page}
+
+);
+
+export default Page;
diff --git a/mapping_workbench/frontend/src/pages/app/fields-registry/index.js b/mapping_workbench/frontend/src/pages/app/fields-registry/index.js
new file mode 100644
index 000000000..122d7a45a
--- /dev/null
+++ b/mapping_workbench/frontend/src/pages/app/fields-registry/index.js
@@ -0,0 +1,182 @@
+import {useCallback, useEffect, useState} from 'react';
+import PlusIcon from '@untitled-ui/icons-react/build/esm/Plus';
+import Breadcrumbs from '@mui/material/Breadcrumbs';
+import Button from '@mui/material/Button';
+import Card from '@mui/material/Card';
+import Link from '@mui/material/Link';
+import Stack from '@mui/material/Stack';
+import SvgIcon from '@mui/material/SvgIcon';
+import Typography from '@mui/material/Typography';
+
+import {fieldsRegistryApi as sectionApi} from 'src/api/fields-registry';
+import {BreadcrumbsSeparator} from 'src/components/breadcrumbs-separator';
+import {RouterLink} from 'src/components/router-link';
+import {Seo} from 'src/components/seo';
+import {useMounted} from 'src/hooks/use-mounted';
+import {usePageView} from 'src/hooks/use-page-view';
+import {Layout as AppLayout} from 'src/layouts/app';
+import {paths} from 'src/paths';
+import {ListSearch} from "../../../sections/app/fields-registry/list-search";
+import {ListTable} from "../../../sections/app/fields-registry/list-table";
+
+const useItemsSearch = () => {
+ const [state, setState] = useState({
+ filters: {
+ name: undefined,
+ category: [],
+ status: [],
+ inStock: undefined
+ },
+ page: sectionApi.DEFAULT_PAGE,
+ rowsPerPage: sectionApi.DEFAULT_ROWS_PER_PAGE
+ });
+
+ const handleFiltersChange = useCallback((filters) => {
+ setState((prevState) => ({
+ ...prevState,
+ filters,
+ page: 0
+ }));
+ }, []);
+
+ const handlePageChange = useCallback((event, page) => {
+ setState((prevState) => ({
+ ...prevState,
+ page
+ }));
+ }, []);
+
+ const handleRowsPerPageChange = useCallback((event) => {
+ setState((prevState) => ({
+ ...prevState,
+ rowsPerPage: parseInt(event.target.value, 10)
+ }));
+ }, []);
+
+ return {
+ handleFiltersChange,
+ handlePageChange,
+ handleRowsPerPageChange,
+ state
+ };
+};
+
+const useItemsStore = (searchState) => {
+ const isMounted = useMounted();
+ const [state, setState] = useState({
+ items: [],
+ itemsCount: 0
+ });
+
+ const handleItemsGet = useCallback(async () => {
+ try {
+ const response = await sectionApi.getItems(searchState);
+ if (isMounted()) {
+ setState({
+ items: response.items,
+ itemsCount: response.count
+ });
+ }
+ } catch (err) {
+ console.error(err);
+ }
+ }, [searchState, isMounted]);
+
+ useEffect(() => {
+ handleItemsGet();
+ },
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ [searchState]);
+
+ return {
+ ...state
+ };
+};
+
+const Page = () => {
+ const itemsSearch = useItemsSearch();
+ const itemsStore = useItemsStore(itemsSearch.state);
+
+ usePageView();
+
+ return (
+ <>
+
+
+
+
+
+ {sectionApi.SECTION_TITLE}
+
+ }>
+
+ App
+
+
+ {sectionApi.SECTION_TITLE}
+
+
+ List
+
+
+
+
+
+
+
+
+
+
+
+
+ >
+ )
+};
+
+Page.getLayout = (page) => (
+
+ {page}
+
+);
+
+export default Page;
diff --git a/mapping_workbench/frontend/src/pages/app/ontology-file-collections/index.js b/mapping_workbench/frontend/src/pages/app/ontology-file-collections/index.js
index ce2e0f6d3..23819c112 100644
--- a/mapping_workbench/frontend/src/pages/app/ontology-file-collections/index.js
+++ b/mapping_workbench/frontend/src/pages/app/ontology-file-collections/index.js
@@ -27,14 +27,15 @@ const useItemsSearch = () => {
status: [],
inStock: undefined
},
- page: 0,
- rowsPerPage: 5
+ page: sectionApi.DEFAULT_PAGE,
+ rowsPerPage: sectionApi.DEFAULT_ROWS_PER_PAGE
});
const handleFiltersChange = useCallback((filters) => {
setState((prevState) => ({
...prevState,
- filters
+ filters,
+ page: 0
}));
}, []);
diff --git a/mapping_workbench/frontend/src/pages/app/resource-collections/index.js b/mapping_workbench/frontend/src/pages/app/resource-collections/index.js
index 1b8eeb8f9..bbb06f0aa 100644
--- a/mapping_workbench/frontend/src/pages/app/resource-collections/index.js
+++ b/mapping_workbench/frontend/src/pages/app/resource-collections/index.js
@@ -1,10 +1,8 @@
import {useCallback, useEffect, useState} from 'react';
import PlusIcon from '@untitled-ui/icons-react/build/esm/Plus';
-import Box from '@mui/material/Box';
import Breadcrumbs from '@mui/material/Breadcrumbs';
import Button from '@mui/material/Button';
import Card from '@mui/material/Card';
-import Container from '@mui/material/Container';
import Link from '@mui/material/Link';
import Stack from '@mui/material/Stack';
import SvgIcon from '@mui/material/SvgIcon';
@@ -21,18 +19,6 @@ import {FileCollectionListSearch} from 'src/sections/app/file-manager/file-colle
import {FileCollectionListTable} from 'src/sections/app/file-manager/file-collection-list-table';
-const mockDataPackages = {
- title: "F03",
- description: "Des03",
- formType: "35",
- minDate: "01/06/2023",
- maxDate: "23/06/2023",
- minVersion: "R2.08.55",
- maxVersion: "R2.09.66",
-};
-
-const collectionsID = [];
-
const useItemsSearch = () => {
const [state, setState] = useState({
filters: {
@@ -41,14 +27,15 @@ const useItemsSearch = () => {
status: [],
inStock: undefined
},
- page: 0,
- rowsPerPage: 5
+ page: sectionApi.DEFAULT_PAGE,
+ rowsPerPage: sectionApi.DEFAULT_ROWS_PER_PAGE
});
const handleFiltersChange = useCallback((filters) => {
setState((prevState) => ({
...prevState,
- filters
+ filters,
+ page: 0
}));
}, []);
@@ -80,10 +67,6 @@ const useItemsStore = (searchState) => {
items: [],
itemsCount: 0
});
- const [stateFile, setStateFile] = useState({
- items: [],
- itemsCount: 0
- });
const handleItemsGet = useCallback(async () => {
try {
@@ -100,26 +83,6 @@ const useItemsStore = (searchState) => {
}
}, [searchState, isMounted]);
- const handleItemsGetFiles = useCallback(async () => {
- try {
- const response2 = await sectionApi.getFileResources(id);
- //const collection = await sectionApi.getItem(id);
-
-
- //console.log("response2: ", response);
- //console.log("collection: ", collection);
-
-
- setStateFile({
- //collection: collection,
- itemsF: response2.items,
- itemsFCount: response2.count
- });
-
- } catch (err) {
- console.error(err);
- }
- }, []);
useEffect(() => {
handleItemsGet().then(response => {
diff --git a/mapping_workbench/frontend/src/pages/app/shacl-test-suites/index.js b/mapping_workbench/frontend/src/pages/app/shacl-test-suites/index.js
index 3720edc38..f538bf18b 100644
--- a/mapping_workbench/frontend/src/pages/app/shacl-test-suites/index.js
+++ b/mapping_workbench/frontend/src/pages/app/shacl-test-suites/index.js
@@ -1,10 +1,8 @@
import {useCallback, useEffect, useState} from 'react';
import PlusIcon from '@untitled-ui/icons-react/build/esm/Plus';
-import Box from '@mui/material/Box';
import Breadcrumbs from '@mui/material/Breadcrumbs';
import Button from '@mui/material/Button';
import Card from '@mui/material/Card';
-import Container from '@mui/material/Container';
import Link from '@mui/material/Link';
import Stack from '@mui/material/Stack';
import SvgIcon from '@mui/material/SvgIcon';
@@ -29,14 +27,15 @@ const useItemsSearch = () => {
status: [],
inStock: undefined
},
- page: 0,
- rowsPerPage: 5
+ page: sectionApi.DEFAULT_PAGE,
+ rowsPerPage: sectionApi.DEFAULT_ROWS_PER_PAGE
});
const handleFiltersChange = useCallback((filters) => {
setState((prevState) => ({
...prevState,
- filters
+ filters,
+ page: 0
}));
}, []);
diff --git a/mapping_workbench/frontend/src/pages/app/sparql-test-suites/index.js b/mapping_workbench/frontend/src/pages/app/sparql-test-suites/index.js
index 69b44eab0..649a11bde 100644
--- a/mapping_workbench/frontend/src/pages/app/sparql-test-suites/index.js
+++ b/mapping_workbench/frontend/src/pages/app/sparql-test-suites/index.js
@@ -1,10 +1,8 @@
import {useCallback, useEffect, useState} from 'react';
import PlusIcon from '@untitled-ui/icons-react/build/esm/Plus';
-import Box from '@mui/material/Box';
import Breadcrumbs from '@mui/material/Breadcrumbs';
import Button from '@mui/material/Button';
import Card from '@mui/material/Card';
-import Container from '@mui/material/Container';
import Link from '@mui/material/Link';
import Stack from '@mui/material/Stack';
import SvgIcon from '@mui/material/SvgIcon';
@@ -29,14 +27,15 @@ const useItemsSearch = () => {
status: [],
inStock: undefined
},
- page: 0,
- rowsPerPage: 5
+ page: sectionApi.DEFAULT_PAGE,
+ rowsPerPage: sectionApi.DEFAULT_ROWS_PER_PAGE
});
const handleFiltersChange = useCallback((filters) => {
setState((prevState) => ({
...prevState,
- filters
+ filters,
+ page: 0
}));
}, []);
diff --git a/mapping_workbench/frontend/src/pages/app/specific-triple-map-fragments/[id]/edit.js b/mapping_workbench/frontend/src/pages/app/specific-triple-map-fragments/[id]/edit.js
index f42ca2bc2..7c4538eff 100644
--- a/mapping_workbench/frontend/src/pages/app/specific-triple-map-fragments/[id]/edit.js
+++ b/mapping_workbench/frontend/src/pages/app/specific-triple-map-fragments/[id]/edit.js
@@ -1,7 +1,5 @@
import ArrowLeftIcon from '@untitled-ui/icons-react/build/esm/ArrowLeft';
-import Box from '@mui/material/Box';
import Chip from '@mui/material/Chip';
-import Container from '@mui/material/Container';
import Link from '@mui/material/Link';
import Stack from '@mui/material/Stack';
import SvgIcon from '@mui/material/SvgIcon';
diff --git a/mapping_workbench/frontend/src/pages/app/test-data-suites/create.js b/mapping_workbench/frontend/src/pages/app/test-data-suites/create.js
index b7084d58a..9ee39ad53 100644
--- a/mapping_workbench/frontend/src/pages/app/test-data-suites/create.js
+++ b/mapping_workbench/frontend/src/pages/app/test-data-suites/create.js
@@ -1,6 +1,4 @@
import ArrowLeftIcon from '@untitled-ui/icons-react/build/esm/ArrowLeft';
-import Box from '@mui/material/Box';
-import Container from '@mui/material/Container';
import Link from '@mui/material/Link';
import Stack from '@mui/material/Stack';
import SvgIcon from '@mui/material/SvgIcon';
diff --git a/mapping_workbench/frontend/src/pages/app/test-data-suites/index.js b/mapping_workbench/frontend/src/pages/app/test-data-suites/index.js
index 8c85b9854..58ea4e56f 100644
--- a/mapping_workbench/frontend/src/pages/app/test-data-suites/index.js
+++ b/mapping_workbench/frontend/src/pages/app/test-data-suites/index.js
@@ -1,10 +1,8 @@
import {useCallback, useEffect, useState} from 'react';
import PlusIcon from '@untitled-ui/icons-react/build/esm/Plus';
-import Box from '@mui/material/Box';
import Breadcrumbs from '@mui/material/Breadcrumbs';
import Button from '@mui/material/Button';
import Card from '@mui/material/Card';
-import Container from '@mui/material/Container';
import Link from '@mui/material/Link';
import Stack from '@mui/material/Stack';
import SvgIcon from '@mui/material/SvgIcon';
@@ -33,14 +31,15 @@ const useItemsSearch = () => {
status: [],
inStock: undefined
},
- page: 0,
- rowsPerPage: 5
+ page: sectionApi.DEFAULT_PAGE,
+ rowsPerPage: sectionApi.DEFAULT_ROWS_PER_PAGE
});
const handleFiltersChange = useCallback((filters) => {
setState((prevState) => ({
...prevState,
- filters
+ filters,
+ page: 0
}));
}, []);
diff --git a/mapping_workbench/frontend/src/paths.js b/mapping_workbench/frontend/src/paths.js
index 218cd631a..ecd49acf4 100644
--- a/mapping_workbench/frontend/src/paths.js
+++ b/mapping_workbench/frontend/src/paths.js
@@ -139,6 +139,12 @@ export const paths = {
edit: '/app/ontology-terms/[id]/edit',
view: '/app/ontology-terms/[id]/view'
},
+ fields_registry: {
+ index: '/app/fields-registry',
+ create: '/app/fields-registry/create',
+ edit: '/app/fields-registry/[id]/edit',
+ view: '/app/fields-registry/[id]/view'
+ },
tasks: {
index: '/app/tasks',
terms_validator: '/app/tasks/terms_validator',
@@ -244,6 +250,11 @@ export const apiPaths = {
me: '/users/me'
},
+ fields_registry: {
+ items: '/fields_registry',
+ item: '/fields_registry/:id'
+ },
+
tasks: {
terms_validator: '/tasks/terms_validator',
generate_cm_assertions_queries: '/tasks/generate_cm_assertions_queries',
diff --git a/mapping_workbench/frontend/src/sections/app/conceptual-mapping-rule/edit-form.js b/mapping_workbench/frontend/src/sections/app/conceptual-mapping-rule/edit-form.js
index 9d6bf57c9..4f8f6b91e 100644
--- a/mapping_workbench/frontend/src/sections/app/conceptual-mapping-rule/edit-form.js
+++ b/mapping_workbench/frontend/src/sections/app/conceptual-mapping-rule/edit-form.js
@@ -183,7 +183,7 @@ export const EditForm = (props) => {
source_xpath: prepareTextareaListValue(item.source_xpath),
target_class_path: item.target_class_path || '',
target_property_path: item.target_property_path || '',
- mapping_packages: (item.mapping_packages || []).map(x => x.id),
+ refers_to_mapping_package_ids: item.refers_to_mapping_package_ids || [],
sparql_assertions: (item.sparql_assertions || []).map(x => x.id),
triple_map_fragment: (item.triple_map_fragment && item.triple_map_fragment.id) || '',
notes: (item.notes || []),
@@ -477,7 +477,7 @@ export const EditForm = (props) => {
-
+
@@ -554,7 +554,7 @@ export const EditForm = (props) => {
)}
value={COMMENT_PRIORITY.HIGH}
- checked={formik.values.note.priority === COMMENT_PRIORITY.HIGH}
+ checked={formik.values.note && formik.values.note.priority === COMMENT_PRIORITY.HIGH}
/>
}
@@ -569,7 +569,7 @@ export const EditForm = (props) => {
)}
value={COMMENT_PRIORITY.NORMAL}
- checked={formik.values.note.priority === COMMENT_PRIORITY.NORMAL}
+ checked={formik.values.note && formik.values.note.priority === COMMENT_PRIORITY.NORMAL}
/>
}
@@ -584,7 +584,7 @@ export const EditForm = (props) => {
)}
value={COMMENT_PRIORITY.LOW}
- checked={formik.values.note.priority === COMMENT_PRIORITY.LOW}
+ checked={formik.values.note && formik.values.note.priority === COMMENT_PRIORITY.LOW}
/>
@@ -595,7 +595,7 @@ export const EditForm = (props) => {
fullWidth
label="Add new Note ..."
helperText="... for external viewers"
- value={formik.values.note.comment}
+ value={formik.values.note && formik.values.note.comment || ''}
onBlur={formik.handleBlur}
onChange={formik.handleChange}
/>
@@ -659,7 +659,7 @@ export const EditForm = (props) => {
)}
value={COMMENT_PRIORITY.HIGH}
- checked={formik.values.comment.priority === COMMENT_PRIORITY.HIGH}
+ checked={formik.values.comment && formik.values.comment.priority === COMMENT_PRIORITY.HIGH}
/>
}
@@ -674,7 +674,7 @@ export const EditForm = (props) => {
)}
value={COMMENT_PRIORITY.NORMAL}
- checked={formik.values.comment.priority === COMMENT_PRIORITY.NORMAL}
+ checked={formik.values.comment && formik.values.comment.priority === COMMENT_PRIORITY.NORMAL}
/>
}
@@ -689,7 +689,7 @@ export const EditForm = (props) => {
)}
value={COMMENT_PRIORITY.LOW}
- checked={formik.values.comment.priority === COMMENT_PRIORITY.LOW}
+ checked={formik.values.comment && formik.values.comment.priority === COMMENT_PRIORITY.LOW}
/>
@@ -700,7 +700,7 @@ export const EditForm = (props) => {
fullWidth
label="Add new Comment ..."
helperText="... for other editors"
- value={formik.values.comment.comment}
+ value={formik.values.comment && formik.values.comment.comment || ''}
onBlur={formik.handleBlur}
onChange={formik.handleChange}
/>
diff --git a/mapping_workbench/frontend/src/sections/app/conceptual-mapping-rule/list-table.js b/mapping_workbench/frontend/src/sections/app/conceptual-mapping-rule/list-table.js
index 510d71d61..226604bb3 100644
--- a/mapping_workbench/frontend/src/sections/app/conceptual-mapping-rule/list-table.js
+++ b/mapping_workbench/frontend/src/sections/app/conceptual-mapping-rule/list-table.js
@@ -301,7 +301,7 @@ export const ListTableMappingPackages = (props) => {
isHovered
} = props;
- let ruleFilteredMappingPackages = item.mapping_packages.map(x => x.id);
+ let ruleFilteredMappingPackages = (item.mapping_packages || []).map(x => x.id);
const [mappingPackages, setMappingPackages] = useState(ruleFilteredMappingPackages);
const [projectMappingPackages, setProjectMappingPackages] = useState(initProjectMappingPackages || []);
const [tempMappingPackages, setTempMappingPackages] =
@@ -665,7 +665,7 @@ export const ListTableRow = (props) => {
- {item.source_xpath.map(
+ {item.source_xpath && item.source_xpath.map(
x => (
{
+ const {id, prefix, uri, is_syncable, ...other} = props;
+
+ const router = useRouter();
+ const itemctx = new ForListItemAction(id, sectionApi);
+
+ const handleEditAction = useCallback(async () => {
+ router.push({
+ //pathname: paths.app[item.api.section].edit,
+ pathname: paths.app.ontology_namespaces.edit, query: {id: id}
+ });
+
+ }, [router]);
+
+ const handleDeleteAction = useCallback(async () => {
+ const response = await itemctx.api.deleteItem(id);
+
+ router.push({
+ pathname: paths.app.ontology_namespaces.index
+ });
+ //window.location.reload();
+ }, [router, itemctx]);
+
+ return (
+ <>
+
+
+
+
+
+ }
+ />
+
+
+
+
+
+
+
+
+
+ >
+
+ )
+ ;
+};
+
+BasicDetails.propTypes = {
+ id: PropTypes.string.isRequired, prefix: PropTypes.string, uri: PropTypes.string, is_syncable: PropTypes.string
+};
diff --git a/mapping_workbench/frontend/src/sections/app/fields-registry/edit-form.js b/mapping_workbench/frontend/src/sections/app/fields-registry/edit-form.js
new file mode 100644
index 000000000..f9dceb709
--- /dev/null
+++ b/mapping_workbench/frontend/src/sections/app/fields-registry/edit-form.js
@@ -0,0 +1,119 @@
+import PropTypes from 'prop-types';
+import toast from 'react-hot-toast';
+import * as Yup from 'yup';
+import {useFormik} from 'formik';
+import Button from '@mui/material/Button';
+import Card from '@mui/material/Card';
+import CardContent from '@mui/material/CardContent';
+import CardHeader from '@mui/material/CardHeader';
+import Grid from '@mui/material/Unstable_Grid2';
+import Stack from '@mui/material/Stack';
+
+import {RouterLink} from 'src/components/router-link';
+import {paths} from 'src/paths';
+import {useRouter} from 'src/hooks/use-router';
+import {FormTextField} from "../../../components/app/form/text-field";
+
+
+export const EditForm = (props) => {
+ const {itemctx, ...other} = props;
+ const router = useRouter();
+ const sectionApi = itemctx.api;
+ const item = itemctx.data;
+
+ let initialValues = {
+ title: item.title || ''
+ };
+
+ const formik = useFormik({
+ initialValues: initialValues,
+ validationSchema: Yup.object({
+ title: Yup
+ .string()
+ .max(255)
+ .required('Title is required')
+ }),
+ onSubmit: async (values, helpers) => {
+ try {
+ let response;
+ if (itemctx.isNew) {
+ response = await sectionApi.createItem(values);
+ } else {
+ values['id'] = item._id;
+ response = await sectionApi.updateItem(values);
+ }
+ helpers.setStatus({success: true});
+ helpers.setSubmitting(false);
+ toast.success(sectionApi.SECTION_ITEM_TITLE + ' ' + (itemctx.isNew ? "created" : "updated"));
+ if (response) {
+ if (itemctx.isNew) {
+ router.push({
+ pathname: paths.app[sectionApi.section].edit,
+ query: {id: response._id}
+ });
+ } else if (itemctx.isStateable) {
+ itemctx.setState(response);
+ }
+ }
+ } catch (err) {
+ console.error(err);
+ toast.error('Something went wrong!');
+ helpers.setStatus({success: false});
+ helpers.setErrors({submit: err.message});
+ helpers.setSubmitting(false);
+ }
+ }
+ });
+
+ return (
+
+ );
+};
+
+EditForm.propTypes = {
+ itemctx: PropTypes.object.isRequired
+};
diff --git a/mapping_workbench/frontend/src/sections/app/fields-registry/list-search.js b/mapping_workbench/frontend/src/sections/app/fields-registry/list-search.js
new file mode 100644
index 000000000..7119eed5f
--- /dev/null
+++ b/mapping_workbench/frontend/src/sections/app/fields-registry/list-search.js
@@ -0,0 +1,255 @@
+import {useCallback, useMemo, useRef, useState} from 'react';
+import PropTypes from 'prop-types';
+import SearchMdIcon from '@untitled-ui/icons-react/build/esm/SearchMd';
+import Box from '@mui/material/Box';
+import Chip from '@mui/material/Chip';
+import Divider from '@mui/material/Divider';
+import Input from '@mui/material/Input';
+import Stack from '@mui/material/Stack';
+import SvgIcon from '@mui/material/SvgIcon';
+import Typography from '@mui/material/Typography';
+
+import {MultiSelect} from 'src/components/multi-select';
+import {useUpdateEffect} from 'src/hooks/use-update-effect';
+
+
+const statusOptions = [
+ {
+ label: 'Published',
+ value: 'published'
+ },
+ {
+ label: 'Draft',
+ value: 'draft'
+ }
+];
+
+export const ListSearch = (props) => {
+ const {onFiltersChange, ...other} = props;
+ const queryRef = useRef(null);
+ const [chips, setChips] = useState([]);
+
+ const handleChipsUpdate = useCallback(() => {
+ const filters = {
+ q: undefined,
+ status: [],
+ };
+
+ chips.forEach((chip) => {
+ switch (chip.field) {
+ case 'q':
+ // There will (or should) be only one chips with field "q"
+ // so we can set up it directly
+ filters.q = chip.value;
+ break;
+ case 'status':
+ filters.status.push(chip.value);
+ break;
+ default:
+ break;
+ }
+ });
+
+ onFiltersChange?.(filters);
+ }, [chips, onFiltersChange]);
+
+ useUpdateEffect(() => {
+ handleChipsUpdate();
+ }, [chips, handleChipsUpdate]);
+
+ const handleChipDelete = useCallback((deletedChip) => {
+ setChips((prevChips) => {
+ return prevChips.filter((chip) => {
+ // There can exist multiple chips for the same field.
+ // Filter them by value.
+
+ return !(deletedChip.field === chip.field && deletedChip.value === chip.value);
+ });
+ });
+ }, []);
+
+ const handleQueryChange = useCallback((event) => {
+ event.preventDefault();
+
+ const value = queryRef.current?.value || '';
+
+ setChips((prevChips) => {
+ const found = prevChips.find((chip) => chip.field === 'q');
+
+ if (found && value) {
+ return prevChips.map((chip) => {
+ if (chip.field === 'q') {
+ return {
+ ...chip,
+ value: queryRef.current?.value || ''
+ };
+ }
+
+ return chip;
+ });
+ }
+
+ if (found && !value) {
+ return prevChips.filter((chip) => chip.field !== 'q');
+ }
+
+ if (!found && value) {
+ const chip = {
+ label: 'Q',
+ field: 'q',
+ value
+ };
+
+ return [...prevChips, chip];
+ }
+
+ return prevChips;
+ });
+
+ if (queryRef.current) {
+ queryRef.current.value = '';
+ }
+ }, []);
+
+ const handleStatusChange = useCallback((values) => {
+ setChips((prevChips) => {
+ const valuesFound = [];
+
+ // First cleanup the previous chips
+ const newChips = prevChips.filter((chip) => {
+ if (chip.field !== 'status') {
+ return true;
+ }
+
+ const found = values.includes(chip.value);
+
+ if (found) {
+ valuesFound.push(chip.value);
+ }
+
+ return found;
+ });
+
+ // Nothing changed
+ if (values.length === valuesFound.length) {
+ return newChips;
+ }
+
+ values.forEach((value) => {
+ if (!valuesFound.includes(value)) {
+ const option = statusOptions.find((option) => option.value === value);
+
+ newChips.push({
+ label: 'Status',
+ field: 'status',
+ value,
+ displayValue: option.label
+ });
+ }
+ });
+
+ return newChips;
+ });
+ }, []);
+
+
+ // We memoize this part to prevent re-render issues
+ const statusValues = useMemo(() => chips
+ .filter((chip) => chip.field === 'status')
+ .map((chip) => chip.value), [chips]);
+
+ const showChips = chips.length > 0;
+
+ return (
+
+
+
+
+
+
+
+
+ {showChips
+ ? (
+
+ {chips.map((chip, index) => (
+
+ <>
+
+ {chip.label}
+
+ :
+ {' '}
+ {chip.displayValue || chip.value}
+ >
+
+ )}
+ onDelete={() => handleChipDelete(chip)}
+ variant="outlined"
+ />
+ ))}
+
+ )
+ : (
+
+
+ No filters applied
+
+
+ )}
+
+ {false &&
+
+ }
+
+ );
+};
+
+ListSearch.propTypes = {
+ onFiltersChange: PropTypes.func
+};
diff --git a/mapping_workbench/frontend/src/components/app/file-manager/collection-files.js b/mapping_workbench/frontend/src/sections/app/fields-registry/list-table.js
similarity index 51%
rename from mapping_workbench/frontend/src/components/app/file-manager/collection-files.js
rename to mapping_workbench/frontend/src/sections/app/fields-registry/list-table.js
index 63c7d5d31..0626fa21e 100644
--- a/mapping_workbench/frontend/src/components/app/file-manager/collection-files.js
+++ b/mapping_workbench/frontend/src/sections/app/fields-registry/list-table.js
@@ -1,14 +1,10 @@
import {Fragment, useCallback, useState} from 'react';
import PropTypes from 'prop-types';
-import {toast} from 'react-hot-toast';
import ChevronDownIcon from '@untitled-ui/icons-react/build/esm/ChevronDown';
import ChevronRightIcon from '@untitled-ui/icons-react/build/esm/ChevronRight';
-import Button from '@mui/material/Button';
import CardContent from '@mui/material/CardContent';
import Divider from '@mui/material/Divider';
-import Grid from '@mui/material/Grid';
import IconButton from '@mui/material/IconButton';
-import Stack from '@mui/material/Stack';
import SvgIcon from '@mui/material/SvgIcon';
import Table from '@mui/material/Table';
import TableBody from '@mui/material/TableBody';
@@ -17,23 +13,17 @@ import TableSortLabel from '@mui/material/TableSortLabel';
import TableHead from '@mui/material/TableHead';
import TablePagination from '@mui/material/TablePagination';
import TableRow from '@mui/material/TableRow';
-import TextField from '@mui/material/TextField';
import Typography from '@mui/material/Typography';
-import { format } from 'date-fns';
-import {useMounted} from 'src/hooks/use-mounted';
import {Scrollbar} from 'src/components/scrollbar';
-import {SeverityPill} from 'src/components/severity-pill';
+import {ListItemActions} from 'src/components/app/list/list-item-actions';
import {ForListItemAction} from 'src/contexts/app/section/for-list-item-action';
import Tooltip from "@mui/material/Tooltip";
-import {ListFileCollectionActions} from "src/components/app/list/list-file-collection-actions";
-import { PropertyListItem } from 'src/components/property-list-item';
-import {FileCollectionListSearch} from "./file-collection-list-search";
-import {sparqlTestSuitesApi as sectionApi} from "../../../api/sparql-test-suites";
-import Card from "@mui/material/Card";
+import Switch from "@mui/material/Switch";
-export const CollectionFiles = (props) => {
+
+export const ListTable = (props) => {
const {
count = 0,
items = [],
@@ -45,15 +35,9 @@ export const CollectionFiles = (props) => {
sectionApi
} = props;
- const [currentItem, setCurrentItem] = useState(null);
- const isMounted = useMounted();
+ //console.log("PROJECT PROPS: ", props);
- // if(isMounted()){
- // console.log("itemsWEneed: ", items[0]._id);
- // const itemFileCollection = useItemsStoreFiles(items[0]._id);
- // }
- //const itemFileCollection = useItemsStoreFiles(items[0]._id);
- //console.log("itemFileCollection: ", itemFileCollection);
+ const [currentItem, setCurrentItem] = useState(null);
const handleItemToggle = useCallback((itemId) => {
setCurrentItem((prevItemId) => {
@@ -63,32 +47,50 @@ export const CollectionFiles = (props) => {
return itemId;
});
- //useItemsStoreFiles(itemId);
}, []);
- const handleItemClose = useCallback(() => {
- setCurrentItem(null);
- }, []);
+ // const handleItemClose = useCallback(() => {
+ // setCurrentItem(null);
+ // }, []);
- const handleItemUpdate = useCallback(() => {
- setCurrentItem(null);
- toast.success('Item updated');
- }, []);
+ // const handleItemUpdate = useCallback(() => {
+ // setCurrentItem(null);
+ // toast.success('Item updated');
+ // }, []);
- const handleItemDelete = useCallback(() => {
- toast.error('Item cannot be deleted');
- }, []);
-
- //console.log("date before: ", items);
- //console.log(" items[0].created_at ",(items[0].created_at).replace("T", " ").split(".")[0]);
+ // const handleItemDelete = useCallback(() => {
+
+ // toast.error('Item cannot be deleted');
+ // }, []);
return (
+
+ {/*
+
+
+ Name
+
+
+ */}
{
- Title
+ Prefix
- Description
+ URI
- {/*
- Status
- */}
-
+
- Created
+ Syncable
@@ -161,24 +159,42 @@ export const CollectionFiles = (props) => {
+ {/*
+
+
+
+ {item.name}
+
+
+
+ */}
- {item.title}
+ {item.prefix}
- {item.description}
+ {item.uri}
- {/*
-
- {item.status}
-
- */}
-
- {(item.created_at).replace("T", " ").split(".")[0]}
+
+
-
@@ -201,73 +217,8 @@ export const CollectionFiles = (props) => {
}}
>
-
-
-
- Details
-
-
-
-
- {/* */}
-
-
-
-
- {/* */}
-
-
-
-
-
-
-
-
-
-
+
)}
@@ -284,13 +235,13 @@ export const CollectionFiles = (props) => {
onRowsPerPageChange={onRowsPerPageChange}
page={page}
rowsPerPage={rowsPerPage}
- rowsPerPageOptions={[5, 10, 25]}
+ rowsPerPageOptions={sectionApi.DEFAULT_ROWS_PER_PAGE_SELECTION}
/>
);
};
-FileCollectionListTable.propTypes = {
+ListTable.propTypes = {
count: PropTypes.number,
items: PropTypes.array,
onPageChange: PropTypes.func,
diff --git a/mapping_workbench/frontend/src/sections/app/file-manager/file-collection-edit-form.js b/mapping_workbench/frontend/src/sections/app/file-manager/file-collection-edit-form.js
index fbde4cfd7..f2557b6a8 100644
--- a/mapping_workbench/frontend/src/sections/app/file-manager/file-collection-edit-form.js
+++ b/mapping_workbench/frontend/src/sections/app/file-manager/file-collection-edit-form.js
@@ -23,6 +23,7 @@ import FormLabel from "@mui/material/FormLabel";
import Select from "@mui/material/Select";
import {FormTextField} from "../../../components/app/form/text-field";
import {FormTextArea} from "../../../components/app/form/text-area";
+import {MappingPackageFormSelect} from "../mapping-package/components/mapping-package-form-select";
export const FileCollectionEditForm = (props) => {
@@ -49,6 +50,10 @@ export const FileCollectionEditForm = (props) => {
initialValues['type'] = item.type || null;
}
+ if (sectionApi.hasMappingPackage) {
+ initialValues['mapping_package_id'] = item.mapping_package_id || '';
+ }
+
switch (sectionApi.section) {
case 'test_data_suites':
customPathName = paths.app.test_data_suites.index;
@@ -131,6 +136,11 @@ export const FileCollectionEditForm = (props) => {
>
+ {sectionApi.hasMappingPackage && (
+
+
+
+ )}
{sectionApi.hasFileCollectionType && (
{
const handleMappingPackageChange = useCallback(async (event) => {
let value = event.target.value;
- formik.setFieldValue('mapping_package', value);
+ formik.setFieldValue('mapping_package_id', value);
}, [formik])
return (
<>
{mappingPackagesStore.items.map((mapping_package) => (
-
+ {false &&
@@ -136,7 +136,7 @@ export const EditForm = (props) => {
-
+ }
diff --git a/mapping_workbench/frontend/src/sections/app/ontology-namespace/edit-form.js b/mapping_workbench/frontend/src/sections/app/ontology-namespace/edit-form.js
index 3cc6d7359..07cde76de 100644
--- a/mapping_workbench/frontend/src/sections/app/ontology-namespace/edit-form.js
+++ b/mapping_workbench/frontend/src/sections/app/ontology-namespace/edit-form.js
@@ -9,13 +9,11 @@ import CardContent from '@mui/material/CardContent';
import CardHeader from '@mui/material/CardHeader';
import Grid from '@mui/material/Unstable_Grid2';
import Stack from '@mui/material/Stack';
-import TextField from '@mui/material/TextField';
import {RouterLink} from 'src/components/router-link';
import {paths} from 'src/paths';
import {useRouter} from 'src/hooks/use-router';
import {FormTextField} from "../../../components/app/form/text-field";
-import {FormTextArea} from "../../../components/app/form/text-area";
import FormControlLabel from "@mui/material/FormControlLabel";
import Switch from "@mui/material/Switch";
import MenuList from "@mui/material/MenuList";
@@ -39,7 +37,7 @@ export const EditForm = (props) => {
prefix: Yup
.string()
.max(255)
- .required('Title is required'),
+ .required('Prefix is required'),
uri: Yup.string().max(2048),
is_syncable: Yup.boolean()
}),
diff --git a/mapping_workbench/frontend/src/sections/app/specific-triple-map-fragment/edit-form.js b/mapping_workbench/frontend/src/sections/app/specific-triple-map-fragment/edit-form.js
index 953a3e4df..9417f4e32 100644
--- a/mapping_workbench/frontend/src/sections/app/specific-triple-map-fragment/edit-form.js
+++ b/mapping_workbench/frontend/src/sections/app/specific-triple-map-fragment/edit-form.js
@@ -16,9 +16,6 @@ import {FormTextField} from "../../../components/app/form/text-field";
import {sessionApi} from "../../../api/session";
import {MappingPackageFormSelect} from "../mapping-package/components/mapping-package-form-select";
import {FormCodeTextArea} from "../../../components/app/form/code-text-area";
-import FormControl from "@mui/material/FormControl";
-import FormLabel from "@mui/material/FormLabel";
-import Select from "@mui/material/Select";
import MenuItem from "@mui/material/MenuItem";
import TextField from "@mui/material/TextField";
import * as React from "react";
@@ -34,7 +31,7 @@ export const EditForm = (props) => {
triple_map_uri: item.triple_map_uri || '',
triple_map_content: item.triple_map_content || '',
format: item.format || sectionApi.FILE_RESOURCE_DEFAULT_FORMAT || '',
- mapping_package: (item.mapping_package && item.mapping_package.id) || ''
+ mapping_package_id: item.mapping_package_id || ''
};
const formik = useFormik({
@@ -45,7 +42,7 @@ export const EditForm = (props) => {
.max(255)
.required('URI is required'),
triple_map_content: Yup.string(),
- mapping_package: Yup.string().max(255).required('Package is required')
+ mapping_package_id: Yup.string().max(255).required('Package is required')
}),
onSubmit: async (values, helpers) => {
try {
diff --git a/mapping_workbench/frontend/src/sections/app/specific-triple-map-fragment/list-table.js b/mapping_workbench/frontend/src/sections/app/specific-triple-map-fragment/list-table.js
index e26a83dd3..7931af9a5 100644
--- a/mapping_workbench/frontend/src/sections/app/specific-triple-map-fragment/list-table.js
+++ b/mapping_workbench/frontend/src/sections/app/specific-triple-map-fragment/list-table.js
@@ -3,7 +3,6 @@ import PropTypes from 'prop-types';
import ChevronDownIcon from '@untitled-ui/icons-react/build/esm/ChevronDown';
import ChevronRightIcon from '@untitled-ui/icons-react/build/esm/ChevronRight';
import CardContent from '@mui/material/CardContent';
-import Divider from '@mui/material/Divider';
import Grid from '@mui/material/Grid';
import IconButton from '@mui/material/IconButton';
import SvgIcon from '@mui/material/SvgIcon';
@@ -57,7 +56,7 @@ export const ListTable = (props) => {
(async () => {
setProjectMappingPackages(await mappingPackagesApi.getProjectPackages());
})()
- }, [mappingPackagesApi])
+ }, [])
const [projectMappingPackagesMap, setProjectMappingPackagesMap] = useState({});
@@ -184,7 +183,7 @@ export const ListTable = (props) => {
- {projectMappingPackagesMap[item.mapping_package.id]}
+ {item.mapping_package && projectMappingPackagesMap[item.mapping_package.id]}
{