156 lines
12 KiB
Markdown
156 lines
12 KiB
Markdown
# Aether (AE) SvelteKit Application
|
|
|
|
This project is a Svelte and SvelteKit based application, part of the Aether (AE) system. It uses Tailwind CSS and Skeleton for styling and some elements. This is the frontend UI/UX. The backend API uses Python FastAPI.
|
|
|
|
Core Aether modules
|
|
|
|
- accounts - client account, not user account
|
|
- hosted_files
|
|
- people
|
|
- users
|
|
- sites and site_domains
|
|
|
|
Additional Aether modules
|
|
|
|
- events
|
|
- presentation management - import the program data (events, session, presentations, presenters, event files, locations/rooms, devices)
|
|
- launcher - Technically this is used with presentation management. It is part of the native app that uses Electron. One of the libraries is for functions that only work when the site is opened in an Electron app. For example the regular browser can not move files around on the local computer or run local commands.
|
|
- badge printing
|
|
- lead retrieval - attendee tracking; QR codes
|
|
- journals - journal, documentation, notes, diary, blog, etc
|
|
- idaa - One of my clients
|
|
|
|
## Documentation
|
|
|
|
- TODO.md
|
|
- Svelte - Introducing runes - https://svelte.dev/blog/runes
|
|
- Svelte - Breaking changes in runes mode - https://svelte.dev/docs/svelte/v5-migration-guide#Breaking-changes-in-runes-mode
|
|
- Dexie.js - Getting Started - https://dexie.org/docs/Tutorial/Getting-started
|
|
- Dexie.js - API Quick Reference - https://dexie.org/docs/API-Reference#quick-reference
|
|
|
|
## Ignored Directories
|
|
|
|
The following directories are ignored for various operations (e.g., search, file listing) to focus on relevant source code:
|
|
|
|
- `build`
|
|
- `node_modules`
|
|
- `tests`
|
|
|
|
## Development Guidelines
|
|
|
|
### Svelte v5 and SvelteKit
|
|
|
|
This project uses Svelte v5 with runes enabled. This introduces significant differences from Svelte v4. It is critical to adhere to v5 conventions to avoid bugs.
|
|
|
|
- **Reactivity:** State is managed with `$state` and `$derived`. Props can be made two-way bindable with `$bindable`. Avoid direct mutation of props.
|
|
- **Event Handling (Updated 2025-11-20):**
|
|
- **DOM Events:** Use the lowercase `onevent` attribute (e.g., `onclick`, `oninput`). Event modifiers like `|preventDefault` may not work as expected; handle prevention logic inside the function (e.g., `event.preventDefault()`).
|
|
- **Component Events:** Continue to use the `on:eventname` directive for events dispatched from child components.
|
|
- **Stores and `liveQuery`:**
|
|
- To access the value of a store in Svelte v5, you must use the `$store_name` syntax (e.g., `$ae_api`).
|
|
- Dexie `liveQuery` returns an observable. To use it in a component, you must subscribe to it within `onMount` to avoid SSR errors. The value from the subscription should then be assigned to a `$state` variable.
|
|
- **Migration Guide:** For a comprehensive overview of the changes, refer to the official [Svelte 5 Migration Guide](https://svelte.dev/docs/svelte/v5-migration-guide).
|
|
|
|
### ID Convention: `id` vs. `id_random`
|
|
|
|
- **Always use `id_random`:** The API returns both a numeric `id` and a string-based `[obj_type]_id_random`. For all frontend operations (routing, data fetching, local storage), you **must** use the `_id_random` string.
|
|
- **Local Storage:** When saving an object to the local IndexedDB (Dexie), the `id_random` value should be aliased to both `id` (as the primary key) and `[obj_type]_id`. This ensures consistency with Dexie's expectations and the rest of the application's data access patterns.
|
|
|
|
---
|
|
|
|
## Refactoring Notes
|
|
|
|
### UI Library Updates (2025-12-08)
|
|
|
|
**Context:** All project packages, including `@skeletonlabs/skeleton` (v4.7.4) and `flowbite-svelte` (v4.0.1), have been successfully updated to their current versions. The `npm run dev` and `build` commands are now working as expected.
|
|
|
|
**Key Insight:** The previous issues and blocking build errors related to UI library compatibility were largely resolved by addressing specific conflicts, particularly those associated with the `ae_comp__badge_template_form.svelte` file. This indicates that direct integration and careful handling of component-specific dependencies were crucial to achieving library compatibility.
|
|
|
|
**Current State:**
|
|
* The project successfully builds and runs with the latest versions of SkeletonLabs and Flowbite-Svelte.
|
|
* The codebase can now move forward with development, leveraging the updated UI libraries.
|
|
|
|
### Data Fetching & Processing Pattern (2025-11-20)
|
|
|
|
A standard pattern for fetching, processing, and caching data has been established to ensure consistency and separation of concerns.
|
|
|
|
1. **API Function (`load_*`, `search_*`, etc.):** This function is responsible for interacting with the API. It takes parameters needed for the API call (e.g., `event_id`, search strings).
|
|
2. **Data Processor (`process_ae_obj__*_props`):** The API function's results are immediately passed to this dedicated processor function for the specific object type.
|
|
- The API function MUST pass any necessary contextual data (like a parent `event_id`) to the processor.
|
|
- The processor is responsible for all data shaping and enrichment before the data is cached.
|
|
3. **Handling API Inconsistencies:** The processor is the designated location for handling any inconsistencies in the data returned by the API.
|
|
- **Example (`event_badge`):** The `search__event_badge` API endpoint does not include the `event_id` in its results. The `process_ae_obj__event_badge_props` function now accepts the `event_id` as a parameter and injects it into each badge object before it's saved. This centralizes the fix and keeps the API-calling function clean.
|
|
4. **Database Caching (`db_save_ae_obj_li__ae_obj`):** After processing, the clean and consistent data is passed to the generic `db_save` function to be cached in IndexedDB.
|
|
|
|
This pattern isolates API logic from data shaping logic, making the code more modular, predictable, and easier to debug.
|
|
|
|
### Session Learnings (2025-12-12)
|
|
|
|
**Context:** Prepared for the upcoming IDAA meeting by working on the new Jitsi video conferencing page and its corresponding Novi iframe template.
|
|
|
|
**Key Learnings & Actions:**
|
|
* **Suppressing Svelte Warnings:** Added an `onwarn` handler to `svelte.config.js` to suppress `state_referenced_locally`, `non_reactive_update`, and `css_unused_selector` warnings for the time being. This helps to focus on critical errors during development.
|
|
* **Configuration Management:**
|
|
- Initial approach of using `.env` files for Novi/Jitsi configuration was incorrect for this project.
|
|
- **Correct Approach:** Configuration values (`jitsi_token_endpoint`, `novi_idaa_api_key`, `novi_idaa_group_guid_li`) are stored in the database and accessed via the `$ae_loc.site_cfg_json` Svelte store.
|
|
- The `.../video_conferences/+page.svelte` component was refactored to use the `$ae_loc` store instead of `import.meta.env`.
|
|
- The logic for fetching moderators was updated to iterate through a list of group GUIDs (`novi_idaa_group_guid_li`) from the store.
|
|
* **Static Iframe Bridges:**
|
|
- The `static/idaa_novi_iframe_jitsi_meeting.html` file acts as a bridge, taking Novi-templated user variables (`<%=Novi.User.*%>`) and passing them as URL parameters to the Svelte application (`/idaa/video_conferences`).
|
|
- **User Feedback:** An attempt to simplify this bridge by removing a client-side `fetch` call for user details was reverted by the user. This indicates that the original, more complex logic (which constructs `full_name` from `FirstName` and `LastName`) is necessary. This is an important lesson in not over-simplifying third-party integration code without full context.
|
|
- The bridge was updated to include an interactive UI for setting Jitsi parameters (e.g., sound settings, moderator settings) and dynamically rebuilding the iframe `src`.
|
|
|
|
---
|
|
## Jitsi "God Mode" Live Stats Architecture (2025-12-15)
|
|
|
|
### Goal
|
|
For the IDAA client, create an administrative dashboard ("god mode") to monitor live Jitsi meetings—including meeting duration, participant lists, and moderator roles—without needing to join the meetings directly. This is primarily for ensuring meetings are running correctly and for data collection.
|
|
|
|
### Architectural Decision
|
|
A purely client-side approach using the Jitsi External API is not feasible, as it requires being a participant in the meeting. A server-side solution is necessary. After considering a log-parsing approach, the following hybrid architecture was chosen as the most robust and scalable solution.
|
|
|
|
1. **Server-Side XMPP Bot (Stats Collector):**
|
|
* A new, lightweight backend service will be created (likely in Python or Node.js).
|
|
* This service will act as a bot, using special credentials to connect to the Jitsi instance's main XMPP server (Prosody).
|
|
* The bot will automatically and invisibly join the Multi-User Chat (MUC) for each active conference. It will not process any audio or video, only presence and metadata.
|
|
* By listening to real-time XMPP events, it will track participant joins, leaves, and role changes.
|
|
|
|
2. **Database Integration:**
|
|
* As the XMPP bot receives events, it will write structured data directly into the Aether system's database (e.g., a `jitsi_events` table).
|
|
* This provides two key benefits: a source for the live dashboard and a clean, persistent historical record for future analysis, avoiding the fragility of parsing raw text logs.
|
|
|
|
3. **API Endpoint:**
|
|
* A new, secure endpoint (e.g., `/api/jitsi/live-stats`) will be added to the FastAPI backend.
|
|
* This endpoint will query the database to get the current state of all active meetings.
|
|
|
|
4. **Frontend Admin Dashboard:**
|
|
* A new, access-controlled page (e.g., `/admin/jitsi-stats`) will be built in the Svelte application.
|
|
* This page will periodically fetch data from the new API endpoint to display a live overview of all ongoing meetings.
|
|
|
|
### Rationale
|
|
This approach was chosen over log-parsing because the XMPP protocol is a stable, official API for Jitsi, making the solution less likely to break on future Jitsi updates. It provides true real-time data for the live dashboard while simultaneously creating a valuable, structured dataset for historical reporting.
|
|
|
|
---
|
|
## Jitsi Stats Reporting Debugging (End of Day 2025-12-15)
|
|
|
|
### Objective
|
|
As a pragmatic first step towards the "God Mode" view, implement a "moderator-pushed" stats reporting system. A moderator's browser will periodically send the meeting stats to an existing Aether activity log endpoint.
|
|
|
|
### Progress
|
|
1. **Client-Side Logic:** The Svelte component now collects live meeting stats (duration, participants, roles) via the Jitsi External API.
|
|
2. **Reporting Function:** A `report_meeting_stats` function has been created to bundle this data and call the `create_ae_obj__activity_log` API function.
|
|
3. **Trigger:** A 30-second timer (`setInterval`) is implemented to call the reporting function automatically for users where `is_moderator` is true.
|
|
|
|
### Current Problem
|
|
The feature is not working. The browser's console logs show that the `report_meeting_stats` function is being called and the data payload is being correctly prepared. However, the API call fails silently:
|
|
* No success or error messages are logged in the console from the `try...catch` block around the API call.
|
|
* The API call never reaches the FastAPI server (no entry in the server's access logs).
|
|
|
|
### Investigation & Last Actions
|
|
* My initial hypothesis was a hanging network request due to a missing timeout.
|
|
* **Action Taken:** I modified the underlying `post_object` function in `src/lib/ae_api/api_post_object.ts` to add a 20-second timeout to the `fetch` call.
|
|
* **Result:** This had no effect. The request still disappears without triggering the success, error, or timeout conditions. This suggests the issue is preventing the `fetch` call from executing correctly at a fundamental level.
|
|
|
|
### Next Step
|
|
The crucial next step is to use the **Network** tab in the browser's developer tools. We need to observe what happens, if anything, at the exact moment the "Stats payload being sent" message appears in the console. This will tell us if a request is being blocked by the browser itself (e.g., CORS pre-flight failure) or if it's failing to even be dispatched.
|