Skip to content

Commit 8bff93e

Browse files
committed
Storing final changes to improve the instance information section and a panel allowing for lab destorying
1 parent 4ea9a15 commit 8bff93e

4 files changed

Lines changed: 334 additions & 126 deletions

File tree

assets/global-instance-panel.js

Lines changed: 89 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -96,54 +96,58 @@
9696
}
9797

9898
const panelHTML = `
99-
<div id="cm-global-floating-panel" style="position: fixed; bottom: 20px; right: 20px; z-index: 1050; width: 320px;">
100-
<div class="card shadow-lg" style="border: 2px solid #479abf;">
101-
<div class="card-header text-white" style="cursor: pointer; background-color: #479abf; padding: 0.75rem 1rem;" onclick="window.cmGlobalPanel.toggle()">
102-
<div style="display: flex; align-items: center; justify-content: space-between;">
103-
<div style="display: flex; align-items: center; gap: 8px;">
104-
<i class="fas fa-server"></i>
105-
<span style="font-weight: 600; font-size: 0.95rem;">Lab Instance</span>
99+
<div id="cm-global-floating-panel" style="position: fixed; bottom: 20px; right: 20px; z-index: 1050; width: 340px;">
100+
<div class="card shadow-lg" style="background-color: #1e1e1e; border: 1px solid #333; border-radius: 10px; overflow: hidden; box-shadow: 0 8px 16px rgba(0,0,0,0.5) !important;">
101+
<div class="card-header" style="background-color: #161616; border-bottom: 1px solid #2a2a2a; color: #fff; cursor: pointer; padding: 12px 16px;" onclick="window.cmGlobalPanel.toggle()">
102+
<div class="d-flex justify-content-between align-items-center">
103+
<div class="d-flex align-items-center" style="font-weight: 700; font-size: 15px;">
104+
<i class="fas fa-server mr-2 text-primary"></i>
105+
Lab Instance
106106
</div>
107-
<div style="display: flex; align-items: center; gap: 8px;">
108-
<span id="cm-global-header-time" style="font-size: 0.9rem; font-weight: 500;"></span>
109-
<i id="cm-global-toggle-icon" class="fas fa-chevron-up"></i>
110-
<button type="button" class="close text-white" style="padding: 0; margin: 0;" onclick="window.cmGlobalPanel.close(event)">
111-
<span>&times;</span>
107+
<div class="d-flex align-items-center">
108+
<span id="cm-global-header-time" class="mr-3 d-none" style="font-family: monospace; font-weight: bold; color: #ebb850; font-size: 14px;"></span>
109+
<i id="cm-global-toggle-icon" class="fas fa-chevron-up mr-2" style="color: #888;"></i>
110+
<button type="button" class="close ml-1" onclick="window.cmGlobalPanel.close(event)" aria-label="Close" style="color: #aaa; text-shadow: none; opacity: 1;">
111+
<span aria-hidden="true">&times;</span>
112112
</button>
113113
</div>
114114
</div>
115115
</div>
116-
<div id="cm-global-panel-body" class="card-body">
117-
<div id="cm-global-loading" style="display: none;">
118-
<p class="text-center text-muted">
116+
<div id="cm-global-panel-body" class="card-body" style="padding: 16px; color: #efefef;">
117+
<div id="cm-global-loading" class="d-none">
118+
<p class="text-center mb-0" style="color: #888;">
119119
<i class="fas fa-spinner fa-spin"></i> Loading...
120120
</p>
121121
</div>
122122
123-
<div id="cm-global-content">
124-
</div>
123+
<div id="cm-global-content"></div>
125124
</div>
126125
</div>
127126
</div>
128127
129128
<style>
130-
#cm-global-floating-panel .card {
131-
border-width: 2px;
132-
}
133-
#cm-global-floating-panel .card-header {
134-
padding: 0.5rem 1rem;
135-
}
136-
#cm-global-floating-panel .card-body {
137-
padding: 1rem;
138-
}
139129
#cm-global-floating-panel.minimized #cm-global-panel-body {
140130
display: none;
141131
}
132+
.floating-btn-lab {
133+
border: none;
134+
border-radius: 6px;
135+
font-weight: 700;
136+
transition: transform 0.1s, opacity 0.2s;
137+
cursor: pointer;
138+
display: flex;
139+
align-items: center;
140+
justify-content: center;
141+
gap: 6px;
142+
padding: 8px 10px;
143+
}
144+
.floating-btn-lab:hover { opacity: 0.9; transform: translateY(-1px); }
145+
.floating-btn-lab:active { transform: translateY(0); }
142146
@media (max-width: 768px) {
143147
#cm-global-floating-panel {
144-
width: calc(100% - 40px);
145-
bottom: 10px;
146-
right: 10px;
148+
width: calc(100% - 40px) !important;
149+
bottom: 10px !important;
150+
right: 10px !important;
147151
}
148152
}
149153
</style>
@@ -157,17 +161,7 @@
157161
const contentDiv = document.getElementById('cm-global-content');
158162
if (!contentDiv) return;
159163

160-
let { challengeId, connectionInfo, until, since, category, created_at, extra_time } = instanceData;
161-
162-
// terraform-challenge-manager doesn't return 'until', calculate it from created_at + extra_time
163-
if (!until && created_at && extra_time !== undefined) {
164-
const createdDate = new Date(created_at);
165-
const timeout = parseInt(extra_time) || 7200; // Default 2 hours
166-
until = new Date(createdDate.getTime() + timeout * 1000).toISOString();
167-
// Update instanceData for storage
168-
instanceData.until = until;
169-
setActiveInstance(instanceData);
170-
}
164+
let { challengeId, connectionInfo, until, since, category, challengeName } = instanceData;
171165

172166
// Calculate time remaining
173167
let countdownHTML = '';
@@ -182,10 +176,10 @@
182176
if (diff > 0) {
183177
timeLeft = diff;
184178
countdownHTML = `
185-
<p class="mb-1">
186-
<strong>Time Left:</strong>
187-
<span id="cm-global-countdown" class="badge badge-info">${formatCountdown(diff)}</span>
188-
</p>
179+
<div class="mb-3">
180+
<strong class="d-block mb-1" style="color: #888; font-size: 12px; text-transform: uppercase;">Time Remaining:</strong>
181+
<div id="cm-global-countdown" style="font-family: monospace; font-size: 1.2rem; font-weight: bold; color: #fff;">${formatCountdown(diff)}</div>
182+
</div>
189183
`;
190184

191185
// Check for expiration warnings
@@ -218,8 +212,8 @@
218212

219213
if (diff <= FIFTEEN_MIN) {
220214
warningHTML = `
221-
<div class="alert alert-warning alert-sm p-2 mb-2" role="alert" style="font-size: 0.85rem;">
222-
<i class="fas fa-exclamation-triangle"></i> ${warningMessage}
215+
<div class="alert alert-warning py-2 px-2 mb-3 small" role="alert" style="background-color: rgba(235, 184, 80, 0.1); border: 1px solid #ebb850; color: #ebb850;">
216+
<i class="fas fa-exclamation-triangle mr-1"></i> ${warningMessage}
223217
</div>
224218
`;
225219
}
@@ -230,30 +224,36 @@
230224
const headerTimeEl = document.getElementById('cm-global-header-time');
231225
if (headerTimeEl && timeLeft) {
232226
headerTimeEl.textContent = formatCountdown(timeLeft);
233-
headerTimeEl.style.display = 'inline';
227+
headerTimeEl.classList.remove('d-none');
234228
} else if (headerTimeEl) {
235-
headerTimeEl.style.display = 'none';
229+
headerTimeEl.classList.add('d-none');
230+
}
231+
232+
let categoryHTML = '';
233+
if (challengeName) {
234+
categoryHTML = `
235+
<div class="mb-3">
236+
<strong class="d-block mb-1" style="color: #888; font-size: 12px; text-transform: uppercase;">Lab:</strong>
237+
<div style="font-size: 13px; font-weight: 500; color: #fff; word-wrap: break-word; overflow-wrap: break-word; white-space: normal; line-height: 1.4;">
238+
${challengeName}
239+
</div>
240+
</div>
241+
`;
236242
}
237243

238244
const html = `
245+
${categoryHTML}
239246
${warningHTML}
240247
${countdownHTML}
241248
242-
<div class="mb-3">
243-
<small class="text-muted font-weight-bold">Connection Info:</small>
244-
<div class="p-2 bg-light rounded" style="font-family: monospace; font-size: 0.85rem; word-break: break-all; border: 1px solid #ddd;">
245-
${connectionInfo ? connectionInfo.replace(/\n/g, '<br>') : 'Waiting for connection details...'}
246-
</div>
247-
</div>
248-
249-
<div class="btn-group btn-group-sm d-flex" role="group">
250-
<button type="button" class="btn btn-warning flex-fill" onclick="window.cmGlobalPanel.renew()" title="Add more time">
249+
<div class="d-flex mt-3" style="gap: 10px;">
250+
<button type="button" class="flex-fill floating-btn-lab" style="background-color:#ebb850; color: #000;" onclick="window.cmGlobalPanel.renew()" title="Add more time">
251251
<i class="fas fa-clock"></i> Renew
252252
</button>
253-
<button type="button" class="btn btn-info flex-fill" onclick="window.cmGlobalPanel.restart()" title="Restart instance">
253+
<button type="button" class="flex-fill floating-btn-lab" style="background-color:#479abf; color: #fff;" onclick="window.cmGlobalPanel.restart()" title="Restart instance">
254254
<i class="fas fa-redo"></i> Restart
255255
</button>
256-
<button type="button" class="btn btn-danger flex-fill" onclick="window.cmGlobalPanel.destroy()" title="Destroy instance">
256+
<button type="button" class="flex-fill floating-btn-lab" style="background-color:#b43c2c; color: #fff;" onclick="window.cmGlobalPanel.destroy()" title="Destroy instance">
257257
<i class="fas fa-trash"></i> Destroy
258258
</button>
259259
</div>
@@ -461,8 +461,23 @@
461461
if (data.success) {
462462
// Reset warning flags
463463
setWarningsShown({ fifteen: false, ten: false, five: false });
464-
// Refresh instance data
464+
465+
// If response includes updated instance data, use it immediately
466+
if (data.data && data.data.until) {
467+
const activeInstance = getActiveInstance();
468+
if (activeInstance) {
469+
activeInstance.until = data.data.until;
470+
if (data.data.connectionInfo) {
471+
activeInstance.connectionInfo = data.data.connectionInfo;
472+
}
473+
setActiveInstance(activeInstance);
474+
updatePanelContent(activeInstance);
475+
}
476+
}
477+
478+
// Also poll to ensure we're in sync
465479
pollInstanceStatus();
480+
466481
if (window.CTFd && window.CTFd._functions && window.CTFd._functions.events) {
467482
CTFd._functions.events.eventAlert({
468483
title: "Success",
@@ -537,7 +552,19 @@
537552
.then(response => response.json())
538553
.then(data => {
539554
if (data.success) {
555+
// Update immediately if response includes instance data
556+
if (data.data) {
557+
const activeInstance = getActiveInstance();
558+
if (activeInstance) {
559+
Object.assign(activeInstance, data.data);
560+
setActiveInstance(activeInstance);
561+
updatePanelContent(activeInstance);
562+
}
563+
}
564+
565+
// Also poll to ensure we're in sync
540566
pollInstanceStatus();
567+
541568
if (window.CTFd && window.CTFd._functions && window.CTFd._functions.events) {
542569
CTFd._functions.events.eventAlert({
543570
title: "Success",
@@ -565,7 +592,7 @@
565592
},
566593

567594
destroy: function() {
568-
if (!confirm('Are you sure you want to destroy your instance? All progress will be lost.')) {
595+
if (!confirm('Are you sure you want to destroy your instance? Your Azure lab environment will be destroyed.')) {
569596
return;
570597
}
571598

@@ -627,6 +654,7 @@
627654
const data = {
628655
challengeId: challengeId,
629656
category: category,
657+
challengeName: instanceData.challengeName || 'Lab Instance',
630658
connectionInfo: instanceData.connectionInfo,
631659
until: instanceData.until,
632660
since: instanceData.since

0 commit comments

Comments
 (0)