Repository navigation
[Infra] Implement dashboard tab UI in host details #178518
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
jennypavlova
merged 52 commits into
elastic:main
from
jennypavlova:176070-infra-implement-dashboard-tab-ui-in-host-details
Apr 10, 2024
Merged
Changes from all commits
Commits
Show all changes
52 commits
Select commit
Hold shift + click to select a range
51cccc7
Add empty dashboard tab based on the frature flag
jennypavlova 00f0202
Update saved object to support hostNameFilterEnabled flag for every d…
jennypavlova e642273
Add hook to get custom dashboards per asset type
jennypavlova c5fface
[WIP] Link dashboards
jennypavlova ec54d3d
Add dashboard id to the url state
jennypavlova 18e3b14
Add unlink dashboard action
jennypavlova bf14ccc
Small ids and translations fixes and cleanup
jennypavlova bda99c1
Tex changes and cleanup
jennypavlova f132a13
Add Dashboards Tab splash screen test
jennypavlova dcb9241
Change unlink
jennypavlova 57ef8dc
Merge branch 'main' into 176070-infra-implement-dashboard-tab-ui-in-h…
jennypavlova 0663734
Change empty state content
jennypavlova a424746
Merge branch 'main' of github.com:elastic/kibana into 176070-infra-im…
jennypavlova 81c0639
[CI] Auto-commit changed files from 'node scripts/lint_ts_projects --…
kibanamachine afe35d7
Config fix
jennypavlova 6b71389
Merge branch '176070-infra-implement-dashboard-tab-ui-in-host-details…
jennypavlova 79d095c
Fix translation
jennypavlova f0b7289
Merge branch 'main' into 176070-infra-implement-dashboard-tab-ui-in-h…
jennypavlova 4e4b8e6
[CI] Auto-commit changed files from 'node scripts/check_mappings_upda…
kibanamachine 5bc706f
[CI] Auto-commit changed files from 'node scripts/eslint --no-cache -…
kibanamachine d95ddb6
Tests fixes
jennypavlova 8d67a50
Merge branch '176070-infra-implement-dashboard-tab-ui-in-host-details…
jennypavlova cf12a2e
Merge branch 'main' into 176070-infra-implement-dashboard-tab-ui-in-h…
jennypavlova abea5bf
Set default dashboard selection and add loading check
jennypavlova c6384c4
Merge branch 'main' into 176070-infra-implement-dashboard-tab-ui-in-h…
jennypavlova d448899
CR changes
jennypavlova ee852ef
CR changes
jennypavlova 4d637e6
Merge branch 'main' into 176070-infra-implement-dashboard-tab-ui-in-h…
jennypavlova ed558a0
fix translation key
jennypavlova 415bbbc
getFilterByAssetName CR changes
jennypavlova 501b46f
Rename to GotoDashboardLink
jennypavlova dfc96db
Merge branch 'main' into 176070-infra-implement-dashboard-tab-ui-in-h…
jennypavlova 6e05055
Update custom dashboards saved object
jennypavlova f5aa13d
[CI] Auto-commit changed files from 'node scripts/check_mappings_upda…
kibanamachine 6689a06
[CI] Auto-commit changed files from 'node scripts/jest_integration -u…
kibanamachine 74d5d3e
Merge branch 'main' of github.com:elastic/kibana into 176070-infra-im…
jennypavlova dfa6b91
Rename to useFetchCustomDashboards
jennypavlova e7ad2f1
Fix switching dashboards not refreshing the content issue
jennypavlova 09c756a
Merge branch 'main' into 176070-infra-implement-dashboard-tab-ui-in-h…
jennypavlova 7d63c93
CR changes
jennypavlova 7076b6e
Merge branch 'main' into 176070-infra-implement-dashboard-tab-ui-in-h…
jennypavlova a398a19
Remove unused imports
jennypavlova f4f317e
CR changes
jennypavlova 758e2c2
Fix import
jennypavlova 2d097b8
Use callback for clicks and fix add/edit message
jennypavlova cd414fc
Fix notifications text param
jennypavlova aab661c
Merge branch 'main' into 176070-infra-implement-dashboard-tab-ui-in-h…
jennypavlova d2117c8
CR changes
jennypavlova 0eebd0e
Merge branch 'main' into 176070-infra-implement-dashboard-tab-ui-in-h…
jennypavlova b651ac2
Merge branch 'main' into 176070-infra-implement-dashboard-tab-ui-in-h…
jennypavlova 7538522
Merge branch 'main' into 176070-infra-implement-dashboard-tab-ui-in-h…
jennypavlova 93aae78
Merge branch 'main' into 176070-infra-implement-dashboard-tab-ui-in-h…
jennypavlova File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or 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
This file contains hidden or 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
This file contains hidden or 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
This file contains hidden or 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 |
|---|---|---|
|
|
@@ -16,6 +16,7 @@ | |
| "data", | ||
| "dataViews", | ||
| "dataViewEditor", | ||
| "dashboard", | ||
| "discover", | ||
| "embeddable", | ||
| "features", | ||
|
|
||
This file contains hidden or 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
This file contains hidden or 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
This file contains hidden or 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
211 changes: 211 additions & 0 deletions
211
...servability_solution/infra/public/components/asset_details/hooks/use_custom_dashboards.ts
This file contains hidden or 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,211 @@ | ||
| /* | ||
| * 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 { useCallback } from 'react'; | ||
| import { fold } from 'fp-ts/lib/Either'; | ||
| import { identity } from 'fp-ts/lib/function'; | ||
| import { pipe } from 'fp-ts/lib/pipeable'; | ||
| import { i18n } from '@kbn/i18n'; | ||
| import { useKibana } from '@kbn/kibana-react-plugin/public'; | ||
| import { useKibanaContextForPlugin } from '../../../hooks/use_kibana'; | ||
| import { useTrackedPromise } from '../../../utils/use_tracked_promise'; | ||
| import type { | ||
| InfraCustomDashboard, | ||
| InfraSavedCustomDashboard, | ||
| InfraCustomDashboardAssetType, | ||
| } from '../../../../common/custom_dashboards'; | ||
| import { | ||
| InfraCustomDashboardRT, | ||
| InfraDeleteCustomDashboardsResponseBodyRT, | ||
| } from '../../../../common/http_api/custom_dashboards_api'; | ||
| import { throwErrors, createPlainError } from '../../../../common/runtime_types'; | ||
|
|
||
| type ActionType = 'create' | 'update' | 'delete'; | ||
| const errorMessages: Record<ActionType, string> = { | ||
| create: i18n.translate('xpack.infra.linkDashboards.addFailure.toast.title', { | ||
| defaultMessage: 'Error while linking dashboards', | ||
| }), | ||
| update: i18n.translate('xpack.infra.updatingLinkedDashboards.addFailure.toast.title', { | ||
| defaultMessage: 'Error while updating linked dashboards', | ||
| }), | ||
| delete: i18n.translate('xpack.infra.deletingLinkedDashboards.addFailure.toast.title', { | ||
| defaultMessage: 'Error while deleting linked dashboards', | ||
| }), | ||
| }; | ||
|
|
||
| const decodeResponse = (response: any) => { | ||
| return pipe( | ||
| InfraCustomDashboardRT.decode(response), | ||
| fold(throwErrors(createPlainError), identity) | ||
| ); | ||
| }; | ||
|
|
||
| export const useUpdateCustomDashboard = () => { | ||
| const { services } = useKibanaContextForPlugin(); | ||
| const { notifications } = useKibana(); | ||
|
|
||
| const onError = useCallback( | ||
| (errorMessage: string) => { | ||
| if (errorMessage) { | ||
| notifications.toasts.danger({ | ||
| title: errorMessages.update, | ||
| body: errorMessage, | ||
| }); | ||
| } | ||
| }, | ||
| [notifications.toasts] | ||
| ); | ||
|
|
||
| const [updateCustomDashboardRequest, updateCustomDashboard] = useTrackedPromise( | ||
| { | ||
| cancelPreviousOn: 'resolution', | ||
| createPromise: async ({ | ||
| assetType, | ||
| id, | ||
| dashboardSavedObjectId, | ||
| dashboardFilterAssetIdEnabled, | ||
| }: InfraSavedCustomDashboard) => { | ||
| const rawResponse = await services.http.fetch( | ||
| `/api/infra/${assetType}/custom-dashboards/${id}`, | ||
| { | ||
| method: 'PUT', | ||
| body: JSON.stringify({ | ||
| assetType, | ||
| dashboardSavedObjectId, | ||
| dashboardFilterAssetIdEnabled, | ||
| }), | ||
| } | ||
| ); | ||
|
|
||
| return decodeResponse(rawResponse); | ||
| }, | ||
| onResolve: (response) => response, | ||
| onReject: (e: Error | unknown) => onError((e as Error)?.message), | ||
| }, | ||
| [] | ||
| ); | ||
|
|
||
| const isUpdateLoading = updateCustomDashboardRequest.state === 'pending'; | ||
|
|
||
| const hasUpdateError = updateCustomDashboardRequest.state === 'rejected'; | ||
|
|
||
| return { | ||
| updateCustomDashboard, | ||
| isUpdateLoading, | ||
| hasUpdateError, | ||
| }; | ||
| }; | ||
|
|
||
| export const useDeleteCustomDashboard = () => { | ||
| const { services } = useKibanaContextForPlugin(); | ||
| const { notifications } = useKibana(); | ||
|
|
||
| const decodeDeleteResponse = (response: any) => { | ||
| return pipe( | ||
| InfraDeleteCustomDashboardsResponseBodyRT.decode(response), | ||
| fold(throwErrors(createPlainError), identity) | ||
| ); | ||
| }; | ||
|
|
||
| const onError = useCallback( | ||
| (errorMessage: string) => { | ||
| if (errorMessage) { | ||
| notifications.toasts.danger({ | ||
| title: errorMessages.delete, | ||
| body: errorMessage, | ||
| }); | ||
| } | ||
| }, | ||
| [notifications.toasts] | ||
| ); | ||
|
|
||
| const [deleteCustomDashboardRequest, deleteCustomDashboard] = useTrackedPromise( | ||
| { | ||
| cancelPreviousOn: 'resolution', | ||
| createPromise: async ({ | ||
| assetType, | ||
| id, | ||
| }: { | ||
| assetType: InfraCustomDashboardAssetType; | ||
| id: string; | ||
| }) => { | ||
| const rawResponse = await services.http.fetch( | ||
| `/api/infra/${assetType}/custom-dashboards/${id}`, | ||
| { | ||
| method: 'DELETE', | ||
| } | ||
| ); | ||
|
|
||
| return decodeDeleteResponse(rawResponse); | ||
| }, | ||
| onResolve: (response) => response, | ||
| onReject: (e: Error | unknown) => onError((e as Error)?.message), | ||
| }, | ||
| [] | ||
| ); | ||
|
|
||
| const isDeleteLoading = deleteCustomDashboardRequest.state === 'pending'; | ||
|
|
||
| const hasDeleteError = deleteCustomDashboardRequest.state === 'rejected'; | ||
|
|
||
| return { | ||
| deleteCustomDashboard, | ||
| isDeleteLoading, | ||
| hasDeleteError, | ||
| }; | ||
| }; | ||
|
|
||
| export const useCreateCustomDashboard = () => { | ||
| const { services } = useKibanaContextForPlugin(); | ||
| const { notifications } = useKibana(); | ||
|
|
||
| const onError = useCallback( | ||
| (errorMessage: string) => { | ||
| if (errorMessage) { | ||
| notifications.toasts.danger({ | ||
| title: errorMessages.delete, | ||
| body: errorMessage, | ||
| }); | ||
| } | ||
| }, | ||
| [notifications.toasts] | ||
| ); | ||
|
|
||
| const [createCustomDashboardRequest, createCustomDashboard] = useTrackedPromise( | ||
| { | ||
| cancelPreviousOn: 'resolution', | ||
| createPromise: async ({ | ||
| assetType, | ||
| dashboardSavedObjectId, | ||
| dashboardFilterAssetIdEnabled, | ||
| }: InfraCustomDashboard) => { | ||
| const rawResponse = await services.http.fetch(`/api/infra/${assetType}/custom-dashboards`, { | ||
| method: 'POST', | ||
| body: JSON.stringify({ | ||
| dashboardSavedObjectId, | ||
| dashboardFilterAssetIdEnabled, | ||
| }), | ||
| }); | ||
|
|
||
| return decodeResponse(rawResponse); | ||
| }, | ||
| onResolve: (response) => response, | ||
| onReject: (e: Error | unknown) => onError((e as Error)?.message), | ||
| }, | ||
| [] | ||
| ); | ||
|
|
||
| const isCreateLoading = createCustomDashboardRequest.state === 'pending'; | ||
|
|
||
| const hasCreateError = createCustomDashboardRequest.state === 'rejected'; | ||
|
|
||
| return { | ||
| createCustomDashboard, | ||
| isCreateLoading, | ||
| hasCreateError, | ||
| }; | ||
| }; | ||
69 changes: 69 additions & 0 deletions
69
...ervability_solution/infra/public/components/asset_details/hooks/use_dashboards_fetcher.ts
This file contains hidden or 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,69 @@ | ||
| /* | ||
| * 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 { useState, useEffect } from 'react'; | ||
| import type { SearchDashboardsResponse } from '@kbn/dashboard-plugin/public/services/dashboard_content_management/lib/find_dashboards'; | ||
| import { i18n } from '@kbn/i18n'; | ||
| import { useKibana } from '@kbn/kibana-react-plugin/public'; | ||
| import { useKibanaContextForPlugin } from '../../../hooks/use_kibana'; | ||
|
|
||
| export enum FETCH_STATUS { | ||
| LOADING = 'loading', | ||
| SUCCESS = 'success', | ||
| FAILURE = 'failure', | ||
| NOT_INITIATED = 'not_initiated', | ||
| } | ||
|
|
||
| export interface SearchDashboardsResult { | ||
| data: SearchDashboardsResponse['hits']; | ||
| status: FETCH_STATUS; | ||
| } | ||
|
|
||
| export function useDashboardFetcher(query = ''): SearchDashboardsResult { | ||
| const { | ||
| services: { dashboard }, | ||
| } = useKibanaContextForPlugin(); | ||
| const { notifications } = useKibana(); | ||
| const [result, setResult] = useState<SearchDashboardsResult>({ | ||
| data: [], | ||
| status: FETCH_STATUS.NOT_INITIATED, | ||
| }); | ||
|
|
||
| useEffect(() => { | ||
| const getDashboards = async () => { | ||
| setResult({ | ||
| data: [], | ||
| status: FETCH_STATUS.LOADING, | ||
| }); | ||
| try { | ||
| const findDashboardsService = await dashboard?.findDashboardsService(); | ||
| const data = await findDashboardsService.search({ | ||
| search: query, | ||
| size: 1000, | ||
| }); | ||
|
|
||
| setResult({ | ||
| data: data.hits, | ||
| status: FETCH_STATUS.SUCCESS, | ||
| }); | ||
| } catch (error) { | ||
| setResult({ | ||
| data: [], | ||
| status: FETCH_STATUS.FAILURE, | ||
| }); | ||
|
Comment on lines
+54
to
+57
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe we should call the toast notification to let the user know that an error happened, and pass the exception to it? |
||
| notifications.toasts.danger({ | ||
| title: i18n.translate('xpack.infra.fetchingDashboards.addFailure.toast.title', { | ||
| defaultMessage: 'Error while fetching dashboards', | ||
| }), | ||
| body: error.message, | ||
| }); | ||
| } | ||
| }; | ||
| getDashboards(); | ||
| }, [dashboard, notifications.toasts, query]); | ||
| return result; | ||
| } | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A lot of boilerplate is needed to call the
useTrackedPromise. It'd be nice if we had something like thecallApmApiutils, eg:I'm not sure why we need the abstraction contained in
useTrackedPromisein infra in general.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, it will be nice to have for sure! I searched for something similar but I couldn't find anything in Infra. We can think about adding something like that in the future. I found only the
useTrackedPromiseused in a similar way and I agree about the boilerplate but I am not sure how to improve it (I tried to reuse some functions where possible (for error handling and response decoding).Another similar case for calling an endpoint on button click is in inventory saved views but there we have the
InventoryViewsClientand there is also boilerplate around the solution (also the usage of react query (example here) can help in this case as well but I tried to not overcomplicate it and keep it similar to the APM solution)There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you're right. let's not overcomplicate this PR, but I guess we can open a ticket to create a solution similar to APM's?