Add NocoDB events/RSVPs table config and improve session handling
All checks were successful
Build And Push Image / docker (push) Successful in 3m24s

- Add events and rsvps table ID fields to NocoDB settings dialog
- Replace mock getUserSession with proper SessionManager integration
- Improve type safety with explicit type casting and error handling
- Add comprehensive events system bug analysis documentation
This commit is contained in:
2025-08-12 12:24:16 +02:00
parent e06f639454
commit 67d4d5236b
10 changed files with 289 additions and 122 deletions

View File

@@ -278,7 +278,11 @@ export function getEffectiveNocoDBConfig(): EffectiveNocoDB {
url: runtimeConfig.nocodb?.url || 'https://database.monacousa.org',
token: runtimeConfig.nocodb?.token || '',
baseId: runtimeConfig.nocodb?.baseId || '',
tables: { members: 'members-table-id' } // Default table mapping
tables: {
members: 'members-table-id',
events: (runtimeConfig.nocodb as any)?.eventsTableId || '',
rsvps: (runtimeConfig.nocodb as any)?.rsvpTableId || ''
} // Default table mapping
};
// Override with file configuration if available
@@ -306,7 +310,11 @@ export async function getCurrentConfig(): Promise<NocoDBSettings> {
url: config.nocodb.url || runtimeConfig.nocodb?.url || 'https://database.monacousa.org',
apiKey: config.nocodb.apiKey ? '••••••••••••••••' : '',
baseId: config.nocodb.baseId || runtimeConfig.nocodb?.baseId || '',
tables: config.nocodb.tables || { members: 'members-table-id' }
tables: config.nocodb.tables || {
members: 'members-table-id',
events: '',
rsvps: ''
}
};
}
@@ -315,7 +323,11 @@ export async function getCurrentConfig(): Promise<NocoDBSettings> {
url: runtimeConfig.nocodb?.url || 'https://database.monacousa.org',
apiKey: runtimeConfig.nocodb?.token ? '••••••••••••••••' : '',
baseId: runtimeConfig.nocodb?.baseId || '',
tables: { members: 'members-table-id' }
tables: {
members: 'members-table-id',
events: '',
rsvps: ''
}
};
}
@@ -328,7 +340,7 @@ export async function saveRecaptchaConfig(config: { siteKey: string; secretKey:
await createBackup();
const currentConfig = configCache || await loadAdminConfig() || {
nocodb: { url: '', apiKey: '', baseId: '', tables: {} },
nocodb: { url: '', apiKey: '', baseId: '', tables: { members: '', events: '', rsvps: '' } },
lastUpdated: new Date().toISOString(),
updatedBy: 'system'
};
@@ -374,7 +386,7 @@ export async function saveRegistrationConfig(config: { membershipFee: number; ib
await createBackup();
const currentConfig = configCache || await loadAdminConfig() || {
nocodb: { url: '', apiKey: '', baseId: '', tables: {} },
nocodb: { url: '', apiKey: '', baseId: '', tables: { members: '', events: '', rsvps: '' } },
lastUpdated: new Date().toISOString(),
updatedBy: 'system'
};
@@ -430,7 +442,7 @@ export async function saveSMTPConfig(config: SMTPConfig, updatedBy: string): Pro
await createBackup();
const currentConfig = configCache || await loadAdminConfig() || {
nocodb: { url: '', apiKey: '', baseId: '', tables: {} },
nocodb: { url: '', apiKey: '', baseId: '', tables: { members: '', events: '', rsvps: '' } },
lastUpdated: new Date().toISOString(),
updatedBy: 'system'
};

View File

@@ -6,12 +6,15 @@ import type { Event, EventRSVP, EventsResponse, EventFilters } from '~/utils/typ
* Provides CRUD operations and specialized queries for events and RSVPs
*/
export function createNocoDBEventsClient() {
const config = useRuntimeConfig();
// Get effective configuration from admin config system
const { getEffectiveNocoDBConfig } = require('./admin-config');
const effectiveConfig = getEffectiveNocoDBConfig();
const baseUrl = config.nocodb.url;
const token = config.nocodb.token;
const eventsBaseId = config.nocodb.eventsBaseId;
const eventsTableId = config.nocodb.eventsTableId || 'events'; // fallback to table name
const baseUrl = effectiveConfig.url;
const token = effectiveConfig.token;
const eventsBaseId = effectiveConfig.baseId;
const eventsTableId = effectiveConfig.tables.events || 'events';
const rsvpTableId = effectiveConfig.tables.rsvps || 'event_rsvps';
if (!baseUrl || !token || !eventsBaseId) {
throw new Error('Events NocoDB configuration is incomplete. Please check environment variables.');
@@ -150,12 +153,12 @@ export function createNocoDBEventsClient() {
* Create an RSVP record for an event
*/
async createRSVP(rsvpData: Partial<EventRSVP>) {
const url = `${baseUrl}/api/v1/db/data/v1/${eventsBaseId}/${eventsTableId}`;
const url = `${baseUrl}/api/v1/db/data/v1/${eventsBaseId}/${rsvpTableId}`;
const data = {
...rsvpData,
created_at: new Date().toISOString(),
updated_at: new Date().toISOString()
created_time: new Date().toISOString(),
updated_time: new Date().toISOString()
};
return await $fetch<EventRSVP>(url, {
@@ -171,9 +174,9 @@ export function createNocoDBEventsClient() {
async findEventRSVPs(eventId: string) {
const queryParams = new URLSearchParams();
queryParams.set('where', `(event_id = '${eventId}')`);
queryParams.set('sort', 'created_at');
queryParams.set('sort', 'created_time');
const url = `${baseUrl}/api/v1/db/data/v1/${eventsBaseId}/${eventsTableId}?${queryParams.toString()}`;
const url = `${baseUrl}/api/v1/db/data/v1/${eventsBaseId}/${rsvpTableId}?${queryParams.toString()}`;
return await $fetch(url, {
method: 'GET',
@@ -189,9 +192,9 @@ export function createNocoDBEventsClient() {
queryParams.set('where', `(event_id = '${eventId}' AND member_id = '${memberId}')`);
queryParams.set('limit', '1');
const url = `${baseUrl}/api/v1/db/data/v1/${eventsBaseId}/${eventsTableId}?${queryParams.toString()}`;
const url = `${baseUrl}/api/v1/db/data/v1/${eventsBaseId}/${rsvpTableId}?${queryParams.toString()}`;
const response = await $fetch(url, {
const response = await $fetch<{ list?: EventRSVP[]; PageInfo?: any }>(url, {
method: 'GET',
headers
});
@@ -203,11 +206,11 @@ export function createNocoDBEventsClient() {
* Update an RSVP record
*/
async updateRSVP(id: string, rsvpData: Partial<EventRSVP>) {
const url = `${baseUrl}/api/v1/db/data/v1/${eventsBaseId}/${eventsTableId}/${id}`;
const url = `${baseUrl}/api/v1/db/data/v1/${eventsBaseId}/${rsvpTableId}/${id}`;
const data = {
...rsvpData,
updated_at: new Date().toISOString()
updated_time: new Date().toISOString()
};
return await $fetch<EventRSVP>(url, {
@@ -238,7 +241,7 @@ export function createNocoDBEventsClient() {
*/
async findUserEvents(memberId: string, filters?: EventFilters) {
// First get all visible events
const events = await this.findAll(filters);
const events = await this.findAll(filters) as { list?: Event[]; PageInfo?: any };
if (!events.list || events.list.length === 0) {
return { list: [], PageInfo: events.PageInfo };
@@ -247,11 +250,11 @@ export function createNocoDBEventsClient() {
// Get user's RSVPs for these events
const eventIds = events.list.map((e: Event) => e.id);
const rsvpQueryParams = new URLSearchParams();
rsvpQueryParams.set('where', `(member_id = '${memberId}' AND event_id IN (${eventIds.map(id => `'${id}'`).join(',')}))`);
rsvpQueryParams.set('where', `(member_id = '${memberId}' AND event_id IN (${eventIds.map((id: string) => `'${id}'`).join(',')}))`);
const url = `${baseUrl}/api/v1/db/data/v1/${eventsBaseId}/${eventsTableId}?${rsvpQueryParams.toString()}`;
const rsvpUrl = `${baseUrl}/api/v1/db/data/v1/${eventsBaseId}/${rsvpTableId}?${rsvpQueryParams.toString()}`;
const rsvps = await $fetch(url, {
const rsvps = await $fetch<{ list?: EventRSVP[]; PageInfo?: any }>(rsvpUrl, {
method: 'GET',
headers
});
@@ -294,7 +297,7 @@ export function createNocoDBEventsClient() {
if (!event.max_attendees) return false; // Unlimited capacity
const maxAttendees = parseInt(event.max_attendees);
const currentAttendees = event.current_attendees || 0;
const currentAttendees = parseInt(String(event.current_attendees || 0));
return currentAttendees >= maxAttendees;
}