Dokumentation: docs/09-anleitung-entwickler.md
This commit is contained in:
@@ -0,0 +1,126 @@
|
||||
# 09 Anleitung für Entwickler
|
||||
|
||||
## Einrichten
|
||||
|
||||
```bash
|
||||
npm install
|
||||
cd server && npm install && cp .env.example .env # Werte anpassen
|
||||
npm start # Backend :5007
|
||||
cd .. && npm run dev # Frontend :3101, /api wird geproxied
|
||||
```
|
||||
|
||||
Lokal braucht es eine erreichbare MariaDB mit der Datenbank `icon_CRM`; das
|
||||
Schema legt das Backend beim Start selbst an.
|
||||
|
||||
```bash
|
||||
npx tsc --noEmit # Typprüfung, laeuft nicht automatisch im Build
|
||||
npm run build # dist/
|
||||
```
|
||||
|
||||
## Aufbau
|
||||
|
||||
```
|
||||
src/
|
||||
App.tsx Layout, gemeinsame Daten, Ansichtswechsel
|
||||
main.tsx Provider-Kette
|
||||
types.ts Gemeinsame Typen und Konstanten
|
||||
index.css Tailwind-Theme, Designs, Dunkelmodus
|
||||
lib/api.ts Fetch-Wrapper + typisierte Endpunkte
|
||||
lib/auth.tsx JWT im localStorage
|
||||
lib/theme.tsx Design und hell/dunkel
|
||||
lib/navigation.tsx Karte oeffnen, Einstellungen-Reiter ansteuern
|
||||
lib/options.tsx Auswahllisten aus den Stammdaten
|
||||
lib/mentions.tsx @-Token: Parser, Renderer, Vorschlagsliste
|
||||
lib/richText.ts Altbestand in Editor-HTML, Bereinigung
|
||||
lib/imageCompress.ts Bilder vor dem Upload verkleinern
|
||||
lib/whisper*.ts(x), dictation.tsx, audio.ts Diktat
|
||||
components/… nach Bereichen
|
||||
server/
|
||||
src/server.js Express-App, Routenmontage
|
||||
src/db.js Pool, Schema-Init, Migrationen, Admin-Seed
|
||||
src/schema.sql Idempotentes Schema
|
||||
src/history.js Historie schreiben, Erwaehnungen indizieren
|
||||
src/ai.js OpenAI-Aufruf an einer Stelle
|
||||
src/cvText.js Text aus PDF/DOCX
|
||||
src/migrate.js Einmalige Uebernahme aus Supabase
|
||||
src/linkedinPhoto.js Profilfoto aus der Open-Graph-Vorschau
|
||||
src/middleware/auth.js requireAuth, requireAdmin
|
||||
src/routes/ ein Router je Bereich
|
||||
deploy/ systemd-Unit, Apache-Vhost, deploy.ps1
|
||||
legacy/ der alte Supabase-Stand, nur zum Nachschlagen
|
||||
```
|
||||
|
||||
## Ein neues Feld hinzufügen
|
||||
|
||||
Am Beispiel eines Kontaktfelds – die Reihenfolge ist wichtig, sonst fehlt das
|
||||
Feld an einer Stelle und fällt erst im Betrieb auf:
|
||||
|
||||
1. **Schema:** Spalte in `server/src/schema.sql` ergänzen **und** eine Migration
|
||||
in `server/src/db.js` (`ALTER TABLE … ADD COLUMN IF NOT EXISTS`) – der
|
||||
Bestand auf dem Server wird nicht neu angelegt.
|
||||
2. **Route:** Feld in `server/src/routes/contacts.js` in die Liste der erlaubten
|
||||
Felder aufnehmen (Lesen **und** Schreiben) und in der Aufbereitung der Zeile
|
||||
berücksichtigen.
|
||||
3. **Historie:** Klarnamen in `server/src/history.js` eintragen, sonst steht in
|
||||
der Historie der Spaltenname.
|
||||
4. **Typ:** `src/types.ts`.
|
||||
5. **Formular:** `src/components/contacts/ContactModal.tsx`.
|
||||
6. **Anzeige:** Liste, Kacheln, ggf. `contactUi.tsx`.
|
||||
7. **Erweiterte Suche:** wenn das Feld für Fragen taugt, in den Bestand in
|
||||
`server/src/routes/search.js` aufnehmen – und im Systemprompt erklären, was
|
||||
`null` bedeutet.
|
||||
|
||||
Schritt 7 ist der, der am leichtesten vergessen wird. Die Sätze standen ein
|
||||
halbes Jahr in der Datenbank und fehlten trotzdem in jeder Antwort der Suche,
|
||||
weil sie nicht im mitgelieferten Bestand standen.
|
||||
|
||||
## Eine neue Ansicht hinzufügen
|
||||
|
||||
1. `View` in `src/types.ts` erweitern.
|
||||
2. Eintrag in `src/components/Sidebar.tsx` (optional mit `children` für ein
|
||||
Untermenü und `badge` für die Zahl daneben).
|
||||
3. Block `{view === '…' && <… />}` in `src/App.tsx`.
|
||||
4. Zählwert im Dashboard-Endpunkt ergänzen, falls ein Badge gewünscht ist.
|
||||
|
||||
Der Name der Ansicht ist zugleich ihr Schlüssel – wird er umbenannt (wie
|
||||
„Projekte" → „Laufende Projekte"), müssen alle vier Stellen mitgehen, dazu die
|
||||
Zuordnung in `navigation.open()` und der Filter in der Historie.
|
||||
|
||||
## Bekannte Fallen
|
||||
|
||||
**`gpt-5.6-luna` und `temperature`.** Jeder eigene Wert wird mit HTTP 400
|
||||
abgewiesen. `ai.js` schickt keinen.
|
||||
|
||||
**Instabile Arrays in der Netzwerkansicht.** Ein `= []` als Vorgabewert erzeugt
|
||||
bei jedem Rendern ein neues Array; `useMemo`/`useEffect` laufen dann endlos und
|
||||
alle Knoten liegen auf einem Punkt. Deshalb `NO_EXTERNALS` auf Modulebene und
|
||||
`useMemo` auf der Aufruferseite.
|
||||
|
||||
**Designs aus der Datenbank.** Wird eine Palette entfernt, tragen Benutzer sie
|
||||
weiterhin am Konto. Drei Sicherungen greifen: das Backend liefert unbekannte
|
||||
Werte als `null` aus, der Theme-Kontext prüft den Serverwert, und die Kopfzeile
|
||||
fällt auf `icon` zurück. Ohne das reicht ein gelöschter Palettenname für eine
|
||||
weiße Seite nach dem Anmelden.
|
||||
|
||||
**Altes HTML im Editor.** Der Bestand bringt Inline-Farben, geschützte
|
||||
Leerzeichen und verschachtelte Listen mit. `toEditorHtml()` räumt zurückhaltend
|
||||
auf, `index.css` hebt Inline-Farben im Editor aus. Wer beides umgeht, bekommt im
|
||||
Dunkelmodus schwarze Schrift auf weißen Kästen und Zeilen, die nicht umbrechen.
|
||||
|
||||
**`notes` vs. `details` bei Ausschreibungen.** Der veröffentlichte Text steht in
|
||||
`notes`. `details` ist im gesamten Bestand leer.
|
||||
|
||||
**Deployment ohne Build.** `-SkipBuild` lädt das vorhandene `dist/` hoch. Nach
|
||||
einer Änderung an `src/` oder `index.html` also erst bauen.
|
||||
|
||||
**Kein automatischer Typcheck im Build.** `vite build` prüft die Typen nicht.
|
||||
`npx tsc --noEmit` gehört vor jedes Deployment.
|
||||
|
||||
## Stil
|
||||
|
||||
Die Kommentare in diesem Projekt erklären **warum**, nicht was. Eine Zeile, die
|
||||
nur wiederholt, was der Code sagt, ist eine Zeile zu viel; eine Zeile, die eine
|
||||
Entscheidung begründet, erspart der nächsten Person eine Stunde.
|
||||
|
||||
Beschriftungen und Meldungen sind auf Deutsch, ohne Fachjargon, und sagen im
|
||||
Zweifel, was zu tun ist – nicht nur, dass etwas fehlgeschlagen ist.
|
||||
Reference in New Issue
Block a user