Hi Team,
I am trying to create a plugin in kibana. I need to move my breadcrumbs to the top nav bar where kibana breadcrumbs are being displayed.
I have attached screenshot explaining the same. Please help me out in this.
Hi Team,
I am trying to create a plugin in kibana. I need to move my breadcrumbs to the top nav bar where kibana breadcrumbs are being displayed.
I have attached screenshot explaining the same. Please help me out in this.
On the core services passed into your plugin there is core.chrome.setBreadcrumbs
.
This is a real-world example about how to use it: https://github.com/elastic/kibana/blob/master/x-pack/plugins/lens/public/app_plugin/app.tsx#L233
Hi Joe,
I have used core.chrome.setBreadcrumbs as suggested by you as shown below
But I am getting "Cannot read property 'chrome' of undefined" at highlighted line.
Are you sure you are passing in the right "core"? Can you show the code registering the app and rendering ´CorreltionAppApp´?
Hi Joe,
This is mine code registering the app.
Earlier i had missed to import core there. But after importing core I am getting different error.
"Cannot destructure property 'core' of 'undefined' as it is undefined."
You are probably not calling renderApp
with the right parameters, please check the whole stack from the setup method of your plugin through core.application.register
to your actual app component whether the parameters you are passing down have the expected values
Hi Joe,
This is mine plugin registration code.
I have passed AppMountContext['core'] as specified above and tried to print core in app.tsx
Can you please help me out in this why is this so?
The second parameter of setup
is not AppMountContext['core']
- depending on which version you are targeting it's deprecated and shouldn't be used anymore - just remove the second the parameter from setup
and use coreStart.chrome
instead, this is the right reference.
In your renderApp
function, jsut pass the first CoreStart
parameter down completely to your app and use it there.
Hi Joe,
Thanks for your help. Breadcrumbs are coming on top now, actuall issue was that i was importing CoreStart from different location on changing it to kibana/public it worked.
But now I am facing another issue. Breadcrumbs are not getting updated using core.chrome.setBreadcrumbs(). Below is mine code. I think state of the breadcrumbs are not getting changed.
import { Route, Switch, NavLink, useHistory } from 'react-router-dom';
import {
EuiHeader,
EuiFieldSearch,
EuiHeaderLogo,
EuiPageBody,
EuiPageHeader,
EuiPageHeaderSection,
EuiPageContent,
EuiPageContentBody,
EuiBreadcrumbs,
EuiFlexGroup,
EuiFlexItem,
EuiToolTip,
EuiIcon,
EuiDatePickerRange,
EuiDatePicker,
} from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { FormattedMessage, I18nProvider } from '@kbn/i18n/react';
import { BrowserRouter as Router } from 'react-router-dom';
import {
EuiTitle,
EuiText,
EuiTabbedContent,
EuiSpacer,
EuiButton,
EuiPanel,
EuiSearchBar,
} from '@elastic/eui';
import { CoreStart } from '../../../../src/core/public';
import { NavigationPublicPluginStart } from '../../../../src/plugins/navigation/public';
import { AppMountContext, AppMountParameters, NotificationsStart } from 'kibana/public';
import { PLUGIN_ID, PLUGIN_NAME } from '../../common';
import AlaramList from './alarms-list';
import moment from 'moment';
import OverView from "./Overview/overview";
import AlertList from './alert-list';
import CorrelationRule from './correlation-rule/correlation-rule';
import CorrelationRuleList from './correlation-rule/correlation-rule-list';
import NewCorrelationRule from './correlation-rule/new-correlation';
import EditCorrelationRule from './correlation-rule/edit-correlation';
import AdminScreen from './Admin_Screen/adminScreenComponent';
import AddGroupName from './Admin_Screen/addGroupName';
import Alarm from './alarms/alarms';
import CaseManagement from './case-management/case-management';
interface CorrelationAppAppDeps {
basename: string;
notifications: CoreStart['notifications'];
http: CoreStart['http'];
navigation: NavigationPublicPluginStart;
core: AppMountContext['core'];
}
export const CorrelationAppApp = ({
basename,
notifications,
http,
navigation,
core
}: CorrelationAppAppDeps) => {
let history = useHistory();
const [position, setPosition] = useState('static');
const [correlationData, setCorrelationData] = useState({});
const [isRuleEditable, setRuleEditable] = useState(false);
const initialQuery = EuiSearchBar.Query.MATCH_ALL;
const [query, setQuery] = useState(initialQuery);
const [error, setError] = useState(null);
const [startDate, setStartDate] = useState(moment().subtract(6, "d"));
const [endDate, setEndDate] = useState(moment());
const [propStartDate, setPropStartDate] = useState(moment().subtract(6, "d"));
const [propEndDate, setPropEndDate] = useState(moment());
const [propQuery, setPropQuery] = useState(initialQuery);
const [breadCrumbs, setBreadCrumbs] = useState([
{
text: 'Alert List',
href: '#',
onClick: e => {
e.preventDefault();
correlationClick("Alert List");
history.replace("/app/correlationapp/correlationrule");
}
},
]);
const onChange = ({ query, error }) => {
if (error) {
setError(error);
} else {
setError(null);
setQuery(query);
}
};
const handleChangeStart = (date) => {
setStartDate(date);
}
const handleChangeEnd = (date) => {
setEndDate(date);
}
const onRefreshClick = () => {
console.log('path - ', history.location.pathname);
console.log('query', query)
const searchQuery = EuiSearchBar.Query.toESQuery(query);
setPropQuery(searchQuery);
setPropStartDate(startDate);
setPropEndDate(endDate);
}
const renderSearch = () => {
const schema = {
strict: true,
fields: {
"_id": {
type: 'string'
},
"@timestamp": {
type: 'string'
},
"src.user": {
type: 'string'
},
"event.name": {
type: 'string'
},
"event.count": {
type: 'string'
},
},
};
return (
<EuiSearchBar className="fl ft p10 mt10 ml10"
defaultQuery={initialQuery}
box={{
placeholder: 'e.g: type the Group Name',
incremental: true,
schema,
}}
onChange={onChange}
/>
);
}
const searchBar = (
<EuiFlexGroup className="ml10 mr10">
<EuiFlexItem>
{renderSearch()}
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiToolTip
position="left"
title="Search query syntax"
content="For 'OR' condition the query should be enclosed in round brackets eg.(_id:'v91gbnQBNaptJ3V4XcXG' or event.count>2000). For 'AND' seperate both condition by space and don't use 'and' eg. _id:'v91gbnQBNaptJ3V4XcXG' event.count>2000">
<EuiIcon type="questionInCircle" />
</EuiToolTip>
</EuiFlexItem>
<EuiFlexItem className="datePckrMaxWidth">
<EuiDatePickerRange
startDateControl={
<EuiDatePicker
selected={startDate}
onChange={handleChangeStart}
startDate={startDate}
endDate={endDate}
isInvalid={startDate > endDate}
aria-label="Start date"
showTimeSelect
/>
}
endDateControl={
<EuiDatePicker
selected={endDate}
onChange={handleChangeEnd}
startDate={startDate}
endDate={endDate}
isInvalid={startDate > endDate}
aria-label="End date"
showTimeSelect
/>
}
/>
</EuiFlexItem>
<EuiFlexItem className="refreshMaxWidth">
<EuiButton fill color="primary" onClick={onRefreshClick}>
<EuiIcon type="refresh" /> Refresh
</EuiButton>
</EuiFlexItem>
</EuiFlexGroup>
)
const tabs = (
<EuiFlexGroup>
<EuiFlexItem>
<ul className="NavigationItems">
<li className="NavigationItem">
<NavLink
to="/app/correlationapp/correlationrule"
activeClassName="active">Correlation</NavLink>
</li>
<div className="tabVerticalSeperator"></div>
<li className="NavigationItem">
<NavLink
to="/app/correlationapp/adminscreen/groups"
activeClassName="active">Administration</NavLink>
</li>
</ul>
</EuiFlexItem>
</EuiFlexGroup>
)
const sections = [
{
items: [<EuiHeaderLogo iconType="logoKibana"></EuiHeaderLogo>, tabs]
},
{
items: [searchBar]
},
];
// Sync Kibana breadcrumbss
useEffect(() => {
console.log('useEffect brdcrmbs', breadCrumbs);
core.chrome.setBreadcrumbs(breadCrumbs);
}, [
core.application,
core.chrome,
core.http.basePath
]);
const mngBrdCrmbs = (val, data) => {
if (history.location.pathname.includes('correlationrule')) {
manageCorrelationRuleBrdcrmbs(val, data);
}
}
const correlationClick = (clickedOn) => {
let tempbrdcrmps = [];
switch (clickedOn) {
case "Correlation List":
tempbrdcrmps = breadCrumbs.filter(item => item.text === "Alert List" || item.text === "Correlation List");
setBreadCrumbs(tempbrdcrmps);
history.replace("/app/correlationapp/correlationrule/rules");
break;
case "Alert List":
tempbrdcrmps = breadCrumbs.filter(item => item.text === "Alert List");
setBreadCrumbs(tempbrdcrmps);
history.replace("/app/correlationapp/correlationrule/alerts");
break;
default:
break;
}
core.chrome.setBreadcrumbs(breadCrumbs);
}
const manageCorrelationRuleBrdcrmbs = (val, data) => {
let tempbrdcrmps = [];
switch (val) {
case "Correlation List":
if (breadCrumbs.some(item => item.text === "Correlation List")) {
correlationClick("Correlation List");
} else {
tempbrdcrmps = breadCrumbs;
tempbrdcrmps.push({
text: val,
href: '#',
onClick: e => {
e.preventDefault();
correlationClick(val);
}
});
history.replace("/app/correlationapp/correlationrule/rules");
setBreadCrumbs(tempbrdcrmps);
}
break;
case "New Rule":
tempbrdcrmps = breadCrumbs;
tempbrdcrmps.push({
text: "New Rule",
href: '#',
onClick: e => {
e.preventDefault();
}
});
history.replace("/app/correlationapp/correlationrule/newrule");
setBreadCrumbs(tempbrdcrmps);
break;
default:
setCorrelationData(data);
http.get('/users/').then((res) => {
const data = res.Response;
console.log("groups", data.groups__name);
setRuleEditable(data.groups__name.includes("KibanaAdmin"));
history.replace("/app/correlationapp/correlationrule/rule/" + val);
});
tempbrdcrmps = breadCrumbs;
tempbrdcrmps.push({
text: data._source.name,
href: '#',
onClick: e => {
e.preventDefault();
}
});
setBreadCrumbs(tempbrdcrmps);
break;
}
console.log('manageCorrelationRuleBrdcrmbs', breadCrumbs);
core.chrome.setBreadcrumbs(breadCrumbs);
console.log('breadcrumbs', core.chrome.getBreadcrumbs$())
}
return (
<div className="correlationApp">
<EuiHeader position='static' sections={sections} />
<Switch>
<Route path="/app/correlationapp/adminscreen/groups" exact
render={(props) => (<AdminScreen http={http} />)} />
<Route path="/app/correlationapp/adminscreen/groups/addgroup" exact
render={(props) => (<AddGroupName http={http} />)} />
<Route path="/app/correlationapp/correlationrule" exact
render={(props) => (<CorrelationRule http={http} mngBrdCrmbs={mngBrdCrmbs} query={propQuery} startDate={propStartDate} endDate={propEndDate} />)} />
<Route path="/app/correlationapp/correlationrule/alerts" exact
render={(props) => (<AlertList http={http} mngBrdCrmbs={mngBrdCrmbs} />)} />
<Route path="/app/correlationapp/correlationrule/rules" exact
render={(props) => (<CorrelationRuleList http={http} mngBrdCrmbs={mngBrdCrmbs} />)} />
<Route path="/app/correlationapp/correlationrule/rule/"
render={(props) => (<EditCorrelationRule http={http} isEditable={isRuleEditable} ruleData={correlationData} mngBrdCrmbs={mngBrdCrmbs} />)} />
<Route path="/app/correlationapp/correlationrule/newrule" exact
render={(props) => (<NewCorrelationRule http={http} mngBrdCrmbs={mngBrdCrmbs} />)} />
<Route path="/app/correlationapp/" exact component={OverView} />
<Route path="/app/correlationapp/casemanagement" exact
render={(props) => (<CaseManagement http={http} />)} />
</Switch>
</div>
);
};
Below is the screen shot of console log. where you "manageCorrelationRuleBrdcrmbs" is the breadcrumb I am passing and after that is core.chrome.getBreadcrumbs(). In that also in value you can see breadcrumbs are added but its not reflected on top.
Can you please help me out in this.
Regards
Praveer.
This component seems a little messy, it's hard to tell what's going on. It seems like there is an effect hook syncing a local breadcrumb variable with the core chrome state, but it's not triggered when the local state changes?
Going forward I would recommend starting with a minimal example - comment out everything besides a button which, when clicked, sets the breadcrumb. If you got that working, start re-enabling things and make sure everything keeps working.
My guess is that something else in your code is immediately resetting the breadcrumbs after manageCorrelationRuleBrdcrmbs
but it's hard to tell without being able to run the code.
Hi Joe,
Thanks for your help. Now bread crumbs are appearing properly on top header pane.
While binding array in core.chrome.setBreadcrumbs() that was getting changed because while manipulating the array passed it was getting changed as it wasn't cloned with another array. On cloning array it worked.
Thanks for your help.
Regards
Praveer.
This topic was automatically closed 28 days after the last reply. New replies are no longer allowed.
© 2020. All Rights Reserved - Elasticsearch
Apache, Apache Lucene, Apache Hadoop, Hadoop, HDFS and the yellow elephant logo are trademarks of the Apache Software Foundation in the United States and/or other countries.