Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ff48befb8a | ||
|
|
9391dfd8d7 | ||
|
|
467e48e1da | ||
|
|
566410eea5 | ||
|
|
37afc2957b | ||
|
|
b1763135aa |
@@ -7,6 +7,7 @@ SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|||||||
DIST_DIR="$SCRIPT_DIR/dist"
|
DIST_DIR="$SCRIPT_DIR/dist"
|
||||||
CSS_FILE="$SCRIPT_DIR/style.css"
|
CSS_FILE="$SCRIPT_DIR/style.css"
|
||||||
JS_FILE="$SCRIPT_DIR/kantine.js"
|
JS_FILE="$SCRIPT_DIR/kantine.js"
|
||||||
|
FAVICON_FILE="$SCRIPT_DIR/favicon.svg"
|
||||||
|
|
||||||
# === VERSION ===
|
# === VERSION ===
|
||||||
if [ -f "$SCRIPT_DIR/version.txt" ]; then
|
if [ -f "$SCRIPT_DIR/version.txt" ]; then
|
||||||
@@ -23,6 +24,11 @@ echo "=== Kantine Bookmarklet Builder ($VERSION) ==="
|
|||||||
# Check files exist
|
# Check files exist
|
||||||
if [ ! -f "$CSS_FILE" ]; then echo "ERROR: $CSS_FILE not found"; exit 1; fi
|
if [ ! -f "$CSS_FILE" ]; then echo "ERROR: $CSS_FILE not found"; exit 1; fi
|
||||||
if [ ! -f "$JS_FILE" ]; then echo "ERROR: $JS_FILE not found"; exit 1; fi
|
if [ ! -f "$JS_FILE" ]; then echo "ERROR: $JS_FILE not found"; exit 1; fi
|
||||||
|
if [ ! -f "$FAVICON_FILE" ]; then echo "ERROR: $FAVICON_FILE not found"; exit 1; fi
|
||||||
|
|
||||||
|
# Generate favicon Base64 data URI
|
||||||
|
FAVICON_B64=$(base64 -w0 "$FAVICON_FILE")
|
||||||
|
FAVICON_URI="data:image/svg+xml;base64,${FAVICON_B64}"
|
||||||
|
|
||||||
CSS_CONTENT=$(cat "$CSS_FILE")
|
CSS_CONTENT=$(cat "$CSS_FILE")
|
||||||
|
|
||||||
@@ -101,6 +107,7 @@ cat > "$DIST_DIR/install.html" << INSTALLEOF
|
|||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<title>Kantine Wrapper Installer ($VERSION)</title>
|
<title>Kantine Wrapper Installer ($VERSION)</title>
|
||||||
|
<link rel="icon" type="image/svg+xml" href="$FAVICON_URI">
|
||||||
<style>
|
<style>
|
||||||
body { font-family: 'Inter', sans-serif; max-width: 600px; margin: 40px auto; padding: 20px; background: #1a1a2e; color: #eee; }
|
body { font-family: 'Inter', sans-serif; max-width: 600px; margin: 40px auto; padding: 20px; background: #1a1a2e; color: #eee; }
|
||||||
h1 { color: #029AA8; } /* Knapp Teal */
|
h1 { color: #029AA8; } /* Knapp Teal */
|
||||||
|
|||||||
@@ -1,3 +1,12 @@
|
|||||||
|
## v1.4.20
|
||||||
|
- 🐛 **Bugfix**: Der Badge-Counter im „Nächste Woche"-Tab wird jetzt sofort nach einer Bestellung oder Stornierung aktualisiert.
|
||||||
|
|
||||||
|
## v1.4.19
|
||||||
|
- 🎨 **Feature**: Eigenes Favicon für die Installer-Seite hinzugefügt (Dreieck + Gabel & Messer). Wird beim Drag & Drop in die Lesezeichenleiste als Icon übernommen.
|
||||||
|
|
||||||
|
## v1.4.18
|
||||||
|
- 🧪 **Testing**: Die automatische DOM-Testing Suite (`test_dom.js`) wurde massiv ausgebaut. Sie prüft nun neben der Alarmglocke und den Highlights auch systematisch alle anderen UI-Komponenten (Login-Modal, History-Modal, Versionen-Modal, Theme-Toggle, und Navigation Tabs) auf korrekte Event-Listener-Bindungen, um Regressionen (tote Buttons) endgültig auszuschließen.
|
||||||
|
|
||||||
## v1.4.17
|
## v1.4.17
|
||||||
- 🐛 **Bugfix**: Regression behoben: Der "Persönliche Highlights" (Stern-Button) Dialog öffnet sich nun wieder korrekt.
|
- 🐛 **Bugfix**: Regression behoben: Der "Persönliche Highlights" (Stern-Button) Dialog öffnet sich nun wieder korrekt.
|
||||||
- 🧪 **Testing**: Es wurde ein initialer UI-Testing-Hook (`test_dom.js` mit `jsdom`) in die Build-Pipeline integriert, um kritische DOM Event-Listener Regressionen (wie den Highlights-Button und die Alarmglocke) automatisch zu preventen.
|
- 🧪 **Testing**: Es wurde ein initialer UI-Testing-Hook (`test_dom.js` mit `jsdom`) in die Build-Pipeline integriert, um kritische DOM Event-Listener Regressionen (wie den Highlights-Button und die Alarmglocke) automatisch zu preventen.
|
||||||
|
|||||||
2
dist/bookmarklet-payload.js
vendored
2
dist/bookmarklet-payload.js
vendored
File diff suppressed because one or more lines are too long
2
dist/bookmarklet.txt
vendored
2
dist/bookmarklet.txt
vendored
File diff suppressed because one or more lines are too long
25
dist/install.html
vendored
25
dist/install.html
vendored
File diff suppressed because one or more lines are too long
9
dist/kantine-standalone.html
vendored
9
dist/kantine-standalone.html
vendored
@@ -2021,7 +2021,7 @@ body {
|
|||||||
<div class="brand">
|
<div class="brand">
|
||||||
<span class="material-icons-round logo-icon">restaurant_menu</span>
|
<span class="material-icons-round logo-icon">restaurant_menu</span>
|
||||||
<div class="header-left">
|
<div class="header-left">
|
||||||
<h1>Kantinen Übersicht <small class="version-tag" style="font-size: 0.6em; opacity: 0.7; font-weight: 400; cursor: pointer;" title="Klick für Versionsmenü">v1.4.17</small></h1>
|
<h1>Kantinen Übersicht <small class="version-tag" style="font-size: 0.6em; opacity: 0.7; font-weight: 400; cursor: pointer;" title="Klick für Versionsmenü">v1.4.20</small></h1>
|
||||||
<div id="last-updated-subtitle" class="subtitle"></div>
|
<div id="last-updated-subtitle" class="subtitle"></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="nav-group" style="margin-left: 1rem;">
|
<div class="nav-group" style="margin-left: 1rem;">
|
||||||
@@ -2163,7 +2163,7 @@ body {
|
|||||||
</div>
|
</div>
|
||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
<div style="margin-bottom: 1rem;">
|
<div style="margin-bottom: 1rem;">
|
||||||
<strong>Aktuell:</strong> <span id="version-current">v1.4.17</span>
|
<strong>Aktuell:</strong> <span id="version-current">v1.4.20</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="dev-toggle">
|
<div class="dev-toggle">
|
||||||
<label style="display:flex;align-items:center;gap:8px;cursor:pointer;">
|
<label style="display:flex;align-items:center;gap:8px;cursor:pointer;">
|
||||||
@@ -2531,6 +2531,7 @@ body {
|
|||||||
}
|
}
|
||||||
console.log(`Fetched ${results.length} orders, mapped active ones.`);
|
console.log(`Fetched ${results.length} orders, mapped active ones.`);
|
||||||
renderVisibleWeeks();
|
renderVisibleWeeks();
|
||||||
|
updateNextWeekBadge();
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error fetching orders:', error);
|
console.error('Error fetching orders:', error);
|
||||||
@@ -4010,7 +4011,7 @@ body {
|
|||||||
|
|
||||||
// Periodic update check (runs on init + every hour)
|
// Periodic update check (runs on init + every hour)
|
||||||
async function checkForUpdates() {
|
async function checkForUpdates() {
|
||||||
const currentVersion = 'v1.4.17';
|
const currentVersion = 'v1.4.20';
|
||||||
const devMode = localStorage.getItem('kantine_dev_mode') === 'true';
|
const devMode = localStorage.getItem('kantine_dev_mode') === 'true';
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -4051,7 +4052,7 @@ body {
|
|||||||
const modal = document.getElementById('version-modal');
|
const modal = document.getElementById('version-modal');
|
||||||
const container = document.getElementById('version-list-container');
|
const container = document.getElementById('version-list-container');
|
||||||
const devToggle = document.getElementById('dev-mode-toggle');
|
const devToggle = document.getElementById('dev-mode-toggle');
|
||||||
const currentVersion = 'v1.4.17';
|
const currentVersion = 'v1.4.20';
|
||||||
|
|
||||||
if (!modal) return;
|
if (!modal) return;
|
||||||
modal.classList.remove('hidden');
|
modal.classList.remove('hidden');
|
||||||
|
|||||||
29
favicon.svg
Executable file
29
favicon.svg
Executable file
@@ -0,0 +1,29 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" width="64" height="64">
|
||||||
|
<!-- Fork (left, with gap to triangle) -->
|
||||||
|
<g transform="translate(2, 10)">
|
||||||
|
<!-- Tines -->
|
||||||
|
<rect x="1" y="0" width="1.8" height="16" rx="0.9" fill="#333"/>
|
||||||
|
<rect x="4.6" y="0" width="1.8" height="16" rx="0.9" fill="#333"/>
|
||||||
|
<rect x="8.2" y="0" width="1.8" height="16" rx="0.9" fill="#333"/>
|
||||||
|
<!-- Connector -->
|
||||||
|
<rect x="1" y="14" width="9" height="3.5" rx="1.5" fill="#333"/>
|
||||||
|
<!-- Handle -->
|
||||||
|
<rect x="3.5" y="16.5" width="4" height="24" rx="2" fill="#333"/>
|
||||||
|
</g>
|
||||||
|
|
||||||
|
<!-- Triangle (center, equilateral aspect ratio ~1:0.866) -->
|
||||||
|
<!-- Equilateral: base=28, height=24.25 => keeps proper ratio -->
|
||||||
|
<polygon points="32,8 47,48 17,48" fill="none" stroke="#333" stroke-width="4" stroke-linejoin="round"/>
|
||||||
|
|
||||||
|
<!-- Knife (right, with gap to triangle) -->
|
||||||
|
<g transform="translate(50, 10)">
|
||||||
|
<!-- Blade (slight curve) -->
|
||||||
|
<path d="M3,0 C3,0 3,0 3,0 L3,17 L10,14 C10,6 7,0 3,0 Z" fill="#333"/>
|
||||||
|
<!-- Spine -->
|
||||||
|
<rect x="1.5" y="0" width="2" height="18" rx="1" fill="#333"/>
|
||||||
|
<!-- Bolster -->
|
||||||
|
<rect x="1.5" y="16.5" width="8.5" height="3.5" rx="1.2" fill="#333"/>
|
||||||
|
<!-- Handle -->
|
||||||
|
<rect x="3.5" y="19" width="4" height="22" rx="2" fill="#333"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.3 KiB |
@@ -581,6 +581,7 @@
|
|||||||
}
|
}
|
||||||
console.log(`Fetched ${results.length} orders, mapped active ones.`);
|
console.log(`Fetched ${results.length} orders, mapped active ones.`);
|
||||||
renderVisibleWeeks();
|
renderVisibleWeeks();
|
||||||
|
updateNextWeekBadge();
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error fetching orders:', error);
|
console.error('Error fetching orders:', error);
|
||||||
|
|||||||
@@ -29,6 +29,43 @@ const html = `
|
|||||||
<button id="btn-add-tag">Add</button>
|
<button id="btn-add-tag">Add</button>
|
||||||
<ul id="tags-list"></ul>
|
<ul id="tags-list"></ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- Mocks for Login Modal -->
|
||||||
|
<button id="btn-login-open">Login</button>
|
||||||
|
<div id="login-modal" class="modal hidden">
|
||||||
|
<button id="btn-login-close">Close</button>
|
||||||
|
<form id="login-form"></form>
|
||||||
|
<div id="login-error" class="hidden"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Mocks for History Modal -->
|
||||||
|
<button id="btn-history">History</button>
|
||||||
|
<div id="history-modal" class="modal hidden">
|
||||||
|
<button id="btn-history-close">Close</button>
|
||||||
|
<div id="history-loading" class="hidden"></div>
|
||||||
|
<div id="history-content"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Mocks for Version Modal -->
|
||||||
|
<span class="version-tag">v1.4.17</span>
|
||||||
|
<div id="version-modal" class="modal hidden">
|
||||||
|
<button id="btn-version-close">Close</button>
|
||||||
|
<button id="btn-clear-cache">Clear</button>
|
||||||
|
<span id="version-current"></span>
|
||||||
|
<div id="version-list-container"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Mocks for Theme Toggle -->
|
||||||
|
<button id="theme-toggle"><span class="theme-icon">light_mode</span></button>
|
||||||
|
|
||||||
|
<!-- Mocks for Navigation Tabs -->
|
||||||
|
<button id="btn-this-week" class="active">This Week</button>
|
||||||
|
<button id="btn-next-week">Next Week</button>
|
||||||
|
|
||||||
|
<button id="btn-refresh">Refresh</button>
|
||||||
|
<button id="btn-logout">Logout</button>
|
||||||
|
<div class="order-history-header">Header</div>
|
||||||
|
<button id="btn-error-redirect">Error Redirect</button>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
`;
|
`;
|
||||||
@@ -37,7 +74,8 @@ log("Reading file jsCode...");
|
|||||||
const jsCode = fs.readFileSync('kantine.js', 'utf8')
|
const jsCode = fs.readFileSync('kantine.js', 'utf8')
|
||||||
.replace('(function () {', '')
|
.replace('(function () {', '')
|
||||||
.replace('})();', '')
|
.replace('})();', '')
|
||||||
.replace('if (window.__KANTINE_LOADED) return;', '');
|
.replace('if (window.__KANTINE_LOADED) return;', '')
|
||||||
|
.replace('window.location.reload();', 'window.__RELOAD_CALLED = true;');
|
||||||
|
|
||||||
log("Instantiating JSDOM...");
|
log("Instantiating JSDOM...");
|
||||||
const dom = new JSDOM(html, { runScripts: "dangerously", url: "http://localhost/" });
|
const dom = new JSDOM(html, { runScripts: "dangerously", url: "http://localhost/" });
|
||||||
@@ -74,9 +112,6 @@ const testCode = `
|
|||||||
const hlModal = document.getElementById('highlights-modal');
|
const hlModal = document.getElementById('highlights-modal');
|
||||||
if (!hlModal.classList.contains('hidden')) throw new Error("Highlights modal should be hidden initially");
|
if (!hlModal.classList.contains('hidden')) throw new Error("Highlights modal should be hidden initially");
|
||||||
|
|
||||||
// Call bindEvents manually to attach the listeners since the IIFE is stripped
|
|
||||||
bindEvents();
|
|
||||||
|
|
||||||
// Click to open
|
// Click to open
|
||||||
document.getElementById('btn-highlights').click();
|
document.getElementById('btn-highlights').click();
|
||||||
if (hlModal.classList.contains('hidden')) throw new Error("Highlights modal did not open upon clicking btn-highlights!");
|
if (hlModal.classList.contains('hidden')) throw new Error("Highlights modal did not open upon clicking btn-highlights!");
|
||||||
@@ -87,6 +122,56 @@ const testCode = `
|
|||||||
|
|
||||||
console.log("✅ Highlights Modal Test Passed");
|
console.log("✅ Highlights Modal Test Passed");
|
||||||
|
|
||||||
|
console.log("--- Testing Login Modal ---");
|
||||||
|
const loginModal = document.getElementById('login-modal');
|
||||||
|
document.getElementById('btn-login-open').click();
|
||||||
|
if (loginModal.classList.contains('hidden')) throw new Error("Login modal should open");
|
||||||
|
document.getElementById('btn-login-close').click();
|
||||||
|
if (!loginModal.classList.contains('hidden')) throw new Error("Login modal should close");
|
||||||
|
console.log("✅ Login Modal Test Passed");
|
||||||
|
|
||||||
|
console.log("--- Testing History Modal ---");
|
||||||
|
// We need authToken to be truthy to open history modal
|
||||||
|
authToken = "fake_token";
|
||||||
|
const historyModal = document.getElementById('history-modal');
|
||||||
|
document.getElementById('btn-history').click();
|
||||||
|
if (historyModal.classList.contains('hidden')) throw new Error("History modal should open");
|
||||||
|
document.getElementById('btn-history-close').click();
|
||||||
|
if (!historyModal.classList.contains('hidden')) throw new Error("History modal should close");
|
||||||
|
console.log("✅ History Modal Test Passed");
|
||||||
|
|
||||||
|
console.log("--- Testing Version Modal ---");
|
||||||
|
const versionModal = document.getElementById('version-modal');
|
||||||
|
document.querySelector('.version-tag').click();
|
||||||
|
if (versionModal.classList.contains('hidden')) throw new Error("Version modal should open");
|
||||||
|
document.getElementById('btn-version-close').click();
|
||||||
|
if (!versionModal.classList.contains('hidden')) throw new Error("Version modal should close");
|
||||||
|
console.log("✅ Version Modal Test Passed");
|
||||||
|
|
||||||
|
console.log("--- Testing Theme Toggle ---");
|
||||||
|
const themeBtn = document.getElementById('theme-toggle');
|
||||||
|
const initialTheme = document.documentElement.getAttribute('data-theme');
|
||||||
|
themeBtn.click();
|
||||||
|
const newTheme = document.documentElement.getAttribute('data-theme');
|
||||||
|
if (initialTheme === newTheme) throw new Error("Theme did not toggle");
|
||||||
|
console.log("✅ Theme Toggle Test Passed");
|
||||||
|
|
||||||
|
console.log("--- Testing Navigation Tabs ---");
|
||||||
|
const btnThis = document.getElementById('btn-this-week');
|
||||||
|
const btnNext = document.getElementById('btn-next-week');
|
||||||
|
btnNext.click();
|
||||||
|
if (!btnNext.classList.contains('active') || btnThis.classList.contains('active')) throw new Error("Next week tab not active");
|
||||||
|
btnThis.click();
|
||||||
|
if (!btnThis.classList.contains('active') || btnNext.classList.contains('active')) throw new Error("This week tab not active");
|
||||||
|
console.log("✅ Navigation Tabs Test Passed");
|
||||||
|
|
||||||
|
console.log("--- Testing Clear Cache Button ---");
|
||||||
|
// Mock confirm directly inside evaluated JSDOM context
|
||||||
|
window.confirm = () => true;
|
||||||
|
document.getElementById('btn-clear-cache').click();
|
||||||
|
if (!window.__RELOAD_CALLED) throw new Error("Clear cache did not reload the page");
|
||||||
|
console.log("✅ Clear Cache Button Test Passed");
|
||||||
|
|
||||||
window.__TEST_PASSED = true;
|
window.__TEST_PASSED = true;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
v1.4.17
|
v1.4.20
|
||||||
|
|||||||
Reference in New Issue
Block a user