diff --git a/server/src/uds/REST/documentation.py b/server/src/uds/REST/documentation.py index e879de01d..af7d49114 100644 --- a/server/src/uds/REST/documentation.py +++ b/server/src/uds/REST/documentation.py @@ -52,8 +52,10 @@ logger = logging.getLogger(__name__) @dataclasses.dataclass class HelpMethodInfo: + method: str text: str + methods: list[types.rest.HelpNode.Methods] def __str__(self) -> str: return f'{self.method}: {self.text}' @@ -63,27 +65,69 @@ class HelpMethodInfo: class HelpMethod(enum.Enum): - ITEM = HelpMethodInfo('', 'Retrieves an item by its UUID') - LOG = HelpMethodInfo(f'/{consts.rest.LOG}', 'Retrieves the log of an item') - OVERVIEW = HelpMethodInfo(consts.rest.OVERVIEW, 'General Overview of all items (a list') - TABLEINFO = HelpMethodInfo(consts.rest.TABLEINFO, 'Table visualization information (types, etc..)') - TYPES = HelpMethodInfo(consts.rest.TYPES, 'Retrieves a list of types available') - TYPES_TYPE = HelpMethodInfo(f'{consts.rest.TYPES}/', 'Retrieves a type information') - GUI = HelpMethodInfo(consts.rest.GUI, 'GUI information') - GUI_TYPES = HelpMethodInfo(f'{consts.rest.GUI}/', 'GUI Types information') + ITEM = HelpMethodInfo( + '', + 'Retrieves an item by its UUID', + [ + types.rest.HelpNode.Methods.GET, + types.rest.HelpNode.Methods.PUT, + types.rest.HelpNode.Methods.DELETE, + ], + ) + LOG = HelpMethodInfo( + f'/{consts.rest.LOG}', + 'Retrieves the logs of an element by its UUID', + [ + types.rest.HelpNode.Methods.GET, + ], + ) + OVERVIEW = HelpMethodInfo( + consts.rest.OVERVIEW, 'General Overview of all items (a list', [types.rest.HelpNode.Methods.GET] + ) + TABLEINFO = HelpMethodInfo( + consts.rest.TABLEINFO, + 'Table visualization information (types, etc..)', + [ + types.rest.HelpNode.Methods.GET, + ], + ) + TYPES = HelpMethodInfo( + consts.rest.TYPES, + 'Retrieves a list of types available', + [ + types.rest.HelpNode.Methods.GET, + ], + ) + TYPES_TYPE = HelpMethodInfo( + f'{consts.rest.TYPES}/', + 'Retrieves a type information', + [ + types.rest.HelpNode.Methods.GET, + ], + ) + GUI = HelpMethodInfo(consts.rest.GUI, 'GUI information', [types.rest.HelpNode.Methods.GET]) + GUI_TYPES = HelpMethodInfo( + f'{consts.rest.GUI}/', 'GUI Types information', [types.rest.HelpNode.Methods.GET] + ) -@dataclasses.dataclass +@dataclasses.dataclass(frozen=True) class HelpInfo: - level: int path: str text: str - methods: list[HelpMethod] + method: types.rest.HelpNode.Methods = types.rest.HelpNode.Methods.GET @property def is_empty(self) -> bool: return not self.path + def as_dict(self) -> dict[str, str]: + return { + 'path': self.path, + 'text': self.text, + 'method': self.method.value, + } + class Documentation(View): @@ -99,48 +143,36 @@ class Documentation(View): help_data: list[HelpInfo] = [] - def _process_node(node: 'types.rest.HelpNode', path: str, level: int) -> None: - if node.kind == types.rest.HelpNode.HelpNodeType.MODEL: - methods = [ - HelpMethod.OVERVIEW, - HelpMethod.GUI, - HelpMethod.GUI_TYPES, - HelpMethod.TYPES, - HelpMethod.TYPES_TYPE, - HelpMethod.TABLEINFO, - HelpMethod.ITEM, - HelpMethod.LOG, - ] - elif node.kind == types.rest.HelpNode.HelpNodeType.DETAIL: - methods = [ - HelpMethod.OVERVIEW, - HelpMethod.GUI, - HelpMethod.GUI_TYPES, - HelpMethod.TYPES, - HelpMethod.TYPES_TYPE, - HelpMethod.TABLEINFO, - HelpMethod.ITEM, - HelpMethod.LOG, - ] - else: - methods = [] - - if node.kind != types.rest.HelpNode.HelpNodeType.PATH: - help_data.append(HelpInfo(level, path, node.help.text, methods)) + def _process_node(node: 'types.rest.HelpNode', path: str) -> None: + match node.kind: + case types.rest.HelpNode.Type.PATH: + pass + case types.rest.HelpNode.Type.MODEL | types.rest.HelpNode.Type.DETAIL: + for func in [ + HelpMethod.OVERVIEW, + HelpMethod.GUI, + HelpMethod.GUI_TYPES, + HelpMethod.TYPES, + HelpMethod.TYPES_TYPE, + HelpMethod.TABLEINFO, + HelpMethod.ITEM, + HelpMethod.LOG, + ]: + for method in func.value.methods: + help_data.append(HelpInfo(f'{path}/{func.value.method}', func.value.text, method)) + case _: + for method in node.methods: + help_data.append(HelpInfo(path, node.help.text, method)) for child in node.children: - _process_node( - child, - child.help.path, - level + (0 if node.kind == types.rest.HelpNode.HelpNodeType.PATH else 1), - ) + _process_node(child, child.help.path) - _process_node(Dispatcher.base_handler_node.help_node(), '', 0) + _process_node(Dispatcher.base_handler_node.help_node(), '') response = render( request=request, template_name='uds/modern/documentation.html', - context={'help': [h for h in help_data if not h.is_empty]}, + context={'help': [h.as_dict() for h in help_data]}, ) return response diff --git a/server/src/uds/core/types/rest.py b/server/src/uds/core/types/rest.py index c20b50485..f2542748d 100644 --- a/server/src/uds/core/types/rest.py +++ b/server/src/uds/core/types/rest.py @@ -159,22 +159,30 @@ class HelpPath: @dataclasses.dataclass(frozen=True) class HelpNode: - class HelpNodeType(enum.StrEnum): + class Type(enum.StrEnum): MODEL = 'model' DETAIL = 'detail' CUSTOM = 'custom' PATH = 'path' + + class Methods(enum.StrEnum): + GET = 'GET' + POST = 'POST' + PUT = 'PUT' + DELETE = 'DELETE' + PATCH = 'PATCH' help: HelpPath children: list['HelpNode'] # Children nodes - kind: HelpNodeType + kind: Type + methods: set[Methods] = dataclasses.field(default_factory=lambda: {HelpNode.Methods.GET}) def __hash__(self) -> int: - return hash(self.help.path) + return hash(self.help.path + ''.join(method for method in self.methods)) def __eq__(self, other: object) -> bool: if isinstance(other, HelpNode): - return self.help.path == other.help.path + return self.help.path == other.help.path and self.methods == other.methods if not isinstance(other, HelpPath): return False @@ -237,12 +245,12 @@ class HandlerNode: custom_help: set[HelpNode] = set() - help_node_type = HelpNode.HelpNodeType.PATH + help_node_type = HelpNode.Type.PATH if self.handler: - help_node_type = HelpNode.HelpNodeType.CUSTOM + help_node_type = HelpNode.Type.CUSTOM if issubclass(self.handler, ModelHandler): - help_node_type = HelpNode.HelpNodeType.MODEL + help_node_type = HelpNode.Type.MODEL # Add custom_methods for method in self.handler.custom_methods: # Method is a Me CustomModelMethod, @@ -252,7 +260,7 @@ class HandlerNode: HelpNode( HelpPath(path=self.full_path() + '/' + method.name, help=doc), [], - HelpNode.HelpNodeType.CUSTOM, + HelpNode.Type.CUSTOM, ) ) @@ -263,7 +271,7 @@ class HandlerNode: HelpNode( HelpPath(path=self.full_path() + '/' + method_name, help=''), [], - HelpNode.HelpNodeType.DETAIL, + HelpNode.Type.DETAIL, ) ) # Add custom_methods @@ -282,7 +290,7 @@ class HandlerNode: help=doc, ), [], - HelpNode.HelpNodeType.CUSTOM, + HelpNode.Type.CUSTOM, ) ) diff --git a/server/src/uds/templates/uds/modern/documentation.html b/server/src/uds/templates/uds/modern/documentation.html index f750b90f9..e73a29030 100644 --- a/server/src/uds/templates/uds/modern/documentation.html +++ b/server/src/uds/templates/uds/modern/documentation.html @@ -43,15 +43,7 @@ {% for h in help %}
{{ h }}
- {% if h.methods %} -
- {% for m in h.methods %} -
{{ h.path }}/{{ m.value.method }} : {{ m.value.text }}
- {% endfor %} -
- {% else %} -
{{ h.path }} : {{ h.text }}
- {% endif %} +
{{ h.path }} : {{ h.text }} {{ h.method }}
{% endfor %}