[Defend workflows] [On-week] Migrate osquery from styled-components to @emotion (#161179)

This commit is contained in:
Tomasz Ciecierski 2023-08-02 19:18:10 +02:00 committed by GitHub
parent 41e5df703a
commit ffb716d8af
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
42 changed files with 505 additions and 495 deletions

View file

@ -14,7 +14,7 @@ module.exports = {
USES_STYLED_COMPONENTS: [ USES_STYLED_COMPONENTS: [
/packages[\/\\]kbn-ui-shared-deps-(npm|src)[\/\\]/, /packages[\/\\]kbn-ui-shared-deps-(npm|src)[\/\\]/,
/src[\/\\]plugins[\/\\](kibana_react)[\/\\]/, /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[\/\\]test[\/\\]plugin_functional[\/\\]plugins[\/\\]resolver_test[\/\\]/,
/x-pack[\/\\]packages[\/\\]elastic_assistant[\/\\]/, /x-pack[\/\\]packages[\/\\]elastic_assistant[\/\\]/,
/x-pack[\/\\]packages[\/\\]security-solution[\/\\]ecs_data_quality_dashboard[\/\\]/, /x-pack[\/\\]packages[\/\\]security-solution[\/\\]ecs_data_quality_dashboard[\/\\]/,

View file

@ -8,6 +8,8 @@
import { EuiLoadingSpinner } from '@elastic/eui'; import { EuiLoadingSpinner } from '@elastic/eui';
import type { ReactNode } from 'react'; import type { ReactNode } from 'react';
import React, { lazy, Suspense } 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'; import type { CasesContextProps } from '../../components/cases_context';
export type GetCasesContextPropsInternal = CasesContextProps; export type GetCasesContextPropsInternal = CasesContextProps;
@ -32,21 +34,25 @@ const CasesProviderLazyWrapper = ({
releasePhase, releasePhase,
getFilesClient, getFilesClient,
}: GetCasesContextPropsInternal & { children: ReactNode }) => { }: GetCasesContextPropsInternal & { children: ReactNode }) => {
const isDarkTheme = useIsDarkTheme();
return ( return (
<Suspense fallback={<EuiLoadingSpinner />}> <Suspense fallback={<EuiLoadingSpinner />}>
<CasesProviderLazy <StyledComponentsThemeProvider darkMode={isDarkTheme}>
value={{ <CasesProviderLazy
externalReferenceAttachmentTypeRegistry, value={{
persistableStateAttachmentTypeRegistry, externalReferenceAttachmentTypeRegistry,
owner, persistableStateAttachmentTypeRegistry,
permissions, owner,
features, permissions,
releasePhase, features,
getFilesClient, releasePhase,
}} getFilesClient,
> }}
{children} >
</CasesProviderLazy> {children}
</CasesProviderLazy>
</StyledComponentsThemeProvider>
</Suspense> </Suspense>
); );
}; };

View file

@ -49,7 +49,12 @@ export const checkResults = () => {
export const typeInECSFieldInput = (text: string, index = 0) => export const typeInECSFieldInput = (text: string, index = 0) =>
cy.getBySel('ECS-field-input').eq(index).type(text); cy.getBySel('ECS-field-input').eq(index).type(text);
export const typeInOsqueryFieldInput = (text: string, index = 0) => 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) => { export const getOsqueryFieldTypes = (value: 'Osquery value' | 'Static value', index = 0) => {
cy.getBySel(`osquery-result-type-select-${index}`).click(); cy.getBySel(`osquery-result-type-select-${index}`).click();

View file

@ -86,7 +86,7 @@ export const getSavedQueriesComplexTest = () =>
cy.contains('Save query'); cy.contains('Save query');
findFormFieldByRowsLabelAndType('ID', savedQueryId); findFormFieldByRowsLabelAndType('ID', savedQueryId);
findFormFieldByRowsLabelAndType('Description (optional)', savedQueryDescription); findFormFieldByRowsLabelAndType('Description (optional)', savedQueryDescription);
cy.react('EuiButtonDisplay').contains('Save').click(); cy.getBySel('savedQueryFlyoutSaveButton').click();
cy.contains('Successfully saved'); cy.contains('Successfully saved');
closeToastIfVisible(); closeToastIfVisible();
@ -120,10 +120,12 @@ export const getSavedQueriesComplexTest = () =>
inputQuery('{selectall}{backspace}{selectall}{backspace}'); inputQuery('{selectall}{backspace}{selectall}{backspace}');
cy.contains('Query is a required field'); cy.contains('Query is a required field');
inputQuery(BIG_QUERY); inputQuery(BIG_QUERY);
cy.contains('Query is a required field').should('not.exist');
}); });
// Save edited // Save edited
cy.react('EuiButton').contains('Update query').click(); cy.getBySel('euiFlyoutCloseButton').click();
cy.getBySel('savedQueryFormUpdateButton').click();
cy.contains(`${savedQueryDescription} Edited`); cy.contains(`${savedQueryDescription} Edited`);
// delete saved query // delete saved query

14
x-pack/plugins/osquery/emotion.d.ts vendored Normal file
View 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 {}
}

View file

@ -5,22 +5,19 @@
* 2.0. * 2.0.
*/ */
import styled from 'styled-components';
import { EuiColorPaletteDisplay } from '@elastic/eui'; import { EuiColorPaletteDisplay } from '@elastic/eui';
import React, { useMemo } from 'react'; import React, { useMemo } from 'react';
import { AGENT_STATUSES, getColorForAgentStatus } from './services/agent_status'; import { AGENT_STATUSES, getColorForAgentStatus } from './services/agent_status';
import type { ActionAgentStatus } from './types'; import type { ActionAgentStatus } from './types';
const StyledEuiColorPaletteDisplay = styled(EuiColorPaletteDisplay)` const euiColorPaletteDisplayCss = {
&.osquery-action-agent-status-bar { border: 'none',
border: none; borderRadius: 0,
border-radius: 0; '&:after': {
&:after { border: 'none',
border: none; },
} };
}
`;
export const AgentStatusBar: React.FC<{ export const AgentStatusBar: React.FC<{
agentStatus: { [k in ActionAgentStatus]: number }; agentStatus: { [k in ActionAgentStatus]: number };
@ -39,11 +36,5 @@ export const AgentStatusBar: React.FC<{
}, [] as Array<{ stop: number; color: string }>); }, [] as Array<{ stop: number; color: string }>);
}, [agentStatus]); }, [agentStatus]);
return ( return <EuiColorPaletteDisplay css={euiColorPaletteDisplayCss} size="s" palette={palette} />;
<StyledEuiColorPaletteDisplay
className="osquery-action-agent-status-bar"
size="s"
palette={palette}
/>
);
}; };

View file

@ -7,18 +7,17 @@
import { EuiLink } from '@elastic/eui'; import { EuiLink } from '@elastic/eui';
import React, { useCallback, useMemo } from 'react'; import React, { useCallback, useMemo } from 'react';
import styled from 'styled-components';
import { PLUGIN_ID } from '@kbn/fleet-plugin/common'; import { PLUGIN_ID } from '@kbn/fleet-plugin/common';
import { pagePathGetters } from '@kbn/fleet-plugin/public'; import { pagePathGetters } from '@kbn/fleet-plugin/public';
import { useKibana, isModifiedEvent, isLeftClickEvent } from '../common/lib/kibana'; import { useKibana, isModifiedEvent, isLeftClickEvent } from '../common/lib/kibana';
import { useAgentPolicy } from './use_agent_policy'; import { useAgentPolicy } from './use_agent_policy';
const StyledEuiLink = styled(EuiLink)` const euiLinkCss = {
white-space: nowrap; whiteSpace: 'nowrap' as const,
text-overflow: ellipsis; textOverflow: 'ellipsis',
overflow: hidden; overflow: 'hidden',
`; };
interface AgentsPolicyLinkProps { interface AgentsPolicyLinkProps {
policyId: string; policyId: string;
@ -52,9 +51,10 @@ const AgentsPolicyLinkComponent: React.FC<AgentsPolicyLinkProps> = ({ policyId }
); );
return ( 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} {data?.name ?? policyId}
</StyledEuiLink> </EuiLink>
); );
}; };

View file

@ -6,40 +6,21 @@
*/ */
import { EuiErrorBoundary } from '@elastic/eui'; import { EuiErrorBoundary } from '@elastic/eui';
import { euiLightVars, euiDarkVars } from '@kbn/ui-theme'; import React from 'react';
import React, { useMemo } from 'react';
import ReactDOM from 'react-dom'; import ReactDOM from 'react-dom';
import { Router } from '@kbn/shared-ux-router'; import { Router } from '@kbn/shared-ux-router';
import { I18nProvider } from '@kbn/i18n-react'; import { I18nProvider } from '@kbn/i18n-react';
import { ThemeProvider } from 'styled-components';
import { QueryClientProvider } from '@tanstack/react-query'; import { QueryClientProvider } from '@tanstack/react-query';
import { ReactQueryDevtools } from '@tanstack/react-query-devtools'; import { ReactQueryDevtools } from '@tanstack/react-query-devtools';
import type { Storage } from '@kbn/kibana-utils-plugin/public'; import type { Storage } from '@kbn/kibana-utils-plugin/public';
import type { AppMountParameters, CoreStart } from '@kbn/core/public'; import type { AppMountParameters, CoreStart } from '@kbn/core/public';
import { useUiSetting$, KibanaThemeProvider } from './shared_imports';
import type { AppPluginStartDependencies } from './types'; import type { AppPluginStartDependencies } from './types';
import { OsqueryApp } from './components/app'; 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 { KibanaContextProvider } from './common/lib/kibana';
import { queryClient } from './query_client'; import { queryClient } from './query_client';
import { KibanaThemeProvider } from './shared_imports';
const OsqueryAppContext = () => {
const [darkMode] = useUiSetting$<boolean>(DEFAULT_DARK_MODE);
const theme = useMemo(
() => ({
eui: darkMode ? euiDarkVars : euiLightVars,
darkMode,
}),
[darkMode]
);
return (
<ThemeProvider theme={theme}>
<OsqueryApp />
</ThemeProvider>
);
};
export const renderApp = ( export const renderApp = (
core: CoreStart, core: CoreStart,
@ -64,7 +45,7 @@ export const renderApp = (
<Router history={history}> <Router history={history}>
<I18nProvider> <I18nProvider>
<QueryClientProvider client={queryClient}> <QueryClientProvider client={queryClient}>
<OsqueryAppContext /> <OsqueryApp />
<ReactQueryDevtools initialIsOpen={false} /> <ReactQueryDevtools initialIsOpen={false} />
</QueryClientProvider> </QueryClientProvider>
</I18nProvider> </I18nProvider>

View file

@ -11,13 +11,13 @@ import {
EuiLoadingSpinner, EuiLoadingSpinner,
EuiPage, EuiPage,
EuiPageBody, EuiPageBody,
EuiPageContent_Deprecated as EuiPageContent, EuiPageSection,
} from '@elastic/eui'; } from '@elastic/eui';
import { useKibana } from '@kbn/kibana-react-plugin/public'; import { useKibana } from '@kbn/kibana-react-plugin/public';
import useObservable from 'react-use/lib/useObservable'; import useObservable from 'react-use/lib/useObservable';
import { of } from 'rxjs'; import { of } from 'rxjs';
import { Container, Wrapper } from './layouts'; import { containerCss, wrapperCss } from './layouts/default';
import { OsqueryAppRoutes } from '../routes'; import { OsqueryAppRoutes } from '../routes';
import { useOsqueryIntegrationStatus } from '../common/hooks'; import { useOsqueryIntegrationStatus } from '../common/hooks';
import { OsqueryAppEmptyState } from './empty_state'; import { OsqueryAppEmptyState } from './empty_state';
@ -31,19 +31,13 @@ const OsqueryAppComponent = () => {
return ( return (
<EuiPage paddingSize="none"> <EuiPage paddingSize="none">
<EuiPageBody> <EuiPageBody>
<EuiPageContent <EuiPageSection paddingSize="none" color="subdued">
verticalPosition="center"
horizontalPosition="center"
paddingSize="none"
color="subdued"
hasShadow={false}
>
{hasCustomBranding ? ( {hasCustomBranding ? (
<EuiLoadingSpinner size="xxl" /> <EuiLoadingSpinner size="xxl" />
) : ( ) : (
<EuiLoadingElastic size="xxl" /> <EuiLoadingElastic size="xxl" />
)} )}
</EuiPageContent> </EuiPageSection>
</EuiPageBody> </EuiPageBody>
</EuiPage> </EuiPage>
); );
@ -54,12 +48,12 @@ const OsqueryAppComponent = () => {
} }
return ( return (
<Container id="osquery-app"> <div css={containerCss} id="osquery-app">
<Wrapper> <div css={wrapperCss}>
<MainNavigation /> <MainNavigation />
<OsqueryAppRoutes /> <OsqueryAppRoutes />
</Wrapper> </div>
</Container> </div>
); );
}; };

