-
-
Notifications
You must be signed in to change notification settings - Fork 6
New algolia #377
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Draft
tlambert03
wants to merge
34
commits into
main
Choose a base branch
from
new-algolia
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Draft
New algolia #377
+2,398
−819
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
…osal - Analyzed current Algolia setup (backend Django integration and frontend JS) - Identified deprecated libraries: autocomplete.js, algoliasearch v3 - Documented 6-year gap vs current best practices - Proposed 4-phase modernization strategy with detailed implementation plans - Included code examples for upgrading to modern stack - Estimated effort: 1-2 weeks for critical phases - Zero cost for phases 1-3 (all open-source upgrades)
- Remove stale algoliasearch-django wrapper (inactive, 11mo old) - Replace with direct Python client + custom indexing service - Frontend-first architecture (10x faster, Algolia recommendation) - Async indexing via Celery (no request blocking) - Modern React InstantSearch UI with faceted search - Explicit control over indexing (no magic abstractions) - Complete migration path with rollback plan - Zero cost upgrade (all open-source)
- Remove inactive algoliasearch_django wrapper (stale, discontinued) - Add algoliasearch>=4.0 direct client (actively maintained) - Remove INSTALLED_APPS conditional for wrapper - Prepare for custom indexing service implementation This is the first step in modernizing Algolia integration with a frontend-first architecture.
- Create ProteinIndexer with explicit serialization logic - Create OrganismIndexer and ReferenceIndexer - Support for index configuration and replica indices - Structured logging for all operations - Graceful handling when Algolia not configured - Clear, maintainable code (~400 LOC) vs opaque wrapper This replaces the algoliasearch-django wrapper with explicit, controllable indexing logic.
- Add index_protein_task with retry logic - Add delete_protein_task for deletions - Add reindex_all_proteins for batch reindexing - Add index_organism_task and index_reference_task - Add configure_all_indices task - All tasks use structlog for structured logging - Exponential backoff on failures This ensures indexing never blocks request/response cycles.
- Add post_save handler for Protein to trigger async indexing - Add post_delete handler for Protein to remove from index - Add handlers for Organism and Reference models - All indexing is async via Celery (no request blocking) - Gracefully skip if Algolia not configured This replaces the algoliasearch-django automatic indexing with our custom async implementation.
These files were for the algoliasearch-django wrapper which we've replaced with custom indexing service in proteins/algolia.py
- Supports --configure flag to set index settings - Supports --sync flag for synchronous operation (testing) - Default async operation via Celery - Clear user feedback and progress messages Usage: uv run backend/manage.py algolia_reindex --configure uv run backend/manage.py algolia_reindex --sync
- Replace deprecated autocomplete.js with @algolia/autocomplete-js - Upgrade algoliasearch from v3 to v5 - Add react-instantsearch for advanced search UI - Add instantsearch.css for styling This modernizes the search stack and removes deprecated libraries.
- Uses @algolia/autocomplete-js (replaces deprecated autocomplete.js) - React-based with createRoot (no jQuery) - Recent searches plugin - Clean component architecture - Proper TypeScript-ready structure - Mobile-optimized with detached mode This replaces the old jQuery-based algolia.js implementation.
- Replace old algolia.js import with SearchAutocomplete.jsx - Remove deprecated autocomplete.js CDN script - Keep jQuery for other components (select2, bootstrap, etc.) - Modern React-based autocomplete now bundled with Vite This completes the transition away from the deprecated autocomplete.js library while maintaining jQuery for other legacy components.
Replaced by modern SearchAutocomplete.jsx component using @algolia/autocomplete-js instead of deprecated autocomplete.js
Comprehensive documentation of: - All changes made (backend + frontend) - Step-by-step commits - Testing instructions - Architecture improvements - Migration checklist for production - Rollback plan - What's not yet implemented (advanced search, tests) This provides a complete reference for the modernization work.
- Add @algolia/autocomplete-plugin-recent-searches - Add @algolia/autocomplete-theme-classic These were missing from the initial dependency update, causing build failures. Build now completes successfully.
- Document missing autocomplete dependencies that were added - Add commit for build fix (77e7f1c) - Clarify that build now works successfully
Lockfile updated to reflect the addition of: - @algolia/[email protected] - @algolia/[email protected]
Move Algolia initialization from module-level to inside useEffect hook to avoid window.FPBASE access at module load time. This fixes the error: '@vitejs/plugin-react can't detect preamble. Something is wrong.' Changes: - Move searchClient initialization inside useEffect - Move recentSearchesPlugin creation inside useEffect - Add safety check for window.FPBASE.ALGOLIA existence - Remove unused React imports (createElement, Fragment) Build now completes successfully without errors.
Changes: - Add data-fpbase-init="autocomplete" to search inputs in templates - Update index.js to handle autocomplete via data-fpbase-init pattern - Remove direct #algolia-search-input check in favor of pattern-based init - Consistent with other components (microscope, litemol, ichart) This makes component initialization more declarative and maintainable.
The Vite React plugin was throwing a preamble detection error because window.FPBASE.imageDir was being accessed directly in JSX template strings. Fixed by: - Moving window.FPBASE.imageDir access to component function body - Using const imageDir = window.FPBASE?.imageDir || '/static/images/' - Applied to ProteinHit, ReferenceHit, and OrganismHit components This ensures window globals are accessed at runtime, not module load time, which allows Vite's React Fast Refresh to properly detect the component. Fixes the console error: "@vitejs/plugin-react can't detect preamble. Something is wrong."
The Vite React plugin preamble error was caused by missing the @vitejs/plugin-react/preamble import in index.js. This import sets up window.$RefreshReg$ and other Fast Refresh globals that React component files expect. Other entry points (simple-spectra-viewer.js, spectra-viewer.js) have this import, but it was missing from index.js. Without this import, when React components load, they check for window.$RefreshReg$ and throw an error when it's not found. Fixes: '@vitejs/plugin-react can\'t detect preamble. Something is wrong.'
The initAutocomplete function was looking for .nav-search form wrapper, which only exists in the navbar (not on home page). Changed to search directly for #algolia-search-input which exists on both the home page and navbar search inputs. Fixes warning: 'Search form not found'
The autocomplete library (@algolia/autocomplete-js) uses Preact internally
for its own rendering. The custom render() and renderNoResults() functions
were trying to use React's createRoot to render Algolia's Preact virtual
nodes, causing the error:
'Objects are not valid as a React child (found: object with keys {type,
props, key, ref, __k, __, __b, __e, __c, constructor, __v, __i, __u})'
Fixed by:
- Removing custom render() and renderNoResults() functions
- Letting Algolia handle its own rendering (as designed)
- Removed unused createRoot import
- Removed unused React import (only need useEffect, useRef)
The JSX in template functions is compiled by Algolia's library, not React.
The template functions (ProteinHit, ReferenceHit, OrganismHit) use JSX, but Algolia's autocomplete library uses Preact internally, not React. When JSX was compiled to React.createElement, it created frozen React elements that Preact couldn't extend, causing: 'Cannot add property __, object is not extensible' Fixed by: - Adding /** @jsx h */ pragma to use Preact's createElement - Importing createElement as h and Fragment from @algolia/autocomplete-js - Now JSX compiles to Preact vnodes that autocomplete can use This is the correct way to use JSX with Algolia autocomplete.
The previous fix tried to import createElement from @algolia/autocomplete-js, but that package doesn't export it - Preact does. Fixed by: - Adding preact as a dependency (pnpm add preact) - Importing h and Fragment from 'preact' directly - JSX pragma /** @jsx h */ now correctly uses Preact's h function - Template functions now compile to proper Preact vnodes This resolves the 'object is not extensible' error that occurred when Algolia's Preact renderer tried to work with React-compiled JSX.
JSX and Preact were causing 'object is not extensible' errors because React/Preact create frozen objects that conflict with each other. The correct solution is to use Algolia's built-in html tagged template function (available since autocomplete v1.6.0), which works directly in the browser without needing JSX transpilation or virtual DOM libraries. Changes: - Removed Preact dependency (pnpm remove preact) - Removed JSX pragma and Preact imports - Converted all template functions to use html tagged template: - ProteinHit, ReferenceHit, OrganismHit now use html`...` - All header() functions use html`...` - All noResults() functions use html`...` - Updated template calls to pass html parameter instead of components This is the official Algolia recommended approach for browser usage.
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #377 +/- ##
==========================================
- Coverage 61.08% 52.74% -8.35%
==========================================
Files 108 108
Lines 8694 9042 +348
==========================================
- Hits 5311 4769 -542
- Misses 3383 4273 +890 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
No description provided.