mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 09:48:58 -04:00
[Defend workflows] [On-week] Migrate osquery from styled-components to @emotion (#161179)
This commit is contained in:
parent
41e5df703a
commit
ffb716d8af
42 changed files with 505 additions and 495 deletions
|
@ -14,7 +14,7 @@ module.exports = {
|
|||
USES_STYLED_COMPONENTS: [
|
||||
/packages[\/\\]kbn-ui-shared-deps-(npm|src)[\/\\]/,
|
||||
/src[\/\\]plugins[\/\\](kibana_react)[\/\\]/,
|
||||
/x-pack[\/\\]plugins[\/\\](apm|beats_management|cases|fleet|infra|lists|observability|observability_shared|exploratory_view|osquery|security_solution|timelines|synthetics|ux|uptime)[\/\\]/,
|
||||
/x-pack[\/\\]plugins[\/\\](apm|beats_management|cases|fleet|infra|lists|observability|observability_shared|exploratory_view|security_solution|timelines|synthetics|ux|uptime)[\/\\]/,
|
||||
/x-pack[\/\\]test[\/\\]plugin_functional[\/\\]plugins[\/\\]resolver_test[\/\\]/,
|
||||
/x-pack[\/\\]packages[\/\\]elastic_assistant[\/\\]/,
|
||||
/x-pack[\/\\]packages[\/\\]security-solution[\/\\]ecs_data_quality_dashboard[\/\\]/,
|
||||
|
|
|
@ -8,6 +8,8 @@
|
|||
import { EuiLoadingSpinner } from '@elastic/eui';
|
||||
import type { ReactNode } from 'react';
|
||||
import React, { lazy, Suspense } from 'react';
|
||||
import { EuiThemeProvider as StyledComponentsThemeProvider } from '@kbn/kibana-react-plugin/common';
|
||||
import { useIsDarkTheme } from '../../common/use_is_dark_theme';
|
||||
import type { CasesContextProps } from '../../components/cases_context';
|
||||
|
||||
export type GetCasesContextPropsInternal = CasesContextProps;
|
||||
|
@ -32,21 +34,25 @@ const CasesProviderLazyWrapper = ({
|
|||
releasePhase,
|
||||
getFilesClient,
|
||||
}: GetCasesContextPropsInternal & { children: ReactNode }) => {
|
||||
const isDarkTheme = useIsDarkTheme();
|
||||
|
||||
return (
|
||||
<Suspense fallback={<EuiLoadingSpinner />}>
|
||||
<CasesProviderLazy
|
||||
value={{
|
||||
externalReferenceAttachmentTypeRegistry,
|
||||
persistableStateAttachmentTypeRegistry,
|
||||
owner,
|
||||
permissions,
|
||||
features,
|
||||
releasePhase,
|
||||
getFilesClient,
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</CasesProviderLazy>
|
||||
<StyledComponentsThemeProvider darkMode={isDarkTheme}>
|
||||
<CasesProviderLazy
|
||||
value={{
|
||||
externalReferenceAttachmentTypeRegistry,
|
||||
persistableStateAttachmentTypeRegistry,
|
||||
owner,
|
||||
permissions,
|
||||
features,
|
||||
releasePhase,
|
||||
getFilesClient,
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</CasesProviderLazy>
|
||||
</StyledComponentsThemeProvider>
|
||||
</Suspense>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -49,7 +49,12 @@ export const checkResults = () => {
|
|||
export const typeInECSFieldInput = (text: string, index = 0) =>
|
||||
cy.getBySel('ECS-field-input').eq(index).type(text);
|
||||
export const typeInOsqueryFieldInput = (text: string, index = 0) =>
|
||||
cy.react('OsqueryColumnFieldComponent').eq(index).react('ResultComboBox').type(text);
|
||||
cy
|
||||
.react('OsqueryColumnFieldComponent')
|
||||
.eq(index)
|
||||
.within(() => {
|
||||
cy.getBySel('comboBoxInput').type(text);
|
||||
});
|
||||
|
||||
export const getOsqueryFieldTypes = (value: 'Osquery value' | 'Static value', index = 0) => {
|
||||
cy.getBySel(`osquery-result-type-select-${index}`).click();
|
||||
|
|
|
@ -86,7 +86,7 @@ export const getSavedQueriesComplexTest = () =>
|
|||
cy.contains('Save query');
|
||||
findFormFieldByRowsLabelAndType('ID', savedQueryId);
|
||||
findFormFieldByRowsLabelAndType('Description (optional)', savedQueryDescription);
|
||||
cy.react('EuiButtonDisplay').contains('Save').click();
|
||||
cy.getBySel('savedQueryFlyoutSaveButton').click();
|
||||
cy.contains('Successfully saved');
|
||||
closeToastIfVisible();
|
||||
|
||||
|
@ -120,10 +120,12 @@ export const getSavedQueriesComplexTest = () =>
|
|||
inputQuery('{selectall}{backspace}{selectall}{backspace}');
|
||||
cy.contains('Query is a required field');
|
||||
inputQuery(BIG_QUERY);
|
||||
cy.contains('Query is a required field').should('not.exist');
|
||||
});
|
||||
|
||||
// Save edited
|
||||
cy.react('EuiButton').contains('Update query').click();
|
||||
cy.getBySel('euiFlyoutCloseButton').click();
|
||||
cy.getBySel('savedQueryFormUpdateButton').click();
|
||||
cy.contains(`${savedQueryDescription} Edited`);
|
||||
|
||||
// delete saved query
|
||||
|
|
14
x-pack/plugins/osquery/emotion.d.ts
vendored
Normal file
14
x-pack/plugins/osquery/emotion.d.ts
vendored
Normal file
|
@ -0,0 +1,14 @@
|
|||
/*
|
||||
* 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 '@emotion/react';
|
||||
import type { UseEuiTheme } from '@elastic/eui';
|
||||
|
||||
declare module '@emotion/react' {
|
||||
// eslint-disable-next-line @typescript-eslint/no-empty-interface
|
||||
export interface Theme extends UseEuiTheme {}
|
||||
}
|
|
@ -5,22 +5,19 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import styled from 'styled-components';
|
||||
import { EuiColorPaletteDisplay } from '@elastic/eui';
|
||||
import React, { useMemo } from 'react';
|
||||
|
||||
import { AGENT_STATUSES, getColorForAgentStatus } from './services/agent_status';
|
||||
import type { ActionAgentStatus } from './types';
|
||||
|
||||
const StyledEuiColorPaletteDisplay = styled(EuiColorPaletteDisplay)`
|
||||
&.osquery-action-agent-status-bar {
|
||||
border: none;
|
||||
border-radius: 0;
|
||||
&:after {
|
||||
border: none;
|
||||
}
|
||||
}
|
||||
`;
|
||||
const euiColorPaletteDisplayCss = {
|
||||
border: 'none',
|
||||
borderRadius: 0,
|
||||
'&:after': {
|
||||
border: 'none',
|
||||
},
|
||||
};
|
||||
|
||||
export const AgentStatusBar: React.FC<{
|
||||
agentStatus: { [k in ActionAgentStatus]: number };
|
||||
|
@ -39,11 +36,5 @@ export const AgentStatusBar: React.FC<{
|
|||
}, [] as Array<{ stop: number; color: string }>);
|
||||
}, [agentStatus]);
|
||||
|
||||
return (
|
||||
<StyledEuiColorPaletteDisplay
|
||||
className="osquery-action-agent-status-bar"
|
||||
size="s"
|
||||
palette={palette}
|
||||
/>
|
||||
);
|
||||
return <EuiColorPaletteDisplay css={euiColorPaletteDisplayCss} size="s" palette={palette} />;
|
||||
};
|
||||
|
|
|
@ -7,18 +7,17 @@
|
|||
|
||||
import { EuiLink } from '@elastic/eui';
|
||||
import React, { useCallback, useMemo } from 'react';
|
||||
import styled from 'styled-components';
|
||||
|
||||
import { PLUGIN_ID } from '@kbn/fleet-plugin/common';
|
||||
import { pagePathGetters } from '@kbn/fleet-plugin/public';
|
||||
import { useKibana, isModifiedEvent, isLeftClickEvent } from '../common/lib/kibana';
|
||||
import { useAgentPolicy } from './use_agent_policy';
|
||||
|
||||
const StyledEuiLink = styled(EuiLink)`
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
`;
|
||||
const euiLinkCss = {
|
||||
whiteSpace: 'nowrap' as const,
|
||||
textOverflow: 'ellipsis',
|
||||
overflow: 'hidden',
|
||||
};
|
||||
|
||||
interface AgentsPolicyLinkProps {
|
||||
policyId: string;
|
||||
|
@ -52,9 +51,10 @@ const AgentsPolicyLinkComponent: React.FC<AgentsPolicyLinkProps> = ({ policyId }
|
|||
);
|
||||
|
||||
return (
|
||||
<StyledEuiLink href={href} onClick={handleClick}>
|
||||
// eslint-disable-next-line @elastic/eui/href-or-on-click
|
||||
<EuiLink href={href} onClick={handleClick} css={euiLinkCss}>
|
||||
{data?.name ?? policyId}
|
||||
</StyledEuiLink>
|
||||
</EuiLink>
|
||||
);
|
||||
};
|
||||
|
||||
|
|
|
@ -6,40 +6,21 @@
|
|||
*/
|
||||
|
||||
import { EuiErrorBoundary } from '@elastic/eui';
|
||||
import { euiLightVars, euiDarkVars } from '@kbn/ui-theme';
|
||||
import React, { useMemo } from 'react';
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import { Router } from '@kbn/shared-ux-router';
|
||||
import { I18nProvider } from '@kbn/i18n-react';
|
||||
import { ThemeProvider } from 'styled-components';
|
||||
import { QueryClientProvider } from '@tanstack/react-query';
|
||||
import { ReactQueryDevtools } from '@tanstack/react-query-devtools';
|
||||
|
||||
import type { Storage } from '@kbn/kibana-utils-plugin/public';
|
||||
import type { AppMountParameters, CoreStart } from '@kbn/core/public';
|
||||
import { useUiSetting$, KibanaThemeProvider } from './shared_imports';
|
||||
import type { AppPluginStartDependencies } from './types';
|
||||
import { OsqueryApp } from './components/app';
|
||||
import { DEFAULT_DARK_MODE, PLUGIN_NAME } from '../common';
|
||||
import { PLUGIN_NAME } from '../common';
|
||||
import { KibanaContextProvider } from './common/lib/kibana';
|
||||
import { queryClient } from './query_client';
|
||||
|
||||
const OsqueryAppContext = () => {
|
||||
const [darkMode] = useUiSetting$<boolean>(DEFAULT_DARK_MODE);
|
||||
const theme = useMemo(
|
||||
() => ({
|
||||
eui: darkMode ? euiDarkVars : euiLightVars,
|
||||
darkMode,
|
||||
}),
|
||||
[darkMode]
|
||||
);
|
||||
|
||||
return (
|
||||
<ThemeProvider theme={theme}>
|
||||
<OsqueryApp />
|
||||
</ThemeProvider>
|
||||
);
|
||||
};
|
||||
import { KibanaThemeProvider } from './shared_imports';
|
||||
|
||||
export const renderApp = (
|
||||
core: CoreStart,
|
||||
|
@ -64,7 +45,7 @@ export const renderApp = (
|
|||
<Router history={history}>
|
||||
<I18nProvider>
|
||||
<QueryClientProvider client={queryClient}>
|
||||
<OsqueryAppContext />
|
||||
<OsqueryApp />
|
||||
<ReactQueryDevtools initialIsOpen={false} />
|
||||
</QueryClientProvider>
|
||||
</I18nProvider>
|
||||
|
|
|
@ -11,13 +11,13 @@ import {
|
|||
EuiLoadingSpinner,
|
||||
EuiPage,
|
||||
EuiPageBody,
|
||||
EuiPageContent_Deprecated as EuiPageContent,
|
||||
EuiPageSection,
|
||||
} from '@elastic/eui';
|
||||
|
||||
import { useKibana } from '@kbn/kibana-react-plugin/public';
|
||||
import useObservable from 'react-use/lib/useObservable';
|
||||
import { of } from 'rxjs';
|
||||
import { Container, Wrapper } from './layouts';
|
||||
import { containerCss, wrapperCss } from './layouts/default';
|
||||
import { OsqueryAppRoutes } from '../routes';
|
||||
import { useOsqueryIntegrationStatus } from '../common/hooks';
|
||||
import { OsqueryAppEmptyState } from './empty_state';
|
||||
|
@ -31,19 +31,13 @@ const OsqueryAppComponent = () => {
|
|||
return (
|
||||
<EuiPage paddingSize="none">
|
||||
<EuiPageBody>
|
||||
<EuiPageContent
|
||||
verticalPosition="center"
|
||||
horizontalPosition="center"
|
||||
paddingSize="none"
|
||||
color="subdued"
|
||||
hasShadow={false}
|
||||
>
|
||||
<EuiPageSection paddingSize="none" color="subdued">
|
||||
{hasCustomBranding ? (
|
||||
<EuiLoadingSpinner size="xxl" />
|
||||
) : (
|
||||
<EuiLoadingElastic size="xxl" />
|
||||
)}
|
||||
</EuiPageContent>
|
||||
</EuiPageSection>
|
||||
</EuiPageBody>
|
||||
</EuiPage>
|
||||
);
|
||||
|
@ -54,12 +48,12 @@ const OsqueryAppComponent = () => {
|
|||
}
|
||||
|
||||
return (
|
||||
<Container id="osquery-app">
|
||||
<Wrapper>
|
||||
<div css={containerCss} id="osquery-app">
|
||||
<div css={wrapperCss}>
|
||||
<MainNavigation />
|
||||
<OsqueryAppRoutes />
|
||||
</Wrapper>
|
||||
</Container>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
|
|
|
@ -5,30 +5,26 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import styled from 'styled-components';
|
||||
import type { UseEuiTheme } from '@elastic/eui';
|
||||
export const containerCss = ({ euiTheme }: UseEuiTheme) => ({
|
||||
minHeight: `calc(100vh - ${parseFloat(euiTheme.size.xxxl) * 2}px)`,
|
||||
background: euiTheme.colors.emptyShade,
|
||||
display: 'flex',
|
||||
flexDirection: 'column' as const,
|
||||
});
|
||||
|
||||
export const Container = styled.div`
|
||||
min-height: calc(
|
||||
100vh - ${(props) => parseFloat(props.theme.eui.euiHeaderHeightCompensation) * 2}px
|
||||
);
|
||||
background: ${(props) => props.theme.eui.euiColorEmptyShade};
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
`;
|
||||
export const wrapperCss = {
|
||||
display: 'flex',
|
||||
flexDirection: 'column' as const,
|
||||
flex: 1,
|
||||
};
|
||||
|
||||
export const Wrapper = styled.div`
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex: 1;
|
||||
`;
|
||||
|
||||
export const Nav = styled.nav`
|
||||
background: ${(props) => props.theme.eui.euiColorEmptyShade};
|
||||
border-bottom: ${(props) => props.theme.eui.euiBorderThin};
|
||||
padding: ${(props) =>
|
||||
`${props.theme.eui.euiSize} ${props.theme.eui.euiSizeL} ${props.theme.eui.euiSize} ${props.theme.eui.euiSizeL}`};
|
||||
.euiTabs {
|
||||
padding-left: 3px;
|
||||
margin-left: -3px;
|
||||
}
|
||||
`;
|
||||
export const navCss = ({ euiTheme }: UseEuiTheme) => ({
|
||||
background: euiTheme.colors.emptyShade,
|
||||
borderBottom: euiTheme.border.thin,
|
||||
padding: `${euiTheme.size.base} ${euiTheme.size.l} ${euiTheme.size.base} ${euiTheme.size.l}`,
|
||||
'.euiTabs': {
|
||||
paddingLeft: '3px',
|
||||
marginLeft: '-3px',
|
||||
},
|
||||
});
|
||||
|
|
|
@ -7,32 +7,24 @@
|
|||
|
||||
// copied from x-pack/plugins/fleet/public/applications/fleet/components/header.tsx
|
||||
|
||||
import React, { memo } from 'react';
|
||||
import styled from 'styled-components';
|
||||
import React, { memo, useCallback } from 'react';
|
||||
import { EuiFlexGroup, EuiFlexItem, EuiTabs, EuiTab, EuiSpacer } from '@elastic/eui';
|
||||
import type { UseEuiTheme } from '@elastic/eui';
|
||||
import type { Props as EuiTabProps } from '@elastic/eui/src/components/tabs/tab';
|
||||
import type { EuiFlexItemProps } from '@elastic/eui/src/components/flex/flex_item';
|
||||
import { css } from '@emotion/react';
|
||||
|
||||
const Container = styled.div`
|
||||
border-bottom: ${(props) => props.theme.eui.euiBorderThin};
|
||||
background-color: ${(props) => props.theme.eui.euiPageBackgroundColor};
|
||||
`;
|
||||
const containerCss = ({ euiTheme }: UseEuiTheme) => ({
|
||||
borderBottom: euiTheme.border.thin,
|
||||
backgroundColor: euiTheme.colors.body,
|
||||
});
|
||||
|
||||
const Wrapper = styled.div<{ maxWidth?: number }>`
|
||||
max-width: ${(props) => props.maxWidth || 1200}px;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
padding-top: ${(props) => props.theme.eui.euiSizeXL};
|
||||
padding-left: ${(props) => props.theme.eui.euiSizeM};
|
||||
padding-right: ${(props) => props.theme.eui.euiSizeM};
|
||||
`;
|
||||
|
||||
const Tabs = styled(EuiTabs)`
|
||||
top: 1px;
|
||||
&:before {
|
||||
height: 0px;
|
||||
}
|
||||
`;
|
||||
const tabsCss = {
|
||||
top: '1px',
|
||||
'&:before': {
|
||||
height: '0px',
|
||||
},
|
||||
};
|
||||
|
||||
export interface HeaderProps {
|
||||
children?: React.ReactNode;
|
||||
|
@ -65,35 +57,50 @@ const HeaderComponent: React.FC<HeaderProps> = ({
|
|||
maxWidth,
|
||||
tabsClassName,
|
||||
'data-test-subj': dataTestSubj,
|
||||
}) => (
|
||||
<Container data-test-subj={dataTestSubj}>
|
||||
<Wrapper maxWidth={maxWidth}>
|
||||
<HeaderColumns
|
||||
leftColumn={leftColumn}
|
||||
rightColumn={rightColumn}
|
||||
rightColumnGrow={rightColumnGrow}
|
||||
/>
|
||||
{children}
|
||||
<EuiFlexGroup>
|
||||
{tabs ? (
|
||||
<EuiFlexItem>
|
||||
<EuiSpacer size="s" />
|
||||
<Tabs className={tabsClassName}>
|
||||
{tabs.map((props) => (
|
||||
<EuiTab {...(props as EuiTabProps)} key={props.id}>
|
||||
{props.name}
|
||||
</EuiTab>
|
||||
))}
|
||||
</Tabs>
|
||||
</EuiFlexItem>
|
||||
) : (
|
||||
<EuiFlexItem>
|
||||
<EuiSpacer size="l" />
|
||||
</EuiFlexItem>
|
||||
)}
|
||||
</EuiFlexGroup>
|
||||
</Wrapper>
|
||||
</Container>
|
||||
);
|
||||
}) => {
|
||||
const wrapperCss = useCallback(
|
||||
({ euiTheme }: UseEuiTheme) => css`
|
||||
max-width: ${maxWidth || 1200}px;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
padding-top: ${euiTheme.size.xl};
|
||||
padding-left: ${euiTheme.size.m};
|
||||
padding-right: ${euiTheme.size.m};
|
||||
`,
|
||||
|
||||
[maxWidth]
|
||||
);
|
||||
|
||||
return (
|
||||
<div css={containerCss} data-test-subj={dataTestSubj}>
|
||||
<div css={wrapperCss}>
|
||||
<HeaderColumns
|
||||
leftColumn={leftColumn}
|
||||
rightColumn={rightColumn}
|
||||
rightColumnGrow={rightColumnGrow}
|
||||
/>
|
||||
{children}
|
||||
<EuiFlexGroup>
|
||||
{tabs ? (
|
||||
<EuiFlexItem>
|
||||
<EuiSpacer size="s" />
|
||||
<EuiTabs className={tabsClassName} css={tabsCss}>
|
||||
{tabs.map((props) => (
|
||||
<EuiTab {...(props as EuiTabProps)} key={props.id}>
|
||||
{props.name}
|
||||
</EuiTab>
|
||||
))}
|
||||
</EuiTabs>
|
||||
</EuiFlexItem>
|
||||
) : (
|
||||
<EuiFlexItem>
|
||||
<EuiSpacer size="l" />
|
||||
</EuiFlexItem>
|
||||
)}
|
||||
</EuiFlexGroup>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export const Header = React.memo(HeaderComponent);
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
// copied from x-pack/plugins/fleet/public/applications/fleet/layouts/index.tsx
|
||||
|
||||
export { Container, Nav, Wrapper } from './default';
|
||||
export { containerCss, navCss, wrapperCss } from './default';
|
||||
export type { WithHeaderLayoutProps } from './with_header';
|
||||
export { WithHeaderLayout } from './with_header';
|
||||
export { WithoutHeaderLayout } from './without_header';
|
||||
|
|
|
@ -6,11 +6,12 @@
|
|||
*/
|
||||
|
||||
import React, { Fragment } from 'react';
|
||||
import { EuiPageBody, EuiSpacer } from '@elastic/eui';
|
||||
import { EuiPage, EuiPageBody, EuiSpacer } from '@elastic/eui';
|
||||
|
||||
import type { HeaderProps } from './header';
|
||||
import { Header } from './header';
|
||||
import { Page, ContentWrapper } from './without_header';
|
||||
import { contentCss } from './without_header';
|
||||
import { pageCss } from './without_header';
|
||||
|
||||
export interface WithHeaderLayoutProps extends HeaderProps {
|
||||
restrictWidth?: number;
|
||||
|
@ -36,16 +37,17 @@ export const WithHeaderLayout: React.FC<WithHeaderLayoutProps> = ({
|
|||
>
|
||||
{headerChildren}
|
||||
</Header>
|
||||
<Page
|
||||
<EuiPage
|
||||
css={pageCss}
|
||||
restrictWidth={restrictWidth || 1200}
|
||||
data-test-subj={dataTestSubj ? `${dataTestSubj}_page` : undefined}
|
||||
>
|
||||
<EuiPageBody>
|
||||
<ContentWrapper>
|
||||
<div css={contentCss}>
|
||||
<EuiSpacer size="l" />
|
||||
{children}
|
||||
</ContentWrapper>
|
||||
</div>
|
||||
</EuiPageBody>
|
||||
</Page>
|
||||
</EuiPage>
|
||||
</Fragment>
|
||||
);
|
||||
|
|
|
@ -6,21 +6,21 @@
|
|||
*/
|
||||
|
||||
import React, { Fragment } from 'react';
|
||||
import styled from 'styled-components';
|
||||
import { EuiPage, EuiPageBody, EuiSpacer } from '@elastic/eui';
|
||||
import type { UseEuiTheme } from '@elastic/eui';
|
||||
|
||||
export const Page = styled(EuiPage)`
|
||||
background: ${(props) => props.theme.eui.euiColorEmptyShade};
|
||||
width: 100%;
|
||||
align-self: center;
|
||||
margin-left: 0;
|
||||
margin-right: 0;
|
||||
flex: 1;
|
||||
`;
|
||||
export const pageCss = ({ euiTheme }: UseEuiTheme) => ({
|
||||
background: euiTheme.colors.emptyShade,
|
||||
width: '100%',
|
||||
alignSelf: 'center',
|
||||
marginLeft: 0,
|
||||
marginRight: 0,
|
||||
flex: 1,
|
||||
});
|
||||
|
||||
export const ContentWrapper = styled.div`
|
||||
height: 100%;
|
||||
`;
|
||||
export const contentCss = {
|
||||
height: '100%',
|
||||
};
|
||||
|
||||
interface Props {
|
||||
restrictWidth?: number;
|
||||
|
@ -29,13 +29,13 @@ interface Props {
|
|||
|
||||
export const WithoutHeaderLayout: React.FC<Props> = ({ restrictWidth, children }) => (
|
||||
<Fragment>
|
||||
<Page restrictWidth={restrictWidth || 1200}>
|
||||
<EuiPage css={pageCss} restrictWidth={restrictWidth || 1200}>
|
||||
<EuiPageBody>
|
||||
<ContentWrapper>
|
||||
<div css={contentCss}>
|
||||
<EuiSpacer size="m" />
|
||||
{children}
|
||||
</ContentWrapper>
|
||||
</div>
|
||||
</EuiPageBody>
|
||||
</Page>
|
||||
</EuiPage>
|
||||
</Fragment>
|
||||
);
|
||||
|
|
|
@ -9,9 +9,9 @@ import React, { useMemo } from 'react';
|
|||
import { FormattedMessage } from '@kbn/i18n-react';
|
||||
import { EuiButtonEmpty, EuiFlexGroup, EuiFlexItem, EuiTab, EuiTabs } from '@elastic/eui';
|
||||
import { useLocation } from 'react-router-dom';
|
||||
import { navCss } from './layouts/default';
|
||||
import { useRouterNavigate } from '../common/lib/kibana';
|
||||
import { ManageIntegrationLink } from './manage_integration_link';
|
||||
import { Nav } from './layouts';
|
||||
|
||||
enum Section {
|
||||
LiveQueries = 'live_queries',
|
||||
|
@ -24,7 +24,7 @@ export const MainNavigation = () => {
|
|||
const section = useMemo(() => location.pathname.split('/')[1] ?? 'overview', [location.pathname]);
|
||||
|
||||
return (
|
||||
<Nav>
|
||||
<div css={navCss}>
|
||||
<EuiFlexGroup gutterSize="l" alignItems="center">
|
||||
<EuiFlexItem>
|
||||
<EuiTabs bottomBorder={false}>
|
||||
|
@ -72,6 +72,6 @@ export const MainNavigation = () => {
|
|||
</EuiFlexGroup>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
</Nav>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -15,12 +15,12 @@ import {
|
|||
EuiCallOut,
|
||||
EuiLink,
|
||||
EuiAccordion,
|
||||
useEuiTheme,
|
||||
} from '@elastic/eui';
|
||||
import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import { produce } from 'immer';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import useDebounce from 'react-use/lib/useDebounce';
|
||||
import styled from 'styled-components';
|
||||
|
||||
import type { AgentPolicy } from '@kbn/fleet-plugin/common';
|
||||
import { agentRouteService, agentPolicyRouteService, PLUGIN_ID } from '@kbn/fleet-plugin/common';
|
||||
|
@ -136,12 +136,6 @@ export const packConfigFilesValidator = (
|
|||
|
||||
const CommonUseField = getUseField({ component: Field });
|
||||
|
||||
const StyledEuiAccordion = styled(EuiAccordion)`
|
||||
.euiAccordion__button {
|
||||
color: ${({ theme }) => theme.eui.euiColorPrimary};
|
||||
}
|
||||
`;
|
||||
|
||||
/**
|
||||
* Exports Osquery-specific package policy instructions
|
||||
* for use in the Fleet app create / edit package policy
|
||||
|
@ -343,6 +337,17 @@ export const OsqueryManagedPolicyCreateImportExtension = React.memo<
|
|||
|
||||
const { permissionDenied } = useFetchStatus();
|
||||
|
||||
const { euiTheme } = useEuiTheme();
|
||||
|
||||
const euiAccordionCss = useMemo(
|
||||
() => ({
|
||||
'.euiAccordion__button': {
|
||||
color: euiTheme.colors.primary,
|
||||
},
|
||||
}),
|
||||
[euiTheme]
|
||||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
{!editMode ? <DisabledCallout /> : null}
|
||||
|
@ -373,7 +378,8 @@ export const OsqueryManagedPolicyCreateImportExtension = React.memo<
|
|||
<>
|
||||
<NavigationButtons isDisabled={!editMode} agentPolicyId={policy?.policy_id} />
|
||||
<EuiSpacer size="xxl" />
|
||||
<StyledEuiAccordion
|
||||
<EuiAccordion
|
||||
css={euiAccordionCss}
|
||||
id="advanced"
|
||||
buttonContent={i18n.translate(
|
||||
'xpack.osquery.fleetIntegration.osqueryConfig.accordionFieldLabel',
|
||||
|
@ -387,7 +393,7 @@ export const OsqueryManagedPolicyCreateImportExtension = React.memo<
|
|||
<CommonUseField path="config" />
|
||||
<ConfigUploader onChange={handleConfigUpload} />
|
||||
</Form>
|
||||
</StyledEuiAccordion>
|
||||
</EuiAccordion>
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
|
|
|
@ -6,10 +6,9 @@
|
|||
*/
|
||||
|
||||
import { isEmpty } from 'lodash';
|
||||
import type { EuiAccordionProps } from '@elastic/eui';
|
||||
import type { EuiAccordionProps, UseEuiTheme } from '@elastic/eui';
|
||||
import { EuiCodeBlock, EuiFormRow, EuiAccordion, EuiSpacer } from '@elastic/eui';
|
||||
import React, { useCallback, useMemo, useState } from 'react';
|
||||
import styled from 'styled-components';
|
||||
import { useController, useFormContext } from 'react-hook-form';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import type { LiveQueryFormFields } from '.';
|
||||
|
@ -19,19 +18,18 @@ import { ECSMappingEditorField } from '../../packs/queries/lazy_ecs_mapping_edit
|
|||
import type { SavedQueriesDropdownProps } from '../../saved_queries/saved_queries_dropdown';
|
||||
import { SavedQueriesDropdown } from '../../saved_queries/saved_queries_dropdown';
|
||||
|
||||
const StyledEuiAccordion = styled(EuiAccordion)`
|
||||
${({ isDisabled }: { isDisabled?: boolean }) => isDisabled && 'display: none;'}
|
||||
.euiAccordion__button {
|
||||
color: ${({ theme }) => theme.eui.euiColorPrimary};
|
||||
}
|
||||
.euiAccordion__childWrapper {
|
||||
-webkit-transition: none;
|
||||
}
|
||||
`;
|
||||
const euiCodeBlockCss = {
|
||||
minHeight: '100px',
|
||||
};
|
||||
|
||||
const StyledEuiCodeBlock = styled(EuiCodeBlock)`
|
||||
min-height: 100px;
|
||||
`;
|
||||
const euiAccordionCss = ({ euiTheme }: UseEuiTheme) => ({
|
||||
'.euiAccordion__button': {
|
||||
color: euiTheme.colors.primary,
|
||||
},
|
||||
'.euiAccordion__childWrapper': {
|
||||
'-webkit-transition': 'none',
|
||||
},
|
||||
});
|
||||
|
||||
export interface LiveQueryQueryFieldProps {
|
||||
handleSubmitForm?: () => void;
|
||||
|
@ -131,14 +129,15 @@ const LiveQueryQueryFieldComponent: React.FC<LiveQueryQueryFieldProps> = ({
|
|||
isDisabled={!permissions.writeLiveQueries || disabled}
|
||||
>
|
||||
{!permissions.writeLiveQueries || disabled ? (
|
||||
<StyledEuiCodeBlock
|
||||
<EuiCodeBlock
|
||||
css={euiCodeBlockCss}
|
||||
language="sql"
|
||||
fontSize="m"
|
||||
paddingSize="m"
|
||||
transparentBackground={!value.length}
|
||||
>
|
||||
{value}
|
||||
</StyledEuiCodeBlock>
|
||||
</EuiCodeBlock>
|
||||
) : (
|
||||
<OsqueryEditor defaultValue={value} onChange={onChange} commands={commands} />
|
||||
)}
|
||||
|
@ -147,7 +146,8 @@ const LiveQueryQueryFieldComponent: React.FC<LiveQueryQueryFieldProps> = ({
|
|||
<EuiSpacer size="m" />
|
||||
|
||||
{!isAdvancedToggleHidden && (
|
||||
<StyledEuiAccordion
|
||||
<EuiAccordion
|
||||
css={euiAccordionCss}
|
||||
id="advanced"
|
||||
forceState={advancedContentState}
|
||||
onToggle={handleToggle}
|
||||
|
@ -156,7 +156,7 @@ const LiveQueryQueryFieldComponent: React.FC<LiveQueryQueryFieldProps> = ({
|
|||
>
|
||||
<EuiSpacer size="xs" />
|
||||
<ECSMappingEditorField euiFieldProps={ecsFieldProps} />
|
||||
</StyledEuiAccordion>
|
||||
</EuiAccordion>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
|
|
|
@ -21,7 +21,6 @@ import {
|
|||
EuiText,
|
||||
} from '@elastic/eui';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import styled from 'styled-components';
|
||||
import type { ECSMapping } from '@kbn/osquery-io-ts-types';
|
||||
import { QueryDetailsFlyout } from './query_details_flyout';
|
||||
import { PackResultsHeader } from './pack_results_header';
|
||||
|
@ -34,43 +33,43 @@ import { PackViewInDiscoverAction } from '../../discover/pack_view_in_discover';
|
|||
import { AddToCaseWrapper } from '../../cases/add_to_cases';
|
||||
import { AddToTimelineButton } from '../../timelines/add_to_timeline_button';
|
||||
|
||||
const TruncateTooltipText = styled.div`
|
||||
width: 100%;
|
||||
const truncateTooltipTextCss = {
|
||||
width: '100%',
|
||||
|
||||
> span {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
`;
|
||||
'> span': {
|
||||
overflow: 'hidden',
|
||||
textOverflow: 'ellipsis',
|
||||
whiteSpace: 'nowrap' as const,
|
||||
},
|
||||
};
|
||||
|
||||
const StyledEuiFlexItem = styled(EuiFlexItem)`
|
||||
cursor: pointer;
|
||||
`;
|
||||
const euiFlexItemCss = {
|
||||
cursor: 'pointer',
|
||||
};
|
||||
|
||||
// TODO fix types
|
||||
const euiBasicTableCss = {
|
||||
'.euiTableRow.euiTableRow-isExpandedRow > td > div': {
|
||||
padding: '0',
|
||||
border: '1px solid #d3dae6',
|
||||
},
|
||||
|
||||
'div.euiDataGrid__virtualized::-webkit-scrollbar': {
|
||||
display: 'none',
|
||||
},
|
||||
|
||||
'.euiDataGrid > div': {
|
||||
'.euiDataGrid__scrollOverlay': {
|
||||
boxShadow: 'none',
|
||||
},
|
||||
|
||||
borderLeft: '0px',
|
||||
borderRight: '0px',
|
||||
},
|
||||
};
|
||||
|
||||
const EMPTY_ARRAY: PackQueryStatusItem[] = [];
|
||||
|
||||
// @ts-expect-error TS2769
|
||||
const StyledEuiBasicTable = styled(EuiBasicTable)`
|
||||
.euiTableRow.euiTableRow-isExpandedRow > td > div {
|
||||
padding: 0;
|
||||
border: 1px solid #d3dae6;
|
||||
}
|
||||
|
||||
div.euiDataGrid__virtualized::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.euiDataGrid > div {
|
||||
.euiDataGrid__scrollOverlay {
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
border-left: 0px;
|
||||
border-right: 0px;
|
||||
}
|
||||
`;
|
||||
|
||||
export enum ViewResultsActionButtonType {
|
||||
icon = 'icon',
|
||||
button = 'button',
|
||||
|
@ -165,14 +164,16 @@ const PackQueriesStatusTableComponent: React.FC<PackQueriesStatusTableProps> = (
|
|||
);
|
||||
const handleQueryFlyoutClose = useCallback(() => setQueryDetailsFlyoutOpen(null), []);
|
||||
|
||||
const [itemIdToExpandedRowMap, setItemIdToExpandedRowMap] = useState<Record<string, unknown>>({});
|
||||
const [itemIdToExpandedRowMap, setItemIdToExpandedRowMap] = useState<
|
||||
Record<string, React.ReactNode>
|
||||
>({});
|
||||
const renderIDColumn = useCallback(
|
||||
(id: string) => (
|
||||
<TruncateTooltipText>
|
||||
<div css={truncateTooltipTextCss}>
|
||||
<EuiToolTip content={id} display="block">
|
||||
<>{id}</>
|
||||
</EuiToolTip>
|
||||
</TruncateTooltipText>
|
||||
</div>
|
||||
),
|
||||
[]
|
||||
);
|
||||
|
@ -183,11 +184,11 @@ const PackQueriesStatusTableComponent: React.FC<PackQueriesStatusTableProps> = (
|
|||
const content = singleLine.length > 55 ? `${singleLine.substring(0, 55)}...` : singleLine;
|
||||
|
||||
return (
|
||||
<StyledEuiFlexItem onClick={handleQueryFlyoutOpen(item)}>
|
||||
<EuiFlexItem css={euiFlexItemCss} onClick={handleQueryFlyoutOpen(item)}>
|
||||
<EuiCodeBlock language="sql" fontSize="s" paddingSize="none" transparentBackground>
|
||||
{content}
|
||||
</EuiCodeBlock>
|
||||
</StyledEuiFlexItem>
|
||||
</EuiFlexItem>
|
||||
);
|
||||
},
|
||||
[handleQueryFlyoutOpen]
|
||||
|
@ -264,7 +265,7 @@ const PackQueriesStatusTableComponent: React.FC<PackQueriesStatusTableProps> = (
|
|||
[data, getHandleErrorsToggle, itemIdToExpandedRowMap]
|
||||
);
|
||||
|
||||
const getItemId = useCallback((item: PackItem) => get(item, 'id'), []);
|
||||
const getItemId = useCallback((item: PackItem) => get(item, 'id'), []) as unknown as string;
|
||||
|
||||
const renderResultActions = useCallback(
|
||||
(row: { action_id: string }) => {
|
||||
|
@ -329,6 +330,7 @@ const PackQueriesStatusTableComponent: React.FC<PackQueriesStatusTableProps> = (
|
|||
width: '40%',
|
||||
},
|
||||
{
|
||||
field: '',
|
||||
name: i18n.translate('xpack.osquery.pack.queriesTable.docsResultsColumnTitle', {
|
||||
defaultMessage: 'Docs',
|
||||
}),
|
||||
|
@ -336,6 +338,7 @@ const PackQueriesStatusTableComponent: React.FC<PackQueriesStatusTableProps> = (
|
|||
render: renderDocsColumn,
|
||||
},
|
||||
{
|
||||
field: '',
|
||||
name: i18n.translate('xpack.osquery.pack.queriesTable.agentsResultsColumnTitle', {
|
||||
defaultMessage: 'Agents',
|
||||
}),
|
||||
|
@ -343,6 +346,7 @@ const PackQueriesStatusTableComponent: React.FC<PackQueriesStatusTableProps> = (
|
|||
render: renderAgentsColumn,
|
||||
},
|
||||
{
|
||||
field: '',
|
||||
name: i18n.translate('xpack.osquery.pack.queriesTable.viewResultsColumnTitle', {
|
||||
defaultMessage: 'View results',
|
||||
}),
|
||||
|
@ -350,6 +354,7 @@ const PackQueriesStatusTableComponent: React.FC<PackQueriesStatusTableProps> = (
|
|||
render: renderResultActions,
|
||||
},
|
||||
{
|
||||
field: '',
|
||||
id: 'actions',
|
||||
width: '45px',
|
||||
isVisuallyHiddenLabel: true,
|
||||
|
@ -373,7 +378,7 @@ const PackQueriesStatusTableComponent: React.FC<PackQueriesStatusTableProps> = (
|
|||
const sorting = useMemo(
|
||||
() => ({
|
||||
sort: {
|
||||
field: 'id' as keyof PackItem,
|
||||
field: 'id' as const,
|
||||
direction: Direction.asc,
|
||||
},
|
||||
}),
|
||||
|
@ -407,8 +412,8 @@ const PackQueriesStatusTableComponent: React.FC<PackQueriesStatusTableProps> = (
|
|||
agentIds={agentIds}
|
||||
/>
|
||||
)}
|
||||
|
||||
<StyledEuiBasicTable
|
||||
<EuiBasicTable
|
||||
css={euiBasicTableCss}
|
||||
items={data ?? EMPTY_ARRAY}
|
||||
itemId={getItemId}
|
||||
columns={columns}
|
||||
|
|
|
@ -5,9 +5,9 @@
|
|||
* 2.0.
|
||||
*/
|
||||
import React, { useMemo } from 'react';
|
||||
import type { UseEuiTheme } from '@elastic/eui';
|
||||
import { EuiFlexGroup, EuiFlexItem, EuiSpacer, EuiText } from '@elastic/eui';
|
||||
import { FormattedMessage } from '@kbn/i18n-react';
|
||||
import styled from 'styled-components';
|
||||
import { AddToTimelineButton } from '../../timelines/add_to_timeline_button';
|
||||
import { AddToCaseWrapper } from '../../cases/add_to_cases';
|
||||
|
||||
|
@ -17,16 +17,16 @@ interface PackResultsHeadersProps {
|
|||
agentIds?: string[];
|
||||
}
|
||||
|
||||
const StyledResultsHeading = styled(EuiFlexItem)`
|
||||
padding-right: 20px;
|
||||
border-right: 2px solid #d3dae6;
|
||||
`;
|
||||
const resultsHeadingCss = ({ euiTheme }: UseEuiTheme) => ({
|
||||
paddingRight: '20px',
|
||||
borderRight: euiTheme.border.thick,
|
||||
});
|
||||
|
||||
const StyledIconsList = styled(EuiFlexItem)`
|
||||
align-content: center;
|
||||
justify-content: center;
|
||||
padding-left: 10px;
|
||||
`;
|
||||
const iconsListCss = {
|
||||
alignContent: 'center',
|
||||
justifyContent: 'center',
|
||||
paddingLeft: '10px',
|
||||
};
|
||||
|
||||
export const PackResultsHeader = React.memo<PackResultsHeadersProps>(
|
||||
({ actionId, agentIds, queryIds }) => {
|
||||
|
@ -36,7 +36,7 @@ export const PackResultsHeader = React.memo<PackResultsHeadersProps>(
|
|||
<>
|
||||
<EuiSpacer size={'l'} />
|
||||
<EuiFlexGroup direction="row" gutterSize="m">
|
||||
<StyledResultsHeading grow={false}>
|
||||
<EuiFlexItem css={resultsHeadingCss} grow={false}>
|
||||
<EuiText>
|
||||
<h2>
|
||||
<FormattedMessage
|
||||
|
@ -45,8 +45,8 @@ export const PackResultsHeader = React.memo<PackResultsHeadersProps>(
|
|||
/>
|
||||
</h2>
|
||||
</EuiText>
|
||||
</StyledResultsHeading>
|
||||
<StyledIconsList grow={false}>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem css={iconsListCss} grow={false}>
|
||||
<span>
|
||||
{actionId && (
|
||||
<EuiFlexGroup>
|
||||
|
@ -69,7 +69,7 @@ export const PackResultsHeader = React.memo<PackResultsHeadersProps>(
|
|||
</EuiFlexGroup>
|
||||
)}
|
||||
</span>
|
||||
</StyledIconsList>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
<EuiSpacer size={'l'} />
|
||||
</>
|
||||
|
|
|
@ -10,16 +10,10 @@ import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
|||
import { i18n } from '@kbn/i18n';
|
||||
import type { EuiComboBoxOptionOption } from '@elastic/eui';
|
||||
import { EuiFormRow, EuiComboBox, EuiTextColor, EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
|
||||
import styled from 'styled-components';
|
||||
|
||||
import { useController } from 'react-hook-form';
|
||||
import type { PackSavedObject } from '../../packs/types';
|
||||
|
||||
const TextTruncate = styled.div`
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
`;
|
||||
|
||||
interface PackComboBoxFieldProps {
|
||||
fieldProps?: {
|
||||
packsData?: PackSavedObject[];
|
||||
|
@ -103,9 +97,9 @@ export const PacksComboBoxField = ({
|
|||
<strong>{option?.name}</strong>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<TextTruncate>
|
||||
<div className="eui-textTruncate">
|
||||
<EuiTextColor color="subdued">{option?.description}</EuiTextColor>
|
||||
</TextTruncate>
|
||||
</div>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
),
|
||||
|
|
|
@ -8,16 +8,16 @@
|
|||
import { EuiCard, EuiFlexGroup, EuiFlexItem, EuiFormRow } from '@elastic/eui';
|
||||
import React, { useCallback, useMemo } from 'react';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import styled from 'styled-components';
|
||||
import { useController } from 'react-hook-form';
|
||||
import styled from '@emotion/styled';
|
||||
|
||||
const StyledEuiCard = styled(EuiCard)`
|
||||
padding: 0;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
border: ${(props) => {
|
||||
if (props.selectable?.isSelected) {
|
||||
return `1px solid ${props.theme.eui.euiColorSuccess}`;
|
||||
border: ${({ theme, selectable }) => {
|
||||
if (selectable?.isSelected) {
|
||||
return `${theme.euiTheme.border.width.thin} solid ${theme.euiTheme.colors.success}`;
|
||||
}
|
||||
}};
|
||||
.euiCard__content {
|
||||
|
@ -28,7 +28,7 @@ const StyledEuiCard = styled(EuiCard)`
|
|||
}
|
||||
.euiText {
|
||||
margin-top: 0;
|
||||
color: ${(props) => props.theme.eui.euiTextSubduedColor};
|
||||
color: ${({ theme }) => theme.euiTheme.colors.subduedText};
|
||||
}
|
||||
|
||||
> button[role='switch'] {
|
||||
|
@ -51,6 +51,7 @@ const StyledEuiCard = styled(EuiCard)`
|
|||
}
|
||||
}
|
||||
`;
|
||||
|
||||
interface QueryPackSelectableProps {
|
||||
canRunSingleQuery: boolean;
|
||||
canRunPacks: boolean;
|
||||
|
|
|
@ -6,9 +6,9 @@
|
|||
*/
|
||||
|
||||
import { EuiSwitch, EuiLoadingSpinner } from '@elastic/eui';
|
||||
import type { UseEuiTheme } from '@elastic/eui';
|
||||
import React, { useCallback, useMemo, useState } from 'react';
|
||||
import { useQueryClient } from '@tanstack/react-query';
|
||||
import styled from 'styled-components';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
|
||||
import { useKibana } from '../common/lib/kibana';
|
||||
|
@ -19,9 +19,9 @@ import { useUpdatePack } from './use_update_pack';
|
|||
import { PACKS_ID } from './constants';
|
||||
import type { PackSavedObject } from './types';
|
||||
|
||||
const StyledEuiLoadingSpinner = styled(EuiLoadingSpinner)`
|
||||
margin-right: ${({ theme }) => theme.eui.euiSizeS};
|
||||
`;
|
||||
const euiLoadingSpinnerCss = ({ euiTheme }: UseEuiTheme) => ({
|
||||
marginRight: euiTheme.size.s,
|
||||
});
|
||||
|
||||
interface ActiveStateSwitchProps {
|
||||
disabled?: boolean;
|
||||
|
@ -91,7 +91,7 @@ const ActiveStateSwitchComponent: React.FC<ActiveStateSwitchProps> = ({ item })
|
|||
|
||||
return (
|
||||
<>
|
||||
{isLoading && <StyledEuiLoadingSpinner />}
|
||||
{isLoading && <EuiLoadingSpinner css={euiLoadingSpinnerCss} />}
|
||||
<EuiSwitch
|
||||
checked={!!item.enabled}
|
||||
disabled={!permissions.writePacks || isLoading}
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
import { filter, isEmpty, map, omit, reduce } from 'lodash';
|
||||
import type { EuiAccordionProps } from '@elastic/eui';
|
||||
import type { UseEuiTheme } from '@elastic/eui';
|
||||
import {
|
||||
EuiFlexGroup,
|
||||
EuiFlexItem,
|
||||
|
@ -22,7 +23,6 @@ import { FormattedMessage } from '@kbn/i18n-react';
|
|||
import deepEqual from 'fast-deep-equal';
|
||||
import { FormProvider, useForm as useHookForm } from 'react-hook-form';
|
||||
|
||||
import styled from 'styled-components';
|
||||
import { PackShardsField } from './shards/pack_shards_field';
|
||||
import { useRouterNavigate } from '../../common/lib/kibana';
|
||||
import { PolicyIdComboBoxField } from './policy_id_combobox_field';
|
||||
|
@ -41,12 +41,11 @@ import { overflowCss } from '../utils';
|
|||
|
||||
type PackFormData = Omit<PackItem, 'id' | 'queries'> & { queries: PackQueryFormData[] };
|
||||
|
||||
const StyledEuiAccordion = styled(EuiAccordion)`
|
||||
${({ isDisabled }: { isDisabled?: boolean }) => isDisabled && 'display: none;'}
|
||||
.euiAccordion__button {
|
||||
color: ${({ theme }) => theme.eui.euiColorPrimary};
|
||||
}
|
||||
`;
|
||||
const euiAccordionCss = ({ euiTheme }: UseEuiTheme) => ({
|
||||
'.euiAccordion__button': {
|
||||
color: euiTheme.colors.primary,
|
||||
},
|
||||
});
|
||||
|
||||
interface PackFormProps {
|
||||
defaultValue?: PackItem;
|
||||
|
@ -271,7 +270,8 @@ const PackFormComponent: React.FC<PackFormProps> = ({
|
|||
|
||||
<EuiFlexGroup>
|
||||
<EuiFlexItem css={overflowCss}>
|
||||
<StyledEuiAccordion
|
||||
<EuiAccordion
|
||||
css={euiAccordionCss}
|
||||
id="shardsToggle"
|
||||
forceState={shardsToggleState}
|
||||
onToggle={handleToggle}
|
||||
|
@ -279,7 +279,7 @@ const PackFormComponent: React.FC<PackFormProps> = ({
|
|||
>
|
||||
<EuiSpacer size="xs" />
|
||||
<PackShardsField options={availableOptions} />
|
||||
</StyledEuiAccordion>
|
||||
</EuiAccordion>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
<EuiSpacer size="m" />
|
||||
|
|
|
@ -10,7 +10,7 @@ import { FormattedMessage } from '@kbn/i18n-react';
|
|||
import type { EuiComboBoxProps, EuiComboBoxOptionOption } from '@elastic/eui';
|
||||
import { EuiComboBox, EuiFormRow, EuiFlexGroup, EuiFlexItem, EuiTextColor } from '@elastic/eui';
|
||||
import React, { useCallback, useMemo } from 'react';
|
||||
import styled from 'styled-components';
|
||||
import styled from '@emotion/styled';
|
||||
import deepEqual from 'fast-deep-equal';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { useController } from 'react-hook-form';
|
||||
|
@ -21,12 +21,9 @@ import { useAgentPolicies } from '../../agent_policies';
|
|||
// names/descriptions from overflowing the flex items
|
||||
// 2) max-width is built from the grow property on the flex items because the value
|
||||
// changes based on if Fleet is enabled/setup or not
|
||||
const AgentPolicyNameColumn = styled(EuiFlexItem)`
|
||||
max-width: ${(props) => `${((props.grow as number) / 9) * 100}%`};
|
||||
overflow: hidden;
|
||||
`;
|
||||
const AgentPolicyDescriptionColumn = styled(EuiFlexItem)`
|
||||
max-width: ${(props) => `${((props.grow as number) / 9) * 100}%`};
|
||||
|
||||
const StyledAgentPolicyColumn = styled(EuiFlexItem)`
|
||||
max-width: ${({ grow }) => ((grow as number) / 9) * 100};
|
||||
overflow: hidden;
|
||||
`;
|
||||
|
||||
|
@ -71,16 +68,16 @@ const PolicyIdComboBoxFieldComponent: React.FC<PolicyIdComboBoxFieldProps> = ({
|
|||
const renderOption = useCallback(
|
||||
(option: EuiComboBoxOptionOption<string>) => (
|
||||
<EuiFlexGroup>
|
||||
<AgentPolicyNameColumn grow={2}>
|
||||
<StyledAgentPolicyColumn grow={2}>
|
||||
<span className="eui-textTruncate">
|
||||
{(option.key && agentPoliciesById?.[option.key]?.name) ?? option.label}
|
||||
</span>
|
||||
</AgentPolicyNameColumn>
|
||||
<AgentPolicyDescriptionColumn grow={5}>
|
||||
</StyledAgentPolicyColumn>
|
||||
<StyledAgentPolicyColumn grow={5}>
|
||||
<EuiTextColor className="eui-textTruncate" color="subdued">
|
||||
{(option.key && agentPoliciesById?.[option.key].description) ?? ''}
|
||||
</EuiTextColor>
|
||||
</AgentPolicyDescriptionColumn>
|
||||
</StyledAgentPolicyColumn>
|
||||
<EuiFlexItem grow={2} className="eui-textRight">
|
||||
<EuiTextColor color="subdued">
|
||||
<FormattedMessage
|
||||
|
|
|
@ -8,14 +8,14 @@
|
|||
import { EuiCard, EuiFlexGroup, EuiFlexItem, EuiFormRow, EuiRadio } from '@elastic/eui';
|
||||
import React, { useCallback, useMemo } from 'react';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import styled from 'styled-components';
|
||||
import { noop } from 'lodash';
|
||||
import styled from '@emotion/styled';
|
||||
|
||||
const StyledEuiCard = styled(EuiCard)`
|
||||
padding: 16px 92px 16px 16px !important;
|
||||
border: ${(props) => {
|
||||
if (props.selectable?.isSelected) {
|
||||
return `1px solid ${props.theme.eui.euiColorPrimary}`;
|
||||
border: ${({ theme, selectable }) => {
|
||||
if (selectable?.isSelected) {
|
||||
return `${theme.euiTheme.border.width.thin} solid ${theme.euiTheme.colors.success}`;
|
||||
}
|
||||
}};
|
||||
|
||||
|
@ -30,7 +30,7 @@ const StyledEuiCard = styled(EuiCard)`
|
|||
.euiText {
|
||||
margin-top: 0;
|
||||
margin-left: 25px;
|
||||
color: ${(props) => props.theme.eui.EuiTextSubduedColor};
|
||||
color: ${({ theme }) => theme.euiTheme.colors.subduedText};
|
||||
}
|
||||
|
||||
> button[role='switch'] {
|
||||
|
|
|
@ -9,17 +9,12 @@ import React, { useCallback } from 'react';
|
|||
import { i18n } from '@kbn/i18n';
|
||||
import type { EuiComboBoxOptionOption } from '@elastic/eui';
|
||||
import { EuiButtonIcon, EuiFlexGroup, EuiFlexItem, EuiSpacer } from '@elastic/eui';
|
||||
import styled from 'styled-components';
|
||||
import type { UseFieldArrayRemove, UseFormReturn } from 'react-hook-form';
|
||||
import type { ShardsArray } from '../../../../common/utils/converters';
|
||||
import { ShardsPolicyField } from './shards_policy_field';
|
||||
import { ShardsPercentageField } from './shards_percentage_field';
|
||||
import { overflowCss } from '../../utils';
|
||||
|
||||
const StyledButtonWrapper = styled.div`
|
||||
margin-top: ${(props: { index: number }) => props.index === 0 && '16px'};
|
||||
`;
|
||||
|
||||
export type ShardsFormReturn = UseFormReturn<{ shardsArray: ShardsArray }>;
|
||||
|
||||
interface ShardsFormProps {
|
||||
|
@ -43,6 +38,11 @@ const ShardsFormComponent = ({
|
|||
}
|
||||
}, [index, onDelete]);
|
||||
|
||||
const buttonWrapperCss = useCallback(
|
||||
({ euiTheme }) => (index === 0 ? { marginTop: euiTheme.size.base } : {}),
|
||||
[index]
|
||||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
<EuiFlexGroup
|
||||
|
@ -65,7 +65,7 @@ const ShardsFormComponent = ({
|
|||
</EuiFlexItem>
|
||||
|
||||
<EuiFlexItem grow={false}>
|
||||
<StyledButtonWrapper index={index}>
|
||||
<div css={buttonWrapperCss}>
|
||||
<EuiButtonIcon
|
||||
aria-label={i18n.translate(
|
||||
'xpack.osquery.pack.form.deleteShardsRowButtonAriaLabel',
|
||||
|
@ -78,7 +78,7 @@ const ShardsFormComponent = ({
|
|||
disabled={isLastItem}
|
||||
onClick={handleDeleteClick}
|
||||
/>
|
||||
</StyledButtonWrapper>
|
||||
</div>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
</EuiFlexItem>
|
||||
|
|
|
@ -18,7 +18,6 @@ import {
|
|||
} from '@elastic/eui';
|
||||
import moment from 'moment-timezone';
|
||||
import React, { useCallback, useMemo, useState } from 'react';
|
||||
import styled from 'styled-components';
|
||||
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { useHistory } from 'react-router-dom';
|
||||
|
@ -28,11 +27,11 @@ import { ActiveStateSwitch } from './active_state_switch';
|
|||
import { AgentsPolicyLink } from '../agent_policies/agents_policy_link';
|
||||
import type { PackSavedObject } from './types';
|
||||
|
||||
const UpdatedBy = styled.span`
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
`;
|
||||
const updatedAtCss = {
|
||||
whiteSpace: 'nowrap' as const,
|
||||
overflow: 'hidden',
|
||||
textOverflow: 'ellipsis',
|
||||
};
|
||||
|
||||
const EMPTY_ARRAY: PackSavedObject[] = [];
|
||||
|
||||
|
@ -105,7 +104,7 @@ const PacksTableComponent = () => {
|
|||
|
||||
return updatedAt ? (
|
||||
<EuiToolTip content={`${moment(updatedAt).fromNow()}${updatedBy}`}>
|
||||
<UpdatedBy>{`${moment(updatedAt).fromNow()}${updatedBy}`}</UpdatedBy>
|
||||
<span css={updatedAtCss}>{`${moment(updatedAt).fromNow()}${updatedBy}`}</span>
|
||||
</EuiToolTip>
|
||||
) : (
|
||||
'-'
|
||||
|
|
59
x-pack/plugins/osquery/public/packs/queries/ecs_field_css.ts
Normal file
59
x-pack/plugins/osquery/public/packs/queries/ecs_field_css.ts
Normal file
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
export const resultComboBoxCss = {
|
||||
'&.euiComboBox': {
|
||||
position: 'relative',
|
||||
left: '-1px',
|
||||
|
||||
'.euiComboBox__inputWrap': {
|
||||
borderRadius: '0 6px 6px 0',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export const euiSuperSelectCss = {
|
||||
minWidth: '70px',
|
||||
borderRadius: '6px 0 0 6px',
|
||||
|
||||
'.euiIcon': {
|
||||
padding: 0,
|
||||
width: '18px',
|
||||
background: 'none',
|
||||
},
|
||||
};
|
||||
|
||||
export const fieldIconCss = {
|
||||
width: '32px',
|
||||
|
||||
'> svg': {
|
||||
padding: '0 6px !important',
|
||||
},
|
||||
};
|
||||
|
||||
export const fieldSpanCss = {
|
||||
paddingTop: '0 !important',
|
||||
paddingBottom: '0 !important',
|
||||
};
|
||||
|
||||
export const descriptionWrapperCss = {
|
||||
overflow: 'hidden',
|
||||
};
|
||||
|
||||
export const semicolonWrapperCss = {
|
||||
marginTop: '28px',
|
||||
};
|
||||
|
||||
// align the icon to the inputs
|
||||
export const buttonWrapperCss = {
|
||||
marginTop: '28px',
|
||||
width: '24px',
|
||||
};
|
||||
|
||||
export const ECSFieldWrapperCss = {
|
||||
maxWidth: '100%',
|
||||
};
|
|
@ -36,7 +36,6 @@ import {
|
|||
import sqliteParser from '@appland/sql-parser';
|
||||
import { FormattedMessage } from '@kbn/i18n-react';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import styled from 'styled-components';
|
||||
import deepEqual from 'fast-deep-equal';
|
||||
|
||||
import type { FieldErrors, UseFieldArrayRemove, UseFormReturn } from 'react-hook-form';
|
||||
|
@ -55,6 +54,16 @@ import { FieldIcon } from '../../common/lib/kibana';
|
|||
import { OsqueryIcon } from '../../components/osquery_icon';
|
||||
import { removeMultilines } from '../../../common/utils/build_query/remove_multilines';
|
||||
import { overflowCss } from '../utils';
|
||||
import {
|
||||
resultComboBoxCss,
|
||||
fieldSpanCss,
|
||||
fieldIconCss,
|
||||
buttonWrapperCss,
|
||||
descriptionWrapperCss,
|
||||
semicolonWrapperCss,
|
||||
ECSFieldWrapperCss,
|
||||
euiSuperSelectCss,
|
||||
} from './ecs_field_css';
|
||||
|
||||
export type ECSMappingFormReturn = UseFormReturn<{ ecsMappingArray: ECSMappingArray }>;
|
||||
|
||||
|
@ -77,61 +86,6 @@ const typeMap = {
|
|||
constant_keyword: 'string',
|
||||
};
|
||||
|
||||
// @ts-expect-error update types
|
||||
const ResultComboBox = styled(EuiComboBox)`
|
||||
&.euiComboBox {
|
||||
position: relative;
|
||||
left: -1px;
|
||||
|
||||
.euiComboBox__inputWrap {
|
||||
border-radius: 0 6px 6px 0;
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const StyledEuiSuperSelect = styled(EuiSuperSelect)`
|
||||
min-width: 70px;
|
||||
border-radius: 6px 0 0 6px;
|
||||
|
||||
.euiIcon {
|
||||
padding: 0;
|
||||
width: 18px;
|
||||
background: none;
|
||||
}
|
||||
`;
|
||||
|
||||
const StyledFieldIcon = styled(FieldIcon)`
|
||||
width: 32px;
|
||||
|
||||
> svg {
|
||||
padding: 0 6px !important;
|
||||
}
|
||||
`;
|
||||
|
||||
const StyledFieldSpan = styled.span`
|
||||
padding-top: 0 !important;
|
||||
padding-bottom: 0 !important;
|
||||
`;
|
||||
|
||||
const DescriptionWrapper = styled(EuiFlexItem)`
|
||||
overflow: hidden;
|
||||
`;
|
||||
|
||||
// align the icon to the inputs
|
||||
const StyledSemicolonWrapper = styled.div`
|
||||
margin-top: 28px;
|
||||
`;
|
||||
|
||||
// align the icon to the inputs
|
||||
const StyledButtonWrapper = styled.div`
|
||||
margin-top: 28px;
|
||||
width: 24px;
|
||||
`;
|
||||
|
||||
const ECSFieldWrapper = styled(EuiFlexItem)`
|
||||
max-width: 100%;
|
||||
`;
|
||||
|
||||
const SINGLE_SELECTION = { asPlainText: true };
|
||||
|
||||
const ECSSchemaOptions = ECSSchema.map((ecs) => ({
|
||||
|
@ -207,16 +161,19 @@ const ECSComboboxFieldComponent: React.FC<ECSComboboxFieldProps> = ({
|
|||
}
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={false}>
|
||||
<StyledFieldSpan className="euiSuggestItem__label euiSuggestItem__label--expand">
|
||||
<span css={fieldSpanCss} className="euiSuggestItem__label euiSuggestItem__label--expand">
|
||||
{option.value.field}
|
||||
</StyledFieldSpan>
|
||||
</span>
|
||||
</EuiFlexItem>
|
||||
|
||||
<DescriptionWrapper grow={false}>
|
||||
<StyledFieldSpan className="euiSuggestItem__description euiSuggestItem__description">
|
||||
<EuiFlexItem css={descriptionWrapperCss} grow={false}>
|
||||
<span
|
||||
css={fieldSpanCss}
|
||||
className="euiSuggestItem__description euiSuggestItem__description"
|
||||
>
|
||||
{option.value.description}
|
||||
</StyledFieldSpan>
|
||||
</DescriptionWrapper>
|
||||
</span>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
),
|
||||
[]
|
||||
|
@ -224,7 +181,8 @@ const ECSComboboxFieldComponent: React.FC<ECSComboboxFieldProps> = ({
|
|||
|
||||
const prepend = useMemo(
|
||||
() => (
|
||||
<StyledFieldIcon
|
||||
<FieldIcon
|
||||
css={fieldIconCss}
|
||||
size="l"
|
||||
type={
|
||||
// @ts-expect-error update types
|
||||
|
@ -435,15 +393,18 @@ const OsqueryColumnFieldComponent: React.FC<OsqueryColumnFieldProps> = ({
|
|||
gutterSize="none"
|
||||
>
|
||||
<EuiFlexItem grow={false}>
|
||||
<StyledFieldSpan className="euiSuggestItem__label euiSuggestItem__label--expand">
|
||||
<span css={fieldSpanCss} className="euiSuggestItem__label euiSuggestItem__label--expand">
|
||||
{option.value.suggestion_label}
|
||||
</StyledFieldSpan>
|
||||
</span>
|
||||
</EuiFlexItem>
|
||||
<DescriptionWrapper grow={false}>
|
||||
<StyledFieldSpan className="euiSuggestItem__description euiSuggestItem__description">
|
||||
<EuiFlexItem css={descriptionWrapperCss} grow={false}>
|
||||
<span
|
||||
css={fieldSpanCss}
|
||||
className="euiSuggestItem__description euiSuggestItem__description"
|
||||
>
|
||||
{option.value.description}
|
||||
</StyledFieldSpan>
|
||||
</DescriptionWrapper>
|
||||
</span>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
),
|
||||
[]
|
||||
|
@ -510,7 +471,8 @@ const OsqueryColumnFieldComponent: React.FC<OsqueryColumnFieldProps> = ({
|
|||
|
||||
const Prepend = useMemo(
|
||||
() => (
|
||||
<StyledEuiSuperSelect
|
||||
<EuiSuperSelect
|
||||
css={euiSuperSelectCss}
|
||||
disabled={euiFieldProps.isDisabled}
|
||||
options={OSQUERY_COLUMN_VALUE_TYPE_OPTIONS}
|
||||
data-test-subj={`osquery-result-type-select-${index}`}
|
||||
|
@ -577,7 +539,10 @@ const OsqueryColumnFieldComponent: React.FC<OsqueryColumnFieldProps> = ({
|
|||
{Prepend}
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem css={overflowCss}>
|
||||
<ResultComboBox
|
||||
{/* eslint-disable-next-line @typescript-eslint/ban-ts-comment */}
|
||||
{/* @ts-ignore*/}
|
||||
<EuiComboBox
|
||||
css={resultComboBoxCss}
|
||||
error={resultFieldState.error?.message}
|
||||
// eslint-disable-next-line react/jsx-no-bind, react-perf/jsx-no-new-function-as-prop
|
||||
inputRef={(ref: HTMLInputElement) => {
|
||||
|
@ -660,16 +625,14 @@ export const ECSMappingEditorForm: React.FC<ECSMappingEditorFormProps> = ({
|
|||
}}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={false}>
|
||||
<StyledSemicolonWrapper>
|
||||
<EuiText>:</EuiText>
|
||||
</StyledSemicolonWrapper>
|
||||
<EuiFlexItem grow={false} css={semicolonWrapperCss}>
|
||||
<EuiText>:</EuiText>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem css={overflowCss}>
|
||||
<EuiFlexGroup alignItems="flexStart" gutterSize="s" wrap>
|
||||
<ECSFieldWrapper>
|
||||
<EuiFlexItem css={ECSFieldWrapperCss}>
|
||||
<OsqueryColumnField
|
||||
control={control}
|
||||
watch={watch}
|
||||
|
@ -683,10 +646,10 @@ export const ECSMappingEditorForm: React.FC<ECSMappingEditorFormProps> = ({
|
|||
isDisabled,
|
||||
}}
|
||||
/>
|
||||
</ECSFieldWrapper>
|
||||
</EuiFlexItem>
|
||||
{!isDisabled && (
|
||||
<EuiFlexItem grow={false}>
|
||||
<StyledButtonWrapper>
|
||||
<div css={buttonWrapperCss}>
|
||||
{!isLastItem && (
|
||||
<EuiButtonIcon
|
||||
aria-label={i18n.translate(
|
||||
|
@ -700,7 +663,7 @@ export const ECSMappingEditorForm: React.FC<ECSMappingEditorFormProps> = ({
|
|||
onClick={handleDeleteClick}
|
||||
/>
|
||||
)}
|
||||
</StyledButtonWrapper>
|
||||
</div>
|
||||
</EuiFlexItem>
|
||||
)}
|
||||
</EuiFlexGroup>
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
*/
|
||||
|
||||
import { get, isEmpty, isArray, isObject, isEqual, keys, map, reduce } from 'lodash/fp';
|
||||
import { css } from '@emotion/react';
|
||||
import type {
|
||||
EuiDataGridSorting,
|
||||
EuiDataGridProps,
|
||||
|
@ -29,7 +28,6 @@ import { FormattedMessage } from '@kbn/i18n-react';
|
|||
import React, { createContext, useEffect, useState, useCallback, useContext, useMemo } from 'react';
|
||||
import type { ECSMapping } from '@kbn/osquery-io-ts-types';
|
||||
import { pagePathGetters } from '@kbn/fleet-plugin/public';
|
||||
import styled from 'styled-components';
|
||||
import { AddToTimelineButton } from '../timelines/add_to_timeline_button';
|
||||
import { useAllResults } from './use_all_results';
|
||||
import type { ResultEdges } from '../../common/search_strategy';
|
||||
|
@ -48,14 +46,18 @@ import { AddToCaseWrapper } from '../cases/add_to_cases';
|
|||
|
||||
const DataContext = createContext<ResultEdges>([]);
|
||||
|
||||
const StyledEuiDataGrid = styled(EuiDataGrid)`
|
||||
:not(.euiDataGrid--fullScreen) {
|
||||
.euiDataGrid__virtualized {
|
||||
height: 100% !important;
|
||||
max-height: 500px;
|
||||
}
|
||||
}
|
||||
`;
|
||||
const euiDataGridCss = {
|
||||
':not(.euiDataGrid--fullScreen)': {
|
||||
'.euiDataGrid__virtualized': {
|
||||
height: '100% !important',
|
||||
maxHeight: '500px',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const euiProgressCss = {
|
||||
marginTop: '-2px',
|
||||
};
|
||||
|
||||
export interface ResultsTableComponentProps {
|
||||
actionId: string;
|
||||
|
@ -425,15 +427,7 @@ const ResultsTableComponent: React.FC<ResultsTableComponentProps> = ({
|
|||
|
||||
return (
|
||||
<>
|
||||
{isLive && (
|
||||
<EuiProgress
|
||||
color="primary"
|
||||
size="xs"
|
||||
css={css`
|
||||
margin-top: -2px;
|
||||
`}
|
||||
/>
|
||||
)}
|
||||
{isLive && <EuiProgress color="primary" size="xs" css={euiProgressCss} />}
|
||||
|
||||
{!allResultsData?.edges.length ? (
|
||||
<EuiPanel hasShadow={false} data-test-subj={'osqueryResultsPanel'}>
|
||||
|
@ -441,7 +435,8 @@ const ResultsTableComponent: React.FC<ResultsTableComponentProps> = ({
|
|||
</EuiPanel>
|
||||
) : (
|
||||
<DataContext.Provider value={allResultsData?.edges}>
|
||||
<StyledEuiDataGrid
|
||||
<EuiDataGrid
|
||||
css={euiDataGridCss}
|
||||
data-test-subj="osqueryResultsTable"
|
||||
aria-label="Osquery results"
|
||||
columns={columns}
|
||||
|
|
|
@ -8,18 +8,17 @@
|
|||
import React from 'react';
|
||||
import { EuiEmptyPrompt, EuiPanel, EuiSpacer } from '@elastic/eui';
|
||||
import { FormattedMessage } from '@kbn/i18n-react';
|
||||
import styled from 'styled-components';
|
||||
|
||||
const Panel = styled(EuiPanel)`
|
||||
max-width: 500px;
|
||||
margin-right: auto;
|
||||
margin-left: auto;
|
||||
`;
|
||||
const panelCss = {
|
||||
maxWidth: '500px',
|
||||
marginRight: 'auto',
|
||||
marginLeft: 'auto',
|
||||
};
|
||||
|
||||
const MissingPrivilegesComponent = () => (
|
||||
<div>
|
||||
<EuiSpacer />
|
||||
<Panel>
|
||||
<EuiPanel css={panelCss}>
|
||||
<EuiEmptyPrompt
|
||||
iconType="securityApp"
|
||||
title={
|
||||
|
@ -39,7 +38,7 @@ const MissingPrivilegesComponent = () => (
|
|||
</p>
|
||||
}
|
||||
/>
|
||||
</Panel>
|
||||
</EuiPanel>
|
||||
<EuiSpacer />
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -10,16 +10,15 @@ import { FormattedMessage } from '@kbn/i18n-react';
|
|||
import React, { useLayoutEffect, useMemo, useState } from 'react';
|
||||
import { useParams } from 'react-router-dom';
|
||||
|
||||
import styled from 'styled-components';
|
||||
import { useRouterNavigate } from '../../../common/lib/kibana';
|
||||
import { WithHeaderLayout } from '../../../components/layouts';
|
||||
import { useLiveQueryDetails } from '../../../actions/use_live_query_details';
|
||||
import { useBreadcrumbs } from '../../../common/hooks/use_breadcrumbs';
|
||||
import { PackQueriesStatusTable } from '../../../live_queries/form/pack_queries_status_table';
|
||||
|
||||
const StyledTableWrapper = styled(EuiFlexItem)`
|
||||
padding-left: 10px;
|
||||
`;
|
||||
const tableWrapperCss = {
|
||||
paddingLeft: '10px',
|
||||
};
|
||||
|
||||
const LiveQueryDetailsPageComponent = () => {
|
||||
const { actionId } = useParams<{ actionId: string }>();
|
||||
|
@ -60,7 +59,7 @@ const LiveQueryDetailsPageComponent = () => {
|
|||
|
||||
return (
|
||||
<WithHeaderLayout leftColumn={LeftColumn} rightColumnGrow={false}>
|
||||
<StyledTableWrapper>
|
||||
<EuiFlexItem css={tableWrapperCss}>
|
||||
<PackQueriesStatusTable
|
||||
actionId={actionId}
|
||||
data={data?.queries}
|
||||
|
@ -69,7 +68,7 @@ const LiveQueryDetailsPageComponent = () => {
|
|||
agentIds={data?.agents}
|
||||
showResultsHeader
|
||||
/>
|
||||
</StyledTableWrapper>
|
||||
</EuiFlexItem>
|
||||
</WithHeaderLayout>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -16,10 +16,10 @@ import {
|
|||
EuiSpacer,
|
||||
EuiText,
|
||||
} from '@elastic/eui';
|
||||
import type { UseEuiTheme } from '@elastic/eui';
|
||||
import { FormattedMessage } from '@kbn/i18n-react';
|
||||
import React, { useMemo } from 'react';
|
||||
import { useParams } from 'react-router-dom';
|
||||
import styled from 'styled-components';
|
||||
|
||||
import { useKibana, useRouterNavigate } from '../../../common/lib/kibana';
|
||||
import { WithHeaderLayout } from '../../../components/layouts';
|
||||
|
@ -29,11 +29,11 @@ import { useBreadcrumbs } from '../../../common/hooks/use_breadcrumbs';
|
|||
import { useAgentPolicyAgentIds } from '../../../agents/use_agent_policy_agent_ids';
|
||||
import { AgentPoliciesPopover } from '../../../packs/packs_table';
|
||||
|
||||
const Divider = styled.div`
|
||||
width: 0;
|
||||
height: 100%;
|
||||
border-left: ${({ theme }) => theme.eui.euiBorderThin};
|
||||
`;
|
||||
const dividerCss = ({ euiTheme }: UseEuiTheme) => ({
|
||||
width: 0,
|
||||
height: '100%',
|
||||
borderLeft: euiTheme.border.thin,
|
||||
});
|
||||
|
||||
const PackDetailsPageComponent = () => {
|
||||
const permissions = useKibana().services.application.capabilities.osquery;
|
||||
|
@ -112,7 +112,7 @@ const PackDetailsPageComponent = () => {
|
|||
</EuiDescriptionList>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={false} key="agents_failed_count_divider">
|
||||
<Divider />
|
||||
<div css={dividerCss} />
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={false} key="edit_button">
|
||||
<EuiButton
|
||||
|
|
|
@ -76,6 +76,7 @@ const EditSavedQueryFormComponent: React.FC<EditSavedQueryFormProps> = ({
|
|||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiButton
|
||||
data-test-subj="savedQueryFormUpdateButton"
|
||||
isLoading={isSubmitting}
|
||||
color="primary"
|
||||
fill
|
||||
|
|
|
@ -19,16 +19,15 @@ import React, { useCallback, useMemo, useState } from 'react';
|
|||
import { FormattedMessage } from '@kbn/i18n-react';
|
||||
import { useParams } from 'react-router-dom';
|
||||
|
||||
import styled from 'styled-components';
|
||||
import { useKibana, useRouterNavigate } from '../../../common/lib/kibana';
|
||||
import { WithHeaderLayout } from '../../../components/layouts';
|
||||
import { useBreadcrumbs } from '../../../common/hooks/use_breadcrumbs';
|
||||
import { EditSavedQueryForm } from './form';
|
||||
import { useDeleteSavedQuery, useUpdateSavedQuery, useSavedQuery } from '../../../saved_queries';
|
||||
|
||||
const StyledEuiCallOut = styled(EuiCallOut)`
|
||||
margin: 10px;
|
||||
`;
|
||||
const euiCalloutCss = {
|
||||
margin: '10px',
|
||||
};
|
||||
|
||||
const EditSavedQueryPageComponent = () => {
|
||||
const permissions = useKibana().services.application.capabilities.osquery;
|
||||
|
@ -88,12 +87,12 @@ const EditSavedQueryPageComponent = () => {
|
|||
}}
|
||||
/>
|
||||
{elasticPrebuiltQuery && (
|
||||
<StyledEuiCallOut size="s">
|
||||
<EuiCallOut css={euiCalloutCss} size="s">
|
||||
<FormattedMessage
|
||||
id="xpack.osquery.viewSavedQuery.prebuiltInfo"
|
||||
defaultMessage="This is a prebuilt Elastic query, and it cannot be edited."
|
||||
/>
|
||||
</StyledEuiCallOut>
|
||||
</EuiCallOut>
|
||||
)}
|
||||
</>
|
||||
) : (
|
||||
|
|
|
@ -9,15 +9,14 @@ import { EuiTabbedContent, EuiNotificationBadge } from '@elastic/eui';
|
|||
import React, { useMemo } from 'react';
|
||||
import type { ECSMapping } from '@kbn/osquery-io-ts-types';
|
||||
|
||||
import styled from 'styled-components';
|
||||
import { ResultsTable } from '../../../results/results_table';
|
||||
import { ActionResultsSummary } from '../../../action_results/action_results_summary';
|
||||
|
||||
const StyledEuiTabbedContent = styled(EuiTabbedContent)`
|
||||
div.euiTabs {
|
||||
padding-left: 8px;
|
||||
}
|
||||
`;
|
||||
const euiTabbedContentCss = {
|
||||
'div.euiTabs': {
|
||||
paddingLeft: '8px',
|
||||
},
|
||||
};
|
||||
|
||||
interface ResultTabsProps {
|
||||
actionId: string;
|
||||
|
@ -90,7 +89,8 @@ const ResultTabsComponent: React.FC<ResultTabsProps> = ({
|
|||
);
|
||||
|
||||
return (
|
||||
<StyledEuiTabbedContent
|
||||
<EuiTabbedContent
|
||||
css={euiTabbedContentCss}
|
||||
// TODO: extend the EuiTabbedContent component to support EuiTabs props
|
||||
// bottomBorder={false}
|
||||
tabs={tabs}
|
||||
|
|
|
@ -8,16 +8,15 @@
|
|||
import { isEmpty } from 'lodash/fp';
|
||||
import { EuiCodeBlock, EuiFormRow } from '@elastic/eui';
|
||||
import React from 'react';
|
||||
import styled from 'styled-components';
|
||||
|
||||
import { useController } from 'react-hook-form';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { OsquerySchemaLink } from '../../components/osquery_schema_link';
|
||||
import { OsqueryEditor } from '../../editor';
|
||||
|
||||
const StyledEuiCodeBlock = styled(EuiCodeBlock)`
|
||||
min-height: 100px;
|
||||
`;
|
||||
const euiCodeBlockCss = {
|
||||
minHeight: '100px',
|
||||
};
|
||||
|
||||
interface CodeEditorFieldProps {
|
||||
euiFieldProps?: Record<string, unknown>;
|
||||
|
@ -58,14 +57,15 @@ const CodeEditorFieldComponent: React.FC<CodeEditorFieldProps> = ({
|
|||
fullWidth
|
||||
>
|
||||
{euiFieldProps?.isDisabled ? (
|
||||
<StyledEuiCodeBlock
|
||||
<EuiCodeBlock
|
||||
css={euiCodeBlockCss}
|
||||
language="sql"
|
||||
fontSize="m"
|
||||
paddingSize="m"
|
||||
transparentBackground={!value.length}
|
||||
>
|
||||
{value}
|
||||
</StyledEuiCodeBlock>
|
||||
</EuiCodeBlock>
|
||||
) : (
|
||||
<OsqueryEditor defaultValue={value} onChange={onChange} />
|
||||
)}
|
||||
|
|
|
@ -7,18 +7,17 @@
|
|||
|
||||
import { EuiFlyout, EuiFlyoutHeader, EuiTitle, EuiFlyoutBody } from '@elastic/eui';
|
||||
import React, { useMemo } from 'react';
|
||||
import styled from 'styled-components';
|
||||
import { FormattedMessage } from '@kbn/i18n-react';
|
||||
|
||||
import { useFormContext } from 'react-hook-form';
|
||||
import { LiveQuery } from '../../live_queries';
|
||||
|
||||
const StyledEuiFlyoutHeader = styled(EuiFlyoutHeader)`
|
||||
&.euiFlyoutHeader {
|
||||
padding-top: 21px;
|
||||
padding-bottom: 20px;
|
||||
}
|
||||
`;
|
||||
const euiFlyoutHeaderCss = {
|
||||
'&.euiFlyoutHeader': {
|
||||
paddingTop: '21px',
|
||||
paddingBottom: '20px',
|
||||
},
|
||||
};
|
||||
|
||||
interface PlaygroundFlyoutProps {
|
||||
enabled?: boolean;
|
||||
|
@ -36,7 +35,7 @@ const PlaygroundFlyoutComponent: React.FC<PlaygroundFlyoutProps> = ({ enabled, o
|
|||
|
||||
return (
|
||||
<EuiFlyout type="push" size="m" onClose={onClose} data-test-subj={'osquery-save-query-flyout'}>
|
||||
<StyledEuiFlyoutHeader hasBorder>
|
||||
<EuiFlyoutHeader css={euiFlyoutHeaderCss} hasBorder>
|
||||
<EuiTitle size="s">
|
||||
<h5>
|
||||
<FormattedMessage
|
||||
|
@ -45,7 +44,7 @@ const PlaygroundFlyoutComponent: React.FC<PlaygroundFlyoutProps> = ({ enabled, o
|
|||
/>
|
||||
</h5>
|
||||
</EuiTitle>
|
||||
</StyledEuiFlyoutHeader>
|
||||
</EuiFlyoutHeader>
|
||||
<EuiFlyoutBody>
|
||||
<LiveQuery
|
||||
enabled={enabled && query !== ''}
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
import { find } from 'lodash/fp';
|
||||
import { EuiCodeBlock, EuiFormRow, EuiComboBox, EuiTextColor } from '@elastic/eui';
|
||||
import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import styled from 'styled-components';
|
||||
import { useWatch, useFormContext } from 'react-hook-form';
|
||||
import { QUERIES_DROPDOWN_LABEL, QUERIES_DROPDOWN_SEARCH_FIELD_LABEL } from './constants';
|
||||
import { OsquerySchemaLink } from '../components/osquery_schema_link';
|
||||
|
@ -16,16 +15,11 @@ import { OsquerySchemaLink } from '../components/osquery_schema_link';
|
|||
import { useSavedQueries } from './use_saved_queries';
|
||||
import type { SavedQuerySO } from '../routes/saved_queries/list';
|
||||
|
||||
const TextTruncate = styled.div`
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
`;
|
||||
|
||||
const StyledEuiCodeBlock = styled(EuiCodeBlock)`
|
||||
.euiCodeBlock__line {
|
||||
white-space: nowrap;
|
||||
}
|
||||
`;
|
||||
const euiCodeBlockCss = {
|
||||
'.euiCodeBlock__line': {
|
||||
whiteSpace: 'nowrap' as const,
|
||||
},
|
||||
};
|
||||
|
||||
export interface SavedQueriesDropdownProps {
|
||||
disabled?: boolean;
|
||||
|
@ -96,12 +90,12 @@ const SavedQueriesDropdownComponent: React.FC<SavedQueriesDropdownProps> = ({
|
|||
({ value }) => (
|
||||
<>
|
||||
<strong>{value.id}</strong>
|
||||
<TextTruncate>
|
||||
<div className="eui-textTruncate">
|
||||
<EuiTextColor color="subdued">{value.description}</EuiTextColor>
|
||||
</TextTruncate>
|
||||
<StyledEuiCodeBlock language="sql" fontSize="m" paddingSize="s">
|
||||
</div>
|
||||
<EuiCodeBlock css={euiCodeBlockCss} language="sql" fontSize="m" paddingSize="s">
|
||||
{value.query.split('\n').join(' ')}
|
||||
</StyledEuiCodeBlock>
|
||||
</EuiCodeBlock>
|
||||
</>
|
||||
),
|
||||
[]
|
||||
|
|
|
@ -95,7 +95,12 @@ const SavedQueryFlyoutComponent: React.FC<AddQueryFlyoutProps> = ({
|
|||
</EuiButtonEmpty>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiButton isLoading={isSubmitting} onClick={handleSubmit(onSubmit)} fill>
|
||||
<EuiButton
|
||||
data-test-subj="savedQueryFlyoutSaveButton"
|
||||
isLoading={isSubmitting}
|
||||
onClick={handleSubmit(onSubmit)}
|
||||
fill
|
||||
>
|
||||
<FormattedMessage
|
||||
id="xpack.osquery.pack.queryFlyoutForm.saveButtonLabel"
|
||||
defaultMessage="Save"
|
||||
|
|
|
@ -6,8 +6,6 @@
|
|||
*/
|
||||
|
||||
import React, { lazy, Suspense } from 'react';
|
||||
import { QueryClientProvider } from '@tanstack/react-query';
|
||||
import { queryClient } from '../query_client';
|
||||
import type { OsqueryResponseActionsParamsFormProps } from './osquery_response_action_type';
|
||||
|
||||
const OsqueryResponseActionParamsForm = lazy(() => import('./osquery_response_action_type'));
|
||||
|
@ -19,13 +17,11 @@ export const getLazyOsqueryResponseActionTypeForm =
|
|||
|
||||
return (
|
||||
<Suspense fallback={null}>
|
||||
<QueryClientProvider client={queryClient}>
|
||||
<OsqueryResponseActionParamsForm
|
||||
onChange={onChange}
|
||||
defaultValues={defaultValues}
|
||||
onError={onError}
|
||||
/>
|
||||
</QueryClientProvider>
|
||||
<OsqueryResponseActionParamsForm
|
||||
onChange={onChange}
|
||||
defaultValues={defaultValues}
|
||||
onError={onError}
|
||||
/>
|
||||
</Suspense>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -18,6 +18,8 @@
|
|||
"../../../typings/**/*",
|
||||
// ECS and Osquery schema files
|
||||
"public/common/schemas/*/**.json",
|
||||
// Emotion theme typing
|
||||
"./emotion.d.ts"
|
||||
],
|
||||
"kbn_references": [
|
||||
"@kbn/core",
|
||||
|
@ -43,7 +45,6 @@
|
|||
"@kbn/utility-types",
|
||||
"@kbn/securitysolution-io-ts-utils",
|
||||
"@kbn/osquery-io-ts-types",
|
||||
"@kbn/ui-theme",
|
||||
"@kbn/i18n-react",
|
||||
"@kbn/discover-plugin",
|
||||
"@kbn/lens-plugin",
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue