Skip to content
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

[Security Solution] Use Dashboard name in the page title #155381

Merged
merged 2 commits into from
Apr 21, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/CODEOWNERS
Validating CODEOWNERS rules …
Original file line number Diff line number Diff line change
Expand Up @@ -1058,6 +1058,7 @@ packages/kbn-yarn-lock-validator @elastic/kibana-operations
/x-pack/plugins/security_solution/public/cases @elastic/security-threat-hunting-explore
/x-pack/plugins/security_solution/public/explore @elastic/security-threat-hunting-explore
/x-pack/plugins/security_solution/public/overview @elastic/security-threat-hunting-explore
/x-pack/plugins/security_solution/public/dashboards @elastic/security-threat-hunting-explore

/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts @elastic/security-threat-hunting-explore
/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram @elastic/security-threat-hunting-explore
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ import type { DashboardAPI } from '@kbn/dashboard-plugin/public';
import type { DashboardCapabilities } from '@kbn/dashboard-plugin/common/types';
import { useParams } from 'react-router-dom';

import { isEmpty, pick } from 'lodash/fp';
import { pick } from 'lodash/fp';
import { EuiLoadingSpinner } from '@elastic/eui';
import { SecurityPageName } from '../../../../common/constants';
import { SpyRoute } from '../../../common/utils/route/spy_routes';
import { useCapabilities } from '../../../common/lib/kibana';
Expand All @@ -25,12 +26,12 @@ import { FiltersGlobal } from '../../../common/components/filters_global';
import { InputsModelId } from '../../../common/store/inputs/constants';
import { useSourcererDataView } from '../../../common/containers/sourcerer';
import { HeaderPage } from '../../../common/components/header_page';
import { DASHBOARD_PAGE_TITLE } from '../translations';
import { DASHBOARD_NOT_FOUND_TITLE } from './translations';
import { inputsSelectors } from '../../../common/store';
import { useDeepEqualSelector } from '../../../common/hooks/use_selector';
import { EditDashboardButton } from '../../components/edit_dashboard_button';

type DashboardDetails = Record<string, string | undefined>;
type DashboardDetails = Record<string, string>;

const DashboardViewComponent: React.FC = () => {
const { fromStr, toStr, from, to } = useDeepEqualSelector((state) =>
Expand All @@ -51,13 +52,20 @@ const DashboardViewComponent: React.FC = () => {
const [currentState, setCurrentState] = useState<DashboardViewPromptState | null>(
canReadDashboard ? null : DashboardViewPromptState.NoReadPermission
);
const [dashboardDetails, setDashboardDetails] = useState<DashboardDetails>();
const [dashboardDetails, setDashboardDetails] = useState<DashboardDetails | undefined>();
const onDashboardContainerLoaded = useCallback((dashboard: DashboardAPI) => {
const dashboardTitle = dashboard?.getTitle().trim();
setDashboardDetails({ dashboardTitle });
if (dashboard) {
const title = dashboard.getTitle().trim();
if (title) {
setDashboardDetails({ title });
} else {
setDashboardDetails({ title: DASHBOARD_NOT_FOUND_TITLE });
}
}
}, []);

const dashboardExists = useMemo(() => dashboardDetails != null, [dashboardDetails]);
const { detailName: savedObjectId } = useParams<{ detailName?: string }>();
const dashboardExists = !isEmpty(dashboardDetails?.dashboardTitle);

useEffect(() => {
if (!indicesExist) {
Expand All @@ -73,7 +81,7 @@ const DashboardViewComponent: React.FC = () => {
</FiltersGlobal>
)}
<SecuritySolutionPageWrapper>
<HeaderPage border title={DASHBOARD_PAGE_TITLE}>
<HeaderPage border title={dashboardDetails?.title ?? <EuiLoadingSpinner size="m" />}>
{showWriteControls && dashboardExists && (
<EditDashboardButton
filters={filters}
Expand All @@ -97,7 +105,10 @@ const DashboardViewComponent: React.FC = () => {
)}

<StatusPropmpt currentState={currentState} />
<SpyRoute pageName={SecurityPageName.dashboards} state={dashboardDetails} />
<SpyRoute
pageName={SecurityPageName.dashboards}
state={{ dashboardName: dashboardDetails?.title }}
/>
</SecuritySolutionPageWrapper>
</>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,13 @@ export const DASHBOARD_INDICES_NOT_FOUND_TITLE = i18n.translate(
}
);

export const DASHBOARD_NOT_FOUND_TITLE = i18n.translate(
'xpack.securitySolution.dashboards.dashboard.notFound.title',
{
defaultMessage: 'Not found',
}
);

export const EDIT_DASHBOARD_BUTTON_TITLE = i18n.translate(
'xpack.securitySolution.dashboards.dashboard.editDashboardButtonTitle',
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,3 @@ import { i18n } from '@kbn/i18n';
export const DASHBOARDS_PAGE_TITLE = i18n.translate('xpack.securitySolution.dashboards.pageTitle', {
defaultMessage: 'Dashboards',
});

export const DASHBOARD_PAGE_TITLE = i18n.translate('xpack.securitySolution.dashboard.pageTitle', {
defaultMessage: 'Dashboard',
});
16 changes: 4 additions & 12 deletions x-pack/plugins/security_solution/public/dashboards/pages/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,13 @@
*/

import type { ChromeBreadcrumb } from '@kbn/core/public';
import { isEmpty } from 'lodash/fp';
import type { RouteSpyState } from '../../common/utils/route/types';

export const getTrailingBreadcrumbs = (params: RouteSpyState): ChromeBreadcrumb[] => {
let breadcrumb: ChromeBreadcrumb[] = [];

const dashboardTitle = params?.state?.dashboardTitle?.trim();
if (params?.state?.dashboardTitle || params.detailName) {
breadcrumb = [
...breadcrumb,
{
text: !isEmpty(dashboardTitle) ? dashboardTitle : params.detailName,
},
];
const breadcrumbName = params?.state?.dashboardName;
if (breadcrumbName) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using params.detailName was causing a change (id -> name) in the last breadcrumb when the dashboard is finally loaded.
I checked other places, the convention seems to be to show the last "name" breadcrumb only when the information is loaded.

return [{ text: breadcrumbName }];
}

return breadcrumb;
return [];
};