Skip to content

Commit

Permalink
Merge branch 'main' into 6999-rule-preview
Browse files Browse the repository at this point in the history
  • Loading branch information
christineweng authored Jul 24, 2023
2 parents 8669578 + e3cc4a9 commit a88b327
Show file tree
Hide file tree
Showing 61 changed files with 2,084 additions and 610 deletions.
1 change: 1 addition & 0 deletions config/serverless.oblt.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ xpack.serverless.observability.enabled: true

## Configure plugins
xpack.infra.logs.app_target: discover
xpack.discoverLogExplorer.featureFlags.deepLinkVisible: true

## Set the home route
uiSettings.overrides.defaultRoute: /app/observability/landing
Expand Down
259 changes: 259 additions & 0 deletions docs/CHANGELOG.asciidoc

Large diffs are not rendered by default.

306 changes: 154 additions & 152 deletions examples/discover_customization_examples/public/plugin.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -74,163 +74,165 @@ export class DiscoverCustomizationExamplesPlugin implements Plugin {
isOptionsOpen = false;
};

discover.customize('customization-examples', async ({ customizations, stateContainer }) => {
customizations.set({
id: 'top_nav',
defaultMenu: {
newItem: { disabled: true },
openItem: { disabled: true },
shareItem: { order: 200 },
alertsItem: { disabled: true },
inspectItem: { disabled: true },
saveItem: { order: 400 },
},
getMenuItems: () => [
{
data: {
id: 'options',
label: 'Options',
iconType: 'arrowDown',
iconSide: 'right',
testId: 'customOptionsButton',
run: (anchorElement: HTMLElement) => {
if (isOptionsOpen) {
closeOptionsPopover();
return;
}

isOptionsOpen = true;
document.body.appendChild(optionsContainer);

const element = (
<EuiWrappingPopover
ownFocus
button={anchorElement}
isOpen={true}
panelPaddingSize="s"
closePopover={closeOptionsPopover}
>
<EuiContextMenu
size="s"
initialPanelId={0}
panels={[
{
id: 0,
items: [
{
name: 'Create new',
icon: 'plusInCircle',
onClick: () => alert('Create new clicked'),
},
{
name: 'Make a copy',
icon: 'copy',
onClick: () => alert('Make a copy clicked'),
},
{
name: 'Manage saved searches',
icon: 'gear',
onClick: () => alert('Manage saved searches clicked'),
},
],
},
]}
data-test-subj="customOptionsPopover"
/>
</EuiWrappingPopover>
);

ReactDOM.render(element, optionsContainer);
discover.registerCustomizationProfile('customization-examples', {
customize: async ({ customizations, stateContainer }) => {
customizations.set({
id: 'top_nav',
defaultMenu: {
newItem: { disabled: true },
openItem: { disabled: true },
shareItem: { order: 200 },
alertsItem: { disabled: true },
inspectItem: { disabled: true },
saveItem: { order: 400 },
},
getMenuItems: () => [
{
data: {
id: 'options',
label: 'Options',
iconType: 'arrowDown',
iconSide: 'right',
testId: 'customOptionsButton',
run: (anchorElement: HTMLElement) => {
if (isOptionsOpen) {
closeOptionsPopover();
return;
}

isOptionsOpen = true;
document.body.appendChild(optionsContainer);

const element = (
<EuiWrappingPopover
ownFocus
button={anchorElement}
isOpen={true}
panelPaddingSize="s"
closePopover={closeOptionsPopover}
>
<EuiContextMenu
size="s"
initialPanelId={0}
panels={[
{
id: 0,
items: [
{
name: 'Create new',
icon: 'plusInCircle',
onClick: () => alert('Create new clicked'),
},
{
name: 'Make a copy',
icon: 'copy',
onClick: () => alert('Make a copy clicked'),
},
{
name: 'Manage saved searches',
icon: 'gear',
onClick: () => alert('Manage saved searches clicked'),
},
],
},
]}
data-test-subj="customOptionsPopover"
/>
</EuiWrappingPopover>
);

ReactDOM.render(element, optionsContainer);
},
},
order: 100,
},
order: 100,
},
{
data: {
id: 'documentExplorer',
label: 'Document explorer',
iconType: 'discoverApp',
testId: 'documentExplorerButton',
run: () => {
discover.locator?.navigate({});
{
data: {
id: 'documentExplorer',
label: 'Document explorer',
iconType: 'discoverApp',
testId: 'documentExplorerButton',
run: () => {
discover.locator?.navigate({});
},
},
order: 300,
},
order: 300,
],
});

customizations.set({
id: 'search_bar',
CustomDataViewPicker: () => {
const [isPopoverOpen, setIsPopoverOpen] = useState(false);
const togglePopover = () => setIsPopoverOpen((open) => !open);
const closePopover = () => setIsPopoverOpen(false);
const [savedSearches, setSavedSearches] = useState<
Array<SimpleSavedObject<{ title: string }>>
>([]);

useEffect(() => {
core.savedObjects.client
.find<{ title: string }>({ type: 'search' })
.then((response) => {
setSavedSearches(response.savedObjects);
});
}, []);

const currentSavedSearch = useObservable(
stateContainer.savedSearchState.getCurrent$(),
stateContainer.savedSearchState.getState()
);

return (
<EuiFlexItem grow={false}>
<EuiPopover
button={
<EuiButton
iconType="arrowDown"
iconSide="right"
fullWidth
onClick={togglePopover}
data-test-subj="logsViewSelectorButton"
>
{currentSavedSearch.title ?? 'None selected'}
</EuiButton>
}
anchorClassName="eui-fullWidth"
isOpen={isPopoverOpen}
panelPaddingSize="none"
closePopover={closePopover}
>
<EuiContextMenu
size="s"
initialPanelId={0}
panels={[
{
id: 0,
title: 'Saved logs views',
items: savedSearches.map((savedSearch) => ({
name: savedSearch.get('title'),
onClick: () => stateContainer.actions.onOpenSavedSearch(savedSearch.id),
icon: savedSearch.id === currentSavedSearch.id ? 'check' : 'empty',
'data-test-subj': `logsViewSelectorOption-${savedSearch.attributes.title.replace(
/[^a-zA-Z0-9]/g,
''
)}`,
})),
},
]}
/>
</EuiPopover>
</EuiFlexItem>
);
},
],
});

customizations.set({
id: 'search_bar',
CustomDataViewPicker: () => {
const [isPopoverOpen, setIsPopoverOpen] = useState(false);
const togglePopover = () => setIsPopoverOpen((open) => !open);
const closePopover = () => setIsPopoverOpen(false);
const [savedSearches, setSavedSearches] = useState<
Array<SimpleSavedObject<{ title: string }>>
>([]);

useEffect(() => {
core.savedObjects.client
.find<{ title: string }>({ type: 'search' })
.then((response) => {
setSavedSearches(response.savedObjects);
});
}, []);

const currentSavedSearch = useObservable(
stateContainer.savedSearchState.getCurrent$(),
stateContainer.savedSearchState.getState()
);

return (
<EuiFlexItem grow={false}>
<EuiPopover
button={
<EuiButton
iconType="arrowDown"
iconSide="right"
fullWidth
onClick={togglePopover}
data-test-subj="logsViewSelectorButton"
>
{currentSavedSearch.title ?? 'None selected'}
</EuiButton>
}
anchorClassName="eui-fullWidth"
isOpen={isPopoverOpen}
panelPaddingSize="none"
closePopover={closePopover}
>
<EuiContextMenu
size="s"
initialPanelId={0}
panels={[
{
id: 0,
title: 'Saved logs views',
items: savedSearches.map((savedSearch) => ({
name: savedSearch.get('title'),
onClick: () => stateContainer.actions.onOpenSavedSearch(savedSearch.id),
icon: savedSearch.id === currentSavedSearch.id ? 'check' : 'empty',
'data-test-subj': `logsViewSelectorOption-${savedSearch.attributes.title.replace(
/[^a-zA-Z0-9]/g,
''
)}`,
})),
},
]}
/>
</EuiPopover>
</EuiFlexItem>
);
},
});

return () => {
// eslint-disable-next-line no-console
console.log('Cleaning up Logs explorer customizations');
};
});

return () => {
// eslint-disable-next-line no-console
console.log('Cleaning up Logs explorer customizations');
};
},
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,12 @@ export type AppDeepLink<Id extends string = string> = {
navLinkStatus?: AppNavLinkStatus;
/** Optional flag to determine if the link is searchable in the global search. Defaulting to `true` if `navLinkStatus` is `visible` or omitted */
searchable?: boolean;
/**
* Optional category to use instead of the parent app category.
* This property is added to customize the way a deep link is rendered in the global search.
* Any other feature that consumes the deep links (navigation tree, etc.) will not be affected by this addition.
*/
category?: AppCategory;
} & AppNavOptions &
(
| {
Expand Down
4 changes: 4 additions & 0 deletions packages/deeplinks/observability/deep_links.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
import { DISCOVER_APP_ID } from '@kbn/deeplinks-analytics';

import {
LOGS_APP_ID,
Expand All @@ -27,6 +28,8 @@ export type AppId =
| ApmApp
| MetricsApp;

export type DiscoverLogExplorerId = `${typeof DISCOVER_APP_ID}:log-explorer`;

export type LogsLinkId = 'log-categories' | 'settings' | 'anomalies' | 'stream';

export type ObservabilityOverviewLinkId =
Expand All @@ -52,6 +55,7 @@ export type LinkId = LogsLinkId | ObservabilityOverviewLinkId | MetricsLinkId |

export type DeepLinkId =
| AppId
| DiscoverLogExplorerId
| `${LogsApp}:${LogsLinkId}`
| `${ObservabilityOverviewApp}:${ObservabilityOverviewLinkId}`
| `${MetricsApp}:${MetricsLinkId}`
Expand Down
4 changes: 3 additions & 1 deletion packages/deeplinks/observability/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,7 @@
"exclude": [
"target/**/*"
],
"kbn_references": []
"kbn_references": [
"@kbn/deeplinks-analytics",
]
}
Original file line number Diff line number Diff line change
Expand Up @@ -130,12 +130,12 @@ const profileRegistry = createProfileRegistry();
const callbacks = [jest.fn()];

profileRegistry.set({
name: 'default',
id: 'default',
customizationCallbacks: callbacks,
});

profileRegistry.set({
name: 'test',
id: 'test',
customizationCallbacks: callbacks,
});

Expand Down
Loading

0 comments on commit a88b327

Please sign in to comment.