drf-to-mkdoc 0.2.3__py3-none-any.whl → 0.2.4__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of drf-to-mkdoc might be problematic. Click here for more details.
- drf_to_mkdoc/static/drf-to-mkdoc/javascripts/field-sections-loader.js +29 -0
- drf_to_mkdoc/static/drf-to-mkdoc/javascripts/query-parameters-loader.js +16 -0
- drf_to_mkdoc/static/drf-to-mkdoc/javascripts/try-out/field-extractor.js +200 -0
- drf_to_mkdoc/static/drf-to-mkdoc/javascripts/try-out/form-manager.js +307 -14
- drf_to_mkdoc/static/drf-to-mkdoc/javascripts/try-out/main.js +39 -11
- drf_to_mkdoc/static/drf-to-mkdoc/javascripts/try-out/modal.js +298 -18
- drf_to_mkdoc/static/drf-to-mkdoc/javascripts/try-out/query-parameters-extractor.js +94 -0
- drf_to_mkdoc/static/drf-to-mkdoc/javascripts/try-out/request-executor.js +278 -62
- drf_to_mkdoc/static/drf-to-mkdoc/javascripts/try-out/response-modal.js +173 -0
- drf_to_mkdoc/static/drf-to-mkdoc/javascripts/try-out/suggestions.js +59 -152
- drf_to_mkdoc/static/drf-to-mkdoc/javascripts/try-out/tabs.js +52 -9
- drf_to_mkdoc/static/drf-to-mkdoc/stylesheets/endpoints/badges.css +13 -5
- drf_to_mkdoc/static/drf-to-mkdoc/stylesheets/endpoints/theme-toggle.css +297 -25
- drf_to_mkdoc/static/drf-to-mkdoc/stylesheets/endpoints/try-out/fab.css +204 -0
- drf_to_mkdoc/static/drf-to-mkdoc/stylesheets/endpoints/try-out/response.css +323 -0
- drf_to_mkdoc/static/drf-to-mkdoc/stylesheets/endpoints/try-out/variables.css +139 -0
- drf_to_mkdoc/static/drf-to-mkdoc/stylesheets/field-sections.css +136 -0
- drf_to_mkdoc/static/drf-to-mkdoc/stylesheets/try-out/form.css +539 -0
- drf_to_mkdoc/static/drf-to-mkdoc/stylesheets/try-out/modal.css +239 -17
- drf_to_mkdoc/static/drf-to-mkdoc/stylesheets/try-out/response.css +503 -43
- drf_to_mkdoc/static/drf-to-mkdoc/stylesheets/try-out/tabs.css +71 -19
- drf_to_mkdoc/static/drf-to-mkdoc/stylesheets/try-out/variables.css +71 -15
- drf_to_mkdoc/templates/endpoints/detail/request_body.html +2 -0
- drf_to_mkdoc/templates/try-out/fab.html +67 -3
- drf_to_mkdoc/templates/try-out/form.html +221 -74
- drf_to_mkdoc/templates/try-out/modal.html +75 -7
- drf_to_mkdoc/templates/try-out/response-modal.html +138 -9
- drf_to_mkdoc/utils/endpoint_detail_generator.py +1 -0
- {drf_to_mkdoc-0.2.3.dist-info → drf_to_mkdoc-0.2.4.dist-info}/METADATA +68 -9
- {drf_to_mkdoc-0.2.3.dist-info → drf_to_mkdoc-0.2.4.dist-info}/RECORD +33 -24
- {drf_to_mkdoc-0.2.3.dist-info → drf_to_mkdoc-0.2.4.dist-info}/WHEEL +0 -0
- {drf_to_mkdoc-0.2.3.dist-info → drf_to_mkdoc-0.2.4.dist-info}/licenses/LICENSE +0 -0
- {drf_to_mkdoc-0.2.3.dist-info → drf_to_mkdoc-0.2.4.dist-info}/top_level.txt +0 -0
|
@@ -1,50 +1,102 @@
|
|
|
1
|
-
/* Tabs */
|
|
2
|
-
.tabs {
|
|
1
|
+
/* Smart Tabs */
|
|
2
|
+
.smart-tabs {
|
|
3
3
|
display: flex;
|
|
4
|
-
gap:
|
|
4
|
+
gap: var(--try-out-spacing-xs);
|
|
5
|
+
border-bottom: 1px solid var(--try-out-border);
|
|
6
|
+
padding-bottom: var(--try-out-spacing-xs);
|
|
5
7
|
margin-bottom: var(--try-out-spacing-lg);
|
|
6
|
-
border: 1px solid var(--try-out-border);
|
|
7
|
-
border-radius: var(--try-out-border-radius);
|
|
8
|
-
overflow: hidden;
|
|
9
|
-
background-color: var(--try-out-surface);
|
|
10
8
|
}
|
|
11
9
|
|
|
12
10
|
.tab {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
11
|
+
display: flex;
|
|
12
|
+
align-items: center;
|
|
13
|
+
gap: var(--try-out-spacing-xs);
|
|
14
|
+
padding: var(--try-out-spacing-sm) var(--try-out-spacing);
|
|
15
|
+
border-radius: var(--try-out-border-radius);
|
|
16
16
|
background: transparent;
|
|
17
|
+
border: none;
|
|
17
18
|
color: var(--try-out-text-light);
|
|
18
19
|
cursor: pointer;
|
|
20
|
+
transition: var(--try-out-transition);
|
|
19
21
|
font-size: var(--try-out-font-base);
|
|
20
22
|
font-weight: 500;
|
|
21
23
|
position: relative;
|
|
22
|
-
transition: var(--try-out-transition);
|
|
23
|
-
border-right: 1px solid var(--try-out-border);
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
-
.tab:
|
|
27
|
-
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
.tab:hover {
|
|
31
|
-
background-color: rgba(25, 118, 210, 0.05);
|
|
26
|
+
.tab:hover:not(.active) {
|
|
27
|
+
background: var(--try-out-surface);
|
|
32
28
|
color: var(--try-out-text);
|
|
33
29
|
}
|
|
34
30
|
|
|
35
31
|
.tab.active {
|
|
36
|
-
background
|
|
32
|
+
background: var(--try-out-primary);
|
|
37
33
|
color: white;
|
|
34
|
+
box-shadow: var(--try-out-shadow-md);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
.tab .icon {
|
|
38
|
+
font-size: 0.9rem;
|
|
39
|
+
line-height: 1;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
.badge {
|
|
43
|
+
background: rgba(255, 255, 255, 0.2);
|
|
44
|
+
padding: 2px 6px;
|
|
45
|
+
border-radius: 10px;
|
|
46
|
+
font-size: 0.7em;
|
|
47
|
+
font-weight: 600;
|
|
48
|
+
line-height: 1;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
.tab.active .badge {
|
|
52
|
+
background: rgba(255, 255, 255, 0.25);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
.tab:not(.active) .badge {
|
|
56
|
+
background: var(--try-out-primary-light);
|
|
57
|
+
color: var(--try-out-primary);
|
|
38
58
|
}
|
|
39
59
|
|
|
40
60
|
.tab-content {
|
|
41
61
|
display: none;
|
|
62
|
+
animation: fadeIn 0.2s ease-out;
|
|
42
63
|
}
|
|
43
64
|
|
|
44
65
|
.tab-content.active {
|
|
45
66
|
display: block;
|
|
46
67
|
}
|
|
47
68
|
|
|
69
|
+
/* Response Tabs */
|
|
70
|
+
.response-tabs {
|
|
71
|
+
display: flex;
|
|
72
|
+
gap: var(--try-out-spacing-xs);
|
|
73
|
+
border-bottom: 1px solid var(--try-out-border);
|
|
74
|
+
padding-bottom: var(--try-out-spacing-xs);
|
|
75
|
+
margin-bottom: var(--try-out-spacing);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
.response-tabs .tab {
|
|
79
|
+
padding: var(--try-out-spacing-xs) var(--try-out-spacing-sm);
|
|
80
|
+
font-size: var(--try-out-font-sm);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/* Tab Focus States */
|
|
84
|
+
.tab:focus-visible {
|
|
85
|
+
outline: 2px solid var(--try-out-primary);
|
|
86
|
+
outline-offset: 2px;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
@keyframes fadeIn {
|
|
90
|
+
from {
|
|
91
|
+
opacity: 0;
|
|
92
|
+
transform: translateY(10px);
|
|
93
|
+
}
|
|
94
|
+
to {
|
|
95
|
+
opacity: 1;
|
|
96
|
+
transform: translateY(0);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
48
100
|
/* Mobile Tabs */
|
|
49
101
|
@media screen and (max-width: 768px) {
|
|
50
102
|
.tabs {
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
:root {
|
|
2
|
+
/* Color Palette */
|
|
2
3
|
--try-out-primary: #1976d2;
|
|
3
4
|
--try-out-primary-hover: #1565c0;
|
|
5
|
+
--try-out-primary-rgb: 25, 118, 210;
|
|
6
|
+
--try-out-primary-light: rgba(25, 118, 210, 0.1);
|
|
4
7
|
--try-out-success: #28a745;
|
|
5
8
|
--try-out-success-hover: #218838;
|
|
6
9
|
--try-out-danger: #dc3545;
|
|
@@ -8,31 +11,84 @@
|
|
|
8
11
|
--try-out-warning: #ffc107;
|
|
9
12
|
--try-out-info: #17a2b8;
|
|
10
13
|
|
|
14
|
+
/* Light Theme Colors */
|
|
11
15
|
--try-out-bg: #ffffff;
|
|
12
16
|
--try-out-surface: #f8f9fa;
|
|
17
|
+
--try-out-surface-raised: #ffffff;
|
|
13
18
|
--try-out-border: #e1e5e9;
|
|
14
19
|
--try-out-text: #333333;
|
|
15
20
|
--try-out-text-light: #666666;
|
|
16
21
|
--try-out-text-lighter: #999999;
|
|
17
22
|
--try-out-shadow: rgba(0, 0, 0, 0.1);
|
|
18
23
|
--try-out-shadow-strong: rgba(0, 0, 0, 0.2);
|
|
24
|
+
--try-out-shadow-md: 0 4px 12px rgba(0, 0, 0, 0.15);
|
|
25
|
+
--try-out-shadow-lg: 0 8px 25px rgba(0, 0, 0, 0.15);
|
|
26
|
+
--try-out-shadow-xl: 0 20px 40px rgba(0, 0, 0, 0.2);
|
|
19
27
|
|
|
20
|
-
|
|
21
|
-
--try-out-
|
|
22
|
-
--try-out-
|
|
23
|
-
--try-out-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
--try-out-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
--try-out-
|
|
30
|
-
--try-out-
|
|
31
|
-
--try-out-
|
|
32
|
-
--try-out-
|
|
33
|
-
|
|
34
|
-
--try-out-
|
|
28
|
+
/* Glass Effect */
|
|
29
|
+
--try-out-glass-bg: rgba(255, 255, 255, 0.95);
|
|
30
|
+
--try-out-glass-border: rgba(255, 255, 255, 0.2);
|
|
31
|
+
--try-out-backdrop-blur: 10px;
|
|
32
|
+
|
|
33
|
+
/* Gradients */
|
|
34
|
+
--try-out-gradient-primary: linear-gradient(135deg, var(--try-out-primary), var(--try-out-primary-hover));
|
|
35
|
+
|
|
36
|
+
/* Layout */
|
|
37
|
+
--try-out-border-radius: 6px;
|
|
38
|
+
--try-out-border-radius-lg: 10px;
|
|
39
|
+
--try-out-spacing-2xs: 0.125rem;
|
|
40
|
+
--try-out-spacing-xs: 0.25rem;
|
|
41
|
+
--try-out-spacing-sm: 0.5rem;
|
|
42
|
+
--try-out-spacing: 0.75rem;
|
|
43
|
+
--try-out-spacing-lg: 1rem;
|
|
44
|
+
--try-out-spacing-xl: 1.5rem;
|
|
45
|
+
--try-out-spacing-xxl: 2rem;
|
|
46
|
+
|
|
47
|
+
/* Typography */
|
|
48
|
+
--try-out-font-sm: 0.875rem;
|
|
49
|
+
--try-out-font-base: 0.9rem;
|
|
50
|
+
--try-out-font-lg: 1rem;
|
|
51
|
+
--try-out-line-height: 1.5;
|
|
52
|
+
|
|
53
|
+
/* Animation */
|
|
54
|
+
--try-out-transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
|
55
|
+
--theme-transition: background-color 0.3s ease, color 0.3s ease, border-color 0.3s ease;
|
|
56
|
+
|
|
57
|
+
/* Z-Index */
|
|
35
58
|
--try-out-z-modal: 1000;
|
|
36
59
|
--try-out-z-response: 1100;
|
|
37
60
|
--try-out-z-fab: 100;
|
|
61
|
+
--try-out-z-sticky: 50;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/* Dark Theme Colors */
|
|
65
|
+
[data-md-color-scheme="slate"] {
|
|
66
|
+
--try-out-bg: #1a1a1a;
|
|
67
|
+
--try-out-surface: #2d2d2d;
|
|
68
|
+
--try-out-surface-raised: #3a3a3a;
|
|
69
|
+
--try-out-border: #404040;
|
|
70
|
+
--try-out-text: #e0e0e0;
|
|
71
|
+
--try-out-text-light: #b0b0b0;
|
|
72
|
+
--try-out-text-lighter: #808080;
|
|
73
|
+
--try-out-shadow: rgba(0, 0, 0, 0.3);
|
|
74
|
+
--try-out-shadow-strong: rgba(0, 0, 0, 0.5);
|
|
75
|
+
--try-out-shadow-md: 0 4px 12px rgba(0, 0, 0, 0.3);
|
|
76
|
+
--try-out-shadow-lg: 0 8px 25px rgba(0, 0, 0, 0.4);
|
|
77
|
+
--try-out-shadow-xl: 0 20px 40px rgba(0, 0, 0, 0.5);
|
|
78
|
+
|
|
79
|
+
/* Glass Effect for Dark Mode */
|
|
80
|
+
--try-out-glass-bg: rgba(45, 45, 45, 0.95);
|
|
81
|
+
--try-out-glass-border: rgba(255, 255, 255, 0.1);
|
|
82
|
+
|
|
83
|
+
/* Adjust primary colors for better contrast */
|
|
84
|
+
--try-out-primary: #42a5f5;
|
|
85
|
+
--try-out-primary-hover: #2196f3;
|
|
86
|
+
--try-out-primary-rgb: 66, 165, 245;
|
|
87
|
+
--try-out-primary-light: rgba(66, 165, 245, 0.15);
|
|
88
|
+
|
|
89
|
+
/* Status colors for dark mode */
|
|
90
|
+
--try-out-success: #4caf50;
|
|
91
|
+
--try-out-danger: #f44336;
|
|
92
|
+
--try-out-warning: #ff9800;
|
|
93
|
+
--try-out-info: #00bcd4;
|
|
38
94
|
}
|
|
@@ -1,4 +1,68 @@
|
|
|
1
1
|
<!-- Try Out Floating Action Button -->
|
|
2
|
-
<
|
|
3
|
-
<
|
|
4
|
-
|
|
2
|
+
<div class="try-out-fab-container">
|
|
3
|
+
<button
|
|
4
|
+
class="try-out-fab"
|
|
5
|
+
role="button"
|
|
6
|
+
tabindex="0"
|
|
7
|
+
aria-label="Open Try It Out"
|
|
8
|
+
aria-expanded="false"
|
|
9
|
+
onclick="TryOutSidebar.openTryOut()"
|
|
10
|
+
data-tooltip="Try out this endpoint"
|
|
11
|
+
>
|
|
12
|
+
<div class="fab-content">
|
|
13
|
+
<span class="fab-icon">🚀</span>
|
|
14
|
+
</div>
|
|
15
|
+
<div class="ripple-container"></div>
|
|
16
|
+
<div class="pulse-ring"></div>
|
|
17
|
+
</button>
|
|
18
|
+
</div>
|
|
19
|
+
|
|
20
|
+
<script>
|
|
21
|
+
document.addEventListener('DOMContentLoaded', function() {
|
|
22
|
+
// Ripple effect
|
|
23
|
+
const fab = document.querySelector('.try-out-fab');
|
|
24
|
+
|
|
25
|
+
fab.addEventListener('click', function(e) {
|
|
26
|
+
const ripple = document.createElement('div');
|
|
27
|
+
ripple.className = 'ripple';
|
|
28
|
+
|
|
29
|
+
const rect = this.getBoundingClientRect();
|
|
30
|
+
const size = Math.max(rect.width, rect.height);
|
|
31
|
+
const x = e.clientX - rect.left - size / 2;
|
|
32
|
+
const y = e.clientY - rect.top - size / 2;
|
|
33
|
+
|
|
34
|
+
ripple.style.width = ripple.style.height = `${size}px`;
|
|
35
|
+
ripple.style.left = `${x}px`;
|
|
36
|
+
ripple.style.top = `${y}px`;
|
|
37
|
+
|
|
38
|
+
this.querySelector('.ripple-container').appendChild(ripple);
|
|
39
|
+
|
|
40
|
+
setTimeout(() => ripple.remove(), 600);
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
// Keyboard shortcut
|
|
44
|
+
document.addEventListener('keydown', function(e) {
|
|
45
|
+
if (e.ctrlKey && e.code === 'Space') {
|
|
46
|
+
e.preventDefault();
|
|
47
|
+
TryOutSidebar.openTryOut();
|
|
48
|
+
|
|
49
|
+
// Animate the FAB
|
|
50
|
+
fab.classList.add('keyboard-triggered');
|
|
51
|
+
setTimeout(() => fab.classList.remove('keyboard-triggered'), 200);
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
// Show/hide shortcut hint
|
|
56
|
+
let hintTimeout;
|
|
57
|
+
fab.addEventListener('mouseenter', function() {
|
|
58
|
+
clearTimeout(hintTimeout);
|
|
59
|
+
document.querySelector('.shortcut-hint').classList.add('visible');
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
fab.addEventListener('mouseleave', function() {
|
|
63
|
+
hintTimeout = setTimeout(() => {
|
|
64
|
+
document.querySelector('.shortcut-hint').classList.remove('visible');
|
|
65
|
+
}, 500);
|
|
66
|
+
});
|
|
67
|
+
});
|
|
68
|
+
</script>
|
|
@@ -1,113 +1,260 @@
|
|
|
1
1
|
{% load custom_filters %}
|
|
2
2
|
|
|
3
3
|
<div class="try-out-form" data-method="{{ method }}">
|
|
4
|
-
<!-- Base URL Section -->
|
|
5
|
-
<div class="
|
|
6
|
-
<
|
|
7
|
-
<div class="url-
|
|
8
|
-
<
|
|
9
|
-
|
|
4
|
+
<!-- Method Badge and Base URL Section -->
|
|
5
|
+
<div class="request-header">
|
|
6
|
+
<div class="method-badge method-{{ method|lower }}" data-method="{{ method|upper }}">{{ method|upper }}</div>
|
|
7
|
+
<div class="base-url-section">
|
|
8
|
+
<div class="floating-label-group">
|
|
9
|
+
<input type="text"
|
|
10
|
+
id="baseUrl"
|
|
11
|
+
class="base-url-input floating-input"
|
|
12
|
+
value="http://localhost:8000"
|
|
13
|
+
placeholder=" "
|
|
14
|
+
required>
|
|
15
|
+
<label for="baseUrl" class="floating-label">Request URL</label>
|
|
16
|
+
<div class="url-preview">
|
|
17
|
+
<code class="path-display">{{ path }}</code>
|
|
18
|
+
<button class="copy-btn" onclick="copyToClipboard(this)" aria-label="Copy URL">
|
|
19
|
+
<span class="icon">📋</span>
|
|
20
|
+
</button>
|
|
21
|
+
</div>
|
|
22
|
+
</div>
|
|
10
23
|
</div>
|
|
11
24
|
</div>
|
|
12
25
|
|
|
13
|
-
<!-- Tabs -->
|
|
14
|
-
<div class="tabs">
|
|
15
|
-
<button class="tab active"
|
|
16
|
-
|
|
26
|
+
<!-- Smart Tabs with Icons -->
|
|
27
|
+
<div class="smart-tabs" role="tablist">
|
|
28
|
+
<button class="tab active"
|
|
29
|
+
id="tab-parameters"
|
|
30
|
+
role="tab"
|
|
31
|
+
aria-selected="true"
|
|
32
|
+
aria-controls="parametersTab"
|
|
33
|
+
data-tab="parameters">
|
|
34
|
+
<span class="icon">📝</span>
|
|
35
|
+
Parameters
|
|
36
|
+
{% if path_params %}<span class="badge">{{ path_params|length }}</span>{% endif %}
|
|
37
|
+
</button>
|
|
38
|
+
<button class="tab"
|
|
39
|
+
id="tab-headers"
|
|
40
|
+
role="tab"
|
|
41
|
+
aria-selected="false"
|
|
42
|
+
aria-controls="headersTab"
|
|
43
|
+
data-tab="headers">
|
|
44
|
+
<span class="icon">📋</span>
|
|
45
|
+
Headers
|
|
46
|
+
</button>
|
|
17
47
|
{% if method|upper in "POST,PUT,PATCH" %}
|
|
18
|
-
<button class="tab"
|
|
48
|
+
<button class="tab"
|
|
49
|
+
id="tab-body"
|
|
50
|
+
role="tab"
|
|
51
|
+
aria-selected="false"
|
|
52
|
+
aria-controls="bodyTab"
|
|
53
|
+
data-tab="body">
|
|
54
|
+
<span class="icon">📦</span>
|
|
55
|
+
Request Body
|
|
56
|
+
</button>
|
|
19
57
|
{% endif %}
|
|
20
58
|
</div>
|
|
21
59
|
|
|
22
60
|
<!-- Parameters Tab -->
|
|
23
|
-
<div class="tab-content active"
|
|
61
|
+
<div class="tab-content active"
|
|
62
|
+
id="parametersTab"
|
|
63
|
+
role="tabpanel"
|
|
64
|
+
aria-labelledby="tab-parameters">
|
|
24
65
|
{% if path_params %}
|
|
25
|
-
<div class="form-
|
|
26
|
-
<
|
|
27
|
-
|
|
66
|
+
<div class="form-section">
|
|
67
|
+
<div class="section-header">
|
|
68
|
+
<h4>Path Parameters</h4>
|
|
69
|
+
<div class="tooltip" data-tooltip="Values that are part of the URL path">ℹ️</div>
|
|
70
|
+
</div>
|
|
71
|
+
<div class="parameter-grid" id="pathParams">
|
|
28
72
|
{% for param in path_params %}
|
|
29
|
-
<div class="
|
|
30
|
-
<
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
73
|
+
<div class="parameter-card{% if param.required %} required{% endif %}">
|
|
74
|
+
<div class="parameter-header">
|
|
75
|
+
<label class="param-label">{{ param.name }}</label>
|
|
76
|
+
{% if param.required %}
|
|
77
|
+
<span class="required-badge">Required</span>
|
|
78
|
+
{% endif %}
|
|
79
|
+
</div>
|
|
80
|
+
<div class="parameter-input-group">
|
|
81
|
+
<input type="text"
|
|
82
|
+
class="modern-input"
|
|
83
|
+
placeholder="Enter value"
|
|
84
|
+
data-param="{{ param.name }}"
|
|
85
|
+
{% if param.required %}required{% endif %}>
|
|
86
|
+
{% if param.description %}
|
|
87
|
+
<div class="param-description">{{ param.description }}</div>
|
|
88
|
+
{% endif %}
|
|
89
|
+
<div class="validation-message"></div>
|
|
90
|
+
</div>
|
|
36
91
|
</div>
|
|
37
92
|
{% endfor %}
|
|
38
93
|
</div>
|
|
39
94
|
</div>
|
|
40
95
|
{% endif %}
|
|
41
96
|
|
|
42
|
-
<div class="form-
|
|
43
|
-
<
|
|
44
|
-
|
|
45
|
-
<div class="
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
97
|
+
<div class="form-section">
|
|
98
|
+
<div class="section-header">
|
|
99
|
+
<h4>Query Parameters</h4>
|
|
100
|
+
<div class="tooltip" data-tooltip="Parameters added to the URL after ?">ℹ️</div>
|
|
101
|
+
</div>
|
|
102
|
+
<div class="parameter-container" id="queryParams">
|
|
103
|
+
<div class="parameter-toolbar">
|
|
104
|
+
<button class="add-param-btn" onclick="TryOutSidebar.addQueryParam()">
|
|
105
|
+
<span class="icon">+</span> Add Parameter
|
|
106
|
+
</button>
|
|
107
|
+
</div>
|
|
108
|
+
<div class="parameter-list">
|
|
109
|
+
<div class="parameter-item">
|
|
110
|
+
<div class="parameter-inputs">
|
|
111
|
+
<input type="text"
|
|
112
|
+
class="modern-input name-input"
|
|
113
|
+
placeholder="Parameter name"
|
|
114
|
+
list="paramSuggestions">
|
|
115
|
+
<input type="text"
|
|
116
|
+
class="modern-input value-input"
|
|
117
|
+
placeholder="Value">
|
|
118
|
+
<button class="remove-btn"
|
|
119
|
+
onclick="TryOutSidebar.removeKvItem(this)"
|
|
120
|
+
aria-label="Remove parameter">
|
|
121
|
+
<span class="icon">✕</span>
|
|
122
|
+
</button>
|
|
123
|
+
</div>
|
|
124
|
+
</div>
|
|
49
125
|
</div>
|
|
126
|
+
<!-- Parameter Suggestions -->
|
|
127
|
+
<datalist id="paramSuggestions">
|
|
128
|
+
{% for field in query_parameters.filter_fields %}
|
|
129
|
+
<option value="{{ field }}"></option>
|
|
130
|
+
{% endfor %}
|
|
131
|
+
|
|
132
|
+
{% if query_parameters.search_fields %}
|
|
133
|
+
|
|
134
|
+
<option value="search"></option>
|
|
135
|
+
{% endif %}
|
|
136
|
+
|
|
137
|
+
{% if query_parameters.ordering_fields %}
|
|
138
|
+
|
|
139
|
+
<option value="ordering"></option>
|
|
140
|
+
{% endif %}
|
|
141
|
+
|
|
142
|
+
{% for field in query_parameters.pagination_fields %}
|
|
143
|
+
<option value="{{ field }}"></option>
|
|
144
|
+
{% endfor %}
|
|
145
|
+
</datalist>
|
|
50
146
|
</div>
|
|
51
|
-
<button class="add-btn" onclick="TryOutSidebar.addQueryParam()">
|
|
52
|
-
<span>+</span> Add Parameter
|
|
53
|
-
</button>
|
|
54
147
|
</div>
|
|
55
148
|
</div>
|
|
56
149
|
|
|
57
150
|
<!-- Headers Tab -->
|
|
58
|
-
<div class="tab-content"
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
151
|
+
<div class="tab-content"
|
|
152
|
+
id="headersTab"
|
|
153
|
+
role="tabpanel"
|
|
154
|
+
aria-labelledby="tab-headers">
|
|
155
|
+
<div class="form-section">
|
|
156
|
+
<div class="section-header">
|
|
157
|
+
<h4>Request Headers</h4>
|
|
158
|
+
<div class="tooltip" data-tooltip="HTTP headers sent with the request">ℹ️</div>
|
|
159
|
+
</div>
|
|
160
|
+
<div class="header-container" id="requestHeaders">
|
|
161
|
+
<div class="header-toolbar">
|
|
162
|
+
<button class="add-header-btn" onclick="TryOutSidebar.addHeader()">
|
|
163
|
+
<span class="icon">+</span> Add Header
|
|
164
|
+
</button>
|
|
66
165
|
</div>
|
|
67
|
-
<div class="
|
|
68
|
-
<
|
|
69
|
-
|
|
70
|
-
|
|
166
|
+
<div class="header-list">
|
|
167
|
+
<div class="header-item">
|
|
168
|
+
<div class="header-inputs">
|
|
169
|
+
<input type="text"
|
|
170
|
+
class="modern-input name-input"
|
|
171
|
+
value="Content-Type"
|
|
172
|
+
list="headerSuggestions">
|
|
173
|
+
<input type="text"
|
|
174
|
+
class="modern-input value-input"
|
|
175
|
+
value="application/json">
|
|
176
|
+
<button class="remove-btn"
|
|
177
|
+
onclick="TryOutSidebar.removeKvItem(this)"
|
|
178
|
+
aria-label="Remove header">
|
|
179
|
+
<span class="icon">✕</span>
|
|
180
|
+
</button>
|
|
181
|
+
</div>
|
|
182
|
+
</div>
|
|
183
|
+
<div class="header-item">
|
|
184
|
+
<div class="header-inputs">
|
|
185
|
+
<input type="text"
|
|
186
|
+
class="modern-input name-input"
|
|
187
|
+
value="Authorization"
|
|
188
|
+
list="headerSuggestions">
|
|
189
|
+
<input type="text"
|
|
190
|
+
class="modern-input value-input"
|
|
191
|
+
placeholder="Bearer your-token">
|
|
192
|
+
<button class="remove-btn"
|
|
193
|
+
onclick="TryOutSidebar.removeKvItem(this)"
|
|
194
|
+
aria-label="Remove header">
|
|
195
|
+
<span class="icon">✕</span>
|
|
196
|
+
</button>
|
|
197
|
+
</div>
|
|
198
|
+
</div>
|
|
71
199
|
</div>
|
|
200
|
+
<!-- Header Suggestions -->
|
|
201
|
+
<datalist id="headerSuggestions">
|
|
202
|
+
<option value="Accept">Response format preference</option>
|
|
203
|
+
<option value="Authorization">Authentication credentials</option>
|
|
204
|
+
<option value="Content-Type">Request body format</option>
|
|
205
|
+
<option value="Cache-Control">Caching behavior</option>
|
|
206
|
+
</datalist>
|
|
72
207
|
</div>
|
|
73
|
-
<button class="add-btn" onclick="TryOutSidebar.addHeader()">
|
|
74
|
-
<span>+</span> Add Header
|
|
75
|
-
</button>
|
|
76
208
|
</div>
|
|
77
209
|
</div>
|
|
78
210
|
|
|
79
211
|
<!-- Request Body Tab -->
|
|
80
212
|
{% if method|upper in "POST,PUT,PATCH" %}
|
|
81
|
-
<div class="tab-content"
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
213
|
+
<div class="tab-content"
|
|
214
|
+
id="bodyTab"
|
|
215
|
+
role="tabpanel"
|
|
216
|
+
aria-labelledby="tab-body">
|
|
217
|
+
<div class="form-section">
|
|
218
|
+
<div class="section-header">
|
|
219
|
+
<h4>Request Body</h4>
|
|
220
|
+
<div class="body-toolbar">
|
|
221
|
+
<button class="format-btn" onclick="formatJson()">
|
|
222
|
+
<span class="icon">🔧</span> Format
|
|
223
|
+
</button>
|
|
224
|
+
<button class="validate-btn" onclick="validateJson()">
|
|
225
|
+
<span class="icon">✓</span> Validate
|
|
226
|
+
</button>
|
|
227
|
+
</div>
|
|
228
|
+
</div>
|
|
229
|
+
<div class="editor-container">
|
|
230
|
+
<div class="editor-wrapper">
|
|
231
|
+
<textarea id="requestBody"
|
|
232
|
+
class="code-editor"
|
|
233
|
+
placeholder="Enter JSON request body..."
|
|
234
|
+
spellcheck="false"
|
|
235
|
+
rows="8">{% if request_example %}{{ request_example|extract_json_from_markdown }}{% endif %}</textarea>
|
|
236
|
+
<div class="editor-overlay"></div>
|
|
237
|
+
</div>
|
|
238
|
+
<div class="validation-status"></div>
|
|
239
|
+
</div>
|
|
88
240
|
</div>
|
|
89
241
|
</div>
|
|
90
242
|
{% endif %}
|
|
91
243
|
|
|
92
|
-
<!--
|
|
93
|
-
<
|
|
94
|
-
<
|
|
95
|
-
|
|
244
|
+
<!-- Action Bar - Hidden since buttons are in modal footer -->
|
|
245
|
+
<div class="action-bar" style="display: none;">
|
|
246
|
+
<div class="action-group">
|
|
247
|
+
<button class="secondary-btn" onclick="resetForm()">
|
|
248
|
+
<span class="icon">↺</span> Reset
|
|
249
|
+
</button>
|
|
250
|
+
<button class="primary-btn" id="executeBtn" onclick="executeRequest()">
|
|
251
|
+
<span class="icon">▶</span> Execute Request
|
|
252
|
+
<div class="loading-spinner"></div>
|
|
253
|
+
</button>
|
|
254
|
+
</div>
|
|
255
|
+
</div>
|
|
96
256
|
</div>
|
|
97
257
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
{% if query_parameters %}
|
|
102
|
-
filter_fields: {{ query_parameters.filter_fields|default:"[]"|safe }},
|
|
103
|
-
search_fields: {{ query_parameters.search_fields|default:"[]"|safe }},
|
|
104
|
-
ordering_fields: {{ query_parameters.ordering_fields|default:"[]"|safe }},
|
|
105
|
-
pagination_fields: {{ query_parameters.pagination_fields|default:"[]"|safe }}
|
|
106
|
-
{% else %}
|
|
107
|
-
filter_fields: [],
|
|
108
|
-
search_fields: [],
|
|
109
|
-
ordering_fields: [],
|
|
110
|
-
pagination_fields: []
|
|
111
|
-
{% endif %}
|
|
112
|
-
};
|
|
113
|
-
</script>
|
|
258
|
+
<!-- Form styles are now in form.css -->
|
|
259
|
+
|
|
260
|
+
<!-- JavaScript functionality is now handled in the modular try-out/*.js files -->
|