Skip to content

Commit

Permalink
[Search Session][Management] Rename "cancel" button and delete "Reloa…
Browse files Browse the repository at this point in the history
…d" button (elastic#90015)

* Rename management button to "delete"

* fix jest

* Delete reload action from management

* Added both cancel and delete session

* Improve texts

* fix test

* ts

* doc

* fix jest
  • Loading branch information
lizozom authored and Liza K committed Feb 4, 2021
1 parent c72ec12 commit 9b89aac
Show file tree
Hide file tree
Showing 20 changed files with 137 additions and 118 deletions.
1 change: 1 addition & 0 deletions src/plugins/data/server/search/mocks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,5 +40,6 @@ export function createSearchRequestHandlerContext() {
updateSession: jest.fn(),
extendSession: jest.fn(),
cancelSession: jest.fn(),
deleteSession: jest.fn(),
};
}
13 changes: 11 additions & 2 deletions src/plugins/data/server/search/search_service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -307,9 +307,8 @@ export class SearchService implements Plugin<ISearchSetup, ISearchStart> {
return strategy.extend(id, keepAlive, options, deps);
};

private cancelSession = async (deps: SearchStrategyDependencies, sessionId: string) => {
private cancelSessionSearches = async (deps: SearchStrategyDependencies, sessionId: string) => {
const searchIdMapping = await deps.searchSessionsClient.getSearchIdMapping(sessionId);
const response = await deps.searchSessionsClient.cancel(sessionId);

for (const [searchId, strategyName] of searchIdMapping.entries()) {
const searchOptions = {
Expand All @@ -319,10 +318,19 @@ export class SearchService implements Plugin<ISearchSetup, ISearchStart> {
};
this.cancel(deps, searchId, searchOptions);
}
};

private cancelSession = async (deps: SearchStrategyDependencies, sessionId: string) => {
const response = await deps.searchSessionsClient.cancel(sessionId);
this.cancelSessionSearches(deps, sessionId);
return response;
};

private deleteSession = async (deps: SearchStrategyDependencies, sessionId: string) => {
this.cancelSessionSearches(deps, sessionId);
return deps.searchSessionsClient.delete(sessionId);
};

private extendSession = async (
deps: SearchStrategyDependencies,
sessionId: string,
Expand Down Expand Up @@ -372,6 +380,7 @@ export class SearchService implements Plugin<ISearchSetup, ISearchStart> {
updateSession: searchSessionsClient.update,
extendSession: this.extendSession.bind(this, deps),
cancelSession: this.cancelSession.bind(this, deps),
deleteSession: this.deleteSession.bind(this, deps),
};
};
};
Expand Down
1 change: 1 addition & 0 deletions src/plugins/data/server/search/session/mocks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,6 @@ export function createSearchSessionsClientMock<T = unknown>(): jest.Mocked<
update: jest.fn(),
cancel: jest.fn(),
extend: jest.fn(),
delete: jest.fn(),
};
}
3 changes: 3 additions & 0 deletions src/plugins/data/server/search/session/session_service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@ export class SearchSessionService implements ISearchSessionService {
cancel: async () => {
throw new Error('cancel not implemented in OSS search session service');
},
delete: async () => {
throw new Error('delete not implemented in OSS search session service');
},
});
}
}
1 change: 1 addition & 0 deletions src/plugins/data/server/search/session/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ export interface IScopedSearchSessionsClient<T = unknown> {
find: (options: Omit<SavedObjectsFindOptions, 'type'>) => Promise<SavedObjectsFindResponse<T>>;
update: (sessionId: string, attributes: Partial<T>) => Promise<SavedObjectsUpdateResponse<T>>;
cancel: (sessionId: string) => Promise<{}>;
delete: (sessionId: string) => Promise<{}>;
extend: (sessionId: string, expires: Date) => Promise<SavedObjectsUpdateResponse<T>>;
}

Expand Down
1 change: 1 addition & 0 deletions src/plugins/data/server/search/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ export interface IScopedSearchClient extends ISearchClient {
findSessions: IScopedSearchSessionsClient['find'];
updateSession: IScopedSearchSessionsClient['update'];
cancelSession: IScopedSearchSessionsClient['cancel'];
deleteSession: IScopedSearchSessionsClient['delete'];
extendSession: IScopedSearchSessionsClient['extend'];
}

Expand Down
3 changes: 2 additions & 1 deletion src/plugins/data/server/server.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -1258,6 +1258,7 @@ export class SearchSessionService implements ISearchSessionService {
update: () => Promise<never>;
extend: () => Promise<never>;
cancel: () => Promise<never>;
delete: () => Promise<never>;
};
}

