I would like to share routes that are already linked via tags via the "selected server".
{
"openapi": "3.1.0",
"info": {
"title": "blue_traktor_api",
"description": "This API handles various functionalities for USEPI, Icons, Dashboard, Settings, Patterns, Devices, Widgets, and more.",
"version": "0.1.0",
"contact": {
"name": "API Support",
"url": "",
"email": ""
}
},
"servers": [
{
"url": "http://localhost:8000",
"description": "TCP server for main operations"
},
{
"url": "ws://localhost:8080",
"description": "WebSocket server for updated parameters"
}
],
"paths": {...},
"components":{...}
}
here is the first part of my openal file.json where I list servers. it will look like this:
and I also have several routes for example:
"paths": {
"/api/usepi/patterns/create": {
"post": {
"tags": ["patterns"],
"summary": "Create a new pattern",
"operationId": "createPattern",
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/RequestStructure_PatternRequest"
},
"examples": {
"PatternExample": {
"summary": "An example of a PatternRequest",
"value": {
"data": {
"id": null,
"title": "test",
"description": "test desc",
"icon": "http://localhost:8000/api/icons/test.svg",
"createDate": null,
"updateDate": null,
"favourite": false,
"data": {
"ID": {},
"QR-Code": {},
"Position": {},
"DeviceParams": {}
}
}
}
}
}
}
}
},
"responses": {
"200": {
"description": "Pattern created.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/GoodResponse_Id"
}
}
}
},
"500": {
"description": "Internal Server Error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ErrorResponse"
}
}
}
}
}
}
}, ...
}
and there are still such routes, but with a different tag:
"/api/widgets/get": {
"post": {
"tags": ["widgets"],
"summary": "Get widget details",
"operationId": "getWidget",
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/RequestStructure_Id"
}
}
}
},
"responses": {
"200": {
"description": "Widget details.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/GoodResponse_GetWidgetResponse"
}
}
}
},
"500": {
"description": "Internal Server Error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ErrorResponse"
}
}
}
}
}
}
},
I would like that when selecting a server, only the routes associated with it are shown. for example, if http://localhost:8000 then /api/usepi/patterns/create ...
where I need to, I also got rid of the try it button and the parameter block in this way:
<script>
window.onload = function() {
const ui = SwaggerUIBundle({
url: "http://localhost:8000/openai.json",
dom_id: '#swagger-ui',
deepLinking: true,
presets: [
SwaggerUIBundle.presets.apis,
SwaggerUIStandalonePreset
],
plugins: [
SwaggerUIBundle.plugins.DownloadUrl
],
layout: "StandaloneLayout"
});
window.ui = ui;
function hideTryItOutButtons() {
const pathsToDisable = [
'#operations-patterns-createPattern > div.no-margin > div > div.opblock-section > div.opblock-section-header > div.try-out > button',
'#operations-patterns-createPattern > div.no-margin > div > div.opblock-section > div.opblock-section-header',
'#operations-patterns-createPattern > div.no-margin > div > div.opblock-section > div.parameters-container', ];
pathsToDisable.forEach(selector => {
const button = document.querySelector(selector);
if (button) {
button.style.display = 'none';
}
});
}
const observer = new MutationObserver(hideTryItOutButtons);
observer.observe(document.getElementById('swagger-ui'), { childList: true, subtree: true });
hideTryItOutButtons();
};
</script>
This is what it looks like:
how can I make the display of only the necessary routes (like filter), if (as far as I remember) you can't do subtags for tags? show routes when selecting a server, also grouping by tags*
I solved this problem so that I didn't have to work on the error where, when hiding the list and switching to another option from the list of servers, the element disappears altogether.
"paths": {
"/api/usepi/patterns/create": {
"post": {
"tags": ["patterns"],
"summary": "http://localhost:8000",
"operationId": "createPattern",
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/RequestStructure_PatternRequest"
},
"examples": {
"PatternExample": {
"summary": "An example of a PatternRequest",
"value": {
"data": {
"id": null,
"title": "test",
"description": "test desc",
"icon": "http://localhost:8000/api/icons/Cтатическое оборудование/Статическое оборудование.svg",
"createDate": null,
"updateDate": null,
"favourite": false,
"data": {
"ID": {},
"QR-Code": {},
"Position": {},
"DeviceParams": {}
}
}
}
}
}
}
}
},
"responses": {
"200": {
"description": "Pattern created.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/GoodResponse_Id"
}
}
}
},
"500": {
"description": "Internal Server Error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ErrorResponse"
}
}
}
}
}
}
},
in the "summary" I write down a variant from the list to determine which element of the list the route belongs to. Next, I look for matches in the list when drawing and delete what does not match the selected list value:
here is how it is implemented:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Swagger UI</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/swagger-ui/5.10.3/swagger-ui.css" crossorigin="anonymous" referrerpolicy="no-referrer" />
<style>
body { background-color: #ffffff; font-family: Arial, sans-serif; }
</style>
</head>
<body>
<div id="swagger-ui"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/swagger-ui/5.10.3/swagger-ui-bundle.js" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/swagger-ui/5.10.3/swagger-ui-standalone-preset.js" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script>
window.onload = function() {
const ui = SwaggerUIBundle({
url: "http://localhost:8000/openai.json",
dom_id: '#swagger-ui',
deepLinking: true,
presets: [
SwaggerUIBundle.presets.apis,
SwaggerUIStandalonePreset
],
plugins: [
SwaggerUIBundle.plugins.DownloadUrl
],
layout: "StandaloneLayout"
});
window.ui = ui;
let isFiltering = false;
function filterElements() {
const selectElement = document.querySelector("#swagger-ui>section>div.swagger-ui>div:nth-child(2)>div.scheme-container>section>div>div>div>label>select");
if (selectElement) {
const selectedValue = selectElement.options[selectElement.selectedIndex].textContent.split(' - ')[0];
console.log("Selected value from dropdown:", selectedValue);
const parentCatalogs = document.querySelectorAll("#swagger-ui>section>div.swagger-ui>div:nth-child(2)>div:nth-child(4)>section>div>span> div > h3");
console.log("Parent catalogs found:", parentCatalogs.length);
parentCatalogs.forEach(parent => {
const parentElement = parent.closest('div.opblock-tag-section');
if (parentElement) {
let childVisible = false;
const childElements = parentElement.querySelectorAll("[id^='operations-']:not([id^='operations-tag'])");
childElements.forEach(childElement => {
const summaryControl = childElement.querySelector("button.opblock-summary-control > div > div");
if (summaryControl) {
const summaryText = summaryControl.textContent.trim();
if (summaryText === selectedValue) {
childElement.style.display = '';
childVisible = true;
console.log(`---/Child Element ID: ${childElement.id} = ${summaryText}`);
} else {
childElement.style.display = 'none';
console.log(`Hiding element with Child Element ID: ${childElement.id} as it does not match the selected value`);
}
} else {
console.log(`Summary control not found for child element: ${childElement.id}`);
}
const elementsToRemove = childElement.querySelectorAll('.opblock-summary-description');
elementsToRemove.forEach(element => {
element.style.display = "none";
});
if (childElement.querySelectorAll('.no-margin').length > 0) {
const opblock = childElement
setTimeout(() => {
const elementToClear = opblock.querySelectorAll('.opblock-summary-path')
elementToClear.forEach(el => {
const dataPath = el.getAttribute('data-path').split('/').at(-1)
try { opblock.querySelectorAll('.opblock-description-wrapper')[0].remove() } catch {}
if (dataPath !== 'list' && dataPath !== 'icons' && dataPath !== '{path}') {
opblock.querySelectorAll('.opblock-section-header')[0].remove()
}
})
}, 30)
}
});
if (isFiltering) {
if (!childVisible) {
parentElement.style.display = 'none';
console.log(`Hiding parent element as all child elements are hidden: ${parent.textContent}`);
} else {
parentElement.style.display = '';
}
}
} else {
console.log("Parent element not found for:", parent.textContent);
}
});
} else {
console.log("Select element not found.");
}
}
document.addEventListener('change', function(event) {
const selectElement = document.querySelector("#swagger-ui > section > div.swagger-ui > div:nth-child(2) > div.scheme-container > section > div > div > div > label > select");
if (event.target === selectElement) {
isFiltering = true;
filterElements();
isFiltering = false;
}
});
document.addEventListener('click', () => {
filterElements();
});
const observer = new MutationObserver(() => {
const selectElement = document.querySelector("#swagger-ui > section > div.swagger-ui > div:nth-child(2) > div.scheme-container > section > div > div > div > label > select");
if (selectElement) {
isFiltering = true;
filterElements();
isFiltering = false;
observer.disconnect();
}
});
observer.observe(document.querySelector('#swagger-ui'), { childList: true, subtree: true });
};
</script>
</body>
</html>
next question: The collapse is not displayed when the selected element is changed