diff --git a/frontend/src/components/settings/SystemSettings.tsx b/frontend/src/components/settings/SystemSettings.tsx index f9bb293..1f75e30 100644 --- a/frontend/src/components/settings/SystemSettings.tsx +++ b/frontend/src/components/settings/SystemSettings.tsx @@ -25,9 +25,11 @@ export default function SystemSettings({}: SystemSettingsProps) { const [solrStatus, setSolrStatus] = useState<{ reindex: { loading: boolean; message: string; success?: boolean }; recreate: { loading: boolean; message: string; success?: boolean }; + migrate: { loading: boolean; message: string; success?: boolean }; }>({ reindex: { loading: false, message: '' }, - recreate: { loading: false, message: '' } + recreate: { loading: false, message: '' }, + migrate: { loading: false, message: '' } }); const [databaseStatus, setDatabaseStatus] = useState<{ @@ -407,6 +409,57 @@ export default function SystemSettings({}: SystemSettingsProps) { } }; + const handleLibraryMigration = async () => { + const confirmed = window.confirm( + 'This will migrate Solr to support library separation. It will clear existing search data and reindex with library context. Continue?' + ); + + if (!confirmed) return; + + setSolrStatus(prev => ({ + ...prev, + migrate: { loading: true, message: 'Migrating to library-aware schema...', success: undefined } + })); + + try { + const result = await searchAdminApi.migrateLibrarySchema(); + + setSolrStatus(prev => ({ + ...prev, + migrate: { + loading: false, + message: result.success + ? `${result.message}${result.note ? ` Note: ${result.note}` : ''}` + : (result.error || result.details || 'Migration failed'), + success: result.success + } + })); + + setTimeout(() => { + setSolrStatus(prev => ({ + ...prev, + migrate: { loading: false, message: '', success: undefined } + })); + }, 10000); // Longer timeout for migration messages + } catch (error: any) { + setSolrStatus(prev => ({ + ...prev, + migrate: { + loading: false, + message: error.message || 'Network error occurred', + success: false + } + })); + + setTimeout(() => { + setSolrStatus(prev => ({ + ...prev, + migrate: { loading: false, message: '', success: undefined } + })); + }, 10000); + } + }; + // Load status on component mount useEffect(() => { loadSearchEngineStatus(); @@ -445,7 +498,7 @@ export default function SystemSettings({}: SystemSettingsProps) {
+ {/* Library Migration Section */} +
+

Library Separation Migration

+

+ Migrate Solr to support proper library separation. This ensures search results are isolated between different libraries (password-based access). +

+ +
+ {/* Status Messages */} {solrStatus.reindex.message && (
)} + + {solrStatus.migrate.message && ( +
+ {solrStatus.migrate.message} +
+ )}
@@ -490,7 +570,12 @@ export default function SystemSettings({}: SystemSettingsProps) { +
+

⚠️ Library Migration:

+

Only run this once to enable library-aware search. Requires Solr schema to support libraryId field.

+
diff --git a/frontend/src/lib/api.ts b/frontend/src/lib/api.ts index 5daa9f8..612a716 100644 --- a/frontend/src/lib/api.ts +++ b/frontend/src/lib/api.ts @@ -636,6 +636,21 @@ export const searchAdminApi = { const response = await api.post('/admin/search/solr/recreate'); return response.data; }, + + // Migrate to library-aware schema + migrateLibrarySchema: async (): Promise<{ + success: boolean; + message: string; + storiesCount?: number; + authorsCount?: number; + totalCount?: number; + error?: string; + details?: string; + note?: string; + }> => { + const response = await api.post('/admin/search/solr/migrate-library-schema'); + return response.data; + }, }; // Collection endpoints