Commit Graph

22 Commits

Author SHA1 Message Date
da3d7319a6 feat: delete pair button in EditPairForm with confirmation
Two-step: "Pair löschen" → confirm "Wirklich löschen" before DELETE /pairs/:id.
On success closes the form and reloads the pairs list.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-27 14:40:38 +02:00
d57313084f fix: robust placeholder resolution + readable pair cards
- resolvePlaceholders: replace fragile [wo] char class with general
  /^(.+?)\.[a-z]+:[0-9a-f-]{36}$/i — handles any type prefix safely
- Add sync stripPlaceholders() helper for card display (no async needed)
- PairsPanel cards now show actual sentence text instead of UUID stubs,
  using enriched pair.question / pair.positive_statement data from API

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-27 13:46:06 +02:00
f739f529e9 feat: new placeholder format, fuzzy word detection, editable word input
- Placeholder format: {{Hund.w:uuid}} / {{Hund.o:uuid}} — label embedded,
  no API lookup needed on render/edit load
- resolvePlaceholders handles both new format (fast) and old {{uuid}} (fallback)
- Word auto-detection: fuzzy match via search API + client-side starts-with
  + 60% length ratio (e.g. "Hunde" matches "Hund")
- "Als Wort erstellen" now shows editable input pre-filled with selection,
  user can correct before saving

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-26 14:55:29 +02:00
29786c531b feat: complete tables config — all tables, all fields, boolean type
- Add missing tables: languages, users, blocklist, user-names, users-public
- Fix categories field names (name_de → titel_de/en/sv)
- Add missing fields: objects_created, sentence_sv, answer, negative_statement_id, etc.
- Fix pairs answer_type options (yes_no/text/question/word)
- Add boolean field type support in RecordModal

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-25 18:19:58 +02:00
8242dab18c feat: unified ContentCreation tool (Object + Statement creation merged)
- New ContentCreation.jsx: 3-column layout
  Left: object list + "+ Objekt hinzufügen" button
  Center: dual-mode canvas (draw OR highlight)
  Right: ObjectAddPanel (mode=add) or PairsPanel (mode=objectId)
- After saving object → auto-switches to PairsPanel for that object
- All ObjectCreation + StatementCreation logic merged into one page
- All pictures loaded (no objects_created filter)
- "Objekte abgeschlossen" button marks picture (visual badge)
- ContentHub: 2 tiles (Content Erstellen + Veröffentlichen placeholder)
- App.jsx: /content/creation route, old /content/objects + /content/statements removed

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-25 17:28:16 +02:00
6cdf09707a feat: edit existing pairs inline in PairsPanel
- EditPairForm: loads question + statement text (resolves {{uuid}} back
  to word titles via resolvePlaceholders), pre-fills all fields
- Per-type editing: text/yes_no/question/word with same UX as create
- Word link diff on save (add new, remove removed via apiUnlink)
- Creates missing question/statement records if type or content added
- ✏️ button per pair card opens EditPairForm, replaces card inline
- onPairsReload: re-fetches pairs list after edit saved

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-25 16:32:28 +02:00
aa4b37c3a4 feat: object assignment per word placeholder in statements
- withPlaceholders(text, wordMap, objectAssignments) — uses {{objectId}}
  when an object is assigned to a word, otherwise {{wordId}}
- PairForm: objectAssignments state (carried over between saves)
- Detected words section shows object dropdown per word
  — only objects from current picture that have the word linked
  — shows "Objekt #N — word1, word2" labels
  — unselected = {{wordId}}, selected = {{objectId}}

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-25 16:25:58 +02:00
6c730889be fix: word detection + highlighting for all pair types
- Remove needsWordDetection guard — wordMap always populated
- "Als Wort erstellen" banner shown for all types
- Erkannte Wörter indicator shown for all types

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-25 16:14:35 +02:00
0c816d3f2d refactor: PairForm — single type dropdown, 4 variants, carry-over behavior
- answer_type is now a single value (text/yes_no/question/word)
- Dropdown replaces checkboxes, per-type field sections
- Text: only positive statement
- Yes/No: optional question + answer picker
- Question: question* + positive* + optional negative
- Word: optional question + word pickers
- After save: texts/words carry over, type resets for next pair
- Fix: closed missing div in PairsPanel scroll container

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-25 16:11:02 +02:00
99ca1c58c2 fix: make PairsPanel fully scrollable including PairForm
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-24 20:54:51 +02:00
25c31adbdf feat: rework PairForm — 3 checkboxes, validation logic, word pickers
Replaces the answer_type dropdown with 3 independent checkboxes:
- Text: positive statement required; negative requires question+positive;
  question is optional standalone; auto-detects words + {{uuid}} placeholders
- Ja/Nein: addon, adds answer field (null/true/false) to positive statement
- Wort: opens positive/negative word pickers → linked via statement_positive/negative_words

Validation rules:
- At least one type must be checked
- Text: positive statement non-empty
- Negative statement only allowed when question + positive both filled

Word creation: highlight text in any field → 'Als Wort erstellen' button

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-24 20:50:18 +02:00
c92191db63 feat: Statement Creation + objects_created workflow + native language
ObjectCreation:
- Filter: only shows pictures where objects_created=false
- New '✓ Alle Objekte erstellt' button (enabled when ≥1 object linked)
  → PATCHes picture with objects_created:true + auto timestamp
  → removes picture from list immediately

ContentHub:
- Statement Creation tile enabled (was: grayed out)

api.js:
- getUserLang() → reads native_lang from stored user (default 'de')
- langField(suffix) → returns e.g. 'sentence_de' based on user lang
- login() stores native_lang in localStorage user object

StatementCreation (/content/statements):
- Shows pictures where objects_created=true
- Left 1/5: clickable objects list → highlights selections on canvas
- Center 2/5: image with canvas, draws selected object's polygons in color
- Right 2/5: PairsPanel
  - answer_type dropdown + 'Add new pair' toggle
  - PairForm: Question / Positive / Negative textareas
  - HighlightedTextarea: overlay technique, auto-detects words from DB
    (debounced GET /words?titel_de=, colored mark via rgba background)
  - 'Als Wort erstellen' button when text is selected
  - 'Save pair' → creates question + 2 separate statements + pair
    → sentences stored with {{uuid}} placeholders for matched words
    → pair linked to selected object
  - List of existing pairs with question/positive/negative preview

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-24 19:23:50 +02:00
e1d5390386 feat: Content Verwaltung — ContentHub + Object Creation
Adds a full Content Management section:
- Nav link "Content" in header (all pages)
- ContentHub at /content with 3 tiles (Object/Statement/Content Creation)
- ObjectCreation at /content/objects:
  - Top bar: ← → pagination through all "uploaded" pictures
  - Left panel (1/5): existing objects per picture with their words, + button to start draw mode
  - Center: image on dark bg with canvas overlay for polygon drawing
  - Right words panel (1/5): picture words + new object words (each with search/create)
  - Right toolbar (1/5): draw instructions, "Auswahl hinzufügen", numbered selections list, "Objekt speichern" (requires ≥1 selection + ≥1 object word)
- Canvas drawing: click=add point, dblclick=close polygon, live preview line to mouse cursor
- Selections stored as [{points:[{x,y},...]}] (relative 0-1 coords) in objects.selections JSONB
- Object saved with status "draft", linked picture + words

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-23 21:53:23 +02:00
6c8eaab034 feat: delete rows via trash icon in all tables
Each row gets a trash can button that appears on hover. Clicking it
shows an inline confirm (✓ / ✕) to prevent accidental deletion. On
confirm, calls DELETE /endpoint/:id and removes the row from state.
If the deleted record is open in the modal, the modal closes too.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-23 19:24:37 +02:00
211bd464d2 feat: picture modal hero panel with image preview
Adds a split-layout hero section at the top of the RecordModal
for pictures: left side shows the image preview (~40%), right side
shows status, design (both editable) and the linked words relation
manager inline. Remaining fields (blurhash, picture_link, metadata)
continue to appear in the sections below.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-22 08:54:03 +02:00
3c59713c25 Use server-side ?search= API instead of client-side filtering
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-21 22:50:53 +02:00
bdf3bd590e Fix relation search: fetch limit=500 instead of 20 for client-side filtering
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-21 22:48:52 +02:00
a02705734d Add relation manager: link/unlink records directly in modal
- RelationManager component: shows linked items as removable tags,
  live search to find and add new links (×-button to unlink)
- tables.js: full fetchRelated config with linkEndpoint + searchEndpoint
  for words↔pictures, words↔categories, objects↔words, objects↔pictures
- api.js: add apiLink, apiUnlink, apiDelete helpers

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-21 22:43:48 +02:00
a8ff541117 Add create modal for words and pictures tables
- + Button in TableView for tables with a create form (words, pictures)
- Words: form with titel_de/en/sv + difficulty_level → POST /words
- Pictures: design field + image uploader → POST /pictures then POST /pictures/:id/upload
- Image drag-drop area with preview before upload, sends multipart to Hetzner via API
- New record prepended to table on success
- apiPost + apiUpload helpers added to api.js

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-21 22:17:55 +02:00
e6c86a97fc Add RecordModal: row-click detail popup with inline editing
- Click any table row to open a full-detail popup
- Editable fields (text, textarea, select, number) with PATCH save
- Read-only display for IDs, timestamps, arrays
- Pictures table fetches words via /pictures/:id/words in modal
- Stop propagation on linked-field chips so they don't trigger modal
- apiPatch + apiFetchOne helpers in api.js
- editableFields + fetchRelated config in tables.js

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-21 21:53:45 +02:00
74082cd333 Initial commit: snakkimo CMT
React + Vite + Tailwind dashboard with:
- Login (JWT via snakkimo auth)
- Dashboard with Datenbankverwaltung + Contentverwaltung tiles
- Table overview with record counts (total, published, blocked)
- Table record viewer with text/status filters and linked field navigation

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-21 21:29:12 +02:00
1f923947bd Initial commit 2026-05-21 19:23:59 +00:00