Rename producer to service and consumer to client #41

Merged
merge-bot merged 8 commits from Qubasa-main into main 2024-01-07 14:24:17 +00:00
38 changed files with 661 additions and 446 deletions
Showing only changes of commit bd30682092 - Show all commits

View File

@@ -81,7 +81,6 @@ def main() -> None:
replace_in_directory(directory_path=src_client, pattern=pattern, replacement=replacement) replace_in_directory(directory_path=src_client, pattern=pattern, replacement=replacement)
dst_client: Path = args.out / "openapi_client" dst_client: Path = args.out / "openapi_client"
breakpoint()
shutil.rmtree(dst_client, ignore_errors=True) shutil.rmtree(dst_client, ignore_errors=True)
shutil.copytree(src_client, dst_client) shutil.copytree(src_client, dst_client)

View File

@@ -13,12 +13,14 @@ from ..errors import ClanError
from . import sql_models from . import sql_models
from .assets import asset_path from .assets import asset_path
from .error_handlers import clan_error_handler, sql_error_handler from .error_handlers import clan_error_handler, sql_error_handler
from .routers import health, root, socket_manager2, sql_connect # sql router hinzufügen from .routers import endpoints, health, root, socket_manager2 # sql router hinzufügen
from .sql_db import engine from .sql_db import engine
from .tags import tags_metadata from .tags import tags_metadata
origins = [ origins = [
"http://localhost:3000", "http://localhost:3000",
"http://127.0.0.1:3000",
"http://0.0.0.0:3000",
] ]
# Logging setup # Logging setup
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
@@ -50,7 +52,7 @@ def setup_app() -> FastAPI:
app.include_router(health.router) app.include_router(health.router)
# sql methodes # sql methodes
app.include_router(sql_connect.router) app.include_router(endpoints.router)
app.include_router(socket_manager2.router) app.include_router(socket_manager2.router)

View File

