diff --git a/x-pack/plugins/index_management/__jest__/client_integration/helpers/http_requests.ts b/x-pack/plugins/index_management/__jest__/client_integration/helpers/http_requests.ts index 9811255af25b0..8b6e4b444c135 100644 --- a/x-pack/plugins/index_management/__jest__/client_integration/helpers/http_requests.ts +++ b/x-pack/plugins/index_management/__jest__/client_integration/helpers/http_requests.ts @@ -94,8 +94,11 @@ const registerHttpRequestMockHelpers = ( const setCreateTemplateResponse = (response?: HttpResponse, error?: ResponseError) => mockResponse('POST', `${API_BASE_PATH}/index_templates`, response, error); - const setLoadIndexSettingsResponse = (response?: HttpResponse, error?: ResponseError) => - mockResponse('GET', `${API_BASE_PATH}/settings/:name`, response, error); + const setLoadIndexSettingsResponse = ( + indexName: string, + response?: HttpResponse, + error?: ResponseError + ) => mockResponse('GET', `${API_BASE_PATH}/settings/${indexName}`, response, error); const setLoadIndexMappingResponse = ( indexName: string, diff --git a/x-pack/plugins/index_management/__jest__/client_integration/index_details_page/index_details_page.helpers.ts b/x-pack/plugins/index_management/__jest__/client_integration/index_details_page/index_details_page.helpers.ts index cdf5e9f5ab841..a92df925be1a6 100644 --- a/x-pack/plugins/index_management/__jest__/client_integration/index_details_page/index_details_page.helpers.ts +++ b/x-pack/plugins/index_management/__jest__/client_integration/index_details_page/index_details_page.helpers.ts @@ -44,6 +44,17 @@ export interface IndexDetailsPageTestBed extends TestBed { isErrorDisplayed: () => boolean; clickErrorReloadButton: () => Promise; }; + settings: { + getCodeBlockContent: () => string; + getDocsLinkHref: () => string; + isErrorDisplayed: () => boolean; + clickErrorReloadButton: () => Promise; + clickEditModeSwitch: () => Promise; + getCodeEditorContent: () => string; + updateCodeEditorContent: (value: string) => Promise; + saveSettings: () => Promise; + resetChanges: () => Promise; + }; clickBackToIndicesButton: () => Promise; discoverLinkExists: () => boolean; contextMenu: { @@ -123,6 +134,53 @@ export const setup = async ( }, }; + const settings = { + getCodeBlockContent: () => { + return find('indexDetailsSettingsCodeBlock').text(); + }, + getDocsLinkHref: () => { + return find('indexDetailsSettingsDocsLink').prop('href'); + }, + isErrorDisplayed: () => { + return exists('indexDetailsSettingsError'); + }, + clickErrorReloadButton: async () => { + await act(async () => { + find('indexDetailsSettingsReloadButton').simulate('click'); + }); + component.update(); + }, + clickEditModeSwitch: async () => { + await act(async () => { + find('indexDetailsSettingsEditModeSwitch').simulate('click'); + }); + component.update(); + }, + getCodeEditorContent: () => { + return find('indexDetailsSettingsEditor').prop('data-currentvalue'); + }, + updateCodeEditorContent: async (value: string) => { + // the code editor is mocked as an input so need to set data-currentvalue attribute to change the value + find('indexDetailsSettingsEditor').getDOMNode().setAttribute('data-currentvalue', value); + await act(async () => { + find('indexDetailsSettingsEditor').simulate('change'); + }); + component.update(); + }, + saveSettings: async () => { + await act(async () => { + find('indexDetailsSettingsSave').simulate('click'); + }); + component.update(); + }, + resetChanges: async () => { + await act(async () => { + find('indexDetailsSettingsResetChanges').simulate('click'); + }); + component.update(); + }, + }; + const clickBackToIndicesButton = async () => { await act(async () => { find('indexDetailsBackToIndicesButton').simulate('click'); @@ -199,6 +257,7 @@ export const setup = async ( clickIndexDetailsTab, getActiveTabContent, mappings, + settings, clickBackToIndicesButton, discoverLinkExists, contextMenu, diff --git a/x-pack/plugins/index_management/__jest__/client_integration/index_details_page/index_details_page.test.ts b/x-pack/plugins/index_management/__jest__/client_integration/index_details_page/index_details_page.test.tsx similarity index 73% rename from x-pack/plugins/index_management/__jest__/client_integration/index_details_page/index_details_page.test.ts rename to x-pack/plugins/index_management/__jest__/client_integration/index_details_page/index_details_page.test.tsx index ddd1d44ac9440..62fe47b2529d4 100644 --- a/x-pack/plugins/index_management/__jest__/client_integration/index_details_page/index_details_page.test.ts +++ b/x-pack/plugins/index_management/__jest__/client_integration/index_details_page/index_details_page.test.tsx @@ -9,8 +9,33 @@ import { setupEnvironment } from '../helpers'; import { IndexDetailsPageTestBed, setup } from './index_details_page.helpers'; import { act } from 'react-dom/test-utils'; import { IndexDetailsSection } from '../../../public/application/sections/home/index_list/details_page'; -import { testIndexMappings, testIndexMock, testIndexName, testIndexStats } from './mocks'; +import { + testIndexEditableSettings, + testIndexMappings, + testIndexMock, + testIndexName, + testIndexSettings, + testIndexStats, +} from './mocks'; import { API_BASE_PATH, INTERNAL_API_BASE_PATH } from '../../../common'; +import React from 'react'; + +jest.mock('@kbn/kibana-react-plugin/public', () => { + const original = jest.requireActual('@kbn/kibana-react-plugin/public'); + return { + ...original, + // Mocking CodeEditor, which uses React Monaco under the hood + CodeEditor: (props: any) => ( + ) => { + props.onChange(e.currentTarget.getAttribute('data-currentvalue')); + }} + /> + ), + }; +}); describe('', () => { let testBed: IndexDetailsPageTestBed; @@ -24,6 +49,7 @@ describe('', () => { httpRequestsMockHelpers.setLoadIndexDetailsResponse(testIndexName, testIndexMock); httpRequestsMockHelpers.setLoadIndexStatsResponse(testIndexName, testIndexStats); httpRequestsMockHelpers.setLoadIndexMappingResponse(testIndexName, testIndexMappings); + httpRequestsMockHelpers.setLoadIndexSettingsResponse(testIndexName, testIndexSettings); await act(async () => { testBed = await setup(httpSetup, { @@ -171,7 +197,7 @@ describe('', () => { expect(tabContent).toEqual('Documents'); }); - describe('mappings tab', () => { + describe('Mappings tab', () => { it('loads mappings from the API', async () => { await testBed.actions.clickIndexDetailsTab(IndexDetailsSection.Mappings); expect(httpSetup.get).toHaveBeenLastCalledWith(`${API_BASE_PATH}/mapping/${testIndexName}`, { @@ -189,7 +215,7 @@ describe('', () => { expect(tabContent).toEqual(JSON.stringify(testIndexMappings, null, 2)); }); - it('sets the docs link href from the documenation service', async () => { + it('sets the docs link href from the documentation service', async () => { await testBed.actions.clickIndexDetailsTab(IndexDetailsSection.Mappings); const docsLinkHref = testBed.actions.mappings.getDocsLinkHref(); // the url from the mocked docs mock @@ -226,10 +252,112 @@ describe('', () => { }); }); - it('settings tab', async () => { - await testBed.actions.clickIndexDetailsTab(IndexDetailsSection.Settings); - const tabContent = testBed.actions.getActiveTabContent(); - expect(tabContent).toEqual('Settings'); + describe('Settings tab', () => { + it('loads settings from the API', async () => { + await testBed.actions.clickIndexDetailsTab(IndexDetailsSection.Settings); + expect(httpSetup.get).toHaveBeenLastCalledWith(`${API_BASE_PATH}/settings/${testIndexName}`, { + asSystemRequest: undefined, + body: undefined, + query: undefined, + version: undefined, + }); + }); + + it('displays the settings in the code block', async () => { + await testBed.actions.clickIndexDetailsTab(IndexDetailsSection.Settings); + + const tabContent = testBed.actions.settings.getCodeBlockContent(); + expect(tabContent).toEqual(JSON.stringify(testIndexSettings, null, 2)); + }); + + it('sets the docs link href from the documentation service', async () => { + await testBed.actions.clickIndexDetailsTab(IndexDetailsSection.Settings); + const docsLinkHref = testBed.actions.settings.getDocsLinkHref(); + // the url from the mocked docs mock + expect(docsLinkHref).toEqual( + 'https://www.elastic.co/guide/en/elasticsearch/reference/mocked-test-branch/index-modules.html#index-modules-settings' + ); + }); + + describe('error loading settings', () => { + beforeEach(async () => { + httpRequestsMockHelpers.setLoadIndexSettingsResponse(testIndexName, undefined, { + statusCode: 400, + message: `Was not able to load settings`, + }); + await act(async () => { + testBed = await setup(httpSetup); + }); + + testBed.component.update(); + await testBed.actions.clickIndexDetailsTab(IndexDetailsSection.Settings); + }); + + it('there is an error prompt', async () => { + expect(testBed.actions.settings.isErrorDisplayed()).toBe(true); + }); + + it('resends a request when reload button is clicked', async () => { + // already sent 3 requests while setting up the component + const numberOfRequests = 3; + expect(httpSetup.get).toHaveBeenCalledTimes(numberOfRequests); + await testBed.actions.settings.clickErrorReloadButton(); + expect(httpSetup.get).toHaveBeenCalledTimes(numberOfRequests + 1); + }); + }); + + describe('edit settings', () => { + beforeEach(async () => { + await testBed.actions.clickIndexDetailsTab(IndexDetailsSection.Settings); + await testBed.actions.settings.clickEditModeSwitch(); + }); + + it('displays the editable settings (flattened and filtered)', () => { + const editorContent = testBed.actions.settings.getCodeEditorContent(); + expect(editorContent).toEqual(JSON.stringify(testIndexEditableSettings, null, 2)); + }); + + it('updates the settings', async () => { + const updatedSettings = { ...testIndexEditableSettings, 'index.priority': '2' }; + await testBed.actions.settings.updateCodeEditorContent(JSON.stringify(updatedSettings)); + await testBed.actions.settings.saveSettings(); + expect(httpSetup.put).toHaveBeenLastCalledWith( + `${API_BASE_PATH}/settings/${testIndexName}`, + { + asSystemRequest: undefined, + body: JSON.stringify({ 'index.priority': '2' }), + query: undefined, + version: undefined, + } + ); + }); + + it('reloads the settings after an update', async () => { + const numberOfRequests = 2; + expect(httpSetup.get).toHaveBeenCalledTimes(numberOfRequests); + const updatedSettings = { ...testIndexEditableSettings, 'index.priority': '2' }; + await testBed.actions.settings.updateCodeEditorContent(JSON.stringify(updatedSettings)); + await testBed.actions.settings.saveSettings(); + expect(httpSetup.get).toHaveBeenCalledTimes(numberOfRequests + 1); + expect(httpSetup.get).toHaveBeenLastCalledWith( + `${API_BASE_PATH}/settings/${testIndexName}`, + { + asSystemRequest: undefined, + body: undefined, + query: undefined, + version: undefined, + } + ); + }); + + it('resets the changes in the editor', async () => { + const updatedSettings = { ...testIndexEditableSettings, 'index.priority': '2' }; + await testBed.actions.settings.updateCodeEditorContent(JSON.stringify(updatedSettings)); + await testBed.actions.settings.resetChanges(); + const editorContent = testBed.actions.settings.getCodeEditorContent(); + expect(editorContent).toEqual(JSON.stringify(testIndexEditableSettings, null, 2)); + }); + }); }); it('pipelines tab', async () => { diff --git a/x-pack/plugins/index_management/__jest__/client_integration/index_details_page/mocks.ts b/x-pack/plugins/index_management/__jest__/client_integration/index_details_page/mocks.ts index 7666c1ac0dee6..67ff8d57a1eb8 100644 --- a/x-pack/plugins/index_management/__jest__/client_integration/index_details_page/mocks.ts +++ b/x-pack/plugins/index_management/__jest__/client_integration/index_details_page/mocks.ts @@ -42,6 +42,37 @@ export const testIndexMappings = { }, }; +// Mocking partial index settings response +export const testIndexSettings = { + settings: { + index: { + routing: { + allocation: { + include: { + _tier_preference: 'data_content', + }, + }, + }, + number_of_shards: '1', + }, + }, + defaults: { + index: { + flush_after_merge: '512mb', + max_script_fields: '32', + query: { + default_field: ['*'], + }, + priority: '1', + }, + }, +}; +export const testIndexEditableSettings = { + 'index.priority': '1', + 'index.query.default_field': ['*'], + 'index.routing.allocation.include._tier_preference': 'data_content', +}; + // Mocking partial index stats response export const testIndexStats = { _shards: { diff --git a/x-pack/plugins/index_management/common/types/indices.ts b/x-pack/plugins/index_management/common/types/indices.ts index 608ee392a3f9e..ab6080f30fdb2 100644 --- a/x-pack/plugins/index_management/common/types/indices.ts +++ b/x-pack/plugins/index_management/common/types/indices.ts @@ -83,3 +83,8 @@ export interface Index { primary_size?: string; documents_deleted?: number; } + +export interface IndexSettingsResponse { + settings: IndexSettings; + defaults: IndexSettings; +} diff --git a/x-pack/plugins/index_management/public/application/lib/__snapshots__/flatten_object.test.js.snap b/x-pack/plugins/index_management/public/application/lib/__snapshots__/flatten_object.test.ts.snap similarity index 100% rename from x-pack/plugins/index_management/public/application/lib/__snapshots__/flatten_object.test.js.snap rename to x-pack/plugins/index_management/public/application/lib/__snapshots__/flatten_object.test.ts.snap diff --git a/x-pack/plugins/index_management/public/application/lib/edit_settings.js b/x-pack/plugins/index_management/public/application/lib/edit_settings.ts similarity index 100% rename from x-pack/plugins/index_management/public/application/lib/edit_settings.js rename to x-pack/plugins/index_management/public/application/lib/edit_settings.ts diff --git a/x-pack/plugins/index_management/public/application/lib/flatten_object.test.js b/x-pack/plugins/index_management/public/application/lib/flatten_object.test.ts similarity index 100% rename from x-pack/plugins/index_management/public/application/lib/flatten_object.test.js rename to x-pack/plugins/index_management/public/application/lib/flatten_object.test.ts diff --git a/x-pack/plugins/index_management/public/application/lib/flatten_object.js b/x-pack/plugins/index_management/public/application/lib/flatten_object.ts similarity index 72% rename from x-pack/plugins/index_management/public/application/lib/flatten_object.js rename to x-pack/plugins/index_management/public/application/lib/flatten_object.ts index ddc6f2851f65f..5dae932938a3a 100644 --- a/x-pack/plugins/index_management/public/application/lib/flatten_object.js +++ b/x-pack/plugins/index_management/public/application/lib/flatten_object.ts @@ -7,14 +7,14 @@ import _ from 'lodash'; -export const flattenObject = (nestedObj, flattenArrays) => { - const stack = []; // track key stack - const flatObj = {}; +export const flattenObject = (nestedObj: any) => { + const stack = [] as any[]; // track key stack + const flatObj = {} as any; const dot = '.'; (function flattenObj(obj) { _.keys(obj).forEach(function (key) { stack.push(key); - if (!flattenArrays && Array.isArray(obj[key])) flatObj[stack.join(dot)] = obj[key]; + if (Array.isArray(obj[key])) flatObj[stack.join(dot)] = obj[key]; else if (_.isObject(obj[key])) flattenObj(obj[key]); else flatObj[stack.join(dot)] = obj[key]; stack.pop(); diff --git a/x-pack/plugins/index_management/public/application/sections/home/index_list/details_page/details_page.tsx b/x-pack/plugins/index_management/public/application/sections/home/index_list/details_page/details_page.tsx index 80f79d9ab3c76..17cbeb7649449 100644 --- a/x-pack/plugins/index_management/public/application/sections/home/index_list/details_page/details_page.tsx +++ b/x-pack/plugins/index_management/public/application/sections/home/index_list/details_page/details_page.tsx @@ -21,6 +21,7 @@ import { SectionLoading } from '@kbn/es-ui-shared-plugin/public'; import { Index } from '../../../../../../common'; import { INDEX_OPEN } from '../../../../../../common/constants'; +import { Error } from '../../../../../shared_imports'; import { loadIndex } from '../../../../services'; import { useAppContext } from '../../../../app_context'; import { DiscoverLink } from '../../../../lib/discover_link'; @@ -29,6 +30,7 @@ import { DetailsPageError } from './details_page_error'; import { ManageIndexButton } from './manage_index_button'; import { DetailsPageStats } from './details_page_stats'; import { DetailsPageMappings } from './details_page_mappings'; +import { DetailsPageSettings } from './details_page_settings'; export enum IndexDetailsSection { Overview = 'overview', @@ -86,7 +88,7 @@ export const DetailsPage: React.FunctionComponent< }) => { const { config } = useAppContext(); const [isLoading, setIsLoading] = useState(false); - const [error, setError] = useState(); + const [error, setError] = useState(null); const [index, setIndex] = useState(); const fetchIndexDetails = useCallback(async () => { @@ -198,8 +200,10 @@ export const DetailsPage: React.FunctionComponent< component={DetailsPageMappings} />
Settings
} + path={`/${Section.Indices}/:indexName/${IndexDetailsSection.Settings}`} + render={(props: RouteComponentProps<{ indexName: string }>) => ( + + )} /> & { isIndexOpen: boolean } +> = ({ + match: { + params: { indexName }, + }, + isIndexOpen, +}) => { + const { isLoading, data, error, resendRequest } = useLoadIndexSettings(indexName); + + if (isLoading) { + return ( + + + + ); + } + if (error || !data) { + return ( + + + + } + body={ + <> + + + + + + + + + } + /> + ); + } + return ( + + ); +}; diff --git a/x-pack/plugins/index_management/public/application/sections/home/index_list/details_page/details_page_settings_content.tsx b/x-pack/plugins/index_management/public/application/sections/home/index_list/details_page/details_page_settings_content.tsx new file mode 100644 index 0000000000000..f418548e5c843 --- /dev/null +++ b/x-pack/plugins/index_management/public/application/sections/home/index_list/details_page/details_page_settings_content.tsx @@ -0,0 +1,280 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React, { useState, FunctionComponent, useCallback } from 'react'; +import { + EuiButton, + EuiCallOut, + EuiCodeBlock, + EuiFlexGroup, + EuiFlexItem, + EuiIcon, + EuiLink, + EuiPanel, + EuiSpacer, + EuiSwitch, + EuiSwitchEvent, + EuiText, +} from '@elastic/eui'; +import { css } from '@emotion/react'; +import _ from 'lodash'; +import { FormattedMessage } from '@kbn/i18n-react'; +import { i18n } from '@kbn/i18n'; +import { CodeEditor } from '@kbn/kibana-react-plugin/public'; +import { IndexSettingsResponse } from '../../../../../../common'; +import { Error } from '../../../../../shared_imports'; +import { documentationService, updateIndexSettings } from '../../../../services'; +import { notificationService } from '../../../../services/notification'; +import { flattenObject } from '../../../../lib/flatten_object'; +import { readOnlySettings, settingsToDisplay } from '../../../../lib/edit_settings'; + +const getEditableSettings = ( + data: Props['data'], + isIndexOpen: boolean +): { originalSettings: Record; settingsString: string } => { + const { defaults, settings } = data; + // settings user has actually set + const flattenedSettings = flattenObject(settings); + // settings with their defaults + const flattenedDefaults = flattenObject(defaults); + const filteredDefaults = _.pick(flattenedDefaults, settingsToDisplay); + const newSettings = { ...filteredDefaults, ...flattenedSettings }; + // store these to be used as autocomplete values later + readOnlySettings.forEach((e) => delete newSettings[e]); + // can't change codec on open index + if (isIndexOpen) { + delete newSettings['index.codec']; + } + const settingsString = JSON.stringify(newSettings, null, 2); + return { originalSettings: newSettings, settingsString }; +}; + +interface Props { + isIndexOpen: boolean; + data: IndexSettingsResponse; + indexName: string; + reloadIndexSettings: () => void; +} + +export const DetailsPageSettingsContent: FunctionComponent = ({ + isIndexOpen, + data, + indexName, + reloadIndexSettings, +}) => { + const [isEditMode, setIsEditMode] = useState(false); + const onEditModeChange = (event: EuiSwitchEvent) => { + setUpdateError(null); + setIsEditMode(event.target.checked); + }; + + const { originalSettings, settingsString } = getEditableSettings(data, isIndexOpen); + const [editableSettings, setEditableSettings] = useState(settingsString); + const [isLoading, setIsLoading] = useState(false); + const [updateError, setUpdateError] = useState(null); + + const resetChanges = useCallback(() => { + setUpdateError(null); + setEditableSettings(settingsString); + }, [settingsString]); + + const updateSettings = useCallback(async () => { + setUpdateError(null); + setIsLoading(true); + try { + const editedSettings = JSON.parse(editableSettings); + // don't set if the values have not changed + Object.keys(originalSettings).forEach((key) => { + if (_.isEqual(originalSettings[key], editedSettings[key])) { + delete editedSettings[key]; + } + }); + + if (Object.keys(editedSettings).length !== 0) { + const { error } = await updateIndexSettings(indexName, editedSettings); + if (error) { + setIsLoading(false); + setUpdateError(error); + } else { + setIsLoading(false); + setIsEditMode(false); + notificationService.showSuccessToast( + i18n.translate('xpack.idxMgmt.indexDetails.settings.updateSuccessMessage', { + defaultMessage: 'Successfully updated settings for index {indexName}', + values: { indexName }, + }) + ); + reloadIndexSettings(); + } + } else { + setIsLoading(false); + setIsEditMode(false); + notificationService.showWarningToast( + i18n.translate('xpack.idxMgmt.indexDetails.settings.noChangeWarning', { + defaultMessage: 'No settings changed', + }) + ); + } + } catch (e) { + setIsLoading(false); + setUpdateError({ + error: i18n.translate('xpack.idxMgmt.indexDetails.settings.updateError', { + defaultMessage: 'Unable to update settings', + }), + }); + } + }, [originalSettings, editableSettings, indexName, reloadIndexSettings]); + return ( + // using "rowReverse" to keep the card on the left side to be on top of the code block on smaller screens + + + + + + + + + + + + + + + + + + } + checked={isEditMode} + onChange={onEditModeChange} + /> + + + + + + + + + + + + + + + {updateError && ( + <> + + +

+ {updateError.error} + {updateError.message && : {updateError.message}} +

+
+ + )} + + + + +
+
+ + + + {isEditMode ? ( + + ) : ( + + {JSON.stringify(data, null, 2)} + + )} + + +
+ ); +}; diff --git a/x-pack/plugins/index_management/public/application/sections/home/index_list/details_page/details_page_stats.tsx b/x-pack/plugins/index_management/public/application/sections/home/index_list/details_page/details_page_stats.tsx index 3e4319a03a9da..91fbf54728bfd 100644 --- a/x-pack/plugins/index_management/public/application/sections/home/index_list/details_page/details_page_stats.tsx +++ b/x-pack/plugins/index_management/public/application/sections/home/index_list/details_page/details_page_stats.tsx @@ -25,7 +25,7 @@ import { import { css } from '@emotion/react'; import { IndicesStatsResponse } from '@elastic/elasticsearch/lib/api/types'; -import { SectionLoading } from '../../../../../shared_imports'; +import { SectionLoading, Error } from '../../../../../shared_imports'; import { loadIndexStatistics, documentationService } from '../../../../services'; interface Props { @@ -41,7 +41,7 @@ export const DetailsPageStats: FunctionComponent< isIndexOpen, }) => { const [isLoading, setIsLoading] = useState(false); - const [error, setError] = useState(); + const [error, setError] = useState(); const [indexStats, setIndexStats] = useState(); const fetchIndexStats = useCallback(async () => { diff --git a/x-pack/plugins/index_management/public/application/services/api.ts b/x-pack/plugins/index_management/public/application/services/api.ts index 3daee29ec62e8..b209e4632bd3c 100644 --- a/x-pack/plugins/index_management/public/application/services/api.ts +++ b/x-pack/plugins/index_management/public/application/services/api.ts @@ -34,7 +34,13 @@ import { UIM_TEMPLATE_SIMULATE, INTERNAL_API_BASE_PATH, } from '../../../common/constants'; -import { TemplateDeserialized, TemplateListItem, DataStream, Index } from '../../../common'; +import { + TemplateDeserialized, + TemplateListItem, + DataStream, + Index, + IndexSettingsResponse, +} from '../../../common'; import { TAB_SETTINGS, TAB_MAPPING, TAB_STATS } from '../constants'; import { useRequest, sendRequest } from './use_request'; import { httpService } from './http'; @@ -334,3 +340,10 @@ export function loadIndexStatistics(indexName: string) { method: 'get', }); } + +export function useLoadIndexSettings(indexName: string) { + return useRequest({ + path: `${API_BASE_PATH}/settings/${encodeURIComponent(indexName)}`, + method: 'get', + }); +} diff --git a/x-pack/plugins/index_management/public/application/services/index.ts b/x-pack/plugins/index_management/public/application/services/index.ts index 5512171b358af..979f4268dc362 100644 --- a/x-pack/plugins/index_management/public/application/services/index.ts +++ b/x-pack/plugins/index_management/public/application/services/index.ts @@ -27,6 +27,7 @@ export { loadIndex, useLoadIndexMappings, loadIndexStatistics, + useLoadIndexSettings, } from './api'; export { sortTable } from './sort_table'; diff --git a/x-pack/plugins/index_management/public/application/services/use_request.ts b/x-pack/plugins/index_management/public/application/services/use_request.ts index 4746890361d59..93719a19c5a75 100644 --- a/x-pack/plugins/index_management/public/application/services/use_request.ts +++ b/x-pack/plugins/index_management/public/application/services/use_request.ts @@ -16,9 +16,9 @@ import { import { httpService } from './http'; -export const sendRequest = ( +export const sendRequest = ( config: SendRequestConfig -): Promise> => { +): Promise> => { return _sendRequest(httpService.httpClient, config); };