Files
OSIT-AE-App-Svelte/GEMINI.md
2025-11-19 13:38:45 -05:00

12 KiB

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

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:
    • DOM events still use the on:eventname directive (e.g., on:click, on:input).
    • Component events are dispatched with createEventDispatcher and listened to with on:eventname.
    • For two-way binding on component props, use bind:propName.
  • 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.

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

process_ae_obj__*_props() Refactoring (2025-11-13)

The process_ae_obj__*_props() family of functions, which are responsible for transforming API data for frontend use, have been refactored to standardize their structure and improve maintainability.

The refactoring strategy involved creating a local, non-exported _process_generic_props helper function within each module (ae_journals, ae_events, ae_archives, ae_posts, ae_core). This approach was chosen to avoid altering the module import graph, which had previously caused a critical InternalError: module record has unexpected status: New in the SvelteKit development server when a shared utility file was introduced.

Key aspects of the refactoring:

  • In-file Generic Helper (_process_generic_props): This function handles common data transformations:

    • *_random ID Aliasing: It automatically iterates over object keys and creates a non-suffixed alias for any key ending in _random (e.g., person_id_random becomes person_id). This is crucial for client-side logic that expects standard ID fields.
    • tmp_sort Field Generation: It creates a set of basic tmp_sort fields for client-side sorting.
  • specific_processor Callback: Module-specific logic is handled by a specific_processor callback function passed to the _process_generic_props helper. This allows for:

    • Unique tmp_sort Logic: Modules can override the default tmp_sort fields with their own specific sorting requirements.
    • Content Processing: Asynchronous operations like Markdown parsing (using marked.parse) are handled within the specific_processor for the relevant modules (e.g., ae_journals__journal_entry.ts).
    • Other Special Cases: Any other module-specific data transformations are handled in this callback.
  • core__crud_generic.ts Cleanup: The generic CRUD functions in src/lib/ae_core/core__crud_generic.ts were simplified:

    • The process_ae_obj__props function in this file was deprecated.
    • All calls to process_ae_obj__props and db_save_ae_obj_li__ae_obj were removed from the generic CRUD functions (load_ae_obj_id, load_ae_obj_li, etc.).
    • These functions are now responsible only for API interaction, delegating all data processing and caching to the module-specific functions that call them. This enforces a cleaner separation of concerns.

Tiptap to CodeMirror Migration (2025-11-17)

The rich text editor component, previously based on Tiptap (shad-editor), has been replaced with a CodeMirror-based solution. This change was driven by the complexity of Tiptap and its compatibility issues with Tailwind CSS, aiming for a simpler, markdown-focused editing experience.

