CompetenceTrack v9 - Rich text editor, Drawing integration, PDF export, Notebook sharing, Templates, Keyboard shortcuts

Features:
- Rich text toolbar for notebook pages (Bold, Italic, Underline, Headings, Lists)
- Drawing canvas integration in notebook pages (toggle drawing mode)
- Notebook PDF export (client-side print with print CSS)
- Page background rendering (lined, grid, blank, dotted, music, calligraphy)
- Page thumbnails in sidebar with bookmark indicators
- Auto-save with 3-second debounce
- Notebook sharing with classes (isPublic toggle)
- Notebook duplication (copy with all pages)
- 6 pre-built notebook templates (Math, Deutsch, Englisch, Kunst, Musik, Sachkunde)
- Shared notebooks tab (view other teachers' shared notebooks)
- Templates tab with one-click creation
- Keyboard shortcuts (Cmd+N, Cmd+D, Cmd+Shift+N, Cmd+E, Cmd+Shift+A, Cmd+.)
- Student notebook access (role-based UI)
- Role indicator in notebook header (Teacher/Student)
- Onboarding tour expanded to 14 steps
- Dashboard improvements (Today's Schedule, Paper Saved counter, Recent Activity)
- Classes view improvements (student/subject counts, type badges)
- Competence flower improvements (shadow, shimmer, mastery summary)
- Progress entries improvements (mastery distribution chart)
- Global CSS improvements (dark scrollbar, focus-visible, card-hover-glow)
- 60+ new i18n keys (German/English)

Bug Fixes:
- Notebook creation not refreshing list (fixed by calling loadData after creation)
- Missing BarChart3 import in progress-entries-view
- Escaped quotes in JSX className attributes
This commit is contained in:
Mustafa Cetin committed 2026-07-29 08:02:04 +00:00
1 parent 04034dca62
commit 62f4a150e0
14 files changed
+1983 -166

No files matched your search

+61 -7
View File
@@ -279,7 +279,7 @@ export default function AppLayout() {
const isMod = e.metaKey || e.ctrlKey;
// Ctrl/Cmd + K: Open command palette
if (isMod && e.key.toLowerCase() === 'k') {
if (isMod && !e.shiftKey && e.key.toLowerCase() === 'k') {
e.preventDefault();
setSearchOpen((v) => !v);
return;
@@ -292,13 +292,67 @@ export default function AppLayout() {
return;
}
// Ctrl/Cmd + N: Create new entry (navigate to progress)
if (isMod && e.key.toLowerCase() === 'n') {
// Ctrl/Cmd + Shift + N: Add new page to current notebook (when on notebooks view)
if (isMod && e.shiftKey && e.key.toLowerCase() === 'n') {
e.preventDefault();
if (currentView === 'notebooks') {
window.dispatchEvent(new CustomEvent('ct-shortcut', { detail: 'new-page' }));
return;
}
}
// Ctrl/Cmd + Shift + A: Toggle archive mode (when on notebooks view)
if (isMod && e.shiftKey && e.key.toLowerCase() === 'a') {
e.preventDefault();
if (currentView === 'notebooks') {
window.dispatchEvent(new CustomEvent('ct-shortcut', { detail: 'archive-toggle' }));
return;
}
}
// Ctrl/Cmd + N: Context-dependent new action
if (isMod && !e.shiftKey && e.key.toLowerCase() === 'n') {
e.preventDefault();
setSearchOpen(false);
setCurrentView('progress');
trackAction('new-entry', t('shortcuts.new_entry'), 'progress');
toast.info(t('shortcuts.new_entry'));
if (currentView === 'notebooks') {
// Open create notebook dialog
window.dispatchEvent(new CustomEvent('ct-shortcut', { detail: 'new-notebook' }));
} else {
// Default: navigate to progress
setCurrentView('progress');
trackAction('new-entry', t('shortcuts.new_entry'), 'progress');
toast.info(t('shortcuts.new_entry'));
}
return;
}
// Ctrl/Cmd + D: Open drawing canvas
if (isMod && e.key.toLowerCase() === 'd') {
e.preventDefault();
if (currentView === 'notebooks') {
window.dispatchEvent(new CustomEvent('ct-shortcut', { detail: 'drawing' }));
} else {
setCurrentView('drawing');
trackAction('drawing', t('shortcuts.drawing'), 'drawing');
}
return;
}
// Ctrl/Cmd + E: Export current notebook as PDF
if (isMod && e.key.toLowerCase() === 'e') {
e.preventDefault();
if (currentView === 'notebooks') {
window.dispatchEvent(new CustomEvent('ct-shortcut', { detail: 'export-pdf' }));
}
return;
}
// Ctrl/Cmd + .: Close current notebook (go back to library)
if (isMod && e.key === '.') {
e.preventDefault();
if (currentView === 'notebooks') {
window.dispatchEvent(new CustomEvent('ct-shortcut', { detail: 'close-notebook' }));
}
return;
}
@@ -326,7 +380,7 @@ export default function AppLayout() {
}
window.addEventListener('keydown', onKey);
return () => window.removeEventListener('keydown', onKey);
}, [searchOpen, shortcutsOpen, helpOpen, setCurrentView, trackAction]);
}, [searchOpen, shortcutsOpen, helpOpen, currentView, setCurrentView, trackAction]);
// Debounced search
useEffect(() => {