Skip to content

Commit 44eb09e

Browse files
committed
Make it work for POST requests
1 parent ac60c44 commit 44eb09e

File tree

10 files changed

+483
-361
lines changed

10 files changed

+483
-361
lines changed

README.md

Lines changed: 0 additions & 98 deletions
This file was deleted.

_layouts/dynamic_template.hbs

100755100644
Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
<html>
2+
23
<head>
34
<title>{{title}}</title>
45
</head>
6+
57
<body>
68
<section>
79
<details>
@@ -10,7 +12,7 @@
1012
<p>
1113
<span class="method {{method}}">{{method}}</span>
1214
<span id="baseUrl">
13-
<span>{{baseUrl}}</span><span class="path">{{path}}</span>
15+
<span>{{baseUrl}}/</span><span class="path">{{path}}</span>
1416
</span>
1517
</p>
1618
<p class="title">{{apiTitle}}</p>
@@ -19,28 +21,36 @@
1921
<div id="detailItems">
2022
<p>{{description}}</p>
2123
<p class="title">Parameters</p>
24+
{{#if path}}
2225
<p class="subtitle">Path</p>
2326
<div id="pathDetails">
24-
<div class="pathName">{{paramName}}<span class="required">{{required}}</span></div>
27+
<div class="pathName">{{path}}</div>
2528
<div class="type">{{type}}</div>
2629
<div class="pathDescription">{{paramDescription}}</div>
2730
</div>
31+
{{/if}}
32+
{{#if requestBody}} <!-- Check if schema exists -->
2833
<p class="subtitle">Body</p>
29-
<div id="requestBody">
30-
<div class="pathName">{{paramName}}<span class="required">{{required}}</span></div>
31-
<div class="type">{{type}}</div>
32-
<div class="pathDescription">{{paramDescription}}</div>
33-
</div>
34+
<details id="requestBody">
35+
<summary>{{requestBody.type}}</summary>
36+
<div class="schema">
37+
{{#renderProperties requestBody.properties}}
38+
{{/renderProperties}}
39+
</div>
40+
</details>
41+
{{/if}} <!-- End check -->
3442
<p class="title">Responses</p>
3543
<!-- Looping through each response -->
3644
{{#each responses}}
3745
<div class="httpResponse">
3846
<div class="httpResponseContainer">
3947
<div class="httpStatus {{status}}">
4048
<svg class="circle-svg" viewBox="0 0 8 16" preserveAspectRatio="xMidYMid meet">
41-
<path class="circle-path" d="M0 8c0-2.2 1.8-4 4-4s4 1.8 4 4-1.8 4-4 4-4-1.8-4-4z"></path>
49+
<path class="circle-path" d="M0 8c0-2.2 1.8-4 4-4s4 1.8 4 4-1.8 4-4 4-4-1.8-4-4z">
50+
</path>
4251
</svg>
43-
{{httpCode}}: {{httpMessage}}</div>
52+
{{httpCode}}: {{httpMessage}}
53+
</div>
4454
<div class="statusDescription">{{statusDescription}}</div>
4555
</div>
4656
{{#if schema}} <!-- Check if schema exists -->
@@ -49,8 +59,8 @@
4959
<div class="schema">
5060
<p class="type">{{schema.type}}</p>
5161
<div>
52-
{{#renderProperties schema.properties}}
53-
{{/renderProperties}}
62+
{{#renderProperties schema.properties}}
63+
{{/renderProperties}}
5464
</div>
5565
</div>
5666
</details>
@@ -61,4 +71,5 @@
6171
</details>
6272
</section>
6373
</body>
74+
6475
</html>

assets/arrow.svg

100755100644
File mode changed.

assets/circle.svg

100755100644
File mode changed.

assets/js/formHandler.js

Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
// Function to parse the form data into a structured object
2+
function parseFormData(formData) {
3+
const data = {};
4+
5+
function setValue(obj, keys, value, isCheckbox = false) {
6+
for (let i = 0; i < keys.length; i++) {
7+
let key = keys[i];
8+
let isArrayIndex = key.match(/^\d+$/) !== null;
9+
10+
if (isArrayIndex) {
11+
key = parseInt(key); // Convert key to an integer for array access
12+
if (!Array.isArray(obj)) {
13+
obj = []; // Ensure the object is treated as an array
14+
}
15+
if (obj.length <= key) {
16+
obj[key] = {}; // Add a new object only if the index is at the end of the array
17+
}
18+
} else if (!obj[key]) {
19+
obj[key] = keys[i + 1] && keys[i + 1].match(/^\d+$/) ? [] : {};
20+
}
21+
22+
if (i === keys.length - 1) {
23+
obj[key] = isCheckbox ? value === "on" : value === "true" ? true : value === "false" ? false : value;
24+
} else {
25+
obj = obj[key];
26+
}
27+
}
28+
}
29+
30+
for (const [key, value] of formData.entries()) {
31+
const isCheckbox = key.endsWith("[required]"); // Assuming 'required' fields are checkboxes
32+
const keys = key.split(/[\[\].]+/).filter((k) => k);
33+
setValue(data, keys, value, isCheckbox);
34+
}
35+
36+
return data;
37+
}
38+
39+
document.addEventListener("DOMContentLoaded", function () {
40+
const form = document.getElementById("json-form");
41+
const responsesContainer = document.getElementById("responses-container");
42+
const addResponseButton = document.getElementById("add-response");
43+
const jsonOutput = document.getElementById("json-output");
44+
45+
// Function to add nested properties
46+
function addNestedProperties(container, type, namePrefix = "") {
47+
// Count only elements with the '.property' class
48+
const propertyDivs = container.querySelectorAll(".property");
49+
const propertyIndex = propertyDivs.length;
50+
51+
const fieldset = document.createElement("fieldset");
52+
fieldset.className = "property"; // Add 'property' class to fieldset for correct indexing
53+
const legend = document.createElement("legend");
54+
legend.textContent = `Property ${propertyIndex}`;
55+
fieldset.appendChild(legend);
56+
57+
const propertyName = `${namePrefix}properties[${propertyIndex}]`;
58+
const propertyHtml = `
59+
<input type="text" name="${propertyName}[title]" placeholder="Title" />
60+
<select name="${propertyName}[type]">
61+
<option value="string">String</option>
62+
<option value="integer">Integer</option>
63+
<option value="object">Object</option>
64+
<option value="array">Array</option>
65+
</select><br>
66+
<input type="checkbox" name="${propertyName}[required]"> Required<br>
67+
`;
68+
69+
fieldset.innerHTML += propertyHtml;
70+
71+
// Add a remove button for each nested property
72+
const removePropertyButton = document.createElement("button");
73+
removePropertyButton.textContent = "Remove Property";
74+
removePropertyButton.type = "button";
75+
removePropertyButton.onclick = function () {
76+
container.removeChild(fieldset);
77+
};
78+
fieldset.appendChild(removePropertyButton);
79+
80+
// Add nested properties for objects and arrays
81+
if (type === "object" || type === "array") {
82+
const nestedContainer = document.createElement("div");
83+
nestedContainer.className = "nested-properties";
84+
const addNestedButton = document.createElement("button");
85+
addNestedButton.textContent = type === "object" ? "Add Nested Property" : "Add Array Item";
86+
addNestedButton.type = "button";
87+
addNestedButton.onclick = () =>
88+
addNestedProperties(nestedContainer, type === "object" ? "string" : "array", `${propertyName}[properties]`);
89+
fieldset.appendChild(addNestedButton);
90+
fieldset.appendChild(nestedContainer);
91+
}
92+
93+
container.appendChild(fieldset);
94+
}
95+
96+
// Function to process and collect data from nested properties
97+
function processNestedProperties(container) {
98+
const properties = [];
99+
const propertyDivs = container.getElementsByClassName("property");
100+
for (const div of propertyDivs) {
101+
const titleInput = div.querySelector('input[name="title"]');
102+
const title = titleInput ? titleInput.value : "";
103+
104+
const typeSelect = div.querySelector('select[name="type"]');
105+
const type = typeSelect ? typeSelect.value : "";
106+
107+
const requiredCheckbox = div.querySelector('input[name="required"]');
108+
const required = requiredCheckbox ? requiredCheckbox.checked : false;
109+
110+
const property = { title, type, required };
111+
112+
// Check for further nested properties
113+
if ((type === "object" || type === "array") && div.querySelector(".nested-properties")) {
114+
const nestedContainer = div.querySelector(".nested-properties");
115+
property.properties = processNestedProperties(nestedContainer);
116+
}
117+
118+
properties.push(property);
119+
}
120+
return properties;
121+
}
122+
123+
// Function to add a new response section
124+
function addResponse() {
125+
const responseIndex = responsesContainer.children.length;
126+
const fieldset = document.createElement("fieldset");
127+
const legend = document.createElement("legend");
128+
legend.textContent = `Response ${responseIndex + 1}`;
129+
fieldset.appendChild(legend);
130+
131+
fieldset.innerHTML += `
132+
<input type="text" name="responses[${responseIndex}].status" placeholder="Status" /><br>
133+
<input type="number" name="responses[${responseIndex}].httpCode" placeholder="HTTP Code" /><br>
134+
<input type="text" name="responses[${responseIndex}].httpMessage" placeholder="HTTP Message" /><br>
135+
<input type="text" name="responses[${responseIndex}].statusDescription" placeholder="Status Description" /><br>
136+
`;
137+
138+
// Button to add schema properties
139+
const addSchemaButton = document.createElement("button");
140+
addSchemaButton.textContent = "Add Schema Property";
141+
addSchemaButton.type = "button";
142+
addSchemaButton.onclick = function () {
143+
addNestedProperties(fieldset, "object", `responses[${responseIndex}].`);
144+
};
145+
fieldset.appendChild(addSchemaButton);
146+
147+
// Add a remove button for each response section
148+
const removeButton = document.createElement("button");
149+
removeButton.textContent = "Remove Response";
150+
removeButton.type = "button";
151+
removeButton.onclick = function () {
152+
responsesContainer.removeChild(fieldset);
153+
};
154+
155+
fieldset.appendChild(removeButton);
156+
responsesContainer.appendChild(fieldset);
157+
}
158+
159+
// Event listener for the Add Response button
160+
addResponseButton?.addEventListener("click", addResponse);
161+
162+
// Function to handle form submission
163+
if (form) {
164+
form.onsubmit = function (event) {
165+
event.preventDefault();
166+
167+
const formData = new FormData(form);
168+
const data = parseFormData(formData);
169+
170+
// Display the generated JSON
171+
jsonOutput.textContent = JSON.stringify(data, null, 2);
172+
};
173+
}
174+
});

0 commit comments

Comments
 (0)