diff --git a/cypress/e2e/2_cache-detail.cy.js b/cypress/e2e/2_cache-detail.cy.js index 3f968351..65d5cbc3 100644 --- a/cypress/e2e/2_cache-detail.cy.js +++ b/cypress/e2e/2_cache-detail.cy.js @@ -326,6 +326,12 @@ describe('Cache Detail Overview', () => { cy.contains('Rebalancing is on'); }); + it('successfully displays delete cache modal', () => { + cy.get('[data-cy=detailCacheActions]').click(); + cy.get("[data-cy=manageDeleteLink]").click(); + cy.get('#deleteCacheModal').should('exist'); + }) + function verifyGet(keyType, key, value) { // Going back to cache entries page cy.get('[data-cy=cacheEntriesTab]').click(); diff --git a/cypress/e2e/3_cache-crud-wizard.cy.js b/cypress/e2e/3_cache-crud-wizard.cy.js index 6cc0e0ce..25b6f5ef 100644 --- a/cypress/e2e/3_cache-crud-wizard.cy.js +++ b/cypress/e2e/3_cache-crud-wizard.cy.js @@ -211,7 +211,7 @@ describe('Cache Creation Wizard', () => { deleteCache('aSimpleCache'); }); - it('successfully creates without a template a XML config', () => { + it.only('successfully creates without a template a XML config', () => { //go to create cache page cy.get('[data-cy=createCacheButton]').click(); cy.get('#cache-name').click(); @@ -242,26 +242,43 @@ describe('Cache Creation Wizard', () => { cy.get('[data-cy="statusInfo-clusterManager"]').should('exist'); cy.get('[data-cy=rebalancingSwitch]').should('exist'); cy.contains('aSimpleXmlCache'); - deleteCache('aSimpleXmlCache'); + deleteCache('aSimpleXmlCache', true); }); - function deleteCache(cacheName) { - cy.login(Cypress.env('username'), Cypress.env('password')); - cy.get(`[data-cy=actions-${cacheName}]`).click(); - cy.get('[aria-label=deleteCacheAction]').click(); + function deleteCache(cacheName, isDetailPage) { + if (isDetailPage) { + cy.login(Cypress.env('username'), Cypress.env('password'), `/cache/${cacheName}`); + cy.get('[data-cy=detailCacheActions]').click(); + cy.get("[data-cy=manageDeleteLink]").click(); + } else { + cy.login(Cypress.env('username'), Cypress.env('password')); + cy.get(`[data-cy=actions-${cacheName}]`).click(); + cy.get('[aria-label=deleteCacheAction]').click(); + } + cy.get('#deleteCacheModal').should('exist'); cy.contains('Permanently delete cache?'); cy.get('#deleteCacheModal [aria-label=Close]').click(); //Closing modal with close button cy.contains('Permanently delete cache?').should('not.exist'); - cy.get(`[data-cy=actions-${cacheName}]`).click(); - cy.get('[aria-label=deleteCacheAction]').click(); + if (isDetailPage) { + cy.get('[data-cy=detailCacheActions]').click(); + cy.get("[data-cy=manageDeleteLink]").click(); + } else { + cy.get(`[data-cy=actions-${cacheName}]`).click(); + cy.get('[aria-label=deleteCacheAction]').click(); + } cy.contains('Permanently delete cache?'); cy.get('[data-cy=cancelCacheDeleteButton]').click(); //Closing modal with Cancel button cy.contains('Permanently delete cache?').should('not.exist'); - cy.get(`[data-cy=actions-${cacheName}]`).click(); - cy.get('[aria-label=deleteCacheAction]').click(); + if (isDetailPage) { + cy.get('[data-cy=detailCacheActions]').click(); + cy.get("[data-cy=manageDeleteLink]").click(); + } else { + cy.get(`[data-cy=actions-${cacheName}]`).click(); + cy.get('[aria-label=deleteCacheAction]').click(); + } cy.get('#cache-to-delete').click(); cy.get('#cache-to-delete').type(cacheName); cy.get('[data-cy=deleteCacheButton]').click(); //Deleting cache aCache diff --git a/src/app/Caches/DetailCache.tsx b/src/app/Caches/DetailCache.tsx index cf47bae9..29539766 100644 --- a/src/app/Caches/DetailCache.tsx +++ b/src/app/Caches/DetailCache.tsx @@ -44,7 +44,8 @@ import { ExclamationCircleIcon, InfoCircleIcon, PencilAltIcon, - RedoIcon + RedoIcon, + TrashIcon } from '@patternfly/react-icons'; import { QueryEntries } from '@app/Caches/Query/QueryEntries'; import { Link } from 'react-router-dom'; @@ -60,6 +61,7 @@ import { TracingEnabled } from '@app/Common/TracingEnabled'; import { InfinispanComponentStatus } from '@app/Common/InfinispanComponentStatus'; import { PageHeader } from '@patternfly/react-component-groups'; import { UpdateAliasCache } from '@app/Caches/UpdateAliasCache'; +import { DeleteCache } from '@app/Caches/DeleteCache'; const DetailCache = (props: { cacheName: string }) => { const cacheName = props.cacheName; @@ -71,6 +73,7 @@ const DetailCache = (props: { cacheName: string }) => { const [activeTabKey1, setActiveTabKey1] = useState(''); const [activeTabKey2, setActiveTabKey2] = useState(10); const [isOpen, setIsOpen] = useState(false); + const [isOpenDelete, setIsOpenDelete] = useState(false); const [cacheAction, setCacheAction] = useState(''); const isAdmin = ConsoleServices.security().hasConsoleACL(ConsoleACL.ADMIN, connectedUser); const isCacheReader = ConsoleServices.security().hasCacheConsoleACL(ConsoleACL.READ, cacheName, connectedUser); @@ -209,6 +212,10 @@ const DetailCache = (props: { cacheName: string }) => { return cache && cache?.features?.indexed; }; + const displayDelete = () => { + return isAdmin && cache; + }; + const displayEditConfigManage = () => { return isAdmin && cache; }; @@ -296,6 +303,25 @@ const DetailCache = (props: { cacheName: string }) => { ); }; + const buildDelete = () => { + if (!displayDelete()) return; + + return ( + } + onClick={(ev) => { + setIsOpenDelete(true); + setIsOpen(false); + }} + > + {t('caches.actions.action-delete')} + + ); + }; + const buildRefresh = () => { return ( @@ -460,6 +486,7 @@ const DetailCache = (props: { cacheName: string }) => { {buildIndexManage()} {buildBackupsManage()} {buildRefresh()} + {buildDelete()} @@ -513,6 +540,20 @@ const DetailCache = (props: { cacheName: string }) => { )} {buildDetailContent()} + { + if (deleteDone) { + navigate({ + pathname: '/', + search: location.search + }); + } else { + setIsOpenDelete(false); + } + }} + /> diff --git a/src/app/assets/languages/en.json b/src/app/assets/languages/en.json index 1c4e947c..b153e8b0 100644 --- a/src/app/assets/languages/en.json +++ b/src/app/assets/languages/en.json @@ -589,6 +589,7 @@ "action-manage-tracing": "Manage tracing", "action-manage-backups": "Manage backups", "action-manage-config": "Edit configuration", + "action-delete": "Delete", "refresh": "Refresh", "back": "Back" }, diff --git a/src/app/index.tsx b/src/app/index.tsx index 9bb65d97..9da71ca2 100644 --- a/src/app/index.tsx +++ b/src/app/index.tsx @@ -25,9 +25,7 @@ const App = () => { ConsoleServices.init(); } // Base is coming from index.html, and can dynamically change in prod with a reverse proxy - const base = - document.querySelector('base')?.getAttribute('href')?.replace(/\/$/, '') || '/'; - + const base = document.querySelector('base')?.getAttribute('href')?.replace(/\/$/, '') || '/'; return ( diff --git a/src/services/ConsoleServices.ts b/src/services/ConsoleServices.ts index f83d406e..fcc2f5f4 100644 --- a/src/services/ConsoleServices.ts +++ b/src/services/ConsoleServices.ts @@ -50,8 +50,8 @@ export class ConsoleServices { return process.env.INFINISPAN_SERVER_URL + '/rest/v2'; } } else { - const x = (window as any); - return window.location.origin.toString() + (x.INFINISPAN_CONFIG?.restContextPath || '/rest') + '/v2'; + const x = window as any; + return window.location.origin.toString() + (x.INFINISPAN_CONFIG?.restContextPath || '/rest') + '/v2'; } }