Skip to content

Commit 7d18c61

Browse files
committed
change video link issue, add embedded feedback form, testing for version control feature
1 parent 8da8e15 commit 7d18c61

6 files changed

Lines changed: 389 additions & 37 deletions

File tree

feedback-loader.js

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
/*************************************************
2+
* Feedback Modal Loader (Search-style)
3+
*************************************************/
4+
5+
const FEEDBACK_ENDPOINT =
6+
"https://script.google.com/macros/s/AKfycbwH1QM0zc4DcYXcG0CJIVoien-vj8VmCi0wEUxeEdZX0EbROxx6rWvLgIi2vSHtd9TBIQ/exec";
7+
8+
/* Wire button safely */
9+
document.addEventListener("DOMContentLoaded", () => {
10+
const btn = document.querySelector(".feedback-btn");
11+
if (!btn) return;
12+
btn.addEventListener("click", openFeedback);
13+
});
14+
15+
/* Open feedback modal */
16+
window.openFeedback = function () {
17+
const overlay = document.getElementById("modal-overlay");
18+
const modal = document.getElementById("modal-content");
19+
20+
if (!overlay || !modal) return;
21+
22+
overlay.hidden = false;
23+
modal.hidden = false;
24+
document.body.style.overflow = "hidden";
25+
26+
modal.innerHTML = `
27+
<div class="feedback-wrapper search-wrapper" role="dialog" aria-modal="true">
28+
29+
<!-- Header -->
30+
<div class="sw-header">
31+
<svg class="sw-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
32+
<path d="M21 15a4 4 0 0 1-4 4H7l-4 4V7a4 4 0 0 1 4-4h10a4 4 0 0 1 4 4z"></path>
33+
</svg>
34+
<h2 class="sw-title">Send Feedback</h2>
35+
<button class="sw-close" data-feedback-close aria-label="Close feedback">
36+
<svg viewBox="0 0 24 24" width="22" height="22" fill="none" stroke="currentColor" stroke-width="3">
37+
<line x1="18" y1="6" x2="6" y2="18"></line>
38+
<line x1="6" y1="6" x2="18" y2="18"></line>
39+
</svg>
40+
</button>
41+
</div>
42+
43+
<!-- Form -->
44+
<form id="feedbackForm" class="feedback-form">
45+
46+
<div class="field">
47+
<label>What is your role? *</label>
48+
<select name="role" required class="sw-input">
49+
<option value="">Select</option>
50+
<option>Author</option>
51+
<option>Instructor</option>
52+
<option>Student</option>
53+
</select>
54+
</div>
55+
56+
<div class="field">
57+
<label>Which part of the Launchpad are you commenting on? *</label>
58+
<input name="section" required class="sw-input" />
59+
</div>
60+
61+
<div class="field">
62+
<label>If you notice an issue, please explain it.</label>
63+
<textarea name="issue" class="sw-input"></textarea>
64+
</div>
65+
66+
<div class="field">
67+
<label>Optional: Email or contact</label>
68+
<input name="contact" class="sw-input" />
69+
</div>
70+
71+
<div class="sw-actions">
72+
<button type="submit" class="sw-btn">
73+
Submit Feedback
74+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
75+
<path d="M9 18l6-6-6-6"></path>
76+
</svg>
77+
</button>
78+
</div>
79+
80+
</form>
81+
</div>
82+
`;
83+
84+
attachFeedbackHandlers();
85+
};
86+
87+
/* Submit + close logic */
88+
function attachFeedbackHandlers() {
89+
const overlay = document.getElementById("modal-overlay");
90+
const modal = document.getElementById("modal-content");
91+
const form = modal.querySelector("#feedbackForm");
92+
93+
if (!form) return;
94+
95+
form.addEventListener("submit", async (e) => {
96+
e.preventDefault();
97+
98+
const formData = new FormData(form);
99+
formData.append("timestamp_client", new Date().toISOString());
100+
formData.append(
101+
"timezone",
102+
Intl.DateTimeFormat().resolvedOptions().timeZone
103+
);
104+
formData.append("page", window.location.href);
105+
106+
await fetch(FEEDBACK_ENDPOINT, {
107+
method: "POST",
108+
body: new URLSearchParams(formData),
109+
});
110+
111+
form.innerHTML = `
112+
<div class="sw-results">
113+
<p><strong>Thank you!</strong></p>
114+
<p>Your feedback has been submitted.</p>
115+
</div>
116+
`;
117+
});
118+
119+
const close = () => {
120+
overlay.hidden = true;
121+
modal.hidden = true;
122+
modal.innerHTML = "";
123+
document.body.style.overflow = "";
124+
};
125+
126+
overlay.addEventListener("click", close, { once: true });
127+
modal
128+
.querySelectorAll("[data-feedback-close]")
129+
.forEach((btn) => btn.addEventListener("click", close));
130+
}

feedback.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
const form = document.getElementById("feedbackForm");
2+
3+
form.addEventListener("submit", e => {
4+
e.preventDefault();
5+
6+
fetch("https://script.google.com/macros/s/AKfycbwTdBpSEDirKJp2KDqHT56N6TNwEx9zkVvGsTRBLc1TL70lTJ_ERmjSWky3UG6gbwYQ6g/exec", {
7+
method: "POST",
8+
body: new URLSearchParams(new FormData(form)),
9+
mode: "no-cors"
10+
}).then(() => {
11+
alert("submitted");
12+
closeFeedback();
13+
});
14+
});

index.html

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
<div class="header-left">
1515
<button id="menu-toggle" class="menu-toggle"></button>
1616

17-
<a href="/" class="brand" aria-label="OLI Torus Launchpad (home)">
17+
<a href="#" class="brand" aria-label="OLI Torus Launchpad (home)">
1818
<img src="assets/images/logo.png" alt="" class="brand-logo" aria-hidden="true" />
1919
<span class="brand-oli">OLI</span>
2020
<span class="brand-torus">Torus</span>
@@ -33,12 +33,13 @@
3333
<line x1="21" y1="21" x2="16.65" y2="16.65"></line>
3434
</svg>
3535
</a>
36-
<a href="https://forms.gle/3ta7TqVyWjRdgTmx9"
37-
target="_blank"
38-
class="feedback-btn"
39-
aria-label="Feedback">
36+
<button
37+
class="feedback-btn"
38+
aria-label="Feedback"
39+
onclick="openFeedback()">
4040
<img src="assets/images/feedback.png" alt="Feedback" class="feedback-icon" />
41-
</a>
41+
</button>
42+
4243

4344
<button class="home-btn" aria-label="Home" data-page="pages/introduction/logging-in.html">
4445
<img src="assets/images/home.png" alt="Home" class="home-icon" />
@@ -253,9 +254,15 @@
253254
</main>
254255
</div>
255256

256-
<script src="main.js"></script>
257-
<div id="searchOverlay" hidden></div>
258-
<div id="searchModal" hidden></div>
259-
<script src="search-wrapper-loader.js" defer></script>
257+
<script src="main.js"></script>
258+
<script src="feedback-loader.js" defer></script>
259+
260+
<div id="feedbackOverlay" hidden></div>
261+
<div id="feedbackModal" hidden></div>
262+
263+
<div id="searchOverlay" hidden></div>
264+
<div id="searchModal" hidden></div>
265+
<script src="search-wrapper-loader.js" defer></script>
266+
260267
</body>
261268
</html>

main.js

Lines changed: 27 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,30 +4,44 @@ console.log('main.js loaded');
44

55

66
(function () {
7-
// --- small DOM helpers ---
7+
// --- DOM helpers ---
88
const $all = (sel, root = document) => Array.from(root.querySelectorAll(sel));
99
const $ = (sel, root = document) => root.querySelector(sel);
1010

1111

1212
// Load welcome page by default on first visit
1313
window.addEventListener("DOMContentLoaded", () => {
1414
const content = document.querySelector(".content");
15-
if (content) {
16-
fetch("pages/introduction/welcome.html")
17-
.then(r => r.text())
18-
.then(html => {
19-
content.innerHTML = html;
20-
const li = document.querySelector('.submenu li[data-page="pages/welcome.html"]');
21-
if (li) {
22-
document.querySelectorAll(".submenu li.selected").forEach(el => el.classList.remove("selected"));
23-
li.classList.add("selected");
24-
}
25-
})
26-
.catch(err => console.error("Error loading welcome page:", err));
15+
if (!content) return;
16+
17+
const params = new URLSearchParams(window.location.search);
18+
const pageFromUrl = params.get("page");
19+
20+
if (pageFromUrl) {
21+
loadPage(pageFromUrl);
22+
23+
const li = document.querySelector(`.submenu li[data-page="${pageFromUrl}"]`);
24+
if (li) {
25+
document
26+
.querySelectorAll(".submenu li.selected")
27+
.forEach(el => el.classList.remove("selected"));
28+
li.classList.add("selected");
29+
}
30+
31+
return;
2732
}
33+
34+
// fallback only when no ?page=
35+
fetch("pages/introduction/welcome.html")
36+
.then(r => r.text())
37+
.then(html => {
38+
content.innerHTML = html;
39+
})
40+
.catch(err => console.error("Error loading welcome page:", err));
2841
});
2942

3043

44+
3145
// clean up badges in the sidebar so text isn’t duplicated in labels
3246
document.querySelectorAll('.submenu .badge').forEach(badge => {
3347
if (!badge.hasAttribute('data-label')) {
@@ -320,5 +334,4 @@ document.addEventListener('click', (e) => {
320334
setTimeout(() => li.classList.remove('spotlight'), 1100);
321335
});
322336

323-
324337
})();

pages/set-up-your-course/create-a-new-project.html

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,7 @@
33
<head>
44
<meta charset="UTF-8" />
55
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
6-
7-
<!-- Existing site styles (includes .video-container, .title-bar, .page-content) -->
86
<link rel="stylesheet" href="./style.css" />
9-
10-
<!-- Optional: silence favicon 404 in dev -->
117
<link rel="icon" href="data:,">
128
</head>
139
<body>
@@ -36,7 +32,13 @@
3632

3733
<!-- UPDATE THIS: video title -->
3834
<div class="title-bar">
39-
Create a New Project
35+
<span class="video-title">Create a New Project</span>
36+
37+
<span class="version-badge">
38+
(Placeholder)This video applies to Torus <strong>0.32.3</strong> and newer <!-- UPDATE THIS: version number -->
39+
</span>
40+
</div>
41+
4042
</div>
4143

4244
</div>

0 commit comments

Comments
 (0)