@@ -15,6 +15,7 @@ from ..schemas import (
Resolution, Resolution,
Service, Service,
ServiceCreate, ServiceCreate,
ServicesByName,
) )
from ..tags import Tags from ..tags import Tags
@@ -57,6 +58,24 @@ async def get_service_by_did(
return service return service
@router.get(
"/api/v1/services_by_entity_name",
response_model=ServicesByName,
tags=[Tags.services],
)
async def get_services_by_name(
entity_name: str,
skip: int = 0,
limit: int = 100,
db: Session = Depends(sql_db.get_db),
) -> ServicesByName:
entity = sql_crud.get_entity_by_name(db, name=entity_name)
if entity is None:
raise ClanError(f"Entity with name '{entity_name}' not found")
services = sql_crud.get_services_by_entity_did(db, entity_did=str(entity.did))
return ServicesByName(entity=entity, services=services) # type: ignore
@router.delete("/api/v1/{entity_did}/service", tags=[Tags.services]) @router.delete("/api/v1/{entity_did}/service", tags=[Tags.services])
async def delete_service( async def delete_service(
entity_did: str = "did:sov:test:1234", entity_did: str = "did:sov:test:1234",
@@ -66,33 +85,11 @@ async def delete_service(
return {"message": "service deleted"} return {"message": "service deleted"}
#########################
# #
# Client #
# #
#########################
@router.get(
"/api/v1/{entity_did}/clients", response_model=List[Service], tags=[Tags.clients]
)
async def get_all_clients(
entity_did: str = "did:sov:test:1234",
skip: int = 0,
limit: int = 100,
db: Session = Depends(sql_db.get_db),
) -> List[sql_models.Service]:
clients = sql_crud.get_services_without_entity_id(
db, entity_did, skip=skip, limit=limit
)
return clients
######################### #########################
# # # #
# REPOSITORY # # REPOSITORY #
# # # #
######################### #########################
@router.get( @router.get(
"/api/v1/repositories", "/api/v1/repositories",
response_model=List[Service], response_model=List[Service],
@@ -117,6 +114,16 @@ async def create_entity(
return sql_crud.create_entity(db, entity) return sql_crud.create_entity(db, entity)
@router.get(
"/api/v1/entity_by_name", response_model=Optional[Entity], tags=[Tags.entities]
)
async def get_entity_by_name(
entity_name: str, db: Session = Depends(sql_db.get_db)
) -> Optional[sql_models.Entity]:
entity = sql_crud.get_entity_by_name(db, name=entity_name)
return entity
@router.get("/api/v1/entities", response_model=List[Entity], tags=[Tags.entities]) @router.get("/api/v1/entities", response_model=List[Entity], tags=[Tags.entities])
async def get_all_entities( async def get_all_entities(
skip: int = 0, limit: int = 100, db: Session = Depends(sql_db.get_db) skip: int = 0, limit: int = 100, db: Session = Depends(sql_db.get_db)

View File

@@ -1,7 +1,8 @@
from datetime import datetime from datetime import datetime
from enum import Enum from enum import Enum
from typing import List
from pydantic import BaseModel from pydantic import BaseModel, Field
class Status(Enum): class Status(Enum):
@@ -15,43 +16,23 @@ class Machine(BaseModel):
status: Status status: Status
#########################
# #
# Service #
# #
#########################
class ServiceBase(BaseModel):
uuid: str = "8e285c0c-4e40-430a-a477-26b3b81e30df"
service_name: str = "Carlos Printing"
service_type: str = "3D Printing"
endpoint_url: str = "http://127.0.0.1:8000"
status: str = "unknown"
other: dict = {"action": ["register", "deregister", "delete", "create"]}
class ServiceCreate(ServiceBase):
entity_did: str = "did:sov:test:1234"
class Service(ServiceCreate):
class Config:
orm_mode = True
######################### #########################
# # # #
# Entity # # Entity #
# # # #
######################### #########################
class EntityBase(BaseModel): class EntityBase(BaseModel):
did: str = "did:sov:test:1234" did: str = Field(..., example="did:sov:test:1234")
name: str = "C1" name: str = Field(..., example="C1")
ip: str = "127.0.0.1" ip: str = Field(..., example="127.0.0.1")
visible: bool = True visible: bool = Field(..., example=True)
other: dict = { other: dict = Field(
"network": "Carlos Home Network", ...,
"roles": ["service repository", "service prosumer"], example={
} "network": "Carlos Home Network",
"roles": ["service repository", "service prosumer"],
},
)
class EntityCreate(EntityBase): class EntityCreate(EntityBase):
@@ -59,7 +40,42 @@ class EntityCreate(EntityBase):
class Entity(EntityCreate): class Entity(EntityCreate):
attached: bool attached: bool = Field(...)
class Config:
orm_mode = True
#########################
# #
# Service #
# #
#########################
class ServiceBase(BaseModel):
uuid: str = Field(..., example="8e285c0c-4e40-430a-a477-26b3b81e30df")
service_name: str = Field(..., example="Carlos Printing")
service_type: str = Field(..., example="3D Printing")
endpoint_url: str = Field(..., example="http://127.0.0.1:8000")
status: str = Field(..., example="unknown")
other: dict = Field(
..., example={"action": ["register", "deregister", "delete", "create"]}
)
class ServiceCreate(ServiceBase):
entity_did: str = Field(..., example="did:sov:test:1234")
class Service(ServiceCreate):
entity: Entity
class Config:
orm_mode = True
class ServicesByName(BaseModel):
entity: Entity
services: List[Service]
class Config: class Config:
orm_mode = True orm_mode = True
@@ -71,10 +87,10 @@ class Entity(EntityCreate):
# # # #
######################### #########################
class ResolutionBase(BaseModel): class ResolutionBase(BaseModel):
requester_name: str = "C1" requester_name: str = Field(..., example="C1")
requester_did: str = "did:sov:test:1122" requester_did: str = Field(..., example="did:sov:test:1122")
resolved_did: str = "did:sov:test:1234" resolved_did: str = Field(..., example="did:sov:test:1234")
other: dict = {"test": "test"} other: dict = Field(..., example={"test": "test"})
class ResolutionCreate(ResolutionBase): class ResolutionCreate(ResolutionBase):

View File

@@ -81,6 +81,10 @@ def get_entity_by_did(db: Session, did: str) -> Optional[sql_models.Entity]:
return db.query(sql_models.Entity).filter(sql_models.Entity.did == did).first() return db.query(sql_models.Entity).filter(sql_models.Entity.did == did).first()
def get_entity_by_name(db: Session, name: str) -> Optional[sql_models.Entity]:
return db.query(sql_models.Entity).filter(sql_models.Entity.name == name).first()
# get attached # get attached
def get_attached_entities( def get_attached_entities(
db: Session, skip: int = 0, limit: int = 100 db: Session, skip: int = 0, limit: int = 100

View File

@@ -19,7 +19,7 @@ class Entity(Base):
## Queryable body ## ## Queryable body ##
did = Column(String, primary_key=True, index=True) did = Column(String, primary_key=True, index=True)
name = Column(String, index=True) name = Column(String, index=True, unique=True)
ip = Column(String, index=True) ip = Column(String, index=True)
attached = Column(Boolean, index=True) attached = Column(Boolean, index=True)
visible = Column(Boolean, index=True) visible = Column(Boolean, index=True)

View File

@@ -45,13 +45,13 @@ class ClientsApi:
self.api_client = api_client self.api_client = api_client
@validate_arguments @validate_arguments
def get_all_clients(self, entity_did : StrictStr, skip : Optional[StrictInt] = None, limit : Optional[StrictInt] = None, **kwargs) -> List[Service]: # noqa: E501 def get_clients_by_did(self, entity_did : StrictStr, skip : Optional[StrictInt] = None, limit : Optional[StrictInt] = None, **kwargs) -> List[Service]: # noqa: E501
"""Get All Clients # noqa: E501 """Get Clients By Did # noqa: E501
This method makes a synchronous HTTP request by default. To make an This method makes a synchronous HTTP request by default. To make an
asynchronous HTTP request, please pass async_req=True asynchronous HTTP request, please pass async_req=True
>>> thread = api.get_all_clients(entity_did, skip, limit, async_req=True) >>> thread = api.get_clients_by_did(entity_did, skip, limit, async_req=True)
>>> result = thread.get() >>> result = thread.get()
:param entity_did: (required) :param entity_did: (required)
@@ -73,18 +73,18 @@ class ClientsApi:
""" """
kwargs['_return_http_data_only'] = True kwargs['_return_http_data_only'] = True
if '_preload_content' in kwargs: if '_preload_content' in kwargs:
message = "Error! Please call the get_all_clients_with_http_info method with `_preload_content` instead and obtain raw data from ApiResponse.raw_data" # noqa: E501 message = "Error! Please call the get_clients_by_did_with_http_info method with `_preload_content` instead and obtain raw data from ApiResponse.raw_data" # noqa: E501
raise ValueError(message) raise ValueError(message)
return self.get_all_clients_with_http_info(entity_did, skip, limit, **kwargs) # noqa: E501 return self.get_clients_by_did_with_http_info(entity_did, skip, limit, **kwargs) # noqa: E501
@validate_arguments @validate_arguments
def get_all_clients_with_http_info(self, entity_did : StrictStr, skip : Optional[StrictInt] = None, limit : Optional[StrictInt] = None, **kwargs) -> ApiResponse: # noqa: E501 def get_clients_by_did_with_http_info(self, entity_did : StrictStr, skip : Optional[StrictInt] = None, limit : Optional[StrictInt] = None, **kwargs) -> ApiResponse: # noqa: E501
"""Get All Clients # noqa: E501 """Get Clients By Did # noqa: E501
This method makes a synchronous HTTP request by default. To make an This method makes a synchronous HTTP request by default. To make an
asynchronous HTTP request, please pass async_req=True asynchronous HTTP request, please pass async_req=True
>>> thread = api.get_all_clients_with_http_info(entity_did, skip, limit, async_req=True) >>> thread = api.get_clients_by_did_with_http_info(entity_did, skip, limit, async_req=True)
>>> result = thread.get() >>> result = thread.get()
:param entity_did: (required) :param entity_did: (required)
@@ -142,7 +142,7 @@ class ClientsApi:
if _key not in _all_params: if _key not in _all_params:
raise ApiTypeError( raise ApiTypeError(
"Got an unexpected keyword argument '%s'" "Got an unexpected keyword argument '%s'"
" to method get_all_clients" % _key " to method get_clients_by_did" % _key
) )
_params[_key] = _val _params[_key] = _val
del _params['kwargs'] del _params['kwargs']

View File

@@ -1072,3 +1072,142 @@ class EntitiesApi:
_request_timeout=_params.get('_request_timeout'), _request_timeout=_params.get('_request_timeout'),
collection_formats=_collection_formats, collection_formats=_collection_formats,
_request_auth=_params.get('_request_auth')) _request_auth=_params.get('_request_auth'))
@validate_arguments
def get_entity_by_name(self, entity_name : StrictStr, **kwargs) -> Entity: # noqa: E501
"""Get Entity By Name # noqa: E501
This method makes a synchronous HTTP request by default. To make an
asynchronous HTTP request, please pass async_req=True
>>> thread = api.get_entity_by_name(entity_name, async_req=True)
>>> result = thread.get()
:param entity_name: (required)
:type entity_name: str
:param async_req: Whether to execute the request asynchronously.
:type async_req: bool, optional
:param _request_timeout: timeout setting for this request.
If one number provided, it will be total request
timeout. It can also be a pair (tuple) of
(connection, read) timeouts.
:return: Returns the result object.
If the method is called asynchronously,
returns the request thread.
:rtype: Entity
"""
kwargs['_return_http_data_only'] = True
if '_preload_content' in kwargs:
message = "Error! Please call the get_entity_by_name_with_http_info method with `_preload_content` instead and obtain raw data from ApiResponse.raw_data" # noqa: E501
raise ValueError(message)
return self.get_entity_by_name_with_http_info(entity_name, **kwargs) # noqa: E501
@validate_arguments
def get_entity_by_name_with_http_info(self, entity_name : StrictStr, **kwargs) -> ApiResponse: # noqa: E501
"""Get Entity By Name # noqa: E501
This method makes a synchronous HTTP request by default. To make an
asynchronous HTTP request, please pass async_req=True
>>> thread = api.get_entity_by_name_with_http_info(entity_name, async_req=True)
>>> result = thread.get()
:param entity_name: (required)
:type entity_name: str
:param async_req: Whether to execute the request asynchronously.
:type async_req: bool, optional
:param _preload_content: if False, the ApiResponse.data will
be set to none and raw_data will store the
HTTP response body without reading/decoding.
Default is True.
:type _preload_content: bool, optional
:param _return_http_data_only: response data instead of ApiResponse
object with status code, headers, etc
:type _return_http_data_only: bool, optional
:param _request_timeout: timeout setting for this request. If one
number provided, it will be total request
timeout. It can also be a pair (tuple) of
(connection, read) timeouts.
:param _request_auth: set to override the auth_settings for an a single
request; this effectively ignores the authentication
in the spec for a single request.
:type _request_auth: dict, optional
:type _content_type: string, optional: force content-type for the request
:return: Returns the result object.
If the method is called asynchronously,
returns the request thread.
:rtype: tuple(Entity, status_code(int), headers(HTTPHeaderDict))
"""
_params = locals()
_all_params = [
'entity_name'
]
_all_params.extend(
[
'async_req',
'_return_http_data_only',
'_preload_content',
'_request_timeout',
'_request_auth',
'_content_type',
'_headers'
]
)
# validate the arguments
for _key, _val in _params['kwargs'].items():
if _key not in _all_params:
raise ApiTypeError(
"Got an unexpected keyword argument '%s'"
" to method get_entity_by_name" % _key
)
_params[_key] = _val
del _params['kwargs']
_collection_formats = {}
# process the path parameters
_path_params = {}
# process the query parameters
_query_params = []
if _params.get('entity_name') is not None: # noqa: E501
_query_params.append(('entity_name', _params['entity_name']))
# process the header parameters
_header_params = dict(_params.get('_headers', {}))
# process the form parameters
_form_params = []
_files = {}
# process the body parameter
_body_params = None
# set the HTTP header `Accept`
_header_params['Accept'] = self.api_client.select_header_accept(
['application/json']) # noqa: E501
# authentication setting
_auth_settings = [] # noqa: E501
_response_types_map = {
'200': "Entity",
'422': "HTTPValidationError",
}
return self.api_client.call_api(
'/api/v1/entity_by_name', 'GET',
_path_params,
_query_params,
_header_params,
body=_body_params,
post_params=_form_params,
files=_files,
response_types_map=_response_types_map,
auth_settings=_auth_settings,
async_req=_params.get('async_req'),
_return_http_data_only=_params.get('_return_http_data_only'), # noqa: E501
_preload_content=_params.get('_preload_content', True),
_request_timeout=_params.get('_request_timeout'),
collection_formats=_collection_formats,
_request_auth=_params.get('_request_auth'))

View File

@@ -2,15 +2,15 @@
All URIs are relative to _http://localhost_ All URIs are relative to _http://localhost_
| Method | HTTP request | Description | | Method | HTTP request | Description |
| ---------------------------------------------------- | ------------------------------------ | --------------- | | ---------------------------------------------------------- | ------------------------------------ | ------------------ |
| [**get_all_clients**](ClientsApi.md#get_all_clients) | **GET** /api/v1/{entity_did}/clients | Get All Clients | | [**get_clients_by_did**](ClientsApi.md#get_clients_by_did) | **GET** /api/v1/{entity_did}/clients | Get Clients By Did |
# **get_all_clients** # **get_clients_by_did**
> List[Service] get_all_clients(entity_did, skip=skip, limit=limit) > List[Service] get_clients_by_did(entity_did, skip=skip, limit=limit)
Get All Clients Get Clients By Did
### Example ### Example
@@ -38,12 +38,12 @@ with openapi_client.ApiClient(configuration) as api_client:
limit = 100 # int | (optional) (default to 100) limit = 100 # int | (optional) (default to 100)
try: try:
# Get All Clients # Get Clients By Did
api_response = api_instance.get_all_clients(entity_did, skip=skip, limit=limit) api_response = api_instance.get_clients_by_did(entity_did, skip=skip, limit=limit)
print("The response of ClientsApi->get_all_clients:\n") print("The response of ClientsApi->get_clients_by_did:\n")
pprint(api_response) pprint(api_response)
except Exception as e: except Exception as e:
print("Exception when calling ClientsApi->get_all_clients: %s\n" % e) print("Exception when calling ClientsApi->get_clients_by_did: %s\n" % e)
``` ```
### Parameters ### Parameters

View File

@@ -11,6 +11,7 @@ All URIs are relative to _http://localhost_
| [**get_all_entities**](EntitiesApi.md#get_all_entities) | **GET** /api/v1/entities | Get All Entities | | [**get_all_entities**](EntitiesApi.md#get_all_entities) | **GET** /api/v1/entities | Get All Entities |
| [**get_attached_entities**](EntitiesApi.md#get_attached_entities) | **GET** /api/v1/attached_entities | Get Attached Entities | | [**get_attached_entities**](EntitiesApi.md#get_attached_entities) | **GET** /api/v1/attached_entities | Get Attached Entities |
| [**get_entity_by_did**](EntitiesApi.md#get_entity_by_did) | **GET** /api/v1/{entity_did}/entity | Get Entity By Did | | [**get_entity_by_did**](EntitiesApi.md#get_entity_by_did) | **GET** /api/v1/{entity_did}/entity | Get Entity By Did |
| [**get_entity_by_name**](EntitiesApi.md#get_entity_by_name) | **GET** /api/v1/entity_by_name | Get Entity By Name |
# **attach_entity** # **attach_entity**
@@ -484,3 +485,69 @@ No authorization required
| **422** | Validation Error | - | | **422** | Validation Error | - |
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) [[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
# **get_entity_by_name**
> Entity get_entity_by_name(entity_name)
Get Entity By Name
### Example
```python
import time
import os
import openapi_client
from openapi_client.models.entity import Entity
from openapi_client.rest import ApiException
from pprint import pprint
# Defining the host is optional and defaults to http://localhost
# See configuration.py for a list of all supported configuration parameters.
configuration = openapi_client.Configuration(
host = "http://localhost"
)
# Enter a context with an instance of the API client
with openapi_client.ApiClient(configuration) as api_client:
# Create an instance of the API class
api_instance = openapi_client.EntitiesApi(api_client)
entity_name = 'entity_name_example' # str |
try:
# Get Entity By Name
api_response = api_instance.get_entity_by_name(entity_name)
print("The response of EntitiesApi->get_entity_by_name:\n")
pprint(api_response)
except Exception as e:
print("Exception when calling EntitiesApi->get_entity_by_name: %s\n" % e)
```
### Parameters
| Name | Type | Description | Notes |
| --------------- | ------- | ----------- | ----- |
| **entity_name** | **str** | |
### Return type
[**Entity**](Entity.md)
### Authorization
No authorization required
### HTTP request headers
- **Content-Type**: Not defined
- **Accept**: application/json
### HTTP response details
| Status code | Description | Response headers |
| ----------- | ------------------- | ---------------- |
| **200** | Successful Response | - |
| **422** | Validation Error | - |
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)

View File

@@ -2,13 +2,13 @@
## Properties ## Properties
| Name | Type | Description | Notes | | Name | Type | Description | Notes |
| ------------ | ---------- | ----------- | ------------------------------------------- | | ------------ | ---------- | ----------- | ----- |
| **did** | **str** | | [optional] [default to 'did:sov:test:1234'] | | **did** | **str** | |
| **name** | **str** | | [optional] [default to 'C1'] | | **name** | **str** | |
| **ip** | **str** | | [optional] [default to '127.0.0.1'] | | **ip** | **str** | |
| **visible** | **bool** | | [optional] [default to True] | | **visible** | **bool** | |
| **other** | **object** | | [optional] | | **other** | **object** | |
| **attached** | **bool** | | | **attached** | **bool** | |
## Example ## Example

View File

@@ -2,13 +2,13 @@
## Properties ## Properties
| Name | Type | Description | Notes | | Name | Type | Description | Notes |
| ----------- | ---------- | ----------- | ------------------------------------------- | | ----------- | ---------- | ----------- | ----- |
| **did** | **str** | | [optional] [default to 'did:sov:test:1234'] | | **did** | **str** | |
| **name** | **str** | | [optional] [default to 'C1'] | | **name** | **str** | |
| **ip** | **str** | | [optional] [default to '127.0.0.1'] | | **ip** | **str** | |
| **visible** | **bool** | | [optional] [default to True] | | **visible** | **bool** | |
| **other** | **object** | | [optional] | | **other** | **object** | |
## Example ## Example

View File

@@ -2,12 +2,12 @@
## Properties ## Properties
| Name | Type | Description | Notes | | Name | Type | Description | Notes |
| ------------------ | ------------ | ----------- | ------------------------------------------- | | ------------------ | ------------ | ----------- | ----- |
| **requester_name** | **str** | | [optional] [default to 'C1'] | | **requester_name** | **str** | |
| **requester_did** | **str** | | [optional] [default to 'did:sov:test:1122'] | | **requester_did** | **str** | |
| **resolved_did** | **str** | | [optional] [default to 'did:sov:test:1234'] | | **resolved_did** | **str** | |
| **other** | **object** | | [optional] | | **other** | **object** | |
| **timestamp** | **datetime** | | | **timestamp** | **datetime** | |
| **id** | **int** | | | **id** | **int** | |

View File

@@ -2,15 +2,16 @@
## Properties ## Properties
| Name | Type | Description | Notes | | Name | Type | Description | Notes |
| ---------------- | ---------- | ----------- | -------------------------------------------------------------- | | ---------------- | ----------------------- | ----------- | ----- |
| **uuid** | **str** | | [optional] [default to '8e285c0c-4e40-430a-a477-26b3b81e30df'] | | **uuid** | **str** | |
| **service_name** | **str** | | [optional] [default to 'Carlos Printing'] | | **service_name** | **str** | |
| **service_type** | **str** | | [optional] [default to '3D Printing'] | | **service_type** | **str** | |
| **endpoint_url** | **str** | | [optional] [default to 'http://127.0.0.1:8000'] | | **endpoint_url** | **str** | |
| **status** | **str** | | [optional] [default to 'unknown'] | | **status** | **str** | |
| **other** | **object** | | [optional] | | **other** | **object** | |
| **entity_did** | **str** | | [optional] [default to 'did:sov:test:1234'] | | **entity_did** | **str** | |
| **entity** | [**Entity**](Entity.md) | |
## Example ## Example

View File

@@ -2,15 +2,15 @@
## Properties ## Properties
| Name | Type | Description | Notes | | Name | Type | Description | Notes |
| ---------------- | ---------- | ----------- | -------------------------------------------------------------- | | ---------------- | ---------- | ----------- | ----- |
| **uuid** | **str** | | [optional] [default to '8e285c0c-4e40-430a-a477-26b3b81e30df'] | | **uuid** | **str** | |
| **service_name** | **str** | | [optional] [default to 'Carlos Printing'] | | **service_name** | **str** | |
| **service_type** | **str** | | [optional] [default to '3D Printing'] | | **service_type** | **str** | |
| **endpoint_url** | **str** | | [optional] [default to 'http://127.0.0.1:8000'] | | **endpoint_url** | **str** | |
| **status** | **str** | | [optional] [default to 'unknown'] | | **status** | **str** | |
| **other** | **object** | | [optional] | | **other** | **object** | |
| **entity_did** | **str** | | [optional] [default to 'did:sov:test:1234'] | | **entity_did** | **str** | |
## Example ## Example

View File

@@ -18,18 +18,18 @@ import re # noqa: F401
import json import json
from typing import Any, Dict, Optional from typing import Any, Dict
from pydantic import BaseModel, Field, StrictBool, StrictStr from pydantic import BaseModel, Field, StrictBool, StrictStr
class Entity(BaseModel): class Entity(BaseModel):
""" """
Entity Entity
""" """
did: Optional[StrictStr] = 'did:sov:test:1234' did: StrictStr = Field(...)
name: Optional[StrictStr] = 'C1' name: StrictStr = Field(...)
ip: Optional[StrictStr] = '127.0.0.1' ip: StrictStr = Field(...)
visible: Optional[StrictBool] = True visible: StrictBool = Field(...)
other: Optional[Dict[str, Any]] = None other: Dict[str, Any] = Field(...)
attached: StrictBool = Field(...) attached: StrictBool = Field(...)
__properties = ["did", "name", "ip", "visible", "other", "attached"] __properties = ["did", "name", "ip", "visible", "other", "attached"]
@@ -69,10 +69,10 @@ class Entity(BaseModel):
return Entity.parse_obj(obj) return Entity.parse_obj(obj)
_obj = Entity.parse_obj({ _obj = Entity.parse_obj({
"did": obj.get("did") if obj.get("did") is not None else 'did:sov:test:1234', "did": obj.get("did"),
"name": obj.get("name") if obj.get("name") is not None else 'C1', "name": obj.get("name"),
"ip": obj.get("ip") if obj.get("ip") is not None else '127.0.0.1', "ip": obj.get("ip"),
"visible": obj.get("visible") if obj.get("visible") is not None else True, "visible": obj.get("visible"),
"other": obj.get("other"), "other": obj.get("other"),
"attached": obj.get("attached") "attached": obj.get("attached")
}) })

View File

@@ -18,18 +18,18 @@ import re # noqa: F401
import json import json
from typing import Any, Dict, Optional from typing import Any, Dict
from pydantic import BaseModel, StrictBool, StrictStr from pydantic import BaseModel, Field, StrictBool, StrictStr
class EntityCreate(BaseModel): class EntityCreate(BaseModel):
""" """
EntityCreate EntityCreate
""" """
did: Optional[StrictStr] = 'did:sov:test:1234' did: StrictStr = Field(...)
name: Optional[StrictStr] = 'C1' name: StrictStr = Field(...)
ip: Optional[StrictStr] = '127.0.0.1' ip: StrictStr = Field(...)
visible: Optional[StrictBool] = True visible: StrictBool = Field(...)
other: Optional[Dict[str, Any]] = None other: Dict[str, Any] = Field(...)
__properties = ["did", "name", "ip", "visible", "other"] __properties = ["did", "name", "ip", "visible", "other"]
class Config: class Config:
@@ -68,10 +68,10 @@ class EntityCreate(BaseModel):
return EntityCreate.parse_obj(obj) return EntityCreate.parse_obj(obj)
_obj = EntityCreate.parse_obj({ _obj = EntityCreate.parse_obj({
"did": obj.get("did") if obj.get("did") is not None else 'did:sov:test:1234', "did": obj.get("did"),
"name": obj.get("name") if obj.get("name") is not None else 'C1', "name": obj.get("name"),
"ip": obj.get("ip") if obj.get("ip") is not None else '127.0.0.1', "ip": obj.get("ip"),
"visible": obj.get("visible") if obj.get("visible") is not None else True, "visible": obj.get("visible"),
"other": obj.get("other") "other": obj.get("other")
}) })
return _obj return _obj

View File

@@ -18,17 +18,17 @@ import re # noqa: F401
import json import json
from datetime import datetime from datetime import datetime
from typing import Any, Dict, Optional from typing import Any, Dict
from pydantic import BaseModel, Field, StrictInt, StrictStr from pydantic import BaseModel, Field, StrictInt, StrictStr
class Resolution(BaseModel): class Resolution(BaseModel):
""" """
Resolution Resolution
""" """
requester_name: Optional[StrictStr] = 'C1' requester_name: StrictStr = Field(...)
requester_did: Optional[StrictStr] = 'did:sov:test:1122' requester_did: StrictStr = Field(...)
resolved_did: Optional[StrictStr] = 'did:sov:test:1234' resolved_did: StrictStr = Field(...)
other: Optional[Dict[str, Any]] = None other: Dict[str, Any] = Field(...)
timestamp: datetime = Field(...) timestamp: datetime = Field(...)
id: StrictInt = Field(...) id: StrictInt = Field(...)
__properties = ["requester_name", "requester_did", "resolved_did", "other", "timestamp", "id"] __properties = ["requester_name", "requester_did", "resolved_did", "other", "timestamp", "id"]
@@ -69,9 +69,9 @@ class Resolution(BaseModel):
return Resolution.parse_obj(obj) return Resolution.parse_obj(obj)
_obj = Resolution.parse_obj({ _obj = Resolution.parse_obj({
"requester_name": obj.get("requester_name") if obj.get("requester_name") is not None else 'C1', "requester_name": obj.get("requester_name"),
"requester_did": obj.get("requester_did") if obj.get("requester_did") is not None else 'did:sov:test:1122', "requester_did": obj.get("requester_did"),
"resolved_did": obj.get("resolved_did") if obj.get("resolved_did") is not None else 'did:sov:test:1234', "resolved_did": obj.get("resolved_did"),
"other": obj.get("other"), "other": obj.get("other"),
"timestamp": obj.get("timestamp"), "timestamp": obj.get("timestamp"),
"id": obj.get("id") "id": obj.get("id")

View File

@@ -18,21 +18,23 @@ import re # noqa: F401
import json import json
from typing import Any, Dict, Optional from typing import Any, Dict
from pydantic import BaseModel, StrictStr from pydantic import BaseModel, Field, StrictStr
from openapi_client.models.entity import Entity
class Service(BaseModel): class Service(BaseModel):
""" """
Service Service
""" """
uuid: Optional[StrictStr] = '8e285c0c-4e40-430a-a477-26b3b81e30df' uuid: StrictStr = Field(...)
service_name: Optional[StrictStr] = 'Carlos Printing' service_name: StrictStr = Field(...)
service_type: Optional[StrictStr] = '3D Printing' service_type: StrictStr = Field(...)
endpoint_url: Optional[StrictStr] = 'http://127.0.0.1:8000' endpoint_url: StrictStr = Field(...)
status: Optional[StrictStr] = 'unknown' status: StrictStr = Field(...)
other: Optional[Dict[str, Any]] = None other: Dict[str, Any] = Field(...)
entity_did: Optional[StrictStr] = 'did:sov:test:1234' entity_did: StrictStr = Field(...)
__properties = ["uuid", "service_name", "service_type", "endpoint_url", "status", "other", "entity_did"] entity: Entity = Field(...)
__properties = ["uuid", "service_name", "service_type", "endpoint_url", "status", "other", "entity_did", "entity"]
class Config: class Config:
"""Pydantic configuration""" """Pydantic configuration"""
@@ -58,6 +60,9 @@ class Service(BaseModel):
exclude={ exclude={
}, },
exclude_none=True) exclude_none=True)
# override the default output from pydantic by calling `to_dict()` of entity
if self.entity:
_dict['entity'] = self.entity.to_dict()
return _dict return _dict
@classmethod @classmethod
@@ -70,13 +75,14 @@ class Service(BaseModel):
return Service.parse_obj(obj) return Service.parse_obj(obj)
_obj = Service.parse_obj({ _obj = Service.parse_obj({
"uuid": obj.get("uuid") if obj.get("uuid") is not None else '8e285c0c-4e40-430a-a477-26b3b81e30df', "uuid": obj.get("uuid"),
"service_name": obj.get("service_name") if obj.get("service_name") is not None else 'Carlos Printing', "service_name": obj.get("service_name"),
"service_type": obj.get("service_type") if obj.get("service_type") is not None else '3D Printing', "service_type": obj.get("service_type"),
"endpoint_url": obj.get("endpoint_url") if obj.get("endpoint_url") is not None else 'http://127.0.0.1:8000', "endpoint_url": obj.get("endpoint_url"),
"status": obj.get("status") if obj.get("status") is not None else 'unknown', "status": obj.get("status"),
"other": obj.get("other"), "other": obj.get("other"),
"entity_did": obj.get("entity_did") if obj.get("entity_did") is not None else 'did:sov:test:1234' "entity_did": obj.get("entity_did"),
"entity": Entity.from_dict(obj.get("entity")) if obj.get("entity") is not None else None
}) })
return _obj return _obj

View File

@@ -18,20 +18,20 @@ import re # noqa: F401
import json import json
from typing import Any, Dict, Optional from typing import Any, Dict
from pydantic import BaseModel, StrictStr from pydantic import BaseModel, Field, StrictStr
class ServiceCreate(BaseModel): class ServiceCreate(BaseModel):
""" """
ServiceCreate ServiceCreate
""" """
uuid: Optional[StrictStr] = '8e285c0c-4e40-430a-a477-26b3b81e30df' uuid: StrictStr = Field(...)
service_name: Optional[StrictStr] = 'Carlos Printing' service_name: StrictStr = Field(...)
service_type: Optional[StrictStr] = '3D Printing' service_type: StrictStr = Field(...)
endpoint_url: Optional[StrictStr] = 'http://127.0.0.1:8000' endpoint_url: StrictStr = Field(...)
status: Optional[StrictStr] = 'unknown' status: StrictStr = Field(...)
other: Optional[Dict[str, Any]] = None other: Dict[str, Any] = Field(...)
entity_did: Optional[StrictStr] = 'did:sov:test:1234' entity_did: StrictStr = Field(...)
__properties = ["uuid", "service_name", "service_type", "endpoint_url", "status", "other", "entity_did"] __properties = ["uuid", "service_name", "service_type", "endpoint_url", "status", "other", "entity_did"]
class Config: class Config:
@@ -70,13 +70,13 @@ class ServiceCreate(BaseModel):
return ServiceCreate.parse_obj(obj) return ServiceCreate.parse_obj(obj)
_obj = ServiceCreate.parse_obj({ _obj = ServiceCreate.parse_obj({
"uuid": obj.get("uuid") if obj.get("uuid") is not None else '8e285c0c-4e40-430a-a477-26b3b81e30df', "uuid": obj.get("uuid"),
"service_name": obj.get("service_name") if obj.get("service_name") is not None else 'Carlos Printing', "service_name": obj.get("service_name"),
"service_type": obj.get("service_type") if obj.get("service_type") is not None else '3D Printing', "service_type": obj.get("service_type"),
"endpoint_url": obj.get("endpoint_url") if obj.get("endpoint_url") is not None else 'http://127.0.0.1:8000', "endpoint_url": obj.get("endpoint_url"),
"status": obj.get("status") if obj.get("status") is not None else 'unknown', "status": obj.get("status"),
"other": obj.get("other"), "other": obj.get("other"),
"entity_did": obj.get("entity_did") if obj.get("entity_did") is not None else 'did:sov:test:1234' "entity_did": obj.get("entity_did")
}) })
return _obj return _obj

View File

@@ -26,10 +26,10 @@ class TestClientsApi(unittest.TestCase):
def tearDown(self) -> None: def tearDown(self) -> None:
pass pass
def test_get_all_clients(self) -> None: def test_get_clients_by_did(self) -> None:
"""Test case for get_all_clients """Test case for get_clients_by_did
Get All Clients # noqa: E501 Get Clients By Did # noqa: E501
""" """
pass pass

View File

@@ -75,6 +75,13 @@ class TestEntitiesApi(unittest.TestCase):
""" """
pass pass
def test_get_entity_by_name(self) -> None:
"""Test case for get_entity_by_name
Get Entity By Name # noqa: E501
"""
pass
if __name__ == '__main__': if __name__ == '__main__':
unittest.main() unittest.main()

View File

@@ -40,11 +40,16 @@ class TestEntity(unittest.TestCase):
name = 'C1', name = 'C1',
ip = '127.0.0.1', ip = '127.0.0.1',
visible = True, visible = True,
other = openapi_client.models.other.Other(), other = {network=Carlos Home Network, roles=[service repository, service prosumer]},
attached = True attached = True
) )
else: else:
return Entity( return Entity(
did = 'did:sov:test:1234',
name = 'C1',
ip = '127.0.0.1',
visible = True,
other = {network=Carlos Home Network, roles=[service repository, service prosumer]},
attached = True, attached = True,
) )
""" """

View File

@@ -40,10 +40,15 @@ class TestEntityCreate(unittest.TestCase):
name = 'C1', name = 'C1',
ip = '127.0.0.1', ip = '127.0.0.1',
visible = True, visible = True,
other = openapi_client.models.other.Other() other = {network=Carlos Home Network, roles=[service repository, service prosumer]}
) )
else: else:
return EntityCreate( return EntityCreate(
did = 'did:sov:test:1234',
name = 'C1',
ip = '127.0.0.1',
visible = True,
other = {network=Carlos Home Network, roles=[service repository, service prosumer]},
) )
""" """

View File

@@ -39,12 +39,16 @@ class TestResolution(unittest.TestCase):
requester_name = 'C1', requester_name = 'C1',
requester_did = 'did:sov:test:1122', requester_did = 'did:sov:test:1122',
resolved_did = 'did:sov:test:1234', resolved_did = 'did:sov:test:1234',
other = openapi_client.models.other.Other(), other = {test=test},
timestamp = datetime.datetime.strptime('2013-10-20 19:20:30.00', '%Y-%m-%d %H:%M:%S.%f'), timestamp = datetime.datetime.strptime('2013-10-20 19:20:30.00', '%Y-%m-%d %H:%M:%S.%f'),
id = 56 id = 56
) )
else: else:
return Resolution( return Resolution(
requester_name = 'C1',
requester_did = 'did:sov:test:1122',
resolved_did = 'did:sov:test:1234',
other = {test=test},
timestamp = datetime.datetime.strptime('2013-10-20 19:20:30.00', '%Y-%m-%d %H:%M:%S.%f'), timestamp = datetime.datetime.strptime('2013-10-20 19:20:30.00', '%Y-%m-%d %H:%M:%S.%f'),
id = 56, id = 56,
) )

View File

@@ -41,11 +41,32 @@ class TestService(unittest.TestCase):
service_type = '3D Printing', service_type = '3D Printing',
endpoint_url = 'http://127.0.0.1:8000', endpoint_url = 'http://127.0.0.1:8000',
status = 'unknown', status = 'unknown',
other = openapi_client.models.other.Other(), other = {action=[register, deregister, delete, create]},
entity_did = 'did:sov:test:1234' entity_did = 'did:sov:test:1234',
entity = openapi_client.models.entity.Entity(
did = 'did:sov:test:1234',
name = 'C1',
ip = '127.0.0.1',
visible = True,
other = {network=Carlos Home Network, roles=[service repository, service prosumer]},
attached = True, )
) )
else: else:
return Service( return Service(
uuid = '8e285c0c-4e40-430a-a477-26b3b81e30df',
service_name = 'Carlos Printing',
service_type = '3D Printing',
endpoint_url = 'http://127.0.0.1:8000',
status = 'unknown',
other = {action=[register, deregister, delete, create]},
entity_did = 'did:sov:test:1234',
entity = openapi_client.models.entity.Entity(
did = 'did:sov:test:1234',
name = 'C1',
ip = '127.0.0.1',
visible = True,
other = {network=Carlos Home Network, roles=[service repository, service prosumer]},
attached = True, ),
) )
""" """

View File

@@ -41,11 +41,18 @@ class TestServiceCreate(unittest.TestCase):
service_type = '3D Printing', service_type = '3D Printing',
endpoint_url = 'http://127.0.0.1:8000', endpoint_url = 'http://127.0.0.1:8000',
status = 'unknown', status = 'unknown',
other = openapi_client.models.other.Other(), other = {action=[register, deregister, delete, create]},
entity_did = 'did:sov:test:1234' entity_did = 'did:sov:test:1234'
) )
else: else:
return ServiceCreate( return ServiceCreate(
uuid = '8e285c0c-4e40-430a-a477-26b3b81e30df',
service_name = 'Carlos Printing',
service_type = '3D Printing',
endpoint_url = 'http://127.0.0.1:8000',
status = 'unknown',
other = {action=[register, deregister, delete, create]},
entity_did = 'did:sov:test:1234',
) )
""" """

View File

@@ -1,16 +1,81 @@
from openapi_client import ApiClient from openapi_client import ApiClient
from openapi_client.api import default_api from openapi_client.api import DefaultApi
from openapi_client.models import Machine, Status from openapi_client.api.entities_api import EntitiesApi
from openapi_client.api.services_api import ServicesApi
from openapi_client.models import (
Entity,
EntityCreate,
Machine,
ServiceCreate,
Status,
)
default_entity_did_url = "entity_did=did%3Asov%3Atest%3A1234" uuids = [
default_entity_did = "did:sov:test:1234" "e95bb72f-b1b3-4452-8065-c7acf09068fc",
default_entity_did2 = "did:sov:test:1235" "411d772e-1ad0-4d99-8da0-133ab2972322",
default_entity_did3 = "did:sov:test:1236" "8cfdf359-c3b9-4951-9e51-08dce797725a",
default_entity_did4 = "did:sov:test:1237" "24b5b4de-9f5f-4e60-878e-cc5be085fd0d",
default_entity_did5 = "did:sov:test:1238" "d45f9687-c413-43b9-8e0d-cb610b39fcaf",
"083e09a0-1d71-4819-83e2-ce2a6d831713",
"e6f74e55-c163-4368-98c0-a2b04c99d6e3",
"1b577ba7-c9dd-4e66-b695-9350e9db0b6c",
"bfd9e653-98a4-4451-9d97-bcc2908f213d",
"0e481624-b886-437c-89a0-b9e73651cc72",
]
def test_health(api_client: ApiClient) -> None: def test_health(api_client: ApiClient) -> None:
default = default_api.DefaultApi(api_client=api_client) default = DefaultApi(api_client=api_client)
res: Machine = default.health() res: Machine = default.health()
assert res.status == Status.ONLINE assert res.status == Status.ONLINE
def test_entities_empty(api_client: ApiClient) -> None:
entity = EntitiesApi(api_client=api_client)
res = entity.get_all_entities()
assert res == []
def create_entities(num: int = 10) -> list[EntityCreate]:
res = []
for i in range(num):
en = EntityCreate(
did=f"did:sov:test:12{i}",
name=f"C{i}",
ip=f"127.0.0.1:{7000+i}",
visible=True,
other={},
)
res.append(en)
return res
def create_service(idx: int, entity: Entity) -> ServiceCreate:
se = ServiceCreate(
uuid=uuids[idx],
service_name=f"Carlos Printing{idx}",
service_type="3D Printing",
endpoint_url=f"{entity.ip}/v1/print_daemon{idx}",
status="unknown",
other={"action": ["register", "deregister", "delete", "create"]},
entity_did=entity.did,
)
return se
def test_create_entities(api_client: ApiClient) -> None:
api = EntitiesApi(api_client=api_client)
for own_entity in create_entities():
res: Entity = api.create_entity(own_entity)
assert res.did == own_entity.did
assert res.attached is False
def test_create_services(api_client: ApiClient) -> None:
sapi = ServicesApi(api_client=api_client)
eapi = EntitiesApi(api_client=api_client)
for idx, entity in enumerate(eapi.get_all_entities()):
service_obj = create_service(idx, entity)
service = sapi.create_service(service_obj)
assert service.uuid == service_obj.uuid

View File

@@ -20,13 +20,13 @@ pkgs.mkShell {
fi fi
ln -sf ${pkgs.roboto}/share/fonts ./src ln -sf ${pkgs.roboto}/share/fonts ./src
export PATH="$PATH:$(realpath ./node_modules)/.bin" export PATH="$PATH:$(realpath ./node_modules)/.bin"
# re-generate the api code # re-generate the api code
rm -rf src/api openapi.json rm -rf src/api openapi.json
cp ${clanPkgs.clan-openapi}/openapi.json . cp ${clanPkgs.clan-openapi}/openapi.json .
orval orval
''; '';
} }

View File

@@ -2,7 +2,7 @@
import { mutate } from "swr"; import { mutate } from "swr";
import { useGetAttachedEntities } from "@/api/entities/entities"; import { useGetAttachedEntities } from "@/api/entities/entities";
import { useGetRepositories } from "@/api/repositories/repositories"; import { useGetAllRepositories } from "@/api/repositories/repositories";
import SummaryDetails from "@/components/summary_card"; import SummaryDetails from "@/components/summary_card";
import CustomTable from "@/components/table"; import CustomTable from "@/components/table";
import { import {
@@ -22,7 +22,7 @@ export default function AccessPoint() {
data: APRepositories, data: APRepositories,
isLoading: laodingRepositories, isLoading: laodingRepositories,
swrKey: repositoriesKeyFunc, swrKey: repositoriesKeyFunc,
} = useGetRepositories(); } = useGetAllRepositories();
const onRefresh = () => { const onRefresh = () => {
const attachedEntitiesKey = const attachedEntitiesKey =

View File

@@ -1,168 +0,0 @@
"use client";
import { useEffect, useRef, useState } from "react";
import {
Client1ConsumerTableConfig,
Client1ProducerTableConfig,
} from "@/config/client_1";
import CustomTable from "@/components/table";
import useGetEntityByName from "@/components/hooks/useGetEntityById";
import {
Alert,
Button,
Card,
CardContent,
CardHeader,
Skeleton,
Snackbar,
Typography,
} from "@mui/material";
import CopyToClipboard from "@/components/copy_to_clipboard";
import { mutate } from "swr";
import { useGetEntity } from "@/api/entities/entities";
import { BASE_URL } from "@/constants";
import axios from "axios";
export default function Client1() {
const { entity } = useGetEntityByName("C1");
const {
data: client1,
isLoading,
swrKey: entityKeyFunc,
} = useGetEntity({ entity_did: entity?.did });
const cardContentRef = useRef(null);
const [isAttached, setIsAttached] = useState(entity?.attached || false);
const [snackbarOpen, setSnackbarOpen] = useState(false);
const [snackbarMessage, setSnackbarMessage] = useState("");
const closeSnackBar = () => {
setSnackbarMessage("");
setSnackbarOpen(false);
};
const onAttachEntity = async () => {
try {
const response = await axios.post(`${BASE_URL}/attach`, {
entity_did: entity?.did,
});
setSnackbarMessage(response.data.message);
setSnackbarOpen(true);
} catch (error) {
console.error(error);
} finally {
setIsAttached(true);
}
};
const onDetachEntity = async () => {
try {
const response = await axios.post(`${BASE_URL}/detach`, {
entity_did: entity?.did,
});
console.log(response);
setSnackbarMessage("Entity detached successfully.");
setSnackbarOpen(true);
} catch (error) {
console.error(error);
} finally {
setIsAttached(false);
}
};
const onRefresh = () => {
const entityKey =
typeof entityKeyFunc === "function" ? entityKeyFunc() : entityKeyFunc;
if (entityKey) mutate(entityKey);
};
useEffect(() => {
const interval = setInterval(() => {
onRefresh();
}, 1000);
return () => clearInterval(interval);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
if (isLoading) return <Skeleton height={500} />;
return (
<div className="m-10">
<div
style={{
display: "flex",
alignItems: "center",
justifyContent: "space-between",
}}
>
<h2>Client 1</h2>
<div>
{isAttached === false ? (
<Button
onClick={onAttachEntity}
className="mr-6"
variant="contained"
>
Attach
</Button>
) : (
<Button
onClick={onDetachEntity}
className="mr-6"
variant="contained"
>
Detach
</Button>
)}
<Button onClick={onRefresh} variant="contained">
Refresh
</Button>
</div>
</div>
<Card variant="outlined">
<CardHeader
subheader="Summary"
action={<CopyToClipboard contentRef={cardContentRef} />}
/>
<CardContent ref={cardContentRef}>
<Typography color="text.primary" gutterBottom>
DID: <code>{client1?.data?.did}</code>
</Typography>
<Typography color="text.primary" gutterBottom>
IP: <code>{client1?.data?.ip}</code>
</Typography>
<Typography color="text.primary" gutterBottom>
Network: <code>{client1?.data?.other?.network}</code>
</Typography>
</CardContent>
</Card>
<div>
<h4>Consumer View</h4>
<CustomTable
loading={isLoading}
data={client1?.data?.producers}
configuration={Client1ConsumerTableConfig}
/>
</div>
<div>
<h4>Producer View</h4>
<CustomTable
loading={isLoading}
data={client1?.data?.producers}
configuration={Client1ProducerTableConfig}
/>
</div>
<Snackbar
onClose={closeSnackBar}
anchorOrigin={{ vertical: "top", horizontal: "center" }}
open={snackbarOpen}
autoHideDuration={1000}
>
<Alert severity="success" sx={{ width: "100%" }}>
{snackbarMessage}
</Alert>
</Snackbar>
</div>
);
}

View File

@@ -1,70 +1,50 @@
"use client"; "use client";
import { useEffect, useRef, useState } from "react"; import { useEffect, useMemo, useRef, useState } from "react";
import { import {
Client2ConsumerTableConfig, ClientTableConfig,
Client2ProducerTableConfig, ServiceTableConfig,
} from "@/config/client_2"; } from "@/config/client_1";
import CustomTable from "@/components/table"; import CustomTable from "@/components/table";
import useGetEntityByName from "@/components/hooks/useGetEntityById";
import { import {
Alert,
Button, Button,
Card, Card,
CardContent, CardContent,
CardHeader, CardHeader,
Skeleton,
Typography,
Snackbar, Snackbar,
Alert, Typography,
} from "@mui/material"; } from "@mui/material";
import CopyToClipboard from "@/components/copy_to_clipboard"; import CopyToClipboard from "@/components/copy_to_clipboard";
import { useGetEntity } from "@/api/entities/entities"; import { useGetServicesByName } from "@/api/services/services";
import { attachEntity, detachEntity } from "@/api/entities/entities";
import { mutate } from "swr"; import { mutate } from "swr";
import axios from "axios"; import { Skeleton } from "@mui/material";
import { BASE_URL } from "@/constants"; import { Service } from "@/api/model";
export default function Client({
params,
}: {
params: { client_name: string };
}) {
const { client_name } = params;
export default function Client2() {
const { entity } = useGetEntityByName("C2");
const { const {
data: client2, data: services,
isLoading, isLoading: services_loading,
swrKey: entityKeyFunc, swrKey: entityKeyFunc,
} = useGetEntity({ entity_did: entity?.did }); } = useGetServicesByName({
const cardContentRef = useRef(null); entity_name: client_name,
const [isAttached, setIsAttached] = useState(entity?.attached); });
const [snackbarOpen, setSnackbarOpen] = useState(false);
const [snackbarMessage, setSnackbarMessage] = useState("");
const closeSnackBar = () => { const entity = services?.data?.entity;
setSnackbarMessage(""); const clients: Service[] = useMemo(() => {
setSnackbarOpen(false); if (services?.data?.services) {
}; return services.data.services.filter((service) => {
if (service.entity_did !== entity?.did) return true;
const onAttachEntity = async () => {
try {
const response = await axios.post(`${BASE_URL}/attach`, {
entity_did: entity?.did,
}); });
alert(response.data.message);
} catch (error) {
console.error(error);
} finally {
setIsAttached(true);
} }
}; return [];
}, [services]);
const onDetachEntity = async () => {
try {
const response = await axios.post(`${BASE_URL}/detach`, {
entity_did: entity?.did,
});
console.log("detach", response);
alert("Entity Detached Successfully.");
} catch (error) {
console.error(error);
} finally {
setIsAttached(false);
}
};
const onRefresh = () => { const onRefresh = () => {
const entityKey = const entityKey =
@@ -81,7 +61,51 @@ export default function Client2() {
// eslint-disable-next-line react-hooks/exhaustive-deps // eslint-disable-next-line react-hooks/exhaustive-deps
}, []); }, []);
if (isLoading) return <Skeleton height={500} />; const cardContentRef = useRef(null);
const [snackbarOpen, setSnackbarOpen] = useState(false);
const [snackbarMessage, setSnackbarMessage] = useState("");
const [isAttached, setIsAttached] = useState(entity?.attached);
const closeSnackBar = () => {
setSnackbarMessage("");
setSnackbarOpen(false);
};
const onAttachEntity = async () => {
try {
if (entity) {
const response = await attachEntity(entity.did);
setSnackbarMessage(response.data.message);
setSnackbarOpen(true);
} else {
console.error("no entity");
}
} catch (error) {
console.error(error);
} finally {
setIsAttached(true);
}
};
const onDetachEntity = async () => {
try {
if (entity) {
const response = await detachEntity(entity.did);
console.log(response);
setSnackbarMessage("Entity detached successfully.");
setSnackbarOpen(true);
} else {
console.error("no entity");
}
} catch (error) {
console.error(error);
} finally {
setIsAttached(false);
}
};
if (services_loading) return <Skeleton height={500} />;
if (!services) return <Alert severity="error">Client not found</Alert>;
return ( return (
<div className="m-10"> <div className="m-10">
@@ -92,7 +116,7 @@ export default function Client2() {
justifyContent: "space-between", justifyContent: "space-between",
}} }}
> >
<h2>Client 2</h2> <h2>Client 1</h2>
<div> <div>
{isAttached === false ? ( {isAttached === false ? (
<Button <Button
@@ -111,6 +135,7 @@ export default function Client2() {
Detach Detach
</Button> </Button>
)} )}
<Button onClick={onRefresh} variant="contained"> <Button onClick={onRefresh} variant="contained">
Refresh Refresh
</Button> </Button>
@@ -124,30 +149,32 @@ export default function Client2() {
/> />
<CardContent ref={cardContentRef}> <CardContent ref={cardContentRef}>
<Typography color="text.primary" gutterBottom> <Typography color="text.primary" gutterBottom>
DID: <code>{client2?.data?.did}</code> DID: <code>{entity?.did}</code>
</Typography> </Typography>
<Typography color="text.primary" gutterBottom> <Typography color="text.primary" gutterBottom>
IP: <code>{client2?.data?.ip}</code> IP: <code>{entity?.ip}</code>
</Typography> </Typography>
<Typography color="text.primary" gutterBottom> <Typography color="text.primary" gutterBottom>
Network: <code>{client2?.data?.other?.network}</code> Network: <code>{entity?.other?.network}</code>
</Typography> </Typography>
</CardContent> </CardContent>
</Card> </Card>
<div> <div>
<h4>Consumer View</h4> <h4>Client View</h4>
<CustomTable <CustomTable
loading={isLoading} loading={services_loading}
data={client2?.data?.producers} data={clients}
configuration={Client2ConsumerTableConfig} configuration={ClientTableConfig}
key="client-table"
/> />
</div> </div>
<div> <div>
<h4>Producer View</h4> <h4>Service View</h4>
<CustomTable <CustomTable
loading={isLoading} loading={services_loading}
data={client2?.data?.producers} data={services?.data?.services}
configuration={Client2ProducerTableConfig} configuration={ServiceTableConfig}
key="service-table"
/> />
</div> </div>
<Snackbar <Snackbar

View File

@@ -1,4 +1,4 @@
import { useGetEntities } from "@/api/entities/entities"; import { useGetAllEntities } from "@/api/entities/entities";
import { Entity } from "@/api/model"; import { Entity } from "@/api/model";
import { AxiosError } from "axios"; import { AxiosError } from "axios";
import React, { import React, {
@@ -33,7 +33,7 @@ interface AppContextProviderProps {
export const WithAppState = (props: AppContextProviderProps) => { export const WithAppState = (props: AppContextProviderProps) => {
const { children } = props; const { children } = props;
const { data: entityData, swrKey: entitiesKeyFunc } = useGetEntities(); const { data: entityData, swrKey: entitiesKeyFunc } = useGetAllEntities();
const isLoading = false; const isLoading = false;
const error = undefined; const error = undefined;

View File

@@ -35,13 +35,13 @@ const menuEntityEntries: MenuEntry[] = [
{ {
icon: <PersonIcon />, icon: <PersonIcon />,
label: "C1", label: "C1",
to: "/client-1", to: "/client/C1",
disabled: false, disabled: false,
}, },
{ {
icon: <PersonIcon />, icon: <PersonIcon />,
label: "C2", label: "C2",
to: "/client-2", to: "/client/C2",
disabled: false, disabled: false,
}, },
]; ];

View File

@@ -11,7 +11,7 @@ import { StyledTableCell, StyledTableRow } from "./style";
import { ICustomTable, CustomTableConfiguration } from "@/types"; import { ICustomTable, CustomTableConfiguration } from "@/types";
import { Checkbox, Skeleton } from "@mui/material"; import { Checkbox, Skeleton } from "@mui/material";
const CustomTable = ({ configuration, data, loading }: ICustomTable) => { const CustomTable = ({ configuration, data, loading, key }: ICustomTable) => {
if (loading) if (loading)
return <Skeleton variant="rectangular" animation="wave" height={200} />; return <Skeleton variant="rectangular" animation="wave" height={200} />;
@@ -25,7 +25,7 @@ const CustomTable = ({ configuration, data, loading }: ICustomTable) => {
render?: (param: any) => void | undefined, render?: (param: any) => void | undefined,
) => { ) => {
let renderedValue = value; let renderedValue = value;
console.log(cellKey)
// cover use case if the data is an array // cover use case if the data is an array
if (Array.isArray(value)) renderedValue = value.join(", "); if (Array.isArray(value)) renderedValue = value.join(", ");
@@ -56,11 +56,11 @@ const CustomTable = ({ configuration, data, loading }: ICustomTable) => {
<TableBody> <TableBody>
{data.map((data: any, rowIndex: number) => ( {data.map((data: any, rowIndex: number) => (
<StyledTableRow key={rowIndex}> <StyledTableRow key={rowIndex}>
{configuration.map((column: CustomTableConfiguration) => { {configuration.map((column: CustomTableConfiguration, columnIndex: number) => {
const cellValue: any = data[column.key]; const cellValue: any = data[column.key];
const cellKey = column.key; const cellKey = key + ":" + column.key + ":" + rowIndex;
const renderComponent = column?.render; const renderComponent = column?.render;
return renderTableCell(cellValue, cellKey, renderComponent); return renderTableCell(cellValue, cellKey + ":" + columnIndex, renderComponent);
})} })}
</StyledTableRow> </StyledTableRow>
))} ))}

View File

@@ -1,6 +1,6 @@
import { Button } from "@mui/material"; import { Button } from "@mui/material";
export const Client1ConsumerTableConfig = [ export const ClientTableConfig = [
{ {
key: "service_name", key: "service_name",
label: "Service name", label: "Service name",
@@ -34,7 +34,7 @@ export const Client1ConsumerTableConfig = [
// }, // },
]; ];
export const Client1ProducerTableConfig = [ export const ServiceTableConfig = [
{ {
key: "service_name", key: "service_name",
label: "Service name", label: "Service name",

View File

@@ -8,7 +8,7 @@ export const HomeTableConfig = [
label: "Entity DID", label: "Entity DID",
}, },
{ {
key: "other", key: "network",
label: "Network", label: "Network",
render: (value: any) => { render: (value: any) => {
const renderedValue = typeof value === "object" ? value?.network : "-"; const renderedValue = typeof value === "object" ? value?.network : "-";
@@ -20,7 +20,7 @@ export const HomeTableConfig = [
label: "IP address", label: "IP address",
}, },
{ {
key: "other", key: "roles",
label: "Roles", label: "Roles",
render: (value: any) => { render: (value: any) => {
const renderedValue = const renderedValue =

View File

@@ -8,6 +8,7 @@ export interface ICustomTable {
configuration: CustomTableConfiguration[]; configuration: CustomTableConfiguration[];
data: any; data: any;
loading?: boolean; loading?: boolean;
key: string;
} }
export interface EntityDetails { export interface EntityDetails {