Key aspects of the migration:

  • Removal of Tiptap: All @tiptap/* and svelte-tiptap dependencies were removed from package.json, and the src/lib/components/shad-editor/ directory was deleted.
  • CodeMirror Integration: A new CodeMirror component (src/lib/elements/element_codemirror_editor.svelte) was created, providing basic markdown formatting capabilities.
  • Wrapper Component Update: The existing editor wrapper (src/lib/elements/element_tiptap_editor.svelte) was renamed to src/lib/elements/element_codemirror_wrapper.svelte and refactored to utilize the new CodeMirror component. Tiptap-specific logic and props were removed.
  • Component Usage Updates: All Svelte components that previously imported and used the Tiptap wrapper were updated to import element_codemirror_wrapper.svelte. Unsupported props such as default_minimal, show_button_kv, bind:new_html, and bind:changed were removed from their usage.
  • Dependency Cleanup: npm install was run to remove unneeded packages, and npm run format was executed to ensure consistent code style.

CodeMirror Bug Fixes (2025-11-18)

Following the initial migration to CodeMirror, several issues were identified and resolved:

  • Initialization Errors: An "Unrecognized extension value" error was fixed by refactoring codemirror_modules.ts to explicitly import individual CodeMirror extensions instead of relying on the basicSetup bundle. This ensures proper singleton usage and prevents module duplication.
  • Text Wrapping: The EditorView.lineWrapping extension was added to element_codemirror_editor.svelte and e_app_codemirror_v5.svelte to enable text wrapping.
  • Content Saving: Content binding issues were resolved in various IDAA components by correctly binding the html_text prop of the CodeMirror wrapper to the corresponding state variables.
  • Save Button Enablement: The logic for enabling the "Save" button was fixed in ae_idaa_comp__post_obj_id_edit.svelte to correctly detect changes in the CodeMirror editor.
  • Editor Buttons: A TypeError in the editor's formatting buttons was fixed by using EditorSelection.range() to correctly create selection ranges.
  • Component Renaming: The Tiptap_editor component alias was renamed to CodeMirror_wrapper across the project for clarity, and the wrapper file was renamed to element_codemirror_editor_wrapper.svelte.

Badge Search Refactoring (2025-11-18)

The new Badge Search functionality was refactored to resolve several issues related to Svelte 5 reactivity and IndexedDB schema design.

  • Svelte 5 Reactivity Fixes:
    • A store_invalid_shape error was fixed by removing the $ prefix from Svelte 5 state variables in templates.
    • A Svelte 5 compilation error (illegal variable name) was resolved by using $derived to create a local reactive variable from a store.
    • A 500 Internal Error was resolved by moving Dexie liveQuery calls into an onMount block to ensure they only run on the client-side.
  • IndexedDB Schema Refactoring:
    • The primary key for the badge table was changed from a numeric id to the string-based event_badge_id_random.
    • All related components were updated to use the new primary key for data retrieval, allowing for more efficient lookups using get() and bulkGet().
  • Data Flow Simplification:
    • The badge search data flow was refactored to pass full badge objects from the search component to the list component, simplifying the logic and resolving reactivity issues.
  • Link Generation:
    • Badge links were updated to use the string-based random IDs for both the event and the badge, ensuring consistency and avoiding the exposure of internal numeric IDs.

Event Settings Page (2025-11-18)

A new event settings page was created at /events/[event_id]/settings to provide a user-friendly interface for managing event configurations.

Key features:

  • Form-Based UI: Instead of raw JSON editing, the page uses form-based components for editing event properties. This includes basic event fields (name, code, dates, etc.) and the JSON configuration fields (cfg_json, mod_pres_mgmt_json, mod_badges_json, mod_abstracts_json).
  • Collapsible Sections: Each configuration section is wrapped in a <details> element, allowing them to be collapsed and expanded for better organization.
  • View Toggling: For the JSON configuration fields, a toggle switch allows the user to switch between the form-based UI and a raw JSON editor (using CodeMirror), providing flexibility for both simple and advanced editing.
  • Svelte 5 Reactivity: The components were built using Svelte 5's bindable props to ensure proper two-way data binding between the parent page and the child form components. This corrected an issue where changes in the child components were not being reflected in the parent's state.

API Payload Cleaning (2025-11-19)

To address issues with the Aether API's strict handling of POST and PATCH request payloads, a more robust solution for cleaning data on the frontend has been implemented.

Key aspects of the changes:

  • Svelte 5 Event Handlers: Corrected the use of on:click to onclick in the event settings components to align with Svelte 5 conventions.
  • Payload Cleaning:
    • The update_ae_obj__event function in src/lib/ae_events/ae_events__event.ts was modified to remove read-only fields (id, event_id, created_on, updated_on, etc.) from the payload before sending it to the API.
    • The function now also correctly renames account_id to account_id_random to match the API's expectations.
  • Editable Fields Whitelist:
    • A new file, src/lib/ae_events/ae_events__event.editable_fields.ts, was created to define a whitelist of fields that are allowed to be sent in POST and PATCH requests for an event.
    • The create_ae_obj__event and update_ae_obj__event functions now use this whitelist to filter the data_kv object, ensuring only allowed fields are sent to the API. This provides a more maintainable and less error-prone way to manage which fields are sent to the API.
  • Component Cleanup: The temporary pre-cleaning logic from the handle_save function in src/routes/events/[event_id]/settings/+page.svelte has been removed, as the filtering is now handled centrally in ae_events__event.ts.
  • Future Work: This pattern of using a whitelist for editable fields will be applied to all other Aether object types to ensure consistent and correct API interactions across the application.