Expand Down Expand Up @@ -1434,7 +1435,7 @@ export function usageProvider(core: CoreSetup_2): SearchUsage;
// src/plugins/data/server/index.ts:266:1 - (ae-forgotten-export) The symbol "calcAutoIntervalLessThan" needs to be exported by the entry point index.d.ts
// src/plugins/data/server/index_patterns/index_patterns_service.ts:59:14 - (ae-forgotten-export) The symbol "IndexPatternsService" needs to be exported by the entry point index.d.ts
// src/plugins/data/server/plugin.ts:79:74 - (ae-forgotten-export) The symbol "DataEnhancements" needs to be exported by the entry point index.d.ts
// src/plugins/data/server/search/types.ts:113:5 - (ae-forgotten-export) The symbol "ISearchStartSearchSource" needs to be exported by the entry point index.d.ts
// src/plugins/data/server/search/types.ts:114:5 - (ae-forgotten-export) The symbol "ISearchStartSearchSource" needs to be exported by the entry point index.d.ts

// (No @packageDocumentation comment for this package)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,31 +13,31 @@ import { SearchSessionsMgmtAPI } from '../../lib/api';
import { TableText } from '../';
import { OnActionComplete } from './types';

interface CancelButtonProps {
interface DeleteButtonProps {
id: string;
name: string;
api: SearchSessionsMgmtAPI;
onActionComplete: OnActionComplete;
}

const CancelConfirm = ({
onConfirmDismiss,
const DeleteConfirm = ({
onConfirmCancel,
...props
}: CancelButtonProps & { onConfirmDismiss: () => void }) => {
}: DeleteButtonProps & { onConfirmCancel: () => void }) => {
const { id, name, api, onActionComplete } = props;
const [isLoading, setIsLoading] = useState(false);

const title = i18n.translate('xpack.data.mgmt.searchSessions.cancelModal.title', {
defaultMessage: 'Cancel search session',
defaultMessage: 'Delete search session',
});
const confirm = i18n.translate('xpack.data.mgmt.searchSessions.cancelModal.cancelButton', {
defaultMessage: 'Cancel',
const confirm = i18n.translate('xpack.data.mgmt.searchSessions.cancelModal.deleteButton', {
defaultMessage: 'Delete',
});
const cancel = i18n.translate('xpack.data.mgmt.searchSessions.cancelModal.dontCancelButton', {
defaultMessage: 'Dismiss',
const cancel = i18n.translate('xpack.data.mgmt.searchSessions.cancelModal.cancelButton', {
defaultMessage: 'Cancel',
});
const message = i18n.translate('xpack.data.mgmt.searchSessions.cancelModal.message', {
defaultMessage: `Canceling the search session \'{name}\' will expire any cached results, so that quick restore will no longer be available. You will still be able to re-run it, using the reload action.`,
defaultMessage: `Deleting the search session \'{name}\' deletes all cached results.`,
values: {
name,
},
Expand All @@ -47,7 +47,7 @@ const CancelConfirm = ({
<EuiOverlayMask>
<EuiConfirmModal
title={title}
onCancel={onConfirmDismiss}
onCancel={onConfirmCancel}
onConfirm={async () => {
setIsLoading(true);
await api.sendCancel(id);
Expand All @@ -65,26 +65,26 @@ const CancelConfirm = ({
);
};

export const CancelButton = (props: CancelButtonProps) => {
export const DeleteButton = (props: DeleteButtonProps) => {
const [showConfirm, setShowConfirm] = useState(false);

const onClick = () => {
setShowConfirm(true);
};

const onConfirmDismiss = () => {
const onConfirmCancel = () => {
setShowConfirm(false);
};

return (
<>
<TableText onClick={onClick}>
<FormattedMessage
id="xpack.data.mgmt.searchSessions.actionCancel"
defaultMessage="Cancel"
id="xpack.data.mgmt.searchSessions.actionDelete"
defaultMessage="Delete"
/>
</TableText>
{showConfirm ? <CancelConfirm {...props} onConfirmDismiss={onConfirmDismiss} /> : null}
{showConfirm ? <DeleteConfirm {...props} onConfirmCancel={onConfirmCancel} /> : null}
</>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -10,30 +10,22 @@ import { IClickActionDescriptor } from '../';
import extendSessionIcon from '../../icons/extend_session.svg';
import { SearchSessionsMgmtAPI } from '../../lib/api';
import { UISession } from '../../types';
import { CancelButton } from './cancel_button';
import { DeleteButton } from './delete_button';
import { ExtendButton } from './extend_button';
import { ReloadButton } from './reload_button';
import { ACTION, OnActionComplete } from './types';

export const getAction = (
api: SearchSessionsMgmtAPI,
actionType: string,
{ id, name, expires, reloadUrl }: UISession,
{ id, name, expires }: UISession,
onActionComplete: OnActionComplete
): IClickActionDescriptor | null => {
switch (actionType) {
case ACTION.CANCEL:
case ACTION.DELETE:
return {
iconType: 'crossInACircleFilled',
textColor: 'default',
label: <CancelButton api={api} id={id} name={name} onActionComplete={onActionComplete} />,
};

case ACTION.RELOAD:
return {
iconType: 'refresh',
textColor: 'default',
label: <ReloadButton api={api} reloadUrl={reloadUrl} />,
label: <DeleteButton api={api} id={id} name={name} onActionComplete={onActionComplete} />,
};

case ACTION.EXTEND:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ export const PopoverActionsMenu = ({ api, onActionComplete, session }: PopoverAc

// add a line above the delete action (when there are multiple)
// NOTE: Delete action MUST be the final action[] item
if (actions.length > 1 && actionType === ACTION.CANCEL) {
if (actions.length > 1 && actionType === ACTION.DELETE) {
itemSet.push({ isSeparator: true, key: 'separadorable' });
}

Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,5 @@ export type OnActionComplete = () => void;

export enum ACTION {
EXTEND = 'extend',
CANCEL = 'cancel',
RELOAD = 'reload',
DELETE = 'delete',
}
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,8 @@ describe('Search Sessions Management API', () => {
Array [
Object {
"actions": Array [
"reload",
"extend",
"cancel",
"delete",
],
"appId": "pizza",
"created": undefined,
Expand Down Expand Up @@ -146,7 +145,7 @@ describe('Search Sessions Management API', () => {
await api.sendCancel('abc-123-cool-session-ID');

expect(mockCoreStart.notifications.toasts.addSuccess).toHaveBeenCalledWith({
title: 'The search session was canceled and expired.',
title: 'The search session was deleted.',
});
});

Expand All @@ -162,37 +161,11 @@ describe('Search Sessions Management API', () => {

expect(mockCoreStart.notifications.toasts.addError).toHaveBeenCalledWith(
new Error('implementation is so bad'),
{ title: 'Failed to cancel the search session!' }
{ title: 'Failed to delete the search session!' }
);
});
});

describe('reload', () => {
beforeEach(() => {
sessionsClient.find = jest.fn().mockImplementation(async () => {
return {
saved_objects: [
{
id: 'hello-pizza-123',
attributes: { name: 'Veggie', appId: 'pizza', status: SearchSessionStatus.COMPLETE },
},
],
} as SavedObjectsFindResponse;
});
});

test('send cancel calls the cancel endpoint with a session ID', async () => {
const api = new SearchSessionsMgmtAPI(sessionsClient, mockConfig, {
urls: mockUrls,
notifications: mockCoreStart.notifications,
application: mockCoreStart.application,
});
await api.reloadSearchSession('www.myurl.com');

expect(mockCoreStart.application.navigateToUrl).toHaveBeenCalledWith('www.myurl.com');
});
});

describe('extend', () => {
beforeEach(() => {
sessionsClient.find = jest.fn().mockImplementation(async () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,9 @@ type UrlGeneratorsStart = SharePluginStart['urlGenerators'];

function getActions(status: SearchSessionStatus) {
const actions: ACTION[] = [];
actions.push(ACTION.RELOAD);
if (status === SearchSessionStatus.IN_PROGRESS || status === SearchSessionStatus.COMPLETE) {
actions.push(ACTION.EXTEND);
actions.push(ACTION.CANCEL);
actions.push(ACTION.DELETE);
}
return actions;
}
Expand Down Expand Up @@ -162,17 +161,17 @@ export class SearchSessionsMgmtAPI {
await this.sessionsClient.delete(id);

this.deps.notifications.toasts.addSuccess({
title: i18n.translate('xpack.data.mgmt.searchSessions.api.canceled', {
defaultMessage: 'The search session was canceled and expired.',
title: i18n.translate('xpack.data.mgmt.searchSessions.api.deleted', {
defaultMessage: 'The search session was deleted.',
}),
});
} catch (err) {
// eslint-disable-next-line no-console
console.error(err);

this.deps.notifications.toasts.addError(err, {
title: i18n.translate('xpack.data.mgmt.searchSessions.api.cancelError', {
defaultMessage: 'Failed to cancel the search session!',
title: i18n.translate('xpack.data.mgmt.searchSessions.api.deletedError', {
defaultMessage: 'Failed to delete the search session!',
}),
});
}
Expand Down
Loading

0 comments on commit 9b89aac

Please sign in to comment.