solr migration button
This commit is contained in:
@@ -25,9 +25,11 @@ export default function SystemSettings({}: SystemSettingsProps) {
|
|||||||
const [solrStatus, setSolrStatus] = useState<{
|
const [solrStatus, setSolrStatus] = useState<{
|
||||||
reindex: { loading: boolean; message: string; success?: boolean };
|
reindex: { loading: boolean; message: string; success?: boolean };
|
||||||
recreate: { loading: boolean; message: string; success?: boolean };
|
recreate: { loading: boolean; message: string; success?: boolean };
|
||||||
|
migrate: { loading: boolean; message: string; success?: boolean };
|
||||||
}>({
|
}>({
|
||||||
reindex: { loading: false, message: '' },
|
reindex: { loading: false, message: '' },
|
||||||
recreate: { loading: false, message: '' }
|
recreate: { loading: false, message: '' },
|
||||||
|
migrate: { loading: false, message: '' }
|
||||||
});
|
});
|
||||||
|
|
||||||
const [databaseStatus, setDatabaseStatus] = useState<{
|
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
|
// Load status on component mount
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
loadSearchEngineStatus();
|
loadSearchEngineStatus();
|
||||||
@@ -445,7 +498,7 @@ export default function SystemSettings({}: SystemSettingsProps) {
|
|||||||
<div className="flex flex-col sm:flex-row gap-3 mb-4">
|
<div className="flex flex-col sm:flex-row gap-3 mb-4">
|
||||||
<Button
|
<Button
|
||||||
onClick={handleSolrReindex}
|
onClick={handleSolrReindex}
|
||||||
disabled={solrStatus.reindex.loading || solrStatus.recreate.loading || !searchEngineStatus.solrAvailable}
|
disabled={solrStatus.reindex.loading || solrStatus.recreate.loading || solrStatus.migrate.loading || !searchEngineStatus.solrAvailable}
|
||||||
loading={solrStatus.reindex.loading}
|
loading={solrStatus.reindex.loading}
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
className="flex-1"
|
className="flex-1"
|
||||||
@@ -454,7 +507,7 @@ export default function SystemSettings({}: SystemSettingsProps) {
|
|||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
onClick={handleSolrRecreate}
|
onClick={handleSolrRecreate}
|
||||||
disabled={solrStatus.reindex.loading || solrStatus.recreate.loading || !searchEngineStatus.solrAvailable}
|
disabled={solrStatus.reindex.loading || solrStatus.recreate.loading || solrStatus.migrate.loading || !searchEngineStatus.solrAvailable}
|
||||||
loading={solrStatus.recreate.loading}
|
loading={solrStatus.recreate.loading}
|
||||||
variant="secondary"
|
variant="secondary"
|
||||||
className="flex-1"
|
className="flex-1"
|
||||||
@@ -463,6 +516,23 @@ export default function SystemSettings({}: SystemSettingsProps) {
|
|||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{/* Library Migration Section */}
|
||||||
|
<div className="border-t theme-border pt-4">
|
||||||
|
<h4 className="text-md font-medium theme-header mb-2">Library Separation Migration</h4>
|
||||||
|
<p className="text-sm theme-text mb-3">
|
||||||
|
Migrate Solr to support proper library separation. This ensures search results are isolated between different libraries (password-based access).
|
||||||
|
</p>
|
||||||
|
<Button
|
||||||
|
onClick={handleLibraryMigration}
|
||||||
|
disabled={solrStatus.reindex.loading || solrStatus.recreate.loading || solrStatus.migrate.loading || !searchEngineStatus.solrAvailable}
|
||||||
|
loading={solrStatus.migrate.loading}
|
||||||
|
variant="primary"
|
||||||
|
className="w-full sm:w-auto"
|
||||||
|
>
|
||||||
|
{solrStatus.migrate.loading ? 'Migrating...' : '🔒 Migrate Library Schema'}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
|
||||||
{/* Status Messages */}
|
{/* Status Messages */}
|
||||||
{solrStatus.reindex.message && (
|
{solrStatus.reindex.message && (
|
||||||
<div className={`text-sm p-3 rounded mb-3 ${
|
<div className={`text-sm p-3 rounded mb-3 ${
|
||||||
@@ -483,6 +553,16 @@ export default function SystemSettings({}: SystemSettingsProps) {
|
|||||||
{solrStatus.recreate.message}
|
{solrStatus.recreate.message}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
{solrStatus.migrate.message && (
|
||||||
|
<div className={`text-sm p-3 rounded mb-3 ${
|
||||||
|
solrStatus.migrate.success
|
||||||
|
? 'bg-green-50 dark:bg-green-900/20 text-green-800 dark:text-green-200'
|
||||||
|
: 'bg-red-50 dark:bg-red-900/20 text-red-800 dark:text-red-200'
|
||||||
|
}`}>
|
||||||
|
{solrStatus.migrate.message}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="text-sm theme-text bg-blue-50 dark:bg-blue-900/20 p-3 rounded-lg">
|
<div className="text-sm theme-text bg-blue-50 dark:bg-blue-900/20 p-3 rounded-lg">
|
||||||
@@ -490,7 +570,12 @@ export default function SystemSettings({}: SystemSettingsProps) {
|
|||||||
<ul className="text-xs space-y-1 ml-4">
|
<ul className="text-xs space-y-1 ml-4">
|
||||||
<li>• <strong>Reindex All:</strong> Refresh all search data while keeping existing schemas (fixes data sync issues)</li>
|
<li>• <strong>Reindex All:</strong> Refresh all search data while keeping existing schemas (fixes data sync issues)</li>
|
||||||
<li>• <strong>Recreate Indices:</strong> Delete and rebuild all search indexes from scratch (fixes schema and structure issues)</li>
|
<li>• <strong>Recreate Indices:</strong> Delete and rebuild all search indexes from scratch (fixes schema and structure issues)</li>
|
||||||
|
<li>• <strong>Migrate Library Schema:</strong> One-time migration to enable library separation (isolates search results by library)</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
<div className="mt-2 pt-2 border-t border-blue-200 dark:border-blue-700">
|
||||||
|
<p className="font-medium text-xs">⚠️ Library Migration:</p>
|
||||||
|
<p className="text-xs">Only run this once to enable library-aware search. Requires Solr schema to support libraryId field.</p>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -636,6 +636,21 @@ export const searchAdminApi = {
|
|||||||
const response = await api.post('/admin/search/solr/recreate');
|
const response = await api.post('/admin/search/solr/recreate');
|
||||||
return response.data;
|
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
|
// Collection endpoints
|
||||||
|
|||||||
Reference in New Issue
Block a user