diff --git a/cypress/e2e/2_cache-detail-search.cy.js b/cypress/e2e/2_cache-detail-search.cy.js index 9fd3628f..9f37fa6f 100644 --- a/cypress/e2e/2_cache-detail-search.cy.js +++ b/cypress/e2e/2_cache-detail-search.cy.js @@ -58,6 +58,15 @@ describe('Cache Detail Overview', () => { cy.get('[data-cy=detailCacheActions]').click(); cy.get("[data-cy=manageIndexesLink]").click(); + + cy.get("[data-cy=updateSchemaIndexButton]").click(); + cy.contains("Update schema?"); + cy.get("[data-cy=cancelButton]").click(); + cy.get("[data-cy=updateSchemaIndexButton]").click(); + cy.contains("Update schema?"); + cy.get("[data-cy=updateCacheSchema]").click(); + cy.contains("Schema of cache indexed-cache updated.").click(); + cy.get("[data-cy=clearIndexButton]").click(); cy.contains("Permanently clear index?"); cy.get("[data-cy=cancelButton]").click(); diff --git a/src/app/IndexManagement/IndexManagement.tsx b/src/app/IndexManagement/IndexManagement.tsx index a46e342b..5032ac28 100644 --- a/src/app/IndexManagement/IndexManagement.tsx +++ b/src/app/IndexManagement/IndexManagement.tsx @@ -38,6 +38,7 @@ import { ConsoleACL } from '@services/securityService'; import { useConnectedUser } from '@app/services/userManagementHook'; import { useSearchStats } from '@app/services/statsHook'; import { DatabaseIcon } from '@patternfly/react-icons'; +import { UpdateSchema } from '@app/IndexManagement/UpdateSchema'; const IndexManagement = () => { const { t } = useTranslation(); @@ -47,6 +48,7 @@ const IndexManagement = () => { const { stats, loading, error, setLoading } = useSearchStats(cacheName); const [purgeModalOpen, setPurgeModalOpen] = useState(false); const [reindexModalOpen, setReindexModalOpen] = useState(false); + const [updateSchemaModalOpen, setUpdateSchemaModalOpen] = useState(false); const closePurgeModal = () => { setPurgeModalOpen(false); @@ -58,6 +60,32 @@ const IndexManagement = () => { setLoading(true); }; + const closeUpdateSchemaModal = () => { + setUpdateSchemaModalOpen(false); + setLoading(true); + }; + + const buildUpdateSchemaAction = () => { + if (!ConsoleServices.security().hasConsoleACL(ConsoleACL.ADMIN, connectedUser)) { + return; + } + + if (stats?.reindexing) { + return ; + } + return ( + + + + ); + }; + const buildReindexAction = () => { if (!ConsoleServices.security().hasConsoleACL(ConsoleACL.ADMIN, connectedUser)) { return; @@ -68,7 +96,11 @@ const IndexManagement = () => { } return ( - @@ -165,6 +197,7 @@ const IndexManagement = () => { {buildIndexPageContent()} + {buildUpdateSchemaAction()} {buildReindexAction()} {buildPurgeIndexButton()} @@ -186,6 +219,7 @@ const IndexManagement = () => { + ); }; diff --git a/src/app/IndexManagement/PurgeIndex.tsx b/src/app/IndexManagement/PurgeIndex.tsx index 8c6e422c..5f4d4ede 100644 --- a/src/app/IndexManagement/PurgeIndex.tsx +++ b/src/app/IndexManagement/PurgeIndex.tsx @@ -9,7 +9,6 @@ import { ConsoleServices } from '@services/ConsoleServices'; */ const PurgeIndex = (props: { cacheName: string; isModalOpen: boolean; closeModal: () => void }) => { const { t } = useTranslation(); - const brandname = t('brandname.brandname'); const { addAlert } = useApiAlert(); const onClickPurgeButton = () => { @@ -24,24 +23,24 @@ const PurgeIndex = (props: { cacheName: string; isModalOpen: boolean; closeModal return ( - Clear + {t('common.actions.clear')} , ]} > - All indexes in {props.cacheName} will be deleted. + {t('caches.index.purge.description1')} {props.cacheName}{' '} + {t('caches.index.purge.description2')} diff --git a/src/app/IndexManagement/Reindex.tsx b/src/app/IndexManagement/Reindex.tsx index 8d7bd936..f73adc9b 100644 --- a/src/app/IndexManagement/Reindex.tsx +++ b/src/app/IndexManagement/Reindex.tsx @@ -10,8 +10,6 @@ import { ConsoleServices } from '@services/ConsoleServices'; const Reindex = (props: { cacheName: string; isModalOpen: boolean; closeModal: () => void }) => { const { addAlert } = useApiAlert(); const { t } = useTranslation(); - const brandname = t('brandname.brandname'); - const onClickReindex = () => { ConsoleServices.search() .reindex(props.cacheName) @@ -24,27 +22,23 @@ const Reindex = (props: { cacheName: string; isModalOpen: boolean; closeModal: ( return ( - Rebuild index + {t('caches.index.reindex.button-rebuild-index')} , ]} > - - All indexes will be rebuilt. To ensure accurate results, do not query caches until rebuilding is complete. -
- This process may take a few minutes. -
+ {t('caches.index.reindex.description1')} + {t('caches.index.reindex.description2')}
); diff --git a/src/app/IndexManagement/UpdateSchema.tsx b/src/app/IndexManagement/UpdateSchema.tsx new file mode 100644 index 00000000..18b2e3b5 --- /dev/null +++ b/src/app/IndexManagement/UpdateSchema.tsx @@ -0,0 +1,48 @@ +import React from 'react'; +import { Button, ButtonVariant, Modal, Text, TextContent } from '@patternfly/react-core'; +import { useApiAlert } from '@app/utils/useApiAlert'; +import { useTranslation } from 'react-i18next'; +import { ConsoleServices } from '@services/ConsoleServices'; + +/** + * Update schema modal + */ +const UpdateSchema = (props: { cacheName: string; isModalOpen: boolean; closeModal: () => void }) => { + const { t } = useTranslation(); + const { addAlert } = useApiAlert(); + + const onClickPurgeButton = () => { + ConsoleServices.search() + .updateSchema(props.cacheName) + .then((actionResponse) => { + props.closeModal(); + addAlert(actionResponse); + }); + }; + + return ( + + {t('common.actions.update')} + , + + ]} + > + + {t('caches.index.update-schema.description1')} + {t('caches.index.update-schema.description2')} + + + ); +}; + +export { UpdateSchema }; diff --git a/src/app/assets/languages/en.json b/src/app/assets/languages/en.json index 7d80c70a..8c8dbcd6 100644 --- a/src/app/assets/languages/en.json +++ b/src/app/assets/languages/en.json @@ -18,7 +18,9 @@ "cancel": "Cancel", "save": "Save", "delete": "Delete", - "remove": "Remove" + "remove": "Remove", + "clear": "Clear", + "update": "Update" }, "loading-error-message": "There was an error retrieving data. Check your connection and try again.", "tracing": { @@ -677,7 +679,24 @@ "size": "Index size in bytes", "indexing-status": "Indexing", "button-clear": "Clear index", - "button-rebuild": "Rebuild index" + "button-rebuild": "Rebuild index", + "button-update-schema": "Update schema", + "reindex": { + "title": "Rebuild index?", + "button-rebuild-index": "Rebuild index", + "description1": "All indexes will be rebuilt. To ensure accurate results, do not query caches until rebuilding is complete.", + "description2": "This process may take a few minutes." + }, + "purge": { + "title": "Permanently clear index?", + "description1": "All indexes in", + "description2": "will be deleted." + }, + "update-schema": { + "title": "Update schema?", + "description1": "Add new fields to the existing schema without having to rebuild the entire index.", + "description2": "This process may take a few minutes." + } }, "tracing": { "title": "Tracing management", diff --git a/src/services/searchService.ts b/src/services/searchService.ts index 30efbacf..f7ff2068 100644 --- a/src/services/searchService.ts +++ b/src/services/searchService.ts @@ -127,6 +127,19 @@ export class SearchService { }); } + /** + * Update schema for the cache name + * + * @param cacheName + */ + public async updateSchema(cacheName: string): Promise { + return this.utils.post({ + url: this.endpoint + encodeURIComponent(cacheName) + '/search/indexes?action=updateSchema', + successMessage: `Schema of cache ${cacheName} updated.`, + errorMessage: `An error occurred when updating the schema for cache ${cacheName}.` + }); + } + /** * Reindex cache *