Lashtw commited on
Commit
e815114
·
verified ·
1 Parent(s): 6ec003e

Upload 9 files

Browse files
src/services/auth.js CHANGED
@@ -84,7 +84,15 @@ export async function checkInstructorPermission(user) {
84
 
85
  const email = user.email;
86
  const instructorRef = doc(db, INSTRUCTORS_COLLECTION, email);
87
- const snap = await getDoc(instructorRef);
 
 
 
 
 
 
 
 
88
 
89
  // Bootstrap Super Admin
90
  if (email === SUPER_ADMIN_EMAIL) {
 
84
 
85
  const email = user.email;
86
  const instructorRef = doc(db, INSTRUCTORS_COLLECTION, email);
87
+ let snap;
88
+
89
+ try {
90
+ snap = await getDoc(instructorRef);
91
+ } catch (error) {
92
+ console.warn("Instructor Permission Check Failed (likely not whitelisted):", error.code);
93
+ // If permission denied, it means they are not allowed to read the doc => likely not in whitelist
94
+ return null;
95
+ }
96
 
97
  // Bootstrap Super Admin
98
  if (email === SUPER_ADMIN_EMAIL) {
src/views/InstructorView.js CHANGED
@@ -336,6 +336,25 @@ export async function renderInstructorView() {
336
  }
337
 
338
  export function setupInstructorEvents() {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
339
  let roomUnsubscribe = null;
340
  let currentInstructor = null;
341
 
@@ -1239,7 +1258,7 @@ export function setupInstructorEvents() {
1239
  document.getElementById('broadcast-content').classList.add('hidden');
1240
  const stage = document.getElementById('stage-view');
1241
  stage.classList.remove('hidden');
1242
- document.getElementById('stage-prompt').textContent = (prompt || '').trim();
1243
  document.getElementById('stage-author').textContent = author;
1244
  };
1245
 
@@ -1353,7 +1372,7 @@ export function setupInstructorEvents() {
1353
  onchange="handlePromptSelection(this)">
1354
  </div>
1355
  <!-- Prompt Content -->
1356
- <div class="bg-black/30 rounded p-2 flex-1 overflow-y-auto font-mono text-green-300 whitespace-pre-wrap custom-scrollbar text-base leading-snug group-hover:text-green-200 transaction-colors mb-2">${(p.prompt || '').trim()}</div>
1357
 
1358
  <!-- Footer: Time + Actions -->
1359
  <div class="flex justify-between items-center text-[10px] text-gray-500 mt-auto">
@@ -1532,7 +1551,7 @@ export function setupInstructorEvents() {
1532
  </div>
1533
  <!-- Prompt Content: Larger Text (text-4xl) -->
1534
  <div class="flex-1 overflow-y-auto font-mono text-green-300 text-3xl leading-relaxed whitespace-pre-wrap p-2 hover:bg-white/5 transition-colors rounded custom-scrollbar text-left">
1535
- ${(item.prompt || '').trim()}
1536
  </div>
1537
  `;
1538
  grid.appendChild(col);
@@ -1848,7 +1867,7 @@ export function setupInstructorEvents() {
1848
  document.getElementById('broadcast-author').textContent = student.nickname;
1849
  document.getElementById('broadcast-challenge').textContent = title;
1850
  // content is already just text, but let's be safe
1851
- document.getElementById('broadcast-prompt').textContent = (p.prompt || p.code || '').trim(); // robust fallback
1852
 
1853
  // Store IDs for actions
1854
  modal.dataset.userId = userId;
 
336
  }
337
 
338
  export function setupInstructorEvents() {
339
+ // Utility for cleaning prompt indentation
340
+ function stripIndent(str) {
341
+ if (!str) return '';
342
+ // Remove first line if empty (common in template literals)
343
+ const lines = str.replace(/^\n/, '').split('\n');
344
+
345
+ // Find min indentation (ignoring empty lines)
346
+ const minIndent = lines.reduce((min, line) => {
347
+ if (!line.trim()) return min;
348
+ const indent = line.match(/^\s*/)[0].length;
349
+ return Math.min(min, indent);
350
+ }, Infinity);
351
+
352
+ if (minIndent === Infinity) return str.trim(); // No non-empty lines
353
+
354
+ // Strip indent
355
+ return lines.map(line => line.slice(minIndent)).join('\n').trim();
356
+ }
357
+
358
  let roomUnsubscribe = null;
359
  let currentInstructor = null;
360
 
 
1258
  document.getElementById('broadcast-content').classList.add('hidden');
1259
  const stage = document.getElementById('stage-view');
1260
  stage.classList.remove('hidden');
1261
+ document.getElementById('stage-prompt').textContent = stripIndent(prompt || '');
1262
  document.getElementById('stage-author').textContent = author;
1263
  };
1264
 
 
1372
  onchange="handlePromptSelection(this)">
1373
  </div>
1374
  <!-- Prompt Content -->
1375
+ <div class="bg-black/30 rounded p-2 flex-1 overflow-y-auto font-mono text-green-300 whitespace-pre-wrap custom-scrollbar text-base leading-snug group-hover:text-green-200 transaction-colors mb-2">${stripIndent(p.prompt)}</div>
1376
 
1377
  <!-- Footer: Time + Actions -->
1378
  <div class="flex justify-between items-center text-[10px] text-gray-500 mt-auto">
 
1551
  </div>
1552
  <!-- Prompt Content: Larger Text (text-4xl) -->
1553
  <div class="flex-1 overflow-y-auto font-mono text-green-300 text-3xl leading-relaxed whitespace-pre-wrap p-2 hover:bg-white/5 transition-colors rounded custom-scrollbar text-left">
1554
+ ${stripIndent(item.prompt)}
1555
  </div>
1556
  `;
1557
  grid.appendChild(col);
 
1867
  document.getElementById('broadcast-author').textContent = student.nickname;
1868
  document.getElementById('broadcast-challenge').textContent = title;
1869
  // content is already just text, but let's be safe
1870
+ document.getElementById('broadcast-prompt').textContent = stripIndent(p.prompt || p.code || ''); // robust fallback
1871
 
1872
  // Store IDs for actions
1873
  modal.dataset.userId = userId;