mirror of
https://github.com/Memo-2023/mana-monorepo.git
synced 2026-05-14 21:41:09 +02:00
## New Features ### Network Graph Visualization (Contacts, Calendar, Todo) - D3.js force simulation for physics-based layout - Zoom & pan with mouse/touchpad - Keyboard shortcuts: +/- zoom, 0 reset, Esc deselect, / search, F focus - Filtering by tags, company/location/project, connection strength - Shared components in @manacore/shared-ui ### Central Tags API (mana-core-auth) - CRUD endpoints for tags - Schema: tags table with userId, name, color, app - Shared tag components in @manacore/shared-ui ### Custom Themes System - Theme editor with live preview and color picker - Community theme gallery - Theme sharing (public, unlisted, private) - Backend API in mana-core-auth ### Todo App Extensions - Glass-pill design for task input and items - Settings page with 20+ preferences - Task edit modal with inline editing - Statistics page with visualizations - PWA support with offline capabilities - Multiple kanban boards ### Contacts App Features - Duplicate detection - Photo upload - Batch operations - Enhanced favorites page with multiple view modes - Alphabet view improvements - Search modal ### Help System - @manacore/shared-help-content - @manacore/shared-help-ui - @manacore/shared-help-types ### Other Features - Themes page for all apps - Referral system frontend - CommandBar (global search) - Skeleton loaders - Settings page improvements ## Bug Fixes - Network graph simulation initialization - Database schema TEXT for user_id columns (Better Auth compatibility) - Various styling fixes ## Documentation - Daily report for 2025-12-10 - CI/CD deployment guide 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
15 KiB
15 KiB
Central Help System
Das zentrale Help-System bietet eine einheitliche Hilfeseite für alle Manacore-Apps. Es unterstützt mehrsprachige Inhalte, Volltextsuche, und die Kombination von zentralen und app-spezifischen Inhalten.
Architektur
┌─────────────────────────────────────────────────────────────┐
│ Zentrale Help-Inhalte │
│ ┌───────────────┐ ┌───────────────┐ ┌───────────────┐ │
│ │ FAQ (allgemein)│ │ Features │ │ Changelog │ │
│ │ - Account │ │ - Theming │ │ - v1.5.0 │ │
│ │ - Billing │ │ - Tags │ │ - v1.4.0 │ │
│ │ - Privacy │ │ - Sync │ │ ... │ │
│ └───────────────┘ └───────────────┘ └───────────────┘ │
└─────────────────────────────────────────────────────────────┘
│
mergeContent()
│
┌─────────────────────┼─────────────────────┐
│ │ │
┌────▼─────┐ ┌─────▼─────┐ ┌─────▼─────┐
│ Todo │ │ Calendar │ │ Contacts │
│ │ │ │ │ │
│ + App- │ │ + App- │ │ + App- │
│ spezif. │ │ spezif. │ │ spezif. │
│ FAQ │ │ Shortcuts │ │ Features │
└──────────┘ └───────────┘ └───────────┘
Packages
| Package | Beschreibung |
|---|---|
@manacore/shared-help-types |
TypeScript-Typen und Zod-Schemas |
@manacore/shared-help-content |
Content-Loader, Parser, Merger, Suche |
@manacore/shared-help-ui |
Svelte 5 UI-Komponenten |
@manacore/shared-help-mobile |
React Native Komponenten |
Content-Typen
FAQ (Frequently Asked Questions)
interface FAQItem {
id: string;
language: 'de' | 'en' | 'fr' | 'it' | 'es';
question: string;
answer: string;
category: 'general' | 'account' | 'billing' | 'features' | 'technical' | 'privacy';
featured?: boolean;
tags?: string[];
relatedFaqs?: string[];
order?: number;
appSpecific?: boolean;
apps?: string[];
}
Features
interface FeatureItem {
id: string;
language: SupportedLanguage;
title: string;
description: string;
content: string;
icon?: string;
category: 'getting-started' | 'core' | 'advanced' | 'integration';
available?: boolean;
comingSoon?: boolean;
highlights?: string[];
learnMoreUrl?: string;
}
Keyboard Shortcuts
interface ShortcutsItem {
id: string;
language: SupportedLanguage;
category: 'navigation' | 'editing' | 'general' | 'app-specific';
title?: string;
shortcuts: Array<{
shortcut: string; // z.B. "Ctrl+S", "⌘+K"
action: string;
description?: string;
}>;
}
Getting Started Guides
interface GettingStartedItem {
id: string;
language: SupportedLanguage;
title: string;
description: string;
content: string;
difficulty: 'beginner' | 'intermediate' | 'advanced';
estimatedTime?: string;
prerequisites?: string[];
steps?: Array<{
title: string;
content: string;
duration?: string;
}>;
}
Changelog
interface ChangelogItem {
id: string;
language: SupportedLanguage;
version: string;
title: string;
releaseDate: Date;
type: 'major' | 'minor' | 'patch' | 'beta';
summary?: string;
content: string;
highlighted?: boolean;
changes?: {
features?: Array<{ title: string; description?: string }>;
improvements?: Array<{ title: string; description?: string }>;
bugfixes?: Array<{ title: string; description?: string }>;
};
platforms?: string[];
}
Contact Info
interface ContactInfo {
id: string;
language: SupportedLanguage;
title: string;
content: string;
supportEmail?: string;
supportUrl?: string;
discordUrl?: string;
twitterUrl?: string;
documentationUrl?: string;
responseTime?: string;
}
Unterstützte Sprachen
type SupportedLanguage = 'en' | 'de' | 'fr' | 'it' | 'es';
Content-Struktur
HelpContent Objekt
interface HelpContent {
faq: FAQItem[];
features: FeatureItem[];
shortcuts: ShortcutsItem[];
gettingStarted: GettingStartedItem[];
changelog: ChangelogItem[];
contact: ContactInfo | null;
}
Content Laden und Mergen
Content Merger
Der Merger kombiniert zentrale und app-spezifische Inhalte:
import { mergeContent, createEmptyContent } from '@manacore/shared-help-content';
// Zentrale Inhalte (für alle Apps)
const centralContent: HelpContent = {
faq: [
{ id: 'account-login', question: 'Wie melde ich mich an?', ... },
{ id: 'billing-cancel', question: 'Wie kündige ich?', ... },
],
features: [...],
// ...
};
// App-spezifische Inhalte
const appContent: Partial<HelpContent> = {
faq: [
{ id: 'todo-recurring', question: 'Wie erstelle ich wiederkehrende Tasks?', ... },
],
shortcuts: [
{ category: 'app-specific', shortcuts: [...] },
],
};
// Zusammenführen
const content = mergeContent(centralContent, appContent, {
appId: 'todo',
locale: 'de',
overrideById: true, // App-Content ersetzt zentralen mit gleicher ID
});
Filterung
Inhalte werden automatisch gefiltert nach:
- Sprache: Nur Inhalte der aktuellen Locale
- App:
appSpecific: trueInhalte nur wennappsdie aktuelle App enthält - Reihenfolge: Sortiert nach
orderProperty
Suche
Such-Index erstellen
import { buildSearchIndex, search, createSearcher } from '@manacore/shared-help-content';
// Index erstellen
const index = buildSearchIndex(content, {
titleWeight: 2.0,
contentWeight: 1.0,
tagsWeight: 1.5,
threshold: 0.3,
minMatchCharLength: 2,
});
// Suchen
const results = search(index, 'wiederkehrend', {
limit: 10,
threshold: 0.4,
types: ['faq', 'guide'], // Optional: Nur bestimmte Typen
});
SearchResult
interface SearchResult {
id: string;
type: 'faq' | 'feature' | 'guide' | 'changelog';
title: string;
excerpt: string;
score: number;
highlight?: string;
item: FAQItem | FeatureItem | GettingStartedItem | ChangelogItem;
}
UI-Komponenten
HelpPage (Hauptkomponente)
Vollständige Hilfeseite mit allen Sektionen:
<script>
import { HelpPage } from '@manacore/shared-help-ui';
import { helpContent, translations } from '$lib/help';
</script>
<HelpPage
content={helpContent}
appName="Todo"
appId="todo"
translations={translations}
searchEnabled={true}
showFAQ={true}
showFeatures={true}
showShortcuts={true}
showGettingStarted={true}
showChangelog={true}
showContact={true}
defaultSection="faq"
showBackButton={true}
onBack={() => goto('/')}
onSectionChange={(section) => console.log(section)}
/>
Einzelne Sektionen
<script>
import {
FAQSection,
FeaturesOverview,
KeyboardShortcuts,
GettingStartedGuide,
ChangelogSection,
ContactSection,
HelpSearch,
} from '@manacore/shared-help-ui';
</script>
<!-- FAQ mit Kategorien -->
<FAQSection
items={content.faq}
translations={translations}
showCategories={true}
maxItems={10}
expandFirst={true}
/>
<!-- Features-Übersicht -->
<FeaturesOverview
items={content.features}
translations={translations}
/>
<!-- Keyboard Shortcuts -->
<KeyboardShortcuts
items={content.shortcuts}
translations={translations}
/>
<!-- Getting Started Guides -->
<GettingStartedGuide
items={content.gettingStarted}
translations={translations}
/>
<!-- Changelog -->
<ChangelogSection
items={content.changelog}
translations={translations}
maxItems={5}
/>
<!-- Kontakt -->
<ContactSection
contact={content.contact}
translations={translations}
/>
<!-- Suche -->
<HelpSearch
content={content}
translations={translations}
placeholder="Hilfe durchsuchen..."
onResultSelect={(result) => navigateToResult(result)}
/>
Übersetzungen
HelpPageTranslations Interface
interface HelpPageTranslations {
title: string;
subtitle?: string;
searchPlaceholder: string;
sections: {
faq: string;
features: string;
shortcuts: string;
gettingStarted: string;
changelog: string;
contact: string;
};
search: {
noResults: string;
resultsCount: string;
searching: string;
};
faq: {
noItems: string;
categories: {
general: string;
account: string;
billing: string;
features: string;
technical: string;
privacy: string;
};
};
features: {
noItems: string;
comingSoon: string;
learnMore: string;
};
shortcuts: {
noItems: string;
};
gettingStarted: {
noItems: string;
estimatedTime: string;
difficulty: {
beginner: string;
intermediate: string;
advanced: string;
};
};
changelog: {
noItems: string;
types: {
major: string;
minor: string;
patch: string;
beta: string;
};
};
contact: {
noInfo: string;
email: string;
responseTime: string;
};
common: {
back: string;
showMore: string;
showLess: string;
};
}
Beispiel (Deutsch)
const translations: HelpPageTranslations = {
title: 'Hilfe',
subtitle: 'Finde Antworten und lerne die App kennen',
searchPlaceholder: 'Suche in der Hilfe...',
sections: {
faq: 'Häufige Fragen',
features: 'Funktionen',
shortcuts: 'Tastaturkürzel',
gettingStarted: 'Erste Schritte',
changelog: 'Neuigkeiten',
contact: 'Kontakt',
},
search: {
noResults: 'Keine Ergebnisse gefunden',
resultsCount: '{count} Ergebnisse',
searching: 'Suche...',
},
faq: {
noItems: 'Keine FAQ-Einträge vorhanden',
categories: {
general: 'Allgemein',
account: 'Konto',
billing: 'Abrechnung',
features: 'Funktionen',
technical: 'Technisch',
privacy: 'Datenschutz',
},
},
// ... weitere
};
Dateien
@manacore/shared-help-types
| Datei | Beschreibung |
|---|---|
src/content.ts |
Content-Typ Definitionen |
src/schemas.ts |
Zod-Validierungsschemas |
src/search.ts |
Such-bezogene Typen |
@manacore/shared-help-content
| Datei | Beschreibung |
|---|---|
src/parser.ts |
Markdown-Parser |
src/loader.ts |
Content-Loader für verschiedene Formate |
src/merger.ts |
Content-Merger (zentral + app-spezifisch) |
src/search.ts |
Volltextsuche mit Fuse.js |
@manacore/shared-help-ui
| Datei | Beschreibung |
|---|---|
src/pages/HelpPage.svelte |
Vollständige Hilfeseite |
src/components/FAQSection.svelte |
FAQ-Bereich |
src/components/FAQItem.svelte |
Einzelner FAQ-Eintrag |
src/components/FeaturesOverview.svelte |
Feature-Übersicht |
src/components/FeatureCard.svelte |
Feature-Karte |
src/components/KeyboardShortcuts.svelte |
Tastaturkürzel |
src/components/GettingStartedGuide.svelte |
Erste-Schritte-Guide |
src/components/ChangelogSection.svelte |
Changelog-Bereich |
src/components/ChangelogEntry.svelte |
Einzelner Changelog-Eintrag |
src/components/ContactSection.svelte |
Kontakt-Bereich |
src/components/HelpSearch.svelte |
Suchkomponente |
Integration in eine App
1. Dependencies
{
"dependencies": {
"@manacore/shared-help-types": "workspace:*",
"@manacore/shared-help-content": "workspace:*",
"@manacore/shared-help-ui": "workspace:*"
}
}
2. Content erstellen
// src/lib/help/content.ts
import type { HelpContent } from '@manacore/shared-help-types';
export const appHelpContent: Partial<HelpContent> = {
faq: [
{
id: 'calendar-recurring',
language: 'de',
question: 'Wie erstelle ich wiederkehrende Termine?',
answer: 'Öffne einen Termin und aktiviere die Wiederholung...',
category: 'features',
appSpecific: true,
apps: ['calendar'],
},
],
shortcuts: [
{
id: 'calendar-shortcuts',
language: 'de',
category: 'app-specific',
title: 'Kalender-Shortcuts',
shortcuts: [
{ shortcut: 'N', action: 'Neuer Termin' },
{ shortcut: 'T', action: 'Zu Heute springen' },
{ shortcut: 'W', action: 'Wochenansicht' },
],
},
],
};
3. Hilfeseite erstellen
<!-- src/routes/(app)/help/+page.svelte -->
<script lang="ts">
import { HelpPage } from '@manacore/shared-help-ui';
import { mergeContent } from '@manacore/shared-help-content';
import { centralContent } from '$lib/help/central';
import { appHelpContent } from '$lib/help/content';
import { translations } from '$lib/help/translations';
import { goto } from '$app/navigation';
const content = mergeContent(centralContent, appHelpContent, {
appId: 'calendar',
locale: 'de',
});
</script>
<HelpPage
{content}
appName="Calendar"
appId="calendar"
{translations}
searchEnabled={true}
onBack={() => goto('/')}
/>
App-spezifische Inhalte
Markierung
Inhalte können als app-spezifisch markiert werden:
{
id: 'todo-labels',
appSpecific: true,
apps: ['todo', 'calendar'], // Nur in diesen Apps sichtbar
// ...
}
Override by ID
Wenn overrideById: true (Standard), ersetzt app-spezifischer Content zentralen Content mit gleicher ID:
// Zentral
{ id: 'feature-tags', title: 'Tags allgemein', ... }
// App-spezifisch
{ id: 'feature-tags', title: 'Tags in Todo', ... } // Ersetzt zentralen Content
Vorteile
- Wiederverwendbarkeit: Zentrale FAQs (Account, Billing) nur einmal schreiben
- Konsistenz: Einheitliches Look & Feel der Hilfeseite
- Mehrsprachigkeit: 5 Sprachen unterstützt
- Suche: Integrierte Volltextsuche
- Flexibilität: App-spezifische Inhalte können hinzugefügt werden
- Typ-Sicherheit: Vollständige TypeScript-Typen und Zod-Validierung