Add multi-schema support and per-base libraries
- Swap MST/BCK and MTH/ATC button positions
- Add schema support for different PostgreSQL schemas:
- secretaria_clara: atc, mst, bck
- production_alfred: mth
- mail_manager: mail
- context_manager: chat
- Libraries now load per-base (library_{base})
- Add new base types: key, mindlink
- Update FetchOptions to use schema instead of headers
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -3,17 +3,22 @@ import { API_BASE } from '@/config/index.ts';
|
||||
interface FetchOptions {
|
||||
method?: 'GET' | 'POST';
|
||||
body?: Record<string, unknown>;
|
||||
schema?: string; // PostgREST Accept-Profile header
|
||||
}
|
||||
|
||||
export async function apiClient<T>(
|
||||
endpoint: string,
|
||||
options: FetchOptions = {}
|
||||
): Promise<T> {
|
||||
const { method = 'GET', body } = options;
|
||||
const { method = 'GET', body, schema } = options;
|
||||
|
||||
const headers: Record<string, string> = {};
|
||||
if (body) headers['Content-Type'] = 'application/json';
|
||||
if (schema) headers['Accept-Profile'] = schema;
|
||||
|
||||
const config: RequestInit = {
|
||||
method,
|
||||
headers: body ? { 'Content-Type': 'application/json' } : undefined,
|
||||
headers: Object.keys(headers).length > 0 ? headers : undefined,
|
||||
body: body ? JSON.stringify(body) : undefined,
|
||||
};
|
||||
|
||||
|
||||
@@ -1,12 +1,24 @@
|
||||
import { apiClientSafe } from './client.ts';
|
||||
import type { Library } from '@/types/index.ts';
|
||||
import type { Library, BaseType } from '@/types/index.ts';
|
||||
|
||||
export const fetchLibraries = (): Promise<Library[]> =>
|
||||
apiClientSafe<Library[]>('/api_library_list', {}, []);
|
||||
// Base types that have library tables (public schema taxonomy tables)
|
||||
const LIBRARY_BASES = new Set(['hst', 'flg', 'itm', 'loc', 'ply']);
|
||||
|
||||
export const fetchLibraryMembers = async (mrf: string): Promise<string[]> => {
|
||||
export const fetchLibraries = (base: BaseType): Promise<Library[]> => {
|
||||
// Only public schema taxonomy tables have libraries
|
||||
if (!LIBRARY_BASES.has(base)) {
|
||||
return Promise.resolve([]);
|
||||
}
|
||||
// Try base-specific endpoint, fallback to generic
|
||||
return apiClientSafe<Library[]>(`/api_library_list?base=eq.${base}`, {}, []);
|
||||
};
|
||||
|
||||
export const fetchLibraryMembers = async (mrf: string, base: BaseType): Promise<string[]> => {
|
||||
if (!LIBRARY_BASES.has(base)) {
|
||||
return [];
|
||||
}
|
||||
const data = await apiClientSafe<Array<{ mrf_tag: string }>>(
|
||||
`/library_hst?mrf_library=eq.${mrf}`,
|
||||
`/library_${base}?mrf_library=eq.${mrf}`,
|
||||
{},
|
||||
[]
|
||||
);
|
||||
|
||||
@@ -1,8 +1,52 @@
|
||||
import { apiClientSafe } from './client.ts';
|
||||
import type { Tag, ChildTag, RelatedTag, BaseType } from '@/types/index.ts';
|
||||
|
||||
export const fetchTags = (base: BaseType): Promise<Tag[]> =>
|
||||
apiClientSafe<Tag[]>(`/${base}?order=ref.asc`, {}, []);
|
||||
// Schema mapping by base type
|
||||
// - public (default): hst, flg, itm, loc, ply
|
||||
// - secretaria_clara: atc, mst, bck
|
||||
// - production_alfred: mth
|
||||
// - mail_manager: mail (table: clara_registros)
|
||||
// - context_manager: chat (table: messages)
|
||||
|
||||
interface SchemaTableConfig {
|
||||
schema: string | null;
|
||||
table: string;
|
||||
}
|
||||
|
||||
const getSchemaAndTable = (base: BaseType): SchemaTableConfig => {
|
||||
switch (base) {
|
||||
// secretaria_clara schema
|
||||
case 'atc':
|
||||
case 'mst':
|
||||
case 'bck':
|
||||
return { schema: 'secretaria_clara', table: base };
|
||||
|
||||
// production_alfred schema
|
||||
case 'mth':
|
||||
return { schema: 'production_alfred', table: base };
|
||||
|
||||
// mail_manager schema
|
||||
case 'mail':
|
||||
return { schema: 'mail_manager', table: 'clara_registros' };
|
||||
|
||||
// context_manager schema
|
||||
case 'chat':
|
||||
return { schema: 'context_manager', table: 'messages' };
|
||||
|
||||
// public schema (default) - hst, flg, itm, loc, ply
|
||||
default:
|
||||
return { schema: null, table: base };
|
||||
}
|
||||
};
|
||||
|
||||
export const fetchTags = (base: BaseType): Promise<Tag[]> => {
|
||||
const { schema, table } = getSchemaAndTable(base);
|
||||
return apiClientSafe<Tag[]>(
|
||||
`/${table}?order=ref.asc`,
|
||||
schema ? { schema } : {},
|
||||
[]
|
||||
);
|
||||
};
|
||||
|
||||
// Fetch HST tags for group name resolution (set_hst points to hst tags)
|
||||
export const fetchHstTags = (): Promise<Tag[]> =>
|
||||
|
||||
@@ -39,7 +39,7 @@ class App {
|
||||
fetchTags(state.base),
|
||||
fetchHstTags(), // Always load HST for group name resolution
|
||||
fetchGroups(),
|
||||
fetchLibraries()
|
||||
fetchLibraries(state.base) // Load libraries for current base
|
||||
]);
|
||||
store.setState({ tags, hstTags, groups, libraries });
|
||||
|
||||
@@ -153,11 +153,12 @@ class App {
|
||||
|
||||
delegateEvent<MouseEvent>(container, '.lib-icon', 'click', async (_, target) => {
|
||||
const library = target.dataset.lib || 'all';
|
||||
const currentBase = store.getState().base;
|
||||
|
||||
if (library === 'all') {
|
||||
store.setState({ library: 'all', libraryMembers: new Set() });
|
||||
} else {
|
||||
const members = await fetchLibraryMembers(library);
|
||||
const members = await fetchLibraryMembers(library, currentBase);
|
||||
store.setState({ library, libraryMembers: new Set(members) });
|
||||
}
|
||||
|
||||
|
||||
@@ -39,7 +39,7 @@ body {
|
||||
gap: 12px;
|
||||
}
|
||||
.topbar-left { display: flex; align-items: center; gap: 10px; }
|
||||
.topbar-center { flex: 1; display: flex; justify-content: center; }
|
||||
.topbar-center { flex: 1; display: flex; justify-content: center; gap: 16px; }
|
||||
.topbar-right { display: flex; align-items: center; gap: 10px; }
|
||||
.logo { font-weight: 700; font-size: 1.2em; color: var(--accent); letter-spacing: 1px; }
|
||||
|
||||
|
||||
@@ -2,7 +2,12 @@ import type { Tag, Group, Library } from './tag.ts';
|
||||
import type { GraphEdge, TreeEdge, CategoryKey, EdgeType } from './graph.ts';
|
||||
|
||||
export type ViewType = 'grid' | 'tree' | 'graph';
|
||||
export type BaseType = 'hst' | 'flg' | 'itm' | 'loc' | 'ply';
|
||||
export type BaseType =
|
||||
| 'hst' | 'flg' | 'itm' | 'loc' | 'ply' // Taxonomía (public)
|
||||
| 'mth' | 'atc' // Registro (secretaria_clara, production_alfred)
|
||||
| 'mst' | 'bck' // Maestros (secretaria_clara)
|
||||
| 'mail' | 'chat' // Comunicación (mail_manager, context_manager)
|
||||
| 'key' | 'mindlink'; // Servicios
|
||||
export type LangType = 'es' | 'en' | 'ch';
|
||||
|
||||
export interface GraphFilters {
|
||||
|
||||
Reference in New Issue
Block a user