-
Notifications
You must be signed in to change notification settings - Fork 8.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[App Search] Added all Document related routes and logic (#83324)
- Loading branch information
1 parent
ee81b5f
commit 9b5605f
Showing
9 changed files
with
478 additions
and
0 deletions.
There are no files selected for viewing
156 changes: 156 additions & 0 deletions
156
..._search/public/applications/app_search/components/documents/document_detail_logic.test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,156 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License; | ||
* you may not use this file except in compliance with the Elastic License. | ||
*/ | ||
|
||
import { resetContext } from 'kea'; | ||
|
||
import { mockHttpValues } from '../../../__mocks__'; | ||
jest.mock('../../../shared/http', () => ({ | ||
HttpLogic: { values: mockHttpValues }, | ||
})); | ||
const { http } = mockHttpValues; | ||
|
||
jest.mock('../engine', () => ({ | ||
EngineLogic: { values: { engineName: 'engine1' } }, | ||
})); | ||
|
||
jest.mock('../../../shared/flash_messages', () => ({ | ||
setQueuedSuccessMessage: jest.fn(), | ||
flashAPIErrors: jest.fn(), | ||
})); | ||
import { setQueuedSuccessMessage, flashAPIErrors } from '../../../shared/flash_messages'; | ||
|
||
import { DocumentDetailLogic } from './document_detail_logic'; | ||
|
||
describe('DocumentDetailLogic', () => { | ||
const DEFAULT_VALUES = { | ||
dataLoading: true, | ||
fields: [], | ||
}; | ||
|
||
const mount = (defaults?: object) => { | ||
if (!defaults) { | ||
resetContext({}); | ||
} else { | ||
resetContext({ | ||
defaults: { | ||
enterprise_search: { | ||
app_search: { | ||
document_detail_logic: { | ||
...defaults, | ||
}, | ||
}, | ||
}, | ||
}, | ||
}); | ||
} | ||
DocumentDetailLogic.mount(); | ||
}; | ||
|
||
beforeEach(() => { | ||
jest.clearAllMocks(); | ||
}); | ||
|
||
describe('actions', () => { | ||
describe('setFields', () => { | ||
it('should set fields to the provided value and dataLoading to false', () => { | ||
const fields = [{ name: 'foo', value: ['foo'], type: 'string' }]; | ||
|
||
mount({ | ||
dataLoading: true, | ||
fields: [], | ||
}); | ||
|
||
DocumentDetailLogic.actions.setFields(fields); | ||
|
||
expect(DocumentDetailLogic.values).toEqual({ | ||
...DEFAULT_VALUES, | ||
dataLoading: false, | ||
fields, | ||
}); | ||
}); | ||
}); | ||
|
||
describe('getDocumentDetails', () => { | ||
it('will call an API endpoint and then store the result', async () => { | ||
const fields = [{ name: 'name', value: 'python', type: 'string' }]; | ||
jest.spyOn(DocumentDetailLogic.actions, 'setFields'); | ||
const promise = Promise.resolve({ fields }); | ||
http.get.mockReturnValue(promise); | ||
|
||
DocumentDetailLogic.actions.getDocumentDetails('1'); | ||
|
||
expect(http.get).toHaveBeenCalledWith(`/api/app_search/engines/engine1/documents/1`); | ||
await promise; | ||
expect(DocumentDetailLogic.actions.setFields).toHaveBeenCalledWith(fields); | ||
}); | ||
|
||
it('handles errors', async () => { | ||
mount(); | ||
const promise = Promise.reject('An error occurred'); | ||
http.get.mockReturnValue(promise); | ||
|
||
try { | ||
DocumentDetailLogic.actions.getDocumentDetails('1'); | ||
await promise; | ||
} catch { | ||
// Do nothing | ||
} | ||
expect(flashAPIErrors).toHaveBeenCalledWith('An error occurred'); | ||
}); | ||
}); | ||
|
||
describe('deleteDocument', () => { | ||
let confirmSpy: any; | ||
let promise: Promise<any>; | ||
|
||
beforeEach(() => { | ||
confirmSpy = jest.spyOn(window, 'confirm'); | ||
confirmSpy.mockImplementation(jest.fn(() => true)); | ||
promise = Promise.resolve({}); | ||
http.delete.mockReturnValue(promise); | ||
}); | ||
|
||
afterEach(() => { | ||
confirmSpy.mockRestore(); | ||
}); | ||
|
||
it('will call an API endpoint and show a success message', async () => { | ||
mount(); | ||
DocumentDetailLogic.actions.deleteDocument('1'); | ||
|
||
expect(http.delete).toHaveBeenCalledWith(`/api/app_search/engines/engine1/documents/1`); | ||
await promise; | ||
expect(setQueuedSuccessMessage).toHaveBeenCalledWith( | ||
'Successfully marked document for deletion. It will be deleted momentarily.' | ||
); | ||
}); | ||
|
||
it('will do nothing if not confirmed', async () => { | ||
mount(); | ||
window.confirm = () => false; | ||
|
||
DocumentDetailLogic.actions.deleteDocument('1'); | ||
|
||
expect(http.delete).not.toHaveBeenCalled(); | ||
await promise; | ||
}); | ||
|
||
it('handles errors', async () => { | ||
mount(); | ||
promise = Promise.reject('An error occured'); | ||
http.delete.mockReturnValue(promise); | ||
|
||
try { | ||
DocumentDetailLogic.actions.deleteDocument('1'); | ||
await promise; | ||
} catch { | ||
// Do nothing | ||
} | ||
expect(flashAPIErrors).toHaveBeenCalledWith('An error occured'); | ||
}); | ||
}); | ||
}); | ||
}); |
92 changes: 92 additions & 0 deletions
92
...prise_search/public/applications/app_search/components/documents/document_detail_logic.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License; | ||
* you may not use this file except in compliance with the Elastic License. | ||
*/ | ||
|
||
import { kea, MakeLogicType } from 'kea'; | ||
import { i18n } from '@kbn/i18n'; | ||
|
||
import { HttpLogic } from '../../../shared/http'; | ||
import { EngineLogic } from '../engine'; | ||
import { flashAPIErrors, setQueuedSuccessMessage } from '../../../shared/flash_messages'; | ||
import { FieldDetails } from './types'; | ||
|
||
interface DocumentDetailLogicValues { | ||
dataLoading: boolean; | ||
fields: FieldDetails[]; | ||
} | ||
|
||
interface DocumentDetailLogicActions { | ||
setFields(fields: FieldDetails[]): { fields: FieldDetails[] }; | ||
deleteDocument(documentId: string): { documentId: string }; | ||
getDocumentDetails(documentId: string): { documentId: string }; | ||
} | ||
|
||
type DocumentDetailLogicType = MakeLogicType<DocumentDetailLogicValues, DocumentDetailLogicActions>; | ||
|
||
const CONFIRM_DELETE = i18n.translate( | ||
'xpack.enterpriseSearch.appSearch.documentDetail.confirmDelete', | ||
{ | ||
defaultMessage: 'Are you sure you want to delete this document?', | ||
} | ||
); | ||
const DELETE_SUCCESS = i18n.translate( | ||
'xpack.enterpriseSearch.appSearch.documentDetail.deleteSuccess', | ||
{ | ||
defaultMessage: 'Successfully marked document for deletion. It will be deleted momentarily.', | ||
} | ||
); | ||
|
||
export const DocumentDetailLogic = kea<DocumentDetailLogicType>({ | ||
path: ['enterprise_search', 'app_search', 'document_detail_logic'], | ||
actions: () => ({ | ||
setFields: (fields) => ({ fields }), | ||
getDocumentDetails: (documentId) => ({ documentId }), | ||
deleteDocument: (documentId) => ({ documentId }), | ||
}), | ||
reducers: () => ({ | ||
dataLoading: [ | ||
true, | ||
{ | ||
setFields: () => false, | ||
}, | ||
], | ||
fields: [ | ||
[], | ||
{ | ||
setFields: (_, { fields }) => fields, | ||
}, | ||
], | ||
}), | ||
listeners: ({ actions }) => ({ | ||
getDocumentDetails: async ({ documentId }) => { | ||
const { engineName } = EngineLogic.values; | ||
|
||
try { | ||
const { http } = HttpLogic.values; | ||
// TODO: Handle 404s | ||
const response = await http.get( | ||
`/api/app_search/engines/${engineName}/documents/${documentId}` | ||
); | ||
actions.setFields(response.fields); | ||
} catch (e) { | ||
flashAPIErrors(e); | ||
} | ||
}, | ||
deleteDocument: async ({ documentId }) => { | ||
const { engineName } = EngineLogic.values; | ||
|
||
if (window.confirm(CONFIRM_DELETE)) { | ||
try { | ||
const { http } = HttpLogic.values; | ||
await http.delete(`/api/app_search/engines/${engineName}/documents/${documentId}`); | ||
setQueuedSuccessMessage(DELETE_SUCCESS); | ||
// TODO Handle routing after success | ||
} catch (e) { | ||
flashAPIErrors(e); | ||
} | ||
} | ||
}, | ||
}), | ||
}); |
66 changes: 66 additions & 0 deletions
66
...rprise_search/public/applications/app_search/components/documents/documents_logic.test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License; | ||
* you may not use this file except in compliance with the Elastic License. | ||
*/ | ||
|
||
import { resetContext } from 'kea'; | ||
|
||
import { DocumentsLogic } from './documents_logic'; | ||
|
||
describe('DocumentsLogic', () => { | ||
const DEFAULT_VALUES = { | ||
isDocumentCreationOpen: false, | ||
}; | ||
|
||
const mount = (defaults?: object) => { | ||
if (!defaults) { | ||
resetContext({}); | ||
} else { | ||
resetContext({ | ||
defaults: { | ||
enterprise_search: { | ||
app_search: { | ||
documents_logic: { | ||
...defaults, | ||
}, | ||
}, | ||
}, | ||
}, | ||
}); | ||
} | ||
DocumentsLogic.mount(); | ||
}; | ||
|
||
describe('actions', () => { | ||
describe('openDocumentCreation', () => { | ||
it('should toggle isDocumentCreationOpen to true', () => { | ||
mount({ | ||
isDocumentCreationOpen: false, | ||
}); | ||
|
||
DocumentsLogic.actions.openDocumentCreation(); | ||
|
||
expect(DocumentsLogic.values).toEqual({ | ||
...DEFAULT_VALUES, | ||
isDocumentCreationOpen: true, | ||
}); | ||
}); | ||
}); | ||
|
||
describe('closeDocumentCreation', () => { | ||
it('should toggle isDocumentCreationOpen to false', () => { | ||
mount({ | ||
isDocumentCreationOpen: true, | ||
}); | ||
|
||
DocumentsLogic.actions.closeDocumentCreation(); | ||
|
||
expect(DocumentsLogic.values).toEqual({ | ||
...DEFAULT_VALUES, | ||
isDocumentCreationOpen: false, | ||
}); | ||
}); | ||
}); | ||
}); | ||
}); |
35 changes: 35 additions & 0 deletions
35
.../enterprise_search/public/applications/app_search/components/documents/documents_logic.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License; | ||
* you may not use this file except in compliance with the Elastic License. | ||
*/ | ||
|
||
import { kea, MakeLogicType } from 'kea'; | ||
|
||
interface DocumentsLogicValues { | ||
isDocumentCreationOpen: boolean; | ||
} | ||
|
||
interface DocumentsLogicActions { | ||
closeDocumentCreation(): void; | ||
openDocumentCreation(): void; | ||
} | ||
|
||
type DocumentsLogicType = MakeLogicType<DocumentsLogicValues, DocumentsLogicActions>; | ||
|
||
export const DocumentsLogic = kea<DocumentsLogicType>({ | ||
path: ['enterprise_search', 'app_search', 'documents_logic'], | ||
actions: () => ({ | ||
openDocumentCreation: true, | ||
closeDocumentCreation: true, | ||
}), | ||
reducers: () => ({ | ||
isDocumentCreationOpen: [ | ||
false, | ||
{ | ||
openDocumentCreation: () => true, | ||
closeDocumentCreation: () => false, | ||
}, | ||
], | ||
}), | ||
}); |
8 changes: 8 additions & 0 deletions
8
...ck/plugins/enterprise_search/public/applications/app_search/components/documents/index.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License; | ||
* you may not use this file except in compliance with the Elastic License. | ||
*/ | ||
|
||
export { DocumentDetailLogic } from './document_detail_logic'; | ||
export { DocumentsLogic } from './documents_logic'; |
11 changes: 11 additions & 0 deletions
11
...ck/plugins/enterprise_search/public/applications/app_search/components/documents/types.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License; | ||
* you may not use this file except in compliance with the Elastic License. | ||
*/ | ||
|
||
export interface FieldDetails { | ||
name: string; | ||
value: string | string[]; | ||
type: string; | ||
} |
Oops, something went wrong.