View file

@ -5,30 +5,26 @@
* 2.0. * 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` export const wrapperCss = {
min-height: calc( display: 'flex',
100vh - ${(props) => parseFloat(props.theme.eui.euiHeaderHeightCompensation) * 2}px flexDirection: 'column' as const,
); flex: 1,
background: ${(props) => props.theme.eui.euiColorEmptyShade}; };
display: flex;
flex-direction: column;
`;
export const Wrapper = styled.div` export const navCss = ({ euiTheme }: UseEuiTheme) => ({
display: flex; background: euiTheme.colors.emptyShade,
flex-direction: column; borderBottom: euiTheme.border.thin,
flex: 1; padding: `${euiTheme.size.base} ${euiTheme.size.l} ${euiTheme.size.base} ${euiTheme.size.l}`,
`; '.euiTabs': {
paddingLeft: '3px',
export const Nav = styled.nav` marginLeft: '-3px',
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;
}
`;

View file

@ -7,32 +7,24 @@
// copied from x-pack/plugins/fleet/public/applications/fleet/components/header.tsx // copied from x-pack/plugins/fleet/public/applications/fleet/components/header.tsx
import React, { memo } from 'react'; import React, { memo, useCallback } from 'react';
import styled from 'styled-components';
import { EuiFlexGroup, EuiFlexItem, EuiTabs, EuiTab, EuiSpacer } from '@elastic/eui'; 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 { Props as EuiTabProps } from '@elastic/eui/src/components/tabs/tab';
import type { EuiFlexItemProps } from '@elastic/eui/src/components/flex/flex_item'; import type { EuiFlexItemProps } from '@elastic/eui/src/components/flex/flex_item';
import { css } from '@emotion/react';
const Container = styled.div` const containerCss = ({ euiTheme }: UseEuiTheme) => ({
border-bottom: ${(props) => props.theme.eui.euiBorderThin}; borderBottom: euiTheme.border.thin,
background-color: ${(props) => props.theme.eui.euiPageBackgroundColor}; backgroundColor: euiTheme.colors.body,
`; });
const Wrapper = styled.div<{ maxWidth?: number }>` const tabsCss = {
max-width: ${(props) => props.maxWidth || 1200}px; top: '1px',
margin-left: auto; '&:before': {
margin-right: auto; height: '0px',
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;
}
`;
export interface HeaderProps { export interface HeaderProps {
children?: React.ReactNode; children?: React.ReactNode;
@ -65,35 +57,50 @@ const HeaderComponent: React.FC<HeaderProps> = ({
maxWidth, maxWidth,
tabsClassName, tabsClassName,
'data-test-subj': dataTestSubj, 'data-test-subj': dataTestSubj,
}) => ( }) => {
<Container data-test-subj={dataTestSubj}> const wrapperCss = useCallback(
<Wrapper maxWidth={maxWidth}> ({ euiTheme }: UseEuiTheme) => css`
<HeaderColumns max-width: ${maxWidth || 1200}px;
leftColumn={leftColumn} margin-left: auto;
rightColumn={rightColumn} margin-right: auto;
rightColumnGrow={rightColumnGrow} padding-top: ${euiTheme.size.xl};
/> padding-left: ${euiTheme.size.m};
{children} padding-right: ${euiTheme.size.m};
<EuiFlexGroup> `,
{tabs ? (
<EuiFlexItem> [maxWidth]
<EuiSpacer size="s" /> );
<Tabs className={tabsClassName}>
{tabs.map((props) => ( return (
<EuiTab {...(props as EuiTabProps)} key={props.id}> <div css={containerCss} data-test-subj={dataTestSubj}>
{props.name} <div css={wrapperCss}>
</EuiTab> <HeaderColumns
))} leftColumn={leftColumn}
</Tabs> rightColumn={rightColumn}
</EuiFlexItem> rightColumnGrow={rightColumnGrow}
) : ( />
<EuiFlexItem> {children}
<EuiSpacer size="l" /> <EuiFlexGroup>
</EuiFlexItem> {tabs ? (
)} <EuiFlexItem>
</EuiFlexGroup> <EuiSpacer size="s" />
</Wrapper> <EuiTabs className={tabsClassName} css={tabsCss}>
</Container> {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); export const Header = React.memo(HeaderComponent);

View file

@ -7,7 +7,7 @@
// copied from x-pack/plugins/fleet/public/applications/fleet/layouts/index.tsx // 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 type { WithHeaderLayoutProps } from './with_header';
export { WithHeaderLayout } from './with_header'; export { WithHeaderLayout } from './with_header';
export { WithoutHeaderLayout } from './without_header'; export { WithoutHeaderLayout } from './without_header';

View file

@ -6,11 +6,12 @@
*/ */
import React, { Fragment } from 'react'; import React, { Fragment } from 'react';
import { EuiPageBody, EuiSpacer } from '@elastic/eui'; import { EuiPage, EuiPageBody, EuiSpacer } from '@elastic/eui';
import type { HeaderProps } from './header'; import type { HeaderProps } from './header';
import { Header } 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 { export interface WithHeaderLayoutProps extends HeaderProps {
restrictWidth?: number; restrictWidth?: number;
@ -36,16 +37,17 @@ export const WithHeaderLayout: React.FC<WithHeaderLayoutProps> = ({
> >
{headerChildren} {headerChildren}
</Header> </Header>
<Page <EuiPage
css={pageCss}
restrictWidth={restrictWidth || 1200} restrictWidth={restrictWidth || 1200}
data-test-subj={dataTestSubj ? `${dataTestSubj}_page` : undefined} data-test-subj={dataTestSubj ? `${dataTestSubj}_page` : undefined}
> >
<EuiPageBody> <EuiPageBody>
<ContentWrapper> <div css={contentCss}>
<EuiSpacer size="l" /> <EuiSpacer size="l" />
{children} {children}
</ContentWrapper> </div>
</EuiPageBody> </EuiPageBody>
</Page> </EuiPage>
</Fragment> </Fragment>
); );

View file

@ -6,21 +6,21 @@
*/ */
import React, { Fragment } from 'react'; import React, { Fragment } from 'react';
import styled from 'styled-components';
import { EuiPage, EuiPageBody, EuiSpacer } from '@elastic/eui'; import { EuiPage, EuiPageBody, EuiSpacer } from '@elastic/eui';
import type { UseEuiTheme } from '@elastic/eui';
export const Page = styled(EuiPage)` export const pageCss = ({ euiTheme }: UseEuiTheme) => ({
background: ${(props) => props.theme.eui.euiColorEmptyShade}; background: euiTheme.colors.emptyShade,
width: 100%; width: '100%',
align-self: center; alignSelf: 'center',
margin-left: 0; marginLeft: 0,
margin-right: 0; marginRight: 0,
flex: 1; flex: 1,
`; });
export const ContentWrapper = styled.div` export const contentCss = {
height: 100%; height: '100%',
`; };
interface Props { interface Props {
restrictWidth?: number; restrictWidth?: number;
@ -29,13 +29,13 @@ interface Props {
export const WithoutHeaderLayout: React.FC<Props> = ({ restrictWidth, children }) => ( export const WithoutHeaderLayout: React.FC<Props> = ({ restrictWidth, children }) => (
<Fragment> <Fragment>
<Page restrictWidth={restrictWidth || 1200}> <EuiPage css={pageCss} restrictWidth={restrictWidth || 1200}>
<EuiPageBody> <EuiPageBody>
<ContentWrapper> <div css={contentCss}>
<EuiSpacer size="m" /> <EuiSpacer size="m" />
{children} {children}
</ContentWrapper> </div>
</EuiPageBody> </EuiPageBody>
</Page> </EuiPage>
</Fragment> </Fragment>
); );

View file

@ -9,9 +9,9 @@ import React, { useMemo } from 'react';
import { FormattedMessage } from '@kbn/i18n-react'; import { FormattedMessage } from '@kbn/i18n-react';
import { EuiButtonEmpty, EuiFlexGroup, EuiFlexItem, EuiTab, EuiTabs } from '@elastic/eui'; import { EuiButtonEmpty, EuiFlexGroup, EuiFlexItem, EuiTab, EuiTabs } from '@elastic/eui';
import { useLocation } from 'react-router-dom'; import { useLocation } from 'react-router-dom';
import { navCss } from './layouts/default';
import { useRouterNavigate } from '../common/lib/kibana'; import { useRouterNavigate } from '../common/lib/kibana';
import { ManageIntegrationLink } from './manage_integration_link'; import { ManageIntegrationLink } from './manage_integration_link';
import { Nav } from './layouts';
enum Section { enum Section {
LiveQueries = 'live_queries', LiveQueries = 'live_queries',
@ -24,7 +24,7 @@ export const MainNavigation = () => {
const section = useMemo(() => location.pathname.split('/')[1] ?? 'overview', [location.pathname]); const section = useMemo(() => location.pathname.split('/')[1] ?? 'overview', [location.pathname]);
return ( return (
<Nav> <div css={navCss}>
<EuiFlexGroup gutterSize="l" alignItems="center"> <EuiFlexGroup gutterSize="l" alignItems="center">
<EuiFlexItem> <EuiFlexItem>
<EuiTabs bottomBorder={false}> <EuiTabs bottomBorder={false}>
@ -72,6 +72,6 @@ export const MainNavigation = () => {
</EuiFlexGroup> </EuiFlexGroup>
</EuiFlexItem> </EuiFlexItem>
</EuiFlexGroup> </EuiFlexGroup>
</Nav> </div>
); );
}; };

View file

@ -15,12 +15,12 @@ import {
EuiCallOut, EuiCallOut,
EuiLink, EuiLink,
EuiAccordion, EuiAccordion,
useEuiTheme,
} from '@elastic/eui'; } from '@elastic/eui';
import React, { useCallback, useEffect, useMemo, useState } from 'react'; import React, { useCallback, useEffect, useMemo, useState } from 'react';
import { produce } from 'immer'; import { produce } from 'immer';
import { i18n } from '@kbn/i18n'; import { i18n } from '@kbn/i18n';
import useDebounce from 'react-use/lib/useDebounce'; import useDebounce from 'react-use/lib/useDebounce';
import styled from 'styled-components';
import type { AgentPolicy } from '@kbn/fleet-plugin/common'; import type { AgentPolicy } from '@kbn/fleet-plugin/common';
import { agentRouteService, agentPolicyRouteService, PLUGIN_ID } 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 CommonUseField = getUseField({ component: Field });
const StyledEuiAccordion = styled(EuiAccordion)`
.euiAccordion__button {
color: ${({ theme }) => theme.eui.euiColorPrimary};
}
`;
/** /**
* Exports Osquery-specific package policy instructions * Exports Osquery-specific package policy instructions
* for use in the Fleet app create / edit package policy * for use in the Fleet app create / edit package policy
@ -343,6 +337,17 @@ export const OsqueryManagedPolicyCreateImportExtension = React.memo<
const { permissionDenied } = useFetchStatus(); const { permissionDenied } = useFetchStatus();
const { euiTheme } = useEuiTheme();
const euiAccordionCss = useMemo(
() => ({
'.euiAccordion__button': {
color: euiTheme.colors.primary,
},
}),
[euiTheme]
);
return ( return (
<> <>
{!editMode ? <DisabledCallout /> : null} {!editMode ? <DisabledCallout /> : null}
@ -373,7 +378,8 @@ export const OsqueryManagedPolicyCreateImportExtension = React.memo<
<> <>
<NavigationButtons isDisabled={!editMode} agentPolicyId={policy?.policy_id} /> <NavigationButtons isDisabled={!editMode} agentPolicyId={policy?.policy_id} />
<EuiSpacer size="xxl" /> <EuiSpacer size="xxl" />
<StyledEuiAccordion <EuiAccordion
css={euiAccordionCss}
id="advanced" id="advanced"
buttonContent={i18n.translate( buttonContent={i18n.translate(
'xpack.osquery.fleetIntegration.osqueryConfig.accordionFieldLabel', 'xpack.osquery.fleetIntegration.osqueryConfig.accordionFieldLabel',
@ -387,7 +393,7 @@ export const OsqueryManagedPolicyCreateImportExtension = React.memo<
<CommonUseField path="config" /> <CommonUseField path="config" />
<ConfigUploader onChange={handleConfigUpload} /> <ConfigUploader onChange={handleConfigUpload} />
</Form> </Form>
</StyledEuiAccordion> </EuiAccordion>
</> </>
)} )}
</> </>

View file

@ -6,10 +6,9 @@
*/ */
import { isEmpty } from 'lodash'; 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 { EuiCodeBlock, EuiFormRow, EuiAccordion, EuiSpacer } from '@elastic/eui';
import React, { useCallback, useMemo, useState } from 'react'; import React, { useCallback, useMemo, useState } from 'react';
import styled from 'styled-components';
import { useController, useFormContext } from 'react-hook-form'; import { useController, useFormContext } from 'react-hook-form';
import { i18n } from '@kbn/i18n'; import { i18n } from '@kbn/i18n';
import type { LiveQueryFormFields } from '.'; 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 type { SavedQueriesDropdownProps } from '../../saved_queries/saved_queries_dropdown';
import { SavedQueriesDropdown } from '../../saved_queries/saved_queries_dropdown'; import { SavedQueriesDropdown } from '../../saved_queries/saved_queries_dropdown';
const StyledEuiAccordion = styled(EuiAccordion)` const euiCodeBlockCss = {
${({ isDisabled }: { isDisabled?: boolean }) => isDisabled && 'display: none;'} minHeight: '100px',
.euiAccordion__button { };
color: ${({ theme }) => theme.eui.euiColorPrimary};
}
.euiAccordion__childWrapper {
-webkit-transition: none;
}
`;
const StyledEuiCodeBlock = styled(EuiCodeBlock)` const euiAccordionCss = ({ euiTheme }: UseEuiTheme) => ({
min-height: 100px; '.euiAccordion__button': {
`; color: euiTheme.colors.primary,
},
'.euiAccordion__childWrapper': {
'-webkit-transition': 'none',
},
});
export interface LiveQueryQueryFieldProps { export interface LiveQueryQueryFieldProps {
handleSubmitForm?: () => void; handleSubmitForm?: () => void;
@ -131,14 +129,15 @@ const LiveQueryQueryFieldComponent: React.FC<LiveQueryQueryFieldProps> = ({
isDisabled={!permissions.writeLiveQueries || disabled} isDisabled={!permissions.writeLiveQueries || disabled}
> >
{!permissions.writeLiveQueries || disabled ? ( {!permissions.writeLiveQueries || disabled ? (
<StyledEuiCodeBlock <EuiCodeBlock
css={euiCodeBlockCss}
language="sql" language="sql"
fontSize="m" fontSize="m"
paddingSize="m" paddingSize="m"
transparentBackground={!value.length} transparentBackground={!value.length}
> >
{value} {value}
</StyledEuiCodeBlock> </EuiCodeBlock>
) : ( ) : (
<OsqueryEditor defaultValue={value} onChange={onChange} commands={commands} /> <OsqueryEditor defaultValue={value} onChange={onChange} commands={commands} />
)} )}
@ -147,7 +146,8 @@ const LiveQueryQueryFieldComponent: React.FC<LiveQueryQueryFieldProps> = ({
<EuiSpacer size="m" /> <EuiSpacer size="m" />
{!isAdvancedToggleHidden && ( {!isAdvancedToggleHidden && (
<StyledEuiAccordion <EuiAccordion
css={euiAccordionCss}
id="advanced" id="advanced"
forceState={advancedContentState} forceState={advancedContentState}
onToggle={handleToggle} onToggle={handleToggle}
@ -156,7 +156,7 @@ const LiveQueryQueryFieldComponent: React.FC<LiveQueryQueryFieldProps> = ({
> >
<EuiSpacer size="xs" /> <EuiSpacer size="xs" />
<ECSMappingEditorField euiFieldProps={ecsFieldProps} /> <ECSMappingEditorField euiFieldProps={ecsFieldProps} />
</StyledEuiAccordion> </EuiAccordion>
)} )}
</> </>
); );

View file

@ -21,7 +21,6 @@ import {
EuiText, EuiText,
} from '@elastic/eui'; } from '@elastic/eui';
import { i18n } from '@kbn/i18n'; import { i18n } from '@kbn/i18n';
import styled from 'styled-components';
import type { ECSMapping } from '@kbn/osquery-io-ts-types'; import type { ECSMapping } from '@kbn/osquery-io-ts-types';
import { QueryDetailsFlyout } from './query_details_flyout'; import { QueryDetailsFlyout } from './query_details_flyout';
import { PackResultsHeader } from './pack_results_header'; 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 { AddToCaseWrapper } from '../../cases/add_to_cases';
import { AddToTimelineButton } from '../../timelines/add_to_timeline_button'; import { AddToTimelineButton } from '../../timelines/add_to_timeline_button';
const TruncateTooltipText = styled.div` const truncateTooltipTextCss = {
width: 100%; width: '100%',
> span { '> span': {
overflow: hidden; overflow: 'hidden',
text-overflow: ellipsis; textOverflow: 'ellipsis',
white-space: nowrap; whiteSpace: 'nowrap' as const,
} },
`; };
const StyledEuiFlexItem = styled(EuiFlexItem)` const euiFlexItemCss = {
cursor: pointer; 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[] = []; 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 { export enum ViewResultsActionButtonType {
icon = 'icon', icon = 'icon',
button = 'button', button = 'button',
@ -165,14 +164,16 @@ const PackQueriesStatusTableComponent: React.FC<PackQueriesStatusTableProps> = (
); );
const handleQueryFlyoutClose = useCallback(() => setQueryDetailsFlyoutOpen(null), []); const handleQueryFlyoutClose = useCallback(() => setQueryDetailsFlyoutOpen(null), []);
const [itemIdToExpandedRowMap, setItemIdToExpandedRowMap] = useState<Record<string, unknown>>({}); const [itemIdToExpandedRowMap, setItemIdToExpandedRowMap] = useState<
Record<string, React.ReactNode>
>({});
const renderIDColumn = useCallback( const renderIDColumn = useCallback(
(id: string) => ( (id: string) => (
<TruncateTooltipText> <div css={truncateTooltipTextCss}>
<EuiToolTip content={id} display="block"> <EuiToolTip content={id} display="block">
<>{id}</> <>{id}</>
</EuiToolTip> </EuiToolTip>
</TruncateTooltipText> </div>
), ),
[] []
); );
@ -183,11 +184,11 @@ const PackQueriesStatusTableComponent: React.FC<PackQueriesStatusTableProps> = (
const content = singleLine.length > 55 ? `${singleLine.substring(0, 55)}...` : singleLine; const content = singleLine.length > 55 ? `${singleLine.substring(0, 55)}...` : singleLine;
return ( return (
<StyledEuiFlexItem onClick={handleQueryFlyoutOpen(item)}> <EuiFlexItem css={euiFlexItemCss} onClick={handleQueryFlyoutOpen(item)}>
<EuiCodeBlock language="sql" fontSize="s" paddingSize="none" transparentBackground> <EuiCodeBlock language="sql" fontSize="s" paddingSize="none" transparentBackground>
{content} {content}
</EuiCodeBlock> </EuiCodeBlock>
</StyledEuiFlexItem> </EuiFlexItem>
); );
}, },
[handleQueryFlyoutOpen] [handleQueryFlyoutOpen]
@ -264,7 +265,7 @@ const PackQueriesStatusTableComponent: React.FC<PackQueriesStatusTableProps> = (
[data, getHandleErrorsToggle, itemIdToExpandedRowMap] [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( const renderResultActions = useCallback(
(row: { action_id: string }) => { (row: { action_id: string }) => {
@ -329,6 +330,7 @@ const PackQueriesStatusTableComponent: React.FC<PackQueriesStatusTableProps> = (
width: '40%', width: '40%',
}, },
{ {
field: '',
name: i18n.translate('xpack.osquery.pack.queriesTable.docsResultsColumnTitle', { name: i18n.translate('xpack.osquery.pack.queriesTable.docsResultsColumnTitle', {
defaultMessage: 'Docs', defaultMessage: 'Docs',
}), }),
@ -336,6 +338,7 @@ const PackQueriesStatusTableComponent: React.FC<PackQueriesStatusTableProps> = (
render: renderDocsColumn, render: renderDocsColumn,
}, },
{ {
field: '',
name: i18n.translate('xpack.osquery.pack.queriesTable.agentsResultsColumnTitle', { name: i18n.translate('xpack.osquery.pack.queriesTable.agentsResultsColumnTitle', {
defaultMessage: 'Agents', defaultMessage: 'Agents',
}), }),
@ -343,6 +346,7 @@ const PackQueriesStatusTableComponent: React.FC<PackQueriesStatusTableProps> = (
render: renderAgentsColumn, render: renderAgentsColumn,
}, },
{ {
field: '',
name: i18n.translate('xpack.osquery.pack.queriesTable.viewResultsColumnTitle', { name: i18n.translate('xpack.osquery.pack.queriesTable.viewResultsColumnTitle', {
defaultMessage: 'View results', defaultMessage: 'View results',
}), }),
@ -350,6 +354,7 @@ const PackQueriesStatusTableComponent: React.FC<PackQueriesStatusTableProps> = (
render: renderResultActions, render: renderResultActions,
}, },
{ {
field: '',
id: 'actions', id: 'actions',
width: '45px', width: '45px',
isVisuallyHiddenLabel: true, isVisuallyHiddenLabel: true,
@ -373,7 +378,7 @@ const PackQueriesStatusTableComponent: React.FC<PackQueriesStatusTableProps> = (
const sorting = useMemo( const sorting = useMemo(
() => ({ () => ({
sort: { sort: {
field: 'id' as keyof PackItem, field: 'id' as const,
direction: Direction.asc, direction: Direction.asc,
}, },
}), }),
@ -407,8 +412,8 @@ const PackQueriesStatusTableComponent: React.FC<PackQueriesStatusTableProps> = (
agentIds={agentIds} agentIds={agentIds}
/> />
)} )}
<EuiBasicTable
<StyledEuiBasicTable css={euiBasicTableCss}
items={data ?? EMPTY_ARRAY} items={data ?? EMPTY_ARRAY}
itemId={getItemId} itemId={getItemId}
columns={columns} columns={columns}

View file

@ -5,9 +5,9 @@
* 2.0. * 2.0.
*/ */
import React, { useMemo } from 'react'; import React, { useMemo } from 'react';
import type { UseEuiTheme } from '@elastic/eui';
import { EuiFlexGroup, EuiFlexItem, EuiSpacer, EuiText } from '@elastic/eui'; import { EuiFlexGroup, EuiFlexItem, EuiSpacer, EuiText } from '@elastic/eui';
import { FormattedMessage } from '@kbn/i18n-react'; import { FormattedMessage } from '@kbn/i18n-react';
import styled from 'styled-components';
import { AddToTimelineButton } from '../../timelines/add_to_timeline_button'; import { AddToTimelineButton } from '../../timelines/add_to_timeline_button';
import { AddToCaseWrapper } from '../../cases/add_to_cases'; import { AddToCaseWrapper } from '../../cases/add_to_cases';
@ -17,16 +17,16 @@ interface PackResultsHeadersProps {
agentIds?: string[]; agentIds?: string[];
} }
const StyledResultsHeading = styled(EuiFlexItem)` const resultsHeadingCss = ({ euiTheme }: UseEuiTheme) => ({
padding-right: 20px; paddingRight: '20px',
border-right: 2px solid #d3dae6; borderRight: euiTheme.border.thick,
`; });
const StyledIconsList = styled(EuiFlexItem)` const iconsListCss = {
align-content: center; alignContent: 'center',
justify-content: center; justifyContent: 'center',
padding-left: 10px; paddingLeft: '10px',
`; };
export const PackResultsHeader = React.memo<PackResultsHeadersProps>( export const PackResultsHeader = React.memo<PackResultsHeadersProps>(
({ actionId, agentIds, queryIds }) => { ({ actionId, agentIds, queryIds }) => {
@ -36,7 +36,7 @@ export const PackResultsHeader = React.memo<PackResultsHeadersProps>(
<> <>
<EuiSpacer size={'l'} /> <EuiSpacer size={'l'} />
<EuiFlexGroup direction="row" gutterSize="m"> <EuiFlexGroup direction="row" gutterSize="m">
<StyledResultsHeading grow={false}> <EuiFlexItem css={resultsHeadingCss} grow={false}>
<EuiText> <EuiText>
<h2> <h2>
<FormattedMessage <FormattedMessage
@ -45,8 +45,8 @@ export const PackResultsHeader = React.memo<PackResultsHeadersProps>(
/> />
</h2> </h2>
</EuiText> </EuiText>
</StyledResultsHeading> </EuiFlexItem>
<StyledIconsList grow={false}> <EuiFlexItem css={iconsListCss} grow={false}>
<span> <span>
{actionId && ( {actionId && (
<EuiFlexGroup> <EuiFlexGroup>
@ -69,7 +69,7 @@ export const PackResultsHeader = React.memo<PackResultsHeadersProps>(
</EuiFlexGroup> </EuiFlexGroup>
)} )}
</span> </span>
</StyledIconsList> </EuiFlexItem>
</EuiFlexGroup> </EuiFlexGroup>
<EuiSpacer size={'l'} /> <EuiSpacer size={'l'} />
</> </>

View file

@ -10,16 +10,10 @@ import React, { useCallback, useEffect, useMemo, useState } from 'react';
import { i18n } from '@kbn/i18n'; import { i18n } from '@kbn/i18n';
import type { EuiComboBoxOptionOption } from '@elastic/eui'; import type { EuiComboBoxOptionOption } from '@elastic/eui';
import { EuiFormRow, EuiComboBox, EuiTextColor, EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; import { EuiFormRow, EuiComboBox, EuiTextColor, EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
import styled from 'styled-components';
import { useController } from 'react-hook-form'; import { useController } from 'react-hook-form';
import type { PackSavedObject } from '../../packs/types'; import type { PackSavedObject } from '../../packs/types';
const TextTruncate = styled.div`
overflow: hidden;
text-overflow: ellipsis;
`;
interface PackComboBoxFieldProps { interface PackComboBoxFieldProps {
fieldProps?: { fieldProps?: {
packsData?: PackSavedObject[]; packsData?: PackSavedObject[];
@ -103,9 +97,9 @@ export const PacksComboBoxField = ({
<strong>{option?.name}</strong> <strong>{option?.name}</strong>
</EuiFlexItem> </EuiFlexItem>
<EuiFlexItem> <EuiFlexItem>
<TextTruncate> <div className="eui-textTruncate">
<EuiTextColor color="subdued">{option?.description}</EuiTextColor> <EuiTextColor color="subdued">{option?.description}</EuiTextColor>
</TextTruncate> </div>
</EuiFlexItem> </EuiFlexItem>
</EuiFlexGroup> </EuiFlexGroup>
), ),

View file

@ -8,16 +8,16 @@
import { EuiCard, EuiFlexGroup, EuiFlexItem, EuiFormRow } from '@elastic/eui'; import { EuiCard, EuiFlexGroup, EuiFlexItem, EuiFormRow } from '@elastic/eui';
import React, { useCallback, useMemo } from 'react'; import React, { useCallback, useMemo } from 'react';
import { i18n } from '@kbn/i18n'; import { i18n } from '@kbn/i18n';
import styled from 'styled-components';
import { useController } from 'react-hook-form'; import { useController } from 'react-hook-form';
import styled from '@emotion/styled';
const StyledEuiCard = styled(EuiCard)` const StyledEuiCard = styled(EuiCard)`
padding: 0; padding: 0;
display: flex; display: flex;
flex-direction: row; flex-direction: row;
border: ${(props) => { border: ${({ theme, selectable }) => {
if (props.selectable?.isSelected) { if (selectable?.isSelected) {
return `1px solid ${props.theme.eui.euiColorSuccess}`; return `${theme.euiTheme.border.width.thin} solid ${theme.euiTheme.colors.success}`;
} }
}}; }};
.euiCard__content { .euiCard__content {
@ -28,7 +28,7 @@ const StyledEuiCard = styled(EuiCard)`
} }
.euiText { .euiText {
margin-top: 0; margin-top: 0;
color: ${(props) => props.theme.eui.euiTextSubduedColor}; color: ${({ theme }) => theme.euiTheme.colors.subduedText};
} }
> button[role='switch'] { > button[role='switch'] {
@ -51,6 +51,7 @@ const StyledEuiCard = styled(EuiCard)`
} }
} }
`; `;
interface QueryPackSelectableProps { interface QueryPackSelectableProps {
canRunSingleQuery: boolean; canRunSingleQuery: boolean;
canRunPacks: boolean; canRunPacks: boolean;

View file

@ -6,9 +6,9 @@
*/ */
import { EuiSwitch, EuiLoadingSpinner } from '@elastic/eui'; import { EuiSwitch, EuiLoadingSpinner } from '@elastic/eui';
import type { UseEuiTheme } from '@elastic/eui';
import React, { useCallback, useMemo, useState } from 'react'; import React, { useCallback, useMemo, useState } from 'react';
import { useQueryClient } from '@tanstack/react-query'; import { useQueryClient } from '@tanstack/react-query';
import styled from 'styled-components';
import { i18n } from '@kbn/i18n'; import { i18n } from '@kbn/i18n';
import { useKibana } from '../common/lib/kibana'; import { useKibana } from '../common/lib/kibana';
@ -19,9 +19,9 @@ import { useUpdatePack } from './use_update_pack';
import { PACKS_ID } from './constants'; import { PACKS_ID } from './constants';
import type { PackSavedObject } from './types'; import type { PackSavedObject } from './types';
const StyledEuiLoadingSpinner = styled(EuiLoadingSpinner)` const euiLoadingSpinnerCss = ({ euiTheme }: UseEuiTheme) => ({
margin-right: ${({ theme }) => theme.eui.euiSizeS}; marginRight: euiTheme.size.s,
`; });
interface ActiveStateSwitchProps { interface ActiveStateSwitchProps {
disabled?: boolean; disabled?: boolean;
@ -91,7 +91,7 @@ const ActiveStateSwitchComponent: React.FC<ActiveStateSwitchProps> = ({ item })
return ( return (
<> <>
{isLoading && <StyledEuiLoadingSpinner />} {isLoading && <EuiLoadingSpinner css={euiLoadingSpinnerCss} />}
<EuiSwitch <EuiSwitch
checked={!!item.enabled} checked={!!item.enabled}
disabled={!permissions.writePacks || isLoading} disabled={!permissions.writePacks || isLoading}

View file

@ -7,6 +7,7 @@
import { filter, isEmpty, map, omit, reduce } from 'lodash'; import { filter, isEmpty, map, omit, reduce } from 'lodash';
import type { EuiAccordionProps } from '@elastic/eui'; import type { EuiAccordionProps } from '@elastic/eui';
import type { UseEuiTheme } from '@elastic/eui';
import { import {
EuiFlexGroup, EuiFlexGroup,
EuiFlexItem, EuiFlexItem,
@ -22,7 +23,6 @@ import { FormattedMessage } from '@kbn/i18n-react';
import deepEqual from 'fast-deep-equal'; import deepEqual from 'fast-deep-equal';
import { FormProvider, useForm as useHookForm } from 'react-hook-form'; import { FormProvider, useForm as useHookForm } from 'react-hook-form';
import styled from 'styled-components';
import { PackShardsField } from './shards/pack_shards_field'; import { PackShardsField } from './shards/pack_shards_field';
import { useRouterNavigate } from '../../common/lib/kibana'; import { useRouterNavigate } from '../../common/lib/kibana';
import { PolicyIdComboBoxField } from './policy_id_combobox_field'; import { PolicyIdComboBoxField } from './policy_id_combobox_field';
@ -41,12 +41,11 @@ import { overflowCss } from '../utils';
type PackFormData = Omit<PackItem, 'id' | 'queries'> & { queries: PackQueryFormData[] }; type PackFormData = Omit<PackItem, 'id' | 'queries'> & { queries: PackQueryFormData[] };
const StyledEuiAccordion = styled(EuiAccordion)` const euiAccordionCss = ({ euiTheme }: UseEuiTheme) => ({
${({ isDisabled }: { isDisabled?: boolean }) => isDisabled && 'display: none;'} '.euiAccordion__button': {
.euiAccordion__button { color: euiTheme.colors.primary,
color: ${({ theme }) => theme.eui.euiColorPrimary}; },
} });
`;
interface PackFormProps { interface PackFormProps {
defaultValue?: PackItem; defaultValue?: PackItem;
@ -271,7 +270,8 @@ const PackFormComponent: React.FC<PackFormProps> = ({
<EuiFlexGroup> <EuiFlexGroup>
<EuiFlexItem css={overflowCss}> <EuiFlexItem css={overflowCss}>
<StyledEuiAccordion <EuiAccordion
css={euiAccordionCss}
id="shardsToggle" id="shardsToggle"
forceState={shardsToggleState} forceState={shardsToggleState}
onToggle={handleToggle} onToggle={handleToggle}
@ -279,7 +279,7 @@ const PackFormComponent: React.FC<PackFormProps> = ({
> >
<EuiSpacer size="xs" /> <EuiSpacer size="xs" />
<PackShardsField options={availableOptions} /> <PackShardsField options={availableOptions} />
</StyledEuiAccordion> </EuiAccordion>
</EuiFlexItem> </EuiFlexItem>
</EuiFlexGroup> </EuiFlexGroup>
<EuiSpacer size="m" /> <EuiSpacer size="m" />

View file

@ -10,7 +10,7 @@ import { FormattedMessage } from '@kbn/i18n-react';
import type { EuiComboBoxProps, EuiComboBoxOptionOption } from '@elastic/eui'; import type { EuiComboBoxProps, EuiComboBoxOptionOption } from '@elastic/eui';
import { EuiComboBox, EuiFormRow, EuiFlexGroup, EuiFlexItem, EuiTextColor } from '@elastic/eui'; import { EuiComboBox, EuiFormRow, EuiFlexGroup, EuiFlexItem, EuiTextColor } from '@elastic/eui';
import React, { useCallback, useMemo } from 'react'; import React, { useCallback, useMemo } from 'react';
import styled from 'styled-components'; import styled from '@emotion/styled';
import deepEqual from 'fast-deep-equal'; import deepEqual from 'fast-deep-equal';
import { i18n } from '@kbn/i18n'; import { i18n } from '@kbn/i18n';
import { useController } from 'react-hook-form'; import { useController } from 'react-hook-form';
@ -21,12 +21,9 @@ import { useAgentPolicies } from '../../agent_policies';
// names/descriptions from overflowing the flex items // names/descriptions from overflowing the flex items
// 2) max-width is built from the grow property on the flex items because the value // 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 // changes based on if Fleet is enabled/setup or not
const AgentPolicyNameColumn = styled(EuiFlexItem)`
max-width: ${(props) => `${((props.grow as number) / 9) * 100}%`}; const StyledAgentPolicyColumn = styled(EuiFlexItem)`
overflow: hidden; max-width: ${({ grow }) => ((grow as number) / 9) * 100};
`;
const AgentPolicyDescriptionColumn = styled(EuiFlexItem)`
max-width: ${(props) => `${((props.grow as number) / 9) * 100}%`};
overflow: hidden; overflow: hidden;
`; `;
@ -71,16 +68,16 @@ const PolicyIdComboBoxFieldComponent: React.FC<PolicyIdComboBoxFieldProps> = ({
const renderOption = useCallback( const renderOption = useCallback(
(option: EuiComboBoxOptionOption<string>) => ( (option: EuiComboBoxOptionOption<string>) => (
<EuiFlexGroup> <EuiFlexGroup>
<AgentPolicyNameColumn grow={2}> <StyledAgentPolicyColumn grow={2}>
<span className="eui-textTruncate"> <span className="eui-textTruncate">
{(option.key && agentPoliciesById?.[option.key]?.name) ?? option.label} {(option.key && agentPoliciesById?.[option.key]?.name) ?? option.label}
</span> </span>
</AgentPolicyNameColumn> </StyledAgentPolicyColumn>
<AgentPolicyDescriptionColumn grow={5}> <StyledAgentPolicyColumn grow={5}>
<EuiTextColor className="eui-textTruncate" color="subdued"> <EuiTextColor className="eui-textTruncate" color="subdued">
{(option.key && agentPoliciesById?.[option.key].description) ?? ''} {(option.key && agentPoliciesById?.[option.key].description) ?? ''}
</EuiTextColor> </EuiTextColor>
</AgentPolicyDescriptionColumn> </StyledAgentPolicyColumn>
<EuiFlexItem grow={2} className="eui-textRight"> <EuiFlexItem grow={2} className="eui-textRight">
<EuiTextColor color="subdued"> <EuiTextColor color="subdued">
<FormattedMessage <FormattedMessage

View file

@ -8,14 +8,14 @@
import { EuiCard, EuiFlexGroup, EuiFlexItem, EuiFormRow, EuiRadio } from '@elastic/eui'; import { EuiCard, EuiFlexGroup, EuiFlexItem, EuiFormRow, EuiRadio } from '@elastic/eui';
import React, { useCallback, useMemo } from 'react'; import React, { useCallback, useMemo } from 'react';
import { i18n } from '@kbn/i18n'; import { i18n } from '@kbn/i18n';
import styled from 'styled-components';
import { noop } from 'lodash'; import { noop } from 'lodash';
import styled from '@emotion/styled';
const StyledEuiCard = styled(EuiCard)` const StyledEuiCard = styled(EuiCard)`
padding: 16px 92px 16px 16px !important; padding: 16px 92px 16px 16px !important;
border: ${(props) => { border: ${({ theme, selectable }) => {
if (props.selectable?.isSelected) { if (selectable?.isSelected) {
return `1px solid ${props.theme.eui.euiColorPrimary}`; return `${theme.euiTheme.border.width.thin} solid ${theme.euiTheme.colors.success}`;
} }
}}; }};
@ -30,7 +30,7 @@ const StyledEuiCard = styled(EuiCard)`
.euiText { .euiText {
margin-top: 0; margin-top: 0;
margin-left: 25px; margin-left: 25px;
color: ${(props) => props.theme.eui.EuiTextSubduedColor}; color: ${({ theme }) => theme.euiTheme.colors.subduedText};
} }
> button[role='switch'] { > button[role='switch'] {

View file

@ -9,17 +9,12 @@ import React, { useCallback } from 'react';
import { i18n } from '@kbn/i18n'; import { i18n } from '@kbn/i18n';
import type { EuiComboBoxOptionOption } from '@elastic/eui'; import type { EuiComboBoxOptionOption } from '@elastic/eui';
import { EuiButtonIcon, EuiFlexGroup, EuiFlexItem, EuiSpacer } 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 { UseFieldArrayRemove, UseFormReturn } from 'react-hook-form';
import type { ShardsArray } from '../../../../common/utils/converters'; import type { ShardsArray } from '../../../../common/utils/converters';
import { ShardsPolicyField } from './shards_policy_field'; import { ShardsPolicyField } from './shards_policy_field';
import { ShardsPercentageField } from './shards_percentage_field'; import { ShardsPercentageField } from './shards_percentage_field';
import { overflowCss } from '../../utils'; import { overflowCss } from '../../utils';
const StyledButtonWrapper = styled.div`
margin-top: ${(props: { index: number }) => props.index === 0 && '16px'};
`;
export type ShardsFormReturn = UseFormReturn<{ shardsArray: ShardsArray }>; export type ShardsFormReturn = UseFormReturn<{ shardsArray: ShardsArray }>;
interface ShardsFormProps { interface ShardsFormProps {
@ -43,6 +38,11 @@ const ShardsFormComponent = ({
} }
}, [index, onDelete]); }, [index, onDelete]);
const buttonWrapperCss = useCallback(
({ euiTheme }) => (index === 0 ? { marginTop: euiTheme.size.base } : {}),
[index]
);
return ( return (
<> <>
<EuiFlexGroup <EuiFlexGroup
@ -65,7 +65,7 @@ const ShardsFormComponent = ({
</EuiFlexItem> </EuiFlexItem>
<EuiFlexItem grow={false}> <EuiFlexItem grow={false}>
<StyledButtonWrapper index={index}> <div css={buttonWrapperCss}>
<EuiButtonIcon <EuiButtonIcon
aria-label={i18n.translate( aria-label={i18n.translate(
'xpack.osquery.pack.form.deleteShardsRowButtonAriaLabel', 'xpack.osquery.pack.form.deleteShardsRowButtonAriaLabel',
@ -78,7 +78,7 @@ const ShardsFormComponent = ({
disabled={isLastItem} disabled={isLastItem}
onClick={handleDeleteClick} onClick={handleDeleteClick}
/> />
</StyledButtonWrapper> </div>
</EuiFlexItem> </EuiFlexItem>
</EuiFlexGroup> </EuiFlexGroup>
</EuiFlexItem> </EuiFlexItem>

View file

@ -18,7 +18,6 @@ import {
} from '@elastic/eui'; } from '@elastic/eui';
import moment from 'moment-timezone'; import moment from 'moment-timezone';
import React, { useCallback, useMemo, useState } from 'react'; import React, { useCallback, useMemo, useState } from 'react';
import styled from 'styled-components';
import { i18n } from '@kbn/i18n'; import { i18n } from '@kbn/i18n';
import { useHistory } from 'react-router-dom'; 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 { AgentsPolicyLink } from '../agent_policies/agents_policy_link';
import type { PackSavedObject } from './types'; import type { PackSavedObject } from './types';
const UpdatedBy = styled.span` const updatedAtCss = {
white-space: nowrap; whiteSpace: 'nowrap' as const,
overflow: hidden; overflow: 'hidden',
text-overflow: ellipsis; textOverflow: 'ellipsis',
`; };
const EMPTY_ARRAY: PackSavedObject[] = []; const EMPTY_ARRAY: PackSavedObject[] = [];
@ -105,7 +104,7 @@ const PacksTableComponent = () => {
return updatedAt ? ( return updatedAt ? (
<EuiToolTip content={`${moment(updatedAt).fromNow()}${updatedBy}`}> <EuiToolTip content={`${moment(updatedAt).fromNow()}${updatedBy}`}>
<UpdatedBy>{`${moment(updatedAt).fromNow()}${updatedBy}`}</UpdatedBy> <span css={updatedAtCss}>{`${moment(updatedAt).fromNow()}${updatedBy}`}</span>
</EuiToolTip> </EuiToolTip>
) : ( ) : (
'-' '-'

View 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%',
};

View file

@ -36,7 +36,6 @@ import {
import sqliteParser from '@appland/sql-parser'; import sqliteParser from '@appland/sql-parser';
import { FormattedMessage } from '@kbn/i18n-react'; import { FormattedMessage } from '@kbn/i18n-react';
import { i18n } from '@kbn/i18n'; import { i18n } from '@kbn/i18n';
import styled from 'styled-components';
import deepEqual from 'fast-deep-equal'; import deepEqual from 'fast-deep-equal';
import type { FieldErrors, UseFieldArrayRemove, UseFormReturn } from 'react-hook-form'; 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 { OsqueryIcon } from '../../components/osquery_icon';
import { removeMultilines } from '../../../common/utils/build_query/remove_multilines'; import { removeMultilines } from '../../../common/utils/build_query/remove_multilines';
import { overflowCss } from '../utils'; import { overflowCss } from '../utils';
import {
resultComboBoxCss,
fieldSpanCss,
fieldIconCss,
buttonWrapperCss,
descriptionWrapperCss,
semicolonWrapperCss,
ECSFieldWrapperCss,
euiSuperSelectCss,
} from './ecs_field_css';
export type ECSMappingFormReturn = UseFormReturn<{ ecsMappingArray: ECSMappingArray }>; export type ECSMappingFormReturn = UseFormReturn<{ ecsMappingArray: ECSMappingArray }>;
@ -77,61 +86,6 @@ const typeMap = {
constant_keyword: 'string', 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 SINGLE_SELECTION = { asPlainText: true };
const ECSSchemaOptions = ECSSchema.map((ecs) => ({ const ECSSchemaOptions = ECSSchema.map((ecs) => ({
@ -207,16 +161,19 @@ const ECSComboboxFieldComponent: React.FC<ECSComboboxFieldProps> = ({
} }
</EuiFlexItem> </EuiFlexItem>
<EuiFlexItem grow={false}> <EuiFlexItem grow={false}>
<StyledFieldSpan className="euiSuggestItem__label euiSuggestItem__label--expand"> <span css={fieldSpanCss} className="euiSuggestItem__label euiSuggestItem__label--expand">
{option.value.field} {option.value.field}
</StyledFieldSpan> </span>
</EuiFlexItem> </EuiFlexItem>
<DescriptionWrapper grow={false}> <EuiFlexItem css={descriptionWrapperCss} grow={false}>
<StyledFieldSpan className="euiSuggestItem__description euiSuggestItem__description"> <span
css={fieldSpanCss}
className="euiSuggestItem__description euiSuggestItem__description"
>
{option.value.description} {option.value.description}
</StyledFieldSpan> </span>
</DescriptionWrapper> </EuiFlexItem>
</EuiFlexGroup> </EuiFlexGroup>
), ),
[] []
@ -224,7 +181,8 @@ const ECSComboboxFieldComponent: React.FC<ECSComboboxFieldProps> = ({
const prepend = useMemo( const prepend = useMemo(
() => ( () => (
<StyledFieldIcon <FieldIcon
css={fieldIconCss}
size="l" size="l"
type={ type={
// @ts-expect-error update types // @ts-expect-error update types
@ -435,15 +393,18 @@ const OsqueryColumnFieldComponent: React.FC<OsqueryColumnFieldProps> = ({
gutterSize="none" gutterSize="none"
> >
<EuiFlexItem grow={false}> <EuiFlexItem grow={false}>
<StyledFieldSpan className="euiSuggestItem__label euiSuggestItem__label--expand"> <span css={fieldSpanCss} className="euiSuggestItem__label euiSuggestItem__label--expand">
{option.value.suggestion_label} {option.value.suggestion_label}
</StyledFieldSpan> </span>
</EuiFlexItem> </EuiFlexItem>
<DescriptionWrapper grow={false}> <EuiFlexItem css={descriptionWrapperCss} grow={false}>
<StyledFieldSpan className="euiSuggestItem__description euiSuggestItem__description"> <span
css={fieldSpanCss}
className="euiSuggestItem__description euiSuggestItem__description"
>
{option.value.description} {option.value.description}
</StyledFieldSpan> </span>
</DescriptionWrapper> </EuiFlexItem>
</EuiFlexGroup> </EuiFlexGroup>
), ),
[] []
@ -510,7 +471,8 @@ const OsqueryColumnFieldComponent: React.FC<OsqueryColumnFieldProps> = ({
const Prepend = useMemo( const Prepend = useMemo(
() => ( () => (
<StyledEuiSuperSelect <EuiSuperSelect
css={euiSuperSelectCss}
disabled={euiFieldProps.isDisabled} disabled={euiFieldProps.isDisabled}
options={OSQUERY_COLUMN_VALUE_TYPE_OPTIONS} options={OSQUERY_COLUMN_VALUE_TYPE_OPTIONS}
data-test-subj={`osquery-result-type-select-${index}`} data-test-subj={`osquery-result-type-select-${index}`}
@ -577,7 +539,10 @@ const OsqueryColumnFieldComponent: React.FC<OsqueryColumnFieldProps> = ({
{Prepend} {Prepend}
</EuiFlexItem> </EuiFlexItem>
<EuiFlexItem css={overflowCss}> <EuiFlexItem css={overflowCss}>
<ResultComboBox {/* eslint-disable-next-line @typescript-eslint/ban-ts-comment */}
{/* @ts-ignore*/}
<EuiComboBox
css={resultComboBoxCss}
error={resultFieldState.error?.message} error={resultFieldState.error?.message}
// eslint-disable-next-line react/jsx-no-bind, react-perf/jsx-no-new-function-as-prop // eslint-disable-next-line react/jsx-no-bind, react-perf/jsx-no-new-function-as-prop
inputRef={(ref: HTMLInputElement) => { inputRef={(ref: HTMLInputElement) => {
@ -660,16 +625,14 @@ export const ECSMappingEditorForm: React.FC<ECSMappingEditorFormProps> = ({
}} }}
/> />
</EuiFlexItem> </EuiFlexItem>
<EuiFlexItem grow={false}> <EuiFlexItem grow={false} css={semicolonWrapperCss}>
<StyledSemicolonWrapper> <EuiText>:</EuiText>
<EuiText>:</EuiText>
</StyledSemicolonWrapper>
</EuiFlexItem> </EuiFlexItem>
</EuiFlexGroup> </EuiFlexGroup>
</EuiFlexItem> </EuiFlexItem>
<EuiFlexItem css={overflowCss}> <EuiFlexItem css={overflowCss}>
<EuiFlexGroup alignItems="flexStart" gutterSize="s" wrap> <EuiFlexGroup alignItems="flexStart" gutterSize="s" wrap>
<ECSFieldWrapper> <EuiFlexItem css={ECSFieldWrapperCss}>
<OsqueryColumnField <OsqueryColumnField
control={control} control={control}
watch={watch} watch={watch}
@ -683,10 +646,10 @@ export const ECSMappingEditorForm: React.FC<ECSMappingEditorFormProps> = ({
isDisabled, isDisabled,
}} }}
/> />
</ECSFieldWrapper> </EuiFlexItem>
{!isDisabled && ( {!isDisabled && (
<EuiFlexItem grow={false}> <EuiFlexItem grow={false}>
<StyledButtonWrapper> <div css={buttonWrapperCss}>
{!isLastItem && ( {!isLastItem && (
<EuiButtonIcon <EuiButtonIcon
aria-label={i18n.translate( aria-label={i18n.translate(
@ -700,7 +663,7 @@ export const ECSMappingEditorForm: React.FC<ECSMappingEditorFormProps> = ({
onClick={handleDeleteClick} onClick={handleDeleteClick}
/> />
)} )}
</StyledButtonWrapper> </div>
</EuiFlexItem> </EuiFlexItem>
)} )}
</EuiFlexGroup> </EuiFlexGroup>

View file

@ -6,7 +6,6 @@
*/ */
import { get, isEmpty, isArray, isObject, isEqual, keys, map, reduce } from 'lodash/fp'; import { get, isEmpty, isArray, isObject, isEqual, keys, map, reduce } from 'lodash/fp';
import { css } from '@emotion/react';
import type { import type {
EuiDataGridSorting, EuiDataGridSorting,
EuiDataGridProps, EuiDataGridProps,
@ -29,7 +28,6 @@ import { FormattedMessage } from '@kbn/i18n-react';
import React, { createContext, useEffect, useState, useCallback, useContext, useMemo } from 'react'; import React, { createContext, useEffect, useState, useCallback, useContext, useMemo } from 'react';
import type { ECSMapping } from '@kbn/osquery-io-ts-types'; import type { ECSMapping } from '@kbn/osquery-io-ts-types';
import { pagePathGetters } from '@kbn/fleet-plugin/public'; import { pagePathGetters } from '@kbn/fleet-plugin/public';
import styled from 'styled-components';
import { AddToTimelineButton } from '../timelines/add_to_timeline_button'; import { AddToTimelineButton } from '../timelines/add_to_timeline_button';
import { useAllResults } from './use_all_results'; import { useAllResults } from './use_all_results';
import type { ResultEdges } from '../../common/search_strategy'; import type { ResultEdges } from '../../common/search_strategy';
@ -48,14 +46,18 @@ import { AddToCaseWrapper } from '../cases/add_to_cases';
const DataContext = createContext<ResultEdges>([]); const DataContext = createContext<ResultEdges>([]);
const StyledEuiDataGrid = styled(EuiDataGrid)` const euiDataGridCss = {
:not(.euiDataGrid--fullScreen) { ':not(.euiDataGrid--fullScreen)': {
.euiDataGrid__virtualized { '.euiDataGrid__virtualized': {
height: 100% !important; height: '100% !important',
max-height: 500px; maxHeight: '500px',
} },
} },
`; };
const euiProgressCss = {
marginTop: '-2px',
};
export interface ResultsTableComponentProps { export interface ResultsTableComponentProps {
actionId: string; actionId: string;
@ -425,15 +427,7 @@ const ResultsTableComponent: React.FC<ResultsTableComponentProps> = ({
return ( return (
<> <>
{isLive && ( {isLive && <EuiProgress color="primary" size="xs" css={euiProgressCss} />}
<EuiProgress
color="primary"
size="xs"
css={css`
margin-top: -2px;
`}
/>
)}
{!allResultsData?.edges.length ? ( {!allResultsData?.edges.length ? (
<EuiPanel hasShadow={false} data-test-subj={'osqueryResultsPanel'}> <EuiPanel hasShadow={false} data-test-subj={'osqueryResultsPanel'}>
@ -441,7 +435,8 @@ const ResultsTableComponent: React.FC<ResultsTableComponentProps> = ({
</EuiPanel> </EuiPanel>
) : ( ) : (
<DataContext.Provider value={allResultsData?.edges}> <DataContext.Provider value={allResultsData?.edges}>
<StyledEuiDataGrid <EuiDataGrid
css={euiDataGridCss}
data-test-subj="osqueryResultsTable" data-test-subj="osqueryResultsTable"
aria-label="Osquery results" aria-label="Osquery results"
columns={columns} columns={columns}

View file

@ -8,18 +8,17 @@
import React from 'react'; import React from 'react';
import { EuiEmptyPrompt, EuiPanel, EuiSpacer } from '@elastic/eui'; import { EuiEmptyPrompt, EuiPanel, EuiSpacer } from '@elastic/eui';
import { FormattedMessage } from '@kbn/i18n-react'; import { FormattedMessage } from '@kbn/i18n-react';
import styled from 'styled-components';
const Panel = styled(EuiPanel)` const panelCss = {
max-width: 500px; maxWidth: '500px',
margin-right: auto; marginRight: 'auto',
margin-left: auto; marginLeft: 'auto',
`; };
const MissingPrivilegesComponent = () => ( const MissingPrivilegesComponent = () => (
<div> <div>
<EuiSpacer /> <EuiSpacer />
<Panel> <EuiPanel css={panelCss}>
<EuiEmptyPrompt <EuiEmptyPrompt
iconType="securityApp" iconType="securityApp"
title={ title={
@ -39,7 +38,7 @@ const MissingPrivilegesComponent = () => (
</p> </p>
} }
/> />
</Panel> </EuiPanel>
<EuiSpacer /> <EuiSpacer />
</div> </div>
); );

View file

@ -10,16 +10,15 @@ import { FormattedMessage } from '@kbn/i18n-react';
import React, { useLayoutEffect, useMemo, useState } from 'react'; import React, { useLayoutEffect, useMemo, useState } from 'react';
import { useParams } from 'react-router-dom'; import { useParams } from 'react-router-dom';
import styled from 'styled-components';
import { useRouterNavigate } from '../../../common/lib/kibana'; import { useRouterNavigate } from '../../../common/lib/kibana';
import { WithHeaderLayout } from '../../../components/layouts'; import { WithHeaderLayout } from '../../../components/layouts';
import { useLiveQueryDetails } from '../../../actions/use_live_query_details'; import { useLiveQueryDetails } from '../../../actions/use_live_query_details';
import { useBreadcrumbs } from '../../../common/hooks/use_breadcrumbs'; import { useBreadcrumbs } from '../../../common/hooks/use_breadcrumbs';
import { PackQueriesStatusTable } from '../../../live_queries/form/pack_queries_status_table'; import { PackQueriesStatusTable } from '../../../live_queries/form/pack_queries_status_table';
const StyledTableWrapper = styled(EuiFlexItem)` const tableWrapperCss = {
padding-left: 10px; paddingLeft: '10px',
`; };
const LiveQueryDetailsPageComponent = () => { const LiveQueryDetailsPageComponent = () => {
const { actionId } = useParams<{ actionId: string }>(); const { actionId } = useParams<{ actionId: string }>();
@ -60,7 +59,7 @@ const LiveQueryDetailsPageComponent = () => {
return ( return (
<WithHeaderLayout leftColumn={LeftColumn} rightColumnGrow={false}> <WithHeaderLayout leftColumn={LeftColumn} rightColumnGrow={false}>
<StyledTableWrapper> <EuiFlexItem css={tableWrapperCss}>
<PackQueriesStatusTable <PackQueriesStatusTable
actionId={actionId} actionId={actionId}
data={data?.queries} data={data?.queries}
@ -69,7 +68,7 @@ const LiveQueryDetailsPageComponent = () => {
agentIds={data?.agents} agentIds={data?.agents}
showResultsHeader showResultsHeader
/> />
</StyledTableWrapper> </EuiFlexItem>
</WithHeaderLayout> </WithHeaderLayout>
); );
}; };

View file

@ -16,10 +16,10 @@ import {
EuiSpacer, EuiSpacer,
EuiText, EuiText,
} from '@elastic/eui'; } from '@elastic/eui';
import type { UseEuiTheme } from '@elastic/eui';
import { FormattedMessage } from '@kbn/i18n-react'; import { FormattedMessage } from '@kbn/i18n-react';
import React, { useMemo } from 'react'; import React, { useMemo } from 'react';
import { useParams } from 'react-router-dom'; import { useParams } from 'react-router-dom';
import styled from 'styled-components';
import { useKibana, useRouterNavigate } from '../../../common/lib/kibana'; import { useKibana, useRouterNavigate } from '../../../common/lib/kibana';
import { WithHeaderLayout } from '../../../components/layouts'; 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 { useAgentPolicyAgentIds } from '../../../agents/use_agent_policy_agent_ids';
import { AgentPoliciesPopover } from '../../../packs/packs_table'; import { AgentPoliciesPopover } from '../../../packs/packs_table';
const Divider = styled.div` const dividerCss = ({ euiTheme }: UseEuiTheme) => ({
width: 0; width: 0,
height: 100%; height: '100%',
border-left: ${({ theme }) => theme.eui.euiBorderThin}; borderLeft: euiTheme.border.thin,
`; });
const PackDetailsPageComponent = () => { const PackDetailsPageComponent = () => {
const permissions = useKibana().services.application.capabilities.osquery; const permissions = useKibana().services.application.capabilities.osquery;
@ -112,7 +112,7 @@ const PackDetailsPageComponent = () => {
</EuiDescriptionList> </EuiDescriptionList>
</EuiFlexItem> </EuiFlexItem>
<EuiFlexItem grow={false} key="agents_failed_count_divider"> <EuiFlexItem grow={false} key="agents_failed_count_divider">
<Divider /> <div css={dividerCss} />
</EuiFlexItem> </EuiFlexItem>
<EuiFlexItem grow={false} key="edit_button"> <EuiFlexItem grow={false} key="edit_button">
<EuiButton <EuiButton

View file

@ -76,6 +76,7 @@ const EditSavedQueryFormComponent: React.FC<EditSavedQueryFormProps> = ({
</EuiFlexItem> </EuiFlexItem>
<EuiFlexItem grow={false}> <EuiFlexItem grow={false}>
<EuiButton <EuiButton
data-test-subj="savedQueryFormUpdateButton"
isLoading={isSubmitting} isLoading={isSubmitting}
color="primary" color="primary"
fill fill

View file

@ -19,16 +19,15 @@ import React, { useCallback, useMemo, useState } from 'react';
import { FormattedMessage } from '@kbn/i18n-react'; import { FormattedMessage } from '@kbn/i18n-react';
import { useParams } from 'react-router-dom'; import { useParams } from 'react-router-dom';
import styled from 'styled-components';
import { useKibana, useRouterNavigate } from '../../../common/lib/kibana'; import { useKibana, useRouterNavigate } from '../../../common/lib/kibana';
import { WithHeaderLayout } from '../../../components/layouts'; import { WithHeaderLayout } from '../../../components/layouts';
import { useBreadcrumbs } from '../../../common/hooks/use_breadcrumbs'; import { useBreadcrumbs } from '../../../common/hooks/use_breadcrumbs';
import { EditSavedQueryForm } from './form'; import { EditSavedQueryForm } from './form';
import { useDeleteSavedQuery, useUpdateSavedQuery, useSavedQuery } from '../../../saved_queries'; import { useDeleteSavedQuery, useUpdateSavedQuery, useSavedQuery } from '../../../saved_queries';
const StyledEuiCallOut = styled(EuiCallOut)` const euiCalloutCss = {
margin: 10px; margin: '10px',
`; };
const EditSavedQueryPageComponent = () => { const EditSavedQueryPageComponent = () => {
const permissions = useKibana().services.application.capabilities.osquery; const permissions = useKibana().services.application.capabilities.osquery;
@ -88,12 +87,12 @@ const EditSavedQueryPageComponent = () => {
}} }}
/> />
{elasticPrebuiltQuery && ( {elasticPrebuiltQuery && (
<StyledEuiCallOut size="s"> <EuiCallOut css={euiCalloutCss} size="s">
<FormattedMessage <FormattedMessage
id="xpack.osquery.viewSavedQuery.prebuiltInfo" id="xpack.osquery.viewSavedQuery.prebuiltInfo"
defaultMessage="This is a prebuilt Elastic query, and it cannot be edited." defaultMessage="This is a prebuilt Elastic query, and it cannot be edited."
/> />
</StyledEuiCallOut> </EuiCallOut>
)} )}
</> </>
) : ( ) : (

View file

@ -9,15 +9,14 @@ import { EuiTabbedContent, EuiNotificationBadge } from '@elastic/eui';
import React, { useMemo } from 'react'; import React, { useMemo } from 'react';
import type { ECSMapping } from '@kbn/osquery-io-ts-types'; import type { ECSMapping } from '@kbn/osquery-io-ts-types';
import styled from 'styled-components';
import { ResultsTable } from '../../../results/results_table'; import { ResultsTable } from '../../../results/results_table';
import { ActionResultsSummary } from '../../../action_results/action_results_summary'; import { ActionResultsSummary } from '../../../action_results/action_results_summary';
const StyledEuiTabbedContent = styled(EuiTabbedContent)` const euiTabbedContentCss = {
div.euiTabs { 'div.euiTabs': {
padding-left: 8px; paddingLeft: '8px',
} },
`; };
interface ResultTabsProps { interface ResultTabsProps {
actionId: string; actionId: string;
@ -90,7 +89,8 @@ const ResultTabsComponent: React.FC<ResultTabsProps> = ({
); );
return ( return (
<StyledEuiTabbedContent <EuiTabbedContent
css={euiTabbedContentCss}
// TODO: extend the EuiTabbedContent component to support EuiTabs props // TODO: extend the EuiTabbedContent component to support EuiTabs props
// bottomBorder={false} // bottomBorder={false}
tabs={tabs} tabs={tabs}

View file

@ -8,16 +8,15 @@
import { isEmpty } from 'lodash/fp'; import { isEmpty } from 'lodash/fp';
import { EuiCodeBlock, EuiFormRow } from '@elastic/eui'; import { EuiCodeBlock, EuiFormRow } from '@elastic/eui';
import React from 'react'; import React from 'react';
import styled from 'styled-components';
import { useController } from 'react-hook-form'; import { useController } from 'react-hook-form';
import { i18n } from '@kbn/i18n'; import { i18n } from '@kbn/i18n';
import { OsquerySchemaLink } from '../../components/osquery_schema_link'; import { OsquerySchemaLink } from '../../components/osquery_schema_link';
import { OsqueryEditor } from '../../editor'; import { OsqueryEditor } from '../../editor';
const StyledEuiCodeBlock = styled(EuiCodeBlock)` const euiCodeBlockCss = {
min-height: 100px; minHeight: '100px',
`; };
interface CodeEditorFieldProps { interface CodeEditorFieldProps {
euiFieldProps?: Record<string, unknown>; euiFieldProps?: Record<string, unknown>;
@ -58,14 +57,15 @@ const CodeEditorFieldComponent: React.FC<CodeEditorFieldProps> = ({
fullWidth fullWidth
> >
{euiFieldProps?.isDisabled ? ( {euiFieldProps?.isDisabled ? (
<StyledEuiCodeBlock <EuiCodeBlock
css={euiCodeBlockCss}
language="sql" language="sql"
fontSize="m" fontSize="m"
paddingSize="m" paddingSize="m"
transparentBackground={!value.length} transparentBackground={!value.length}
> >
{value} {value}
</StyledEuiCodeBlock> </EuiCodeBlock>
) : ( ) : (
<OsqueryEditor defaultValue={value} onChange={onChange} /> <OsqueryEditor defaultValue={value} onChange={onChange} />
)} )}

View file

@ -7,18 +7,17 @@
import { EuiFlyout, EuiFlyoutHeader, EuiTitle, EuiFlyoutBody } from '@elastic/eui'; import { EuiFlyout, EuiFlyoutHeader, EuiTitle, EuiFlyoutBody } from '@elastic/eui';
import React, { useMemo } from 'react'; import React, { useMemo } from 'react';
import styled from 'styled-components';
import { FormattedMessage } from '@kbn/i18n-react'; import { FormattedMessage } from '@kbn/i18n-react';
import { useFormContext } from 'react-hook-form'; import { useFormContext } from 'react-hook-form';
import { LiveQuery } from '../../live_queries'; import { LiveQuery } from '../../live_queries';
const StyledEuiFlyoutHeader = styled(EuiFlyoutHeader)` const euiFlyoutHeaderCss = {
&.euiFlyoutHeader { '&.euiFlyoutHeader': {
padding-top: 21px; paddingTop: '21px',
padding-bottom: 20px; paddingBottom: '20px',
} },
`; };
interface PlaygroundFlyoutProps { interface PlaygroundFlyoutProps {
enabled?: boolean; enabled?: boolean;
@ -36,7 +35,7 @@ const PlaygroundFlyoutComponent: React.FC<PlaygroundFlyoutProps> = ({ enabled, o
return ( return (
<EuiFlyout type="push" size="m" onClose={onClose} data-test-subj={'osquery-save-query-flyout'}> <EuiFlyout type="push" size="m" onClose={onClose} data-test-subj={'osquery-save-query-flyout'}>
<StyledEuiFlyoutHeader hasBorder> <EuiFlyoutHeader css={euiFlyoutHeaderCss} hasBorder>
<EuiTitle size="s"> <EuiTitle size="s">
<h5> <h5>
<FormattedMessage <FormattedMessage
@ -45,7 +44,7 @@ const PlaygroundFlyoutComponent: React.FC<PlaygroundFlyoutProps> = ({ enabled, o
/> />
</h5> </h5>
</EuiTitle> </EuiTitle>
</StyledEuiFlyoutHeader> </EuiFlyoutHeader>
<EuiFlyoutBody> <EuiFlyoutBody>
<LiveQuery <LiveQuery
enabled={enabled && query !== ''} enabled={enabled && query !== ''}

View file

@ -8,7 +8,6 @@
import { find } from 'lodash/fp'; import { find } from 'lodash/fp';
import { EuiCodeBlock, EuiFormRow, EuiComboBox, EuiTextColor } from '@elastic/eui'; import { EuiCodeBlock, EuiFormRow, EuiComboBox, EuiTextColor } from '@elastic/eui';
import React, { useCallback, useEffect, useMemo, useState } from 'react'; import React, { useCallback, useEffect, useMemo, useState } from 'react';
import styled from 'styled-components';
import { useWatch, useFormContext } from 'react-hook-form'; import { useWatch, useFormContext } from 'react-hook-form';
import { QUERIES_DROPDOWN_LABEL, QUERIES_DROPDOWN_SEARCH_FIELD_LABEL } from './constants'; import { QUERIES_DROPDOWN_LABEL, QUERIES_DROPDOWN_SEARCH_FIELD_LABEL } from './constants';
import { OsquerySchemaLink } from '../components/osquery_schema_link'; 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 { useSavedQueries } from './use_saved_queries';
import type { SavedQuerySO } from '../routes/saved_queries/list'; import type { SavedQuerySO } from '../routes/saved_queries/list';
const TextTruncate = styled.div` const euiCodeBlockCss = {
overflow: hidden; '.euiCodeBlock__line': {
text-overflow: ellipsis; whiteSpace: 'nowrap' as const,
`; },
};
const StyledEuiCodeBlock = styled(EuiCodeBlock)`
.euiCodeBlock__line {
white-space: nowrap;
}
`;
export interface SavedQueriesDropdownProps { export interface SavedQueriesDropdownProps {
disabled?: boolean; disabled?: boolean;
@ -96,12 +90,12 @@ const SavedQueriesDropdownComponent: React.FC<SavedQueriesDropdownProps> = ({
({ value }) => ( ({ value }) => (
<> <>
<strong>{value.id}</strong> <strong>{value.id}</strong>
<TextTruncate> <div className="eui-textTruncate">
<EuiTextColor color="subdued">{value.description}</EuiTextColor> <EuiTextColor color="subdued">{value.description}</EuiTextColor>
</TextTruncate> </div>
<StyledEuiCodeBlock language="sql" fontSize="m" paddingSize="s"> <EuiCodeBlock css={euiCodeBlockCss} language="sql" fontSize="m" paddingSize="s">
{value.query.split('\n').join(' ')} {value.query.split('\n').join(' ')}
</StyledEuiCodeBlock> </EuiCodeBlock>
</> </>
), ),
[] []

View file

@ -95,7 +95,12 @@ const SavedQueryFlyoutComponent: React.FC<AddQueryFlyoutProps> = ({
</EuiButtonEmpty> </EuiButtonEmpty>
</EuiFlexItem> </EuiFlexItem>
<EuiFlexItem grow={false}> <EuiFlexItem grow={false}>
<EuiButton isLoading={isSubmitting} onClick={handleSubmit(onSubmit)} fill> <EuiButton
data-test-subj="savedQueryFlyoutSaveButton"
isLoading={isSubmitting}
onClick={handleSubmit(onSubmit)}
fill
>
<FormattedMessage <FormattedMessage
id="xpack.osquery.pack.queryFlyoutForm.saveButtonLabel" id="xpack.osquery.pack.queryFlyoutForm.saveButtonLabel"
defaultMessage="Save" defaultMessage="Save"

View file

@ -6,8 +6,6 @@
*/ */
import React, { lazy, Suspense } from 'react'; 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'; import type { OsqueryResponseActionsParamsFormProps } from './osquery_response_action_type';
const OsqueryResponseActionParamsForm = lazy(() => import('./osquery_response_action_type')); const OsqueryResponseActionParamsForm = lazy(() => import('./osquery_response_action_type'));
@ -19,13 +17,11 @@ export const getLazyOsqueryResponseActionTypeForm =
return ( return (
<Suspense fallback={null}> <Suspense fallback={null}>
<QueryClientProvider client={queryClient}> <OsqueryResponseActionParamsForm
<OsqueryResponseActionParamsForm onChange={onChange}
onChange={onChange} defaultValues={defaultValues}
defaultValues={defaultValues} onError={onError}
onError={onError} />
/>
</QueryClientProvider>
</Suspense> </Suspense>
); );
}; };

View file

@ -18,6 +18,8 @@
"../../../typings/**/*", "../../../typings/**/*",
// ECS and Osquery schema files // ECS and Osquery schema files
"public/common/schemas/*/**.json", "public/common/schemas/*/**.json",
// Emotion theme typing
"./emotion.d.ts"
], ],
"kbn_references": [ "kbn_references": [
"@kbn/core", "@kbn/core",
@ -43,7 +45,6 @@
"@kbn/utility-types", "@kbn/utility-types",
"@kbn/securitysolution-io-ts-utils", "@kbn/securitysolution-io-ts-utils",
"@kbn/osquery-io-ts-types", "@kbn/osquery-io-ts-types",
"@kbn/ui-theme",
"@kbn/i18n-react", "@kbn/i18n-react",
"@kbn/discover-plugin", "@kbn/discover-plugin",
"@kbn/lens-plugin", "@kbn/lens-plugin",