1- <!-- app/templates/terminal/index.html -->
1+ <!-- app/templates/terminal/index.html - Fixed Custom Modals - ->
22{% extends "base.html" %}
33{% block css %}
44< link rel ="stylesheet " href ="{{ url_for('static', filename='css/terminal.css') }} ">
5+ < style >
6+ /* Custom Modal Styles with Theme Support */
7+ .custom-modal {
8+ position : fixed;
9+ top : 0 ;
10+ left : 0 ;
11+ width : 100% ;
12+ height : 100% ;
13+ z-index : 1050 ;
14+ display : none;
15+ }
16+
17+ .custom-modal-backdrop {
18+ position : absolute;
19+ top : 0 ;
20+ left : 0 ;
21+ width : 100% ;
22+ height : 100% ;
23+ background : rgba (0 , 0 , 0 , 0.5 );
24+ backdrop-filter : blur (4px );
25+ }
26+
27+ .custom-modal-content {
28+ position : absolute;
29+ top : 50% ;
30+ left : 50% ;
31+ transform : translate (-50% , -50% );
32+ background : var (--w11-card-bg );
33+ backdrop-filter : blur (20px );
34+ border : 1px solid var (--w11-card-stroke );
35+ border-radius : var (--w11-radius-large );
36+ box-shadow : var (--w11-shadow-16 );
37+ min-width : 400px ;
38+ max-width : 600px ;
39+ color : var (--w11-text-primary );
40+ transition : all var (--w11-duration-normal ) var (--w11-ease-standard );
41+ }
42+
43+ .custom-modal-header {
44+ padding : 20px 24px ;
45+ border-bottom : 1px solid var (--w11-surface-stroke );
46+ display : flex;
47+ justify-content : space-between;
48+ align-items : center;
49+ background : var (--w11-bg-secondary );
50+ border-radius : var (--w11-radius-large ) var (--w11-radius-large ) 0 0 ;
51+ transition : all var (--w11-duration-normal ) var (--w11-ease-standard );
52+ }
53+
54+ .custom-modal-header h5 {
55+ margin : 0 ;
56+ font-size : 18px ;
57+ font-weight : 600 ;
58+ color : var (--w11-text-primary );
59+ transition : color var (--w11-duration-normal ) var (--w11-ease-standard );
60+ }
61+
62+ .custom-modal-body {
63+ padding : 24px ;
64+ color : var (--w11-text-primary );
65+ transition : color var (--w11-duration-normal ) var (--w11-ease-standard );
66+ }
67+
68+ .custom-modal-body p {
69+ margin-bottom : 16px ;
70+ color : var (--w11-text-primary );
71+ transition : color var (--w11-duration-normal ) var (--w11-ease-standard );
72+ }
73+
74+ .custom-modal-body .text-danger {
75+ color : var (--w11-danger ) !important ;
76+ background : var (--w11-danger-bg );
77+ border : 1px solid var (--w11-danger );
78+ border-radius : var (--w11-radius-medium );
79+ padding : 12px 16px ;
80+ margin-top : 16px ;
81+ display : flex;
82+ align-items : center;
83+ transition : all var (--w11-duration-normal ) var (--w11-ease-standard );
84+ }
85+
86+ .custom-modal-footer {
87+ padding : 20px 24px ;
88+ border-top : 1px solid var (--w11-surface-stroke );
89+ display : flex;
90+ gap : 12px ;
91+ justify-content : flex-end;
92+ background : var (--w11-bg-secondary );
93+ border-radius : 0 0 var (--w11-radius-large ) var (--w11-radius-large );
94+ transition : all var (--w11-duration-normal ) var (--w11-ease-standard );
95+ }
96+
97+ .btn-close {
98+ background : transparent;
99+ border : none;
100+ font-size : 1.2rem ;
101+ color : var (--w11-text-secondary );
102+ cursor : pointer;
103+ padding : 4px ;
104+ border-radius : var (--w11-radius-small );
105+ transition : all var (--w11-duration-fast ) var (--w11-ease-standard );
106+ }
107+
108+ .btn-close : hover {
109+ background : var (--w11-bg-tertiary );
110+ color : var (--w11-text-primary );
111+ }
112+
113+ .btn-close ::before {
114+ content : '✕' ;
115+ font-weight : bold;
116+ }
117+
118+ /* Animation for custom modals */
119+ .custom-modal .show .custom-modal-content {
120+ animation : modalFadeIn 0.3s ease-out;
121+ }
122+
123+ @keyframes modalFadeIn {
124+ from {
125+ opacity : 0 ;
126+ transform : translate (-50% , -60% );
127+ }
128+ to {
129+ opacity : 1 ;
130+ transform : translate (-50% , -50% );
131+ }
132+ }
133+
134+ /* Responsive modal */
135+ @media (max-width : 768px ) {
136+ .custom-modal-content {
137+ min-width : 300px ;
138+ max-width : 90vw ;
139+ margin : 20px ;
140+ }
141+
142+ .custom-modal-header ,
143+ .custom-modal-body ,
144+ .custom-modal-footer {
145+ padding : 16px 20px ;
146+ }
147+ }
148+ </ style >
5149{% endblock %}
150+
6151{% block content %}
7152< div class ="row mb-3 ">
8153 < div class ="col-md-12 d-flex justify-content-between align-items-center ">
@@ -72,22 +217,20 @@ <h1>Terminal Sessions</h1>
72217 </ div >
73218
74219 <!-- Close Modal -->
75- < div id ="customCloseModal{{ session.id }} " class ="custom-modal "
76- style ="display: none; ">
77- < div class ="custom-modal-backdrop "> </ div >
220+ < div id ="customCloseModal{{ session.id }} " class ="custom-modal ">
221+ < div class ="custom-modal-backdrop " onclick ="closeCustomModal('customCloseModal{{ session.id }}') "> </ div >
78222 < div class ="custom-modal-content ">
79223 < div class ="custom-modal-header ">
80224 < h5 > Close Terminal Session</ h5 >
81225 < button type ="button " class ="btn-close "
82226 onclick ="closeCustomModal('customCloseModal{{ session.id }}') "> </ button >
83227 </ div >
84228 < div class ="custom-modal-body ">
85- < p > Are you sure you want to close the terminal session "{{ session.name
86- }}"?</ p >
87- < p class ="text-danger ">
88- < i class ="bi bi-exclamation-triangle me-1 "> </ i >
229+ < p > Are you sure you want to close the terminal session "< strong > {{ session.name }}</ strong > "?</ p >
230+ < div class ="text-danger ">
231+ < i class ="bi bi-exclamation-triangle me-2 "> </ i >
89232 This will terminate all processes running in this session.
90- </ p >
233+ </ div >
91234 </ div >
92235 < div class ="custom-modal-footer ">
93236 < button type ="button " class ="btn btn-secondary "
@@ -103,8 +246,6 @@ <h5>Close Terminal Session</h5>
103246 </ div >
104247 </ div >
105248 </ div >
106-
107-
108249 </ td >
109250 </ tr >
110251 {% else %}
@@ -170,20 +311,22 @@ <h5>Close Terminal Session</h5>
170311 < i class ="bi bi-trash "> </ i > Delete
171312 </ button >
172313 </ div >
314+
173315 <!-- Delete Modal -->
174- < div id ="customModal{{ session.id }} " class ="custom-modal " style =" display: none; " >
175- < div class ="custom-modal-backdrop "> </ div >
316+ < div id ="customModal{{ session.id }} " class ="custom-modal ">
317+ < div class ="custom-modal-backdrop " onclick =" closeCustomModal('customModal{{ session.id }}') " > </ div >
176318 < div class ="custom-modal-content ">
177319 < div class ="custom-modal-header ">
178320 < h5 > Delete Terminal Session</ h5 >
179321 < button type ="button " class ="btn-close "
180322 onclick ="closeCustomModal('customModal{{ session.id }}') "> </ button >
181323 </ div >
182324 < div class ="custom-modal-body ">
183- < p > Are you sure you want to delete the terminal session "{{ session.name
184- }}"?</ p >
185- < p class ="text-danger "> This will permanently delete all logs and history
186- for this session.</ p >
325+ < p > Are you sure you want to delete the terminal session "< strong > {{ session.name }}</ strong > "?</ p >
326+ < div class ="text-danger ">
327+ < i class ="bi bi-exclamation-triangle me-2 "> </ i >
328+ This will permanently delete all logs and history for this session.
329+ </ div >
187330 </ div >
188331 < div class ="custom-modal-footer ">
189332 < button type ="button " class ="btn btn-secondary "
@@ -192,7 +335,9 @@ <h5>Delete Terminal Session</h5>
192335 action ="{{ url_for('terminal.delete', session_id=session.session_id) }} "
193336 method ="post " style ="display: inline; ">
194337 < input type ="hidden " name ="csrf_token " value ="{{ csrf_token() }} ">
195- < button type ="submit " class ="btn btn-danger "> Delete Session</ button >
338+ < button type ="submit " class ="btn btn-danger ">
339+ < i class ="bi bi-trash me-1 "> </ i > Delete Session
340+ </ button >
196341 </ form >
197342 </ div >
198343 </ div >
@@ -212,22 +357,33 @@ <h5>Delete Terminal Session</h5>
212357 </ div >
213358</ div >
214359{% endblock %}
360+
215361{% block scripts %}
216362{{ super() }}
217363< script >
218364 function openCustomModal ( modalId ) {
219365 const modal = document . getElementById ( modalId ) ;
220366 if ( modal ) {
221367 modal . style . display = 'block' ;
368+ modal . classList . add ( 'show' ) ;
222369 document . body . style . overflow = 'hidden' ;
370+
371+ // Focus trap for accessibility
372+ const focusableElements = modal . querySelectorAll ( 'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])' ) ;
373+ if ( focusableElements . length > 0 ) {
374+ focusableElements [ 0 ] . focus ( ) ;
375+ }
223376 }
224377 }
225378
226379 function closeCustomModal ( modalId ) {
227380 const modal = document . getElementById ( modalId ) ;
228381 if ( modal ) {
229- modal . style . display = 'none' ;
230- document . body . style . overflow = '' ;
382+ modal . classList . remove ( 'show' ) ;
383+ setTimeout ( ( ) => {
384+ modal . style . display = 'none' ;
385+ document . body . style . overflow = '' ;
386+ } , 300 ) ;
231387 }
232388 }
233389
@@ -236,10 +392,29 @@ <h5>Delete Terminal Session</h5>
236392 if ( e . target . classList . contains ( 'custom-modal-backdrop' ) ) {
237393 const modal = e . target . closest ( '.custom-modal' ) ;
238394 if ( modal ) {
239- modal . style . display = 'none' ;
240- document . body . style . overflow = '' ;
395+ closeCustomModal ( modal . id ) ;
241396 }
242397 }
243398 } ) ;
399+
400+ // Close modal with Escape key
401+ document . addEventListener ( 'keydown' , function ( e ) {
402+ if ( e . key === 'Escape' ) {
403+ const visibleModals = document . querySelectorAll ( '.custom-modal.show' ) ;
404+ visibleModals . forEach ( modal => {
405+ closeCustomModal ( modal . id ) ;
406+ } ) ;
407+ }
408+ } ) ;
409+
410+ // Prevent form submission when modal is not visible
411+ document . addEventListener ( 'submit' , function ( e ) {
412+ const form = e . target ;
413+ const modal = form . closest ( '.custom-modal' ) ;
414+ if ( modal && ! modal . classList . contains ( 'show' ) ) {
415+ e . preventDefault ( ) ;
416+ return false ;
417+ }
418+ } ) ;
244419</ script >
245420{% endblock %}
0 commit comments