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>
This commit is contained in:
@@ -80,6 +80,20 @@ function EditableField({ fieldKey, value, fieldDef, onChange }) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (type === 'boolean') {
|
||||||
|
return (
|
||||||
|
<select
|
||||||
|
value={value === true ? 'true' : value === false ? 'false' : ''}
|
||||||
|
onChange={e => onChange(e.target.value === 'true' ? true : e.target.value === 'false' ? false : null)}
|
||||||
|
className="w-full border border-slate-300 rounded-lg px-3 py-1.5 text-sm focus:outline-none focus:ring-2 focus:ring-indigo-400 bg-white"
|
||||||
|
>
|
||||||
|
<option value="">— wählen —</option>
|
||||||
|
<option value="true">true</option>
|
||||||
|
<option value="false">false</option>
|
||||||
|
</select>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
if (type === 'number') {
|
if (type === 'number') {
|
||||||
return (
|
return (
|
||||||
<input
|
<input
|
||||||
|
|||||||
@@ -5,14 +5,14 @@ export const TABLES = {
|
|||||||
endpoint: '/words',
|
endpoint: '/words',
|
||||||
statusField: 'status',
|
statusField: 'status',
|
||||||
primaryLabel: 'titel_de',
|
primaryLabel: 'titel_de',
|
||||||
columns: ['titel_de', 'titel_en', 'status', 'difficulty_level', 'created_at'],
|
columns: ['titel_de', 'titel_en', 'titel_sv', 'status', 'difficulty_level', 'created_at'],
|
||||||
linkedFields: { picture_ids: 'pictures', category_ids: 'categories' },
|
linkedFields: { picture_ids: 'pictures', category_ids: 'categories' },
|
||||||
editableFields: {
|
editableFields: {
|
||||||
titel_de: { type: 'text' },
|
titel_de: { type: 'text' },
|
||||||
titel_en: { type: 'text' },
|
titel_en: { type: 'text' },
|
||||||
titel_sv: { type: 'text' },
|
titel_sv: { type: 'text' },
|
||||||
status: { type: 'select', options: ['published', 'blocked', 'draft', 'requested', 'translated'] },
|
status: { type: 'select', options: ['requested', 'translated', 'generated', 'published', 'blocked'] },
|
||||||
difficulty_level:{ type: 'number', min: 1, max: 10 },
|
difficulty_level:{ type: 'number', min: 1, max: 50 },
|
||||||
},
|
},
|
||||||
fetchRelated: [
|
fetchRelated: [
|
||||||
{
|
{
|
||||||
@@ -29,21 +29,22 @@ export const TABLES = {
|
|||||||
key: 'categories',
|
key: 'categories',
|
||||||
label: 'Kategorien',
|
label: 'Kategorien',
|
||||||
endpoint: id => `/words/${id}/categories`,
|
endpoint: id => `/words/${id}/categories`,
|
||||||
display: c => c.name_de || c.id,
|
display: c => c.titel_de || c.id,
|
||||||
targetTable: 'categories',
|
targetTable: 'categories',
|
||||||
linkEndpoint: (id, targetId) => `/words/${id}/categories/${targetId}`,
|
linkEndpoint: (id, targetId) => `/words/${id}/categories/${targetId}`,
|
||||||
searchEndpoint: '/categories',
|
searchEndpoint: '/categories',
|
||||||
searchLabel: c => c.name_de || c.id,
|
searchLabel: c => c.titel_de || c.id,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|
||||||
pictures: {
|
pictures: {
|
||||||
label: 'Bilder',
|
label: 'Bilder',
|
||||||
icon: '🖼️',
|
icon: '🖼️',
|
||||||
endpoint: '/pictures',
|
endpoint: '/pictures',
|
||||||
statusField: 'status',
|
statusField: 'status',
|
||||||
primaryLabel: 'design',
|
primaryLabel: 'design',
|
||||||
columns: ['design', 'status', 'picture_link', 'blurhash', 'created_at'],
|
columns: ['design', 'status', 'objects_created', 'picture_link', 'blurhash', 'generation_prompt', 'created_at'],
|
||||||
linkedFields: {},
|
linkedFields: {},
|
||||||
heroPanel: {
|
heroPanel: {
|
||||||
imageField: 'picture_link',
|
imageField: 'picture_link',
|
||||||
@@ -51,10 +52,13 @@ export const TABLES = {
|
|||||||
quickRelatedKey: 'words',
|
quickRelatedKey: 'words',
|
||||||
},
|
},
|
||||||
editableFields: {
|
editableFields: {
|
||||||
design: { type: 'text' },
|
design: { type: 'text' },
|
||||||
status: { type: 'select', options: ['published', 'blocked', 'uploaded', 'requested', 'generated'] },
|
status: { type: 'select', options: ['uploaded', 'published', 'blocked'] },
|
||||||
picture_link: { type: 'text' },
|
picture_link: { type: 'text' },
|
||||||
blurhash: { type: 'text' },
|
blurhash: { type: 'text' },
|
||||||
|
generation_prompt:{ type: 'textarea' },
|
||||||
|
blocked_reason: { type: 'select', options: ['regenerate', 'not_to_use'] },
|
||||||
|
objects_created: { type: 'boolean' },
|
||||||
},
|
},
|
||||||
fetchRelated: [
|
fetchRelated: [
|
||||||
{
|
{
|
||||||
@@ -69,17 +73,19 @@ export const TABLES = {
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|
||||||
objects: {
|
objects: {
|
||||||
label: 'Objekte',
|
label: 'Objekte',
|
||||||
icon: '📦',
|
icon: '📦',
|
||||||
endpoint: '/objects',
|
endpoint: '/objects',
|
||||||
statusField: 'status',
|
statusField: 'status',
|
||||||
primaryLabel: 'notes',
|
primaryLabel: 'notes',
|
||||||
columns: ['id', 'status', 'notes', 'created_at'],
|
columns: ['id', 'status', 'notes', 'blocked_topic', 'created_at'],
|
||||||
linkedFields: { word_ids: 'words', picture_ids: 'pictures', pair_ids: 'pairs' },
|
linkedFields: { word_ids: 'words', picture_ids: 'pictures', pair_ids: 'pairs' },
|
||||||
editableFields: {
|
editableFields: {
|
||||||
notes: { type: 'textarea' },
|
notes: { type: 'textarea' },
|
||||||
status: { type: 'select', options: ['published', 'blocked', 'draft'] },
|
blocked_topic:{ type: 'text' },
|
||||||
|
status: { type: 'select', options: ['draft', 'published', 'blocked'] },
|
||||||
},
|
},
|
||||||
fetchRelated: [
|
fetchRelated: [
|
||||||
{
|
{
|
||||||
@@ -104,69 +110,166 @@ export const TABLES = {
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|
||||||
pairs: {
|
pairs: {
|
||||||
label: 'Pairs',
|
label: 'Pairs',
|
||||||
icon: '🔗',
|
icon: '🔗',
|
||||||
endpoint: '/pairs',
|
endpoint: '/pairs',
|
||||||
statusField: 'status',
|
statusField: 'status',
|
||||||
primaryLabel: 'id',
|
primaryLabel: 'id',
|
||||||
columns: ['id', 'answer_type', 'difficulty_level', 'status', 'question_id', 'positive_statement_id', 'created_at'],
|
columns: ['id', 'answer_type', 'difficulty_level', 'status', 'question_id', 'positive_statement_id', 'negative_statement_id', 'created_at'],
|
||||||
linkedFields: {
|
linkedFields: {
|
||||||
question_id: 'questions',
|
question_id: 'questions',
|
||||||
positive_statement_id: 'statements',
|
positive_statement_id: 'statements',
|
||||||
negative_statement_id: 'statements',
|
negative_statement_id: 'statements',
|
||||||
},
|
},
|
||||||
editableFields: {
|
editableFields: {
|
||||||
answer_type: { type: 'select', options: ['word', 'sentence'] },
|
answer_type: { type: 'select', options: ['yes_no', 'text', 'question', 'word'] },
|
||||||
difficulty_level:{ type: 'number', min: 1, max: 10 },
|
difficulty_level: { type: 'number', min: 1, max: 50 },
|
||||||
status: { type: 'select', options: ['published', 'blocked', 'draft'] },
|
blocked_topic: { type: 'text' },
|
||||||
|
status: { type: 'select', options: ['draft', 'published', 'blocked'] },
|
||||||
},
|
},
|
||||||
fetchRelated: [],
|
fetchRelated: [],
|
||||||
},
|
},
|
||||||
|
|
||||||
questions: {
|
questions: {
|
||||||
label: 'Fragen',
|
label: 'Fragen',
|
||||||
icon: '❓',
|
icon: '❓',
|
||||||
endpoint: '/questions',
|
endpoint: '/questions',
|
||||||
statusField: 'status',
|
statusField: 'status',
|
||||||
primaryLabel: 'sentence_de',
|
primaryLabel: 'sentence_de',
|
||||||
columns: ['sentence_de', 'sentence_en', 'status', 'created_at'],
|
columns: ['sentence_de', 'sentence_en', 'sentence_sv', 'status', 'blocked_topic', 'created_at'],
|
||||||
linkedFields: {},
|
linkedFields: {},
|
||||||
editableFields: {
|
editableFields: {
|
||||||
sentence_de: { type: 'textarea' },
|
sentence_de: { type: 'textarea' },
|
||||||
sentence_en: { type: 'textarea' },
|
sentence_en: { type: 'textarea' },
|
||||||
status: { type: 'select', options: ['published', 'blocked', 'draft'] },
|
sentence_sv: { type: 'textarea' },
|
||||||
|
blocked_topic:{ type: 'text' },
|
||||||
|
status: { type: 'select', options: ['draft', 'published', 'blocked'] },
|
||||||
},
|
},
|
||||||
fetchRelated: [],
|
fetchRelated: [],
|
||||||
},
|
},
|
||||||
|
|
||||||
statements: {
|
statements: {
|
||||||
label: 'Statements',
|
label: 'Statements',
|
||||||
icon: '💬',
|
icon: '💬',
|
||||||
endpoint: '/statements',
|
endpoint: '/statements',
|
||||||
statusField: 'status',
|
statusField: 'status',
|
||||||
primaryLabel: 'positive_sentence_de',
|
primaryLabel: 'positive_sentence_de',
|
||||||
columns: ['positive_sentence_de', 'negative_sentence_de', 'status', 'created_at'],
|
columns: ['positive_sentence_de', 'negative_sentence_de', 'answer', 'status', 'created_at'],
|
||||||
linkedFields: {},
|
linkedFields: {},
|
||||||
editableFields: {
|
editableFields: {
|
||||||
positive_sentence_de: { type: 'textarea' },
|
positive_sentence_de: { type: 'textarea' },
|
||||||
negative_sentence_de: { type: 'textarea' },
|
negative_sentence_de: { type: 'textarea' },
|
||||||
positive_sentence_en: { type: 'textarea' },
|
positive_sentence_en: { type: 'textarea' },
|
||||||
negative_sentence_en: { type: 'textarea' },
|
negative_sentence_en: { type: 'textarea' },
|
||||||
status: { type: 'select', options: ['published', 'blocked', 'draft'] },
|
positive_sentence_sv: { type: 'textarea' },
|
||||||
|
negative_sentence_sv: { type: 'textarea' },
|
||||||
|
answer: { type: 'boolean' },
|
||||||
|
blocked_topic: { type: 'text' },
|
||||||
|
status: { type: 'select', options: ['draft', 'published', 'blocked'] },
|
||||||
},
|
},
|
||||||
fetchRelated: [],
|
fetchRelated: [],
|
||||||
},
|
},
|
||||||
|
|
||||||
categories: {
|
categories: {
|
||||||
label: 'Kategorien',
|
label: 'Kategorien',
|
||||||
icon: '🏷️',
|
icon: '🏷️',
|
||||||
endpoint: '/categories',
|
endpoint: '/categories',
|
||||||
statusField: null,
|
statusField: 'status',
|
||||||
primaryLabel: 'name_de',
|
primaryLabel: 'titel_de',
|
||||||
columns: ['name_de', 'name_en', 'name_sv', 'created_at'],
|
columns: ['titel_de', 'titel_en', 'titel_sv', 'status', 'difficulty_level', 'created_at'],
|
||||||
linkedFields: {},
|
linkedFields: {},
|
||||||
editableFields: {
|
editableFields: {
|
||||||
name_de: { type: 'text' },
|
titel_de: { type: 'text' },
|
||||||
name_en: { type: 'text' },
|
titel_en: { type: 'text' },
|
||||||
name_sv: { type: 'text' },
|
titel_sv: { type: 'text' },
|
||||||
|
status: { type: 'select', options: ['requested', 'published', 'blocked'] },
|
||||||
|
difficulty_level:{ type: 'number', min: 1, max: 50 },
|
||||||
|
},
|
||||||
|
fetchRelated: [],
|
||||||
|
},
|
||||||
|
|
||||||
|
languages: {
|
||||||
|
label: 'Sprachen',
|
||||||
|
icon: '🌐',
|
||||||
|
endpoint: '/languages',
|
||||||
|
statusField: 'status',
|
||||||
|
primaryLabel: 'titel_en',
|
||||||
|
columns: ['titel_en', 'titel_de', 'titel_sv', 'short_en', 'status', 'created_at'],
|
||||||
|
linkedFields: {},
|
||||||
|
editableFields: {
|
||||||
|
titel_en: { type: 'text' },
|
||||||
|
titel_de: { type: 'text' },
|
||||||
|
titel_sv: { type: 'text' },
|
||||||
|
short_en: { type: 'text' },
|
||||||
|
status: { type: 'select', options: ['draft', 'published', 'blocked'] },
|
||||||
|
},
|
||||||
|
fetchRelated: [],
|
||||||
|
},
|
||||||
|
|
||||||
|
users: {
|
||||||
|
label: 'Users',
|
||||||
|
icon: '👤',
|
||||||
|
endpoint: '/users',
|
||||||
|
statusField: null,
|
||||||
|
primaryLabel: 'email',
|
||||||
|
columns: ['email', 'role', 'is_active', 'created_at'],
|
||||||
|
linkedFields: {},
|
||||||
|
editableFields: {
|
||||||
|
role: { type: 'select', options: ['end-user', 'admin'] },
|
||||||
|
is_active: { type: 'boolean' },
|
||||||
|
},
|
||||||
|
fetchRelated: [],
|
||||||
|
},
|
||||||
|
|
||||||
|
blocklist: {
|
||||||
|
label: 'Blocklist',
|
||||||
|
icon: '🚫',
|
||||||
|
endpoint: '/blocklist',
|
||||||
|
statusField: null,
|
||||||
|
primaryLabel: 'email',
|
||||||
|
columns: ['email', 'username', 'phone', 'ip', 'is_blocked', 'blocked_at', 'created_at'],
|
||||||
|
linkedFields: {},
|
||||||
|
editableFields: {
|
||||||
|
email: { type: 'text' },
|
||||||
|
username: { type: 'text' },
|
||||||
|
phone: { type: 'text' },
|
||||||
|
ip: { type: 'text' },
|
||||||
|
is_blocked: { type: 'boolean' },
|
||||||
|
},
|
||||||
|
fetchRelated: [],
|
||||||
|
},
|
||||||
|
|
||||||
|
'user-names': {
|
||||||
|
label: 'Usernames',
|
||||||
|
icon: '🪪',
|
||||||
|
endpoint: '/user-names',
|
||||||
|
statusField: null,
|
||||||
|
primaryLabel: 'username',
|
||||||
|
columns: ['username', 'username_lowercase', 'created_at'],
|
||||||
|
linkedFields: {},
|
||||||
|
editableFields: {
|
||||||
|
username: { type: 'text' },
|
||||||
|
},
|
||||||
|
fetchRelated: [],
|
||||||
|
},
|
||||||
|
|
||||||
|
'users-public': {
|
||||||
|
label: 'Users Public',
|
||||||
|
icon: '🧑🤝🧑',
|
||||||
|
endpoint: '/users-public',
|
||||||
|
statusField: null,
|
||||||
|
primaryLabel: 'id',
|
||||||
|
columns: ['id', 'username_id', 'language_native_id', 'language_target_id', 'created_at'],
|
||||||
|
linkedFields: {
|
||||||
|
username_id: 'user-names',
|
||||||
|
language_native_id: 'languages',
|
||||||
|
language_target_id: 'languages',
|
||||||
|
},
|
||||||
|
editableFields: {
|
||||||
|
language_native_id: { type: 'text' },
|
||||||
|
language_target_id: { type: 'text' },
|
||||||
},
|
},
|
||||||
fetchRelated: [],
|
fetchRelated: [],
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user