{visiblePanel}
diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/formatted_field_helpers.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/formatted_field_helpers.tsx
index d33192528a090..ef509cdfbda17 100644
--- a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/formatted_field_helpers.tsx
+++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/formatted_field_helpers.tsx
@@ -48,14 +48,15 @@ export const RenderRuleName: React.FC
= ({
}) => {
const ruleName = `${value}`;
const ruleId = linkValue;
- const { search } = useFormatUrl(SecurityPageName.detections);
+ const { search } = useFormatUrl(SecurityPageName.rules);
const { navigateToApp, getUrlForApp } = useKibana().services.application;
const content = truncate ? {value} : value;
const goToRuleDetails = useCallback(
(ev) => {
ev.preventDefault();
- navigateToApp(`${APP_ID}:${SecurityPageName.detections}`, {
+ navigateToApp(APP_ID, {
+ deepLinkId: SecurityPageName.rules,
path: getRuleDetailsUrl(ruleId ?? '', search),
});
},
@@ -71,7 +72,8 @@ export const RenderRuleName: React.FC = ({
>
diff --git a/x-pack/plugins/security_solution/public/timelines/index.ts b/x-pack/plugins/security_solution/public/timelines/index.ts
index 224eec7568c6b..8725072e61849 100644
--- a/x-pack/plugins/security_solution/public/timelines/index.ts
+++ b/x-pack/plugins/security_solution/public/timelines/index.ts
@@ -6,7 +6,7 @@
*/
import { SecuritySubPluginWithStore } from '../app/types';
-import { TimelinesRoutes } from './routes';
+import { routes } from './routes';
import { initialTimelineState, timelineReducer } from './store/timeline/reducer';
import { TimelineState } from './store/timeline/types';
@@ -15,7 +15,7 @@ export class Timelines {
public start(): SecuritySubPluginWithStore<'timeline', TimelineState> {
return {
- SubPluginRoutes: TimelinesRoutes,
+ routes,
store: {
initialState: { timeline: initialTimelineState },
reducer: { timeline: timelineReducer },
diff --git a/x-pack/plugins/security_solution/public/timelines/pages/index.tsx b/x-pack/plugins/security_solution/public/timelines/pages/index.tsx
index 806ac57df1f65..2bf6e1259ff75 100644
--- a/x-pack/plugins/security_solution/public/timelines/pages/index.tsx
+++ b/x-pack/plugins/security_solution/public/timelines/pages/index.tsx
@@ -7,7 +7,7 @@
import { isEmpty } from 'lodash/fp';
import React from 'react';
-import { Switch, Route, useHistory } from 'react-router-dom';
+import { Switch, Route, Redirect } from 'react-router-dom';
import { ChromeBreadcrumb } from '../../../../../../src/core/public';
@@ -18,11 +18,11 @@ import { TimelinesPage } from './timelines_page';
import { PAGE_TITLE } from './translations';
import { appendSearch } from '../../common/components/link_to/helpers';
import { GetUrlForApp } from '../../common/components/navigation/types';
-import { APP_ID } from '../../../common/constants';
+import { APP_ID, TIMELINES_PATH } from '../../../common/constants';
import { SecurityPageName } from '../../app/types';
-const timelinesPagePath = `/:tabName(${TimelineType.default}|${TimelineType.template})`;
-const timelinesDefaultPath = `/${TimelineType.default}`;
+const timelinesPagePath = `${TIMELINES_PATH}/:tabName(${TimelineType.default}|${TimelineType.template})`;
+const timelinesDefaultPath = `${TIMELINES_PATH}/${TimelineType.default}`;
export const getBreadcrumbs = (
params: TimelineRouteSpyState,
@@ -31,28 +31,25 @@ export const getBreadcrumbs = (
): ChromeBreadcrumb[] => [
{
text: PAGE_TITLE,
- href: getUrlForApp(`${APP_ID}:${SecurityPageName.timelines}`, {
+ href: getUrlForApp(APP_ID, {
+ deepLinkId: SecurityPageName.timelines,
path: !isEmpty(search[0]) ? search[0] : '',
}),
},
];
-export const Timelines = React.memo(() => {
- const history = useHistory();
- return (
-
-
-
-
- {
- history.replace(`${timelinesDefaultPath}${appendSearch(search)}`);
- return null;
- }}
- />
-
- );
-});
+export const Timelines = React.memo(() => (
+
+
+
+
+ (
+
+ )}
+ />
+
+));
Timelines.displayName = 'Timelines';
diff --git a/x-pack/plugins/security_solution/public/timelines/routes.tsx b/x-pack/plugins/security_solution/public/timelines/routes.tsx
index 010a022bfefb7..0bc95b3b4959f 100644
--- a/x-pack/plugins/security_solution/public/timelines/routes.tsx
+++ b/x-pack/plugins/security_solution/public/timelines/routes.tsx
@@ -6,20 +6,21 @@
*/
import React from 'react';
-import { Route, Switch } from 'react-router-dom';
-
+import { TrackApplicationView } from '../../../../../src/plugins/usage_collection/public';
import { Timelines } from './pages';
-import { NotFoundPage } from '../app/404';
+import { TIMELINES_PATH } from '../../common/constants';
+
+import { SecurityPageName, SecuritySubPluginRoutes } from '../app/types';
-const TimelinesRoutesComponent = () => (
-
-
-
-
-
-
-
-
+const TimelinesRoutes = () => (
+
+
+
);
-export const TimelinesRoutes = React.memo(TimelinesRoutesComponent);
+export const routes: SecuritySubPluginRoutes = [
+ {
+ path: TIMELINES_PATH,
+ render: TimelinesRoutes,
+ },
+];
diff --git a/x-pack/plugins/security_solution/public/types.ts b/x-pack/plugins/security_solution/public/types.ts
index aad685f9fb103..98187b7d25f5c 100644
--- a/x-pack/plugins/security_solution/public/types.ts
+++ b/x-pack/plugins/security_solution/public/types.ts
@@ -30,9 +30,11 @@ import { MlPluginSetup, MlPluginStart } from '../../ml/public';
import { Detections } from './detections';
import { Cases } from './cases';
+import { Exceptions } from './exceptions';
import { Hosts } from './hosts';
import { Network } from './network';
import { Overview } from './overview';
+import { Rules } from './rules';
import { Timelines } from './timelines';
import { Management } from './management';
import { LicensingPluginStart, LicensingPluginSetup } from '../../licensing/public';
@@ -81,7 +83,9 @@ export interface AppObservableLibs {
export type InspectResponse = Inspect & { response: string[] };
export interface SubPlugins {
- detections: Detections;
+ alerts: Detections;
+ rules: Rules;
+ exceptions: Exceptions;
cases: Cases;
hosts: Hosts;
network: Network;
@@ -89,3 +93,16 @@ export interface SubPlugins {
timelines: Timelines;
management: Management;
}
+
+// TODO: find a better way to defined these types
+export interface StartedSubPlugins {
+ alerts: ReturnType;
+ rules: ReturnType;
+ exceptions: ReturnType;
+ cases: ReturnType;
+ hosts: ReturnType;
+ network: ReturnType;
+ overview: ReturnType;
+ timelines: ReturnType;
+ management: ReturnType;
+}
diff --git a/x-pack/plugins/security_solution/server/plugin.ts b/x-pack/plugins/security_solution/server/plugin.ts
index 4bcbcb71d048c..9f8b1923ff5b8 100644
--- a/x-pack/plugins/security_solution/server/plugin.ts
+++ b/x-pack/plugins/security_solution/server/plugin.ts
@@ -65,7 +65,6 @@ import { initUiSettings } from './ui_settings';
import {
APP_ID,
SERVER_APP_ID,
- SecurityPageName,
SIGNALS_ID,
NOTIFICATIONS_ID,
REFERENCE_RULE_ALERT_TYPE_ID,
@@ -125,24 +124,6 @@ export interface PluginSetup {}
// eslint-disable-next-line @typescript-eslint/no-empty-interface
export interface PluginStart {}
-
-const casesSubPlugin = `${APP_ID}:${SecurityPageName.case}`;
-
-/**
- * Don't include cases here so that the sub feature can govern whether Cases is enabled in the navigation
- */
-const securitySubPluginsNoCases = [
- APP_ID,
- `${APP_ID}:${SecurityPageName.overview}`,
- `${APP_ID}:${SecurityPageName.detections}`,
- `${APP_ID}:${SecurityPageName.hosts}`,
- `${APP_ID}:${SecurityPageName.network}`,
- `${APP_ID}:${SecurityPageName.timelines}`,
- `${APP_ID}:${SecurityPageName.administration}`,
-];
-
-const allSecuritySubPlugins = [...securitySubPluginsNoCases, casesSubPlugin];
-
export class Plugin implements IPlugin {
private readonly logger: Logger;
private readonly config: ConfigType;
@@ -308,7 +289,7 @@ export class Plugin implements IPlugin