Custom Dashboard CUrsor
Custom Dashboard CUrsor
Overview
The Custom Dashboard feature will allow users to create personalized
dashboards within the existing NDR (Network Detection and Response)
platform. Users can add, configure, and visualize different metrics from
network data in customizable charts. This functionality must reuse
existing components and adhere to established design patterns, coding
standards, and the platform theme.
3. Scope
In-Scope
Navigation: A new page “Custom Dashboard” under Apps (or
relevant section) in the navigation drawer.
Create Dashboard Flow:
1. Click “Create Dashboard” button.
2. Modal popup to capture dashboard title and description.
3. Dashboard creation confirmation and auto-navigation to the
new dashboard.
Add Metrics Flow:
1. Configuring metrics (X-Axis, Y-Axis, optional Breakdown).
2. Selecting chart type (Stacked, Area, etc.).
3. Automatic preview of the chart.
4. Dummy API integration referencing provided JSON fields.
Dashboard Management:
o Drag, drop, and resize cards.
o Auto-save changes.
o Delete entire dashboard (with confirmation).
o Delete individual metrics (with “More” icon, no confirmation
needed).
UI Components: Use the existing theme library; do not create new
custom components.
Out of Scope
Advanced data transformations beyond the breakdown or intervals.
Real-time streaming updates of charts (current requirement is based
on the dummy API with JSON).
Custom-coded chart components that deviate from
ApexGradientChart.jsx.
4. Figma Reference
Figma:
https://www.figma.com/design/dYGmfQ2X4ap4UMDnmA1dai/Hawk
-7.5-(Latest)?node-id=27683-99493&t=38VAqovCvcMVHkBj-0
A Figma screenshot (attached) illustrates the layout and labeling of each
screen:
1. Dashboard List Page – showing “Create Dashboard” button.
2. Create Dashboard Modal – fields for title, description.
3. Custom Dashboard – drag-and-drop grid with chart cards.
4. Add Metrics Form – X Axis, Y Axis, Breakdown, chart type, preview.
5. Delete/Confirmation – modals and toast notifications.
Key Observations / Suggested Improvements:
Ensure the “Add Metrics” button is visually distinct and consistent
with the theme.
Confirm that the “More” icon is placed on the top-right corner of
each chart card for a consistent user experience.
Provide user feedback (e.g., loading/spinner) when saving or
deleting dashboards.
5. Detailed Requirements
5.1. Navigation & Page Setup
1. New Page: Create a page named Custom Dashboard under the
Apps section.
2. Navigation Drawer: Add an entry “Custom Dashboard” in the
drawer.
3. Routing: Ensure the route is protected (if needed) and consistent
with existing patterns.
5.2. Create Dashboard Workflow
1. Step 1: User opens the Custom Dashboard page.
2. Step 2: User clicks on Create Dashboard.
3. Step 3: A modal popup appears with fields:
o Dashboard Title (required)
o Description (optional)
4. Step 4: User clicks Save.
5. Step 5: On successful creation:
o Show a confirmation popup (e.g., “Dashboard created
successfully!”).
o Automatically navigate to the newly created dashboard view.
5.3. Adding Metrics
1. Open Dashboard: The user selects a newly created (or existing)
dashboard from a table/list.
2. Click on “Add Metrics”: Opens a configuration form.
3. Configuration Fields:
1. X Axis (Interval): Time range (1 day, 1 week, 1 month, 6
months, 1 year).
2. Y Axis (Count): Select from JSON keys (e.g., client.bytes,
client.packets).
3. Breakdown (Optional): Also from JSON keys.
If a breakdown is chosen, show “Number of values”
(default: 3, range: 1–10,000).
4. Chart Type: e.g., Stacked, Area, etc.
5. Chart Preview: Auto-updates based on user selections.
6. Important: Use your deep thinking to successfully forming
chart in multiple types. Effective way to use the Breakdown
option.
4. Dummy API:
o Create a mock endpoint returning data in the shape of the
provided JSON example.
o Data from the JSON file can be used to populate the charts.
5. Save: Once metrics are configured, the card is added to the
dashboard layout.
5.4. Drag & Drop / Resizable Cards
Reusability: Must use the existing logic from
src/views/dashboards/alert-summary/AlertSummaryView.jsx.
Chart Component: Must reuse
src/views/charts/apex/ApexGradientChart.jsx.
Behavior:
o Each metric card can be moved around the dashboard grid.
o Each metric card can be resized.
o Changes persist automatically (auto-save).
5.5. Deleting Dashboards & Metrics
1. Delete Dashboard:
o A “Delete” button on the dashboard page triggers a
confirmation modal.
o If confirmed, remove the dashboard from the system.
o Show toast: “Dashboard Deleted successfully.”
2. Delete Metric:
o Within each card, a “More” icon → “Delete” option.
o No confirmation needed.
o On success, remove the card from the layout.
5.6. Auto-Save & Error Handling
Auto-Save:
o Every user action (add metric, move card, resize card) triggers
an auto-save.
o Show a brief loading spinner or “Saving…” state in the UI.
Error Handling:
o Wrap all API calls with try/catch blocks.
o If any error occurs, show an error toast or alert.
o Log errors and update the cursor rule file to prevent repeating
the same mistakes.
5.7. Theming & Styling
1. Theme Library: Use only the existing theme library components for
all UI elements.
2. CSS: Must reside within the theme or follow the theme’s styling
guidelines.
3. No Custom Components: Do not introduce new custom or 3rd-
party libraries that conflict with existing code.
5.8. Cursor Rule File
1. Cursor Rule File:
o Review the rule file before making changes.
o Update it whenever a bug is found and fixed, so future code
generations avoid the same pitfalls.
2. Documentation:
o For each new rule or fix, add a comment or short description
explaining the issue and the resolution.
JSON File:
{
"_index": ".internal.alerts-security.alerts-default-000006",
"_id": "356924b74ce2273e635f03624d28cc331bdec4ea",
"_version": 1,
"_score": 0,
"_source": {
"kibana.alert.rule.execution.timestamp": "2025-03-28T06:21:24.496Z",
"kibana.alert.start": "2025-03-28T06:21:24.496Z",
"kibana.alert.last_detected": "2025-03-28T06:21:24.496Z",
"kibana.version": "8.15.0",
"kibana.alert.rule.parameters": {
"description": "testing recreation of policy 1",
"risk_score": 0,
"severity": "critical",
"author": [],
"false_positives": [],
"from": "now-5m",
"rule_id": "ab1e5b08-64d0-4faf-9348-f3b305f71642",
"max_signals": 100,
"risk_score_mapping": [],
"severity_mapping": [],
"threat": [],
"to": "now",
"references": [],
"version": 1,
"exceptions_list": [],
"immutable": false,
"rule_source": {
"type": "internal"
},
"related_integrations": [],
"required_fields": [],
"setup": "",
"type": "esql",
"language": "esql",
"query": "FROM wiresense*| EVAL minute =
DATE_EXTRACT(\"minute_of_day\", network.start) | WHERE
(CIDR_MATCH(source.ip,\"192.168.3.0/24\",\"192.168.4.0/24\",\"192.168.1.
70/32\") OR
CIDR_MATCH(destination.ip,\"192.168.3.0/24\",\"192.168.4.0/24\",\"192.16
8.1.70/32\")) AND ((source.locality==\"public\" AND server.bytes>0) OR
(destination.locality==\"public\" AND client.bytes>0)) AND
network.start>= now() - 10 minute"
},
"kibana.alert.rule.category": "ES|QL Rule",
"kibana.alert.rule.consumer": "siem",
"kibana.alert.rule.execution.uuid": "ded5424e-bd37-4ee4-bdc7-
150642c87338",
"kibana.alert.rule.name": "shantanu",
"kibana.alert.rule.producer": "siem",
"kibana.alert.rule.revision": 0,
"kibana.alert.rule.rule_type_id": "siem.esqlRule",
"kibana.alert.rule.uuid": "04e36cb7-7f20-49aa-b296-a3494780ad7b",
"kibana.space_ids": [
"default"
],
"kibana.alert.rule.tags": [
"Policy Violation"
],
"@timestamp": "2025-03-28T06:21:24.219Z",
"client.bytes": 168,
"client.packets": 1,
"destination.address": "8.8.8.8",
"destination.as.number": 15169,
"destination.as.organization.name": "GOOGLE",
"destination.geo.continent_code": "NA",
"destination.geo.continent_name": "North America",
"destination.geo.country_iso_code": "US",
"destination.geo.country_name": "United States",
"destination.geo.location": "POINT (-97.822 37.751)",
"destination.geo.timezone": "America/Chicago",
"destination.ip": "8.8.8.8",
"destination.ip_version": "IPv4",
"destination.locality": "public",
"destination.mac": "00:08:a2:0d:23:0b",
"destination.mac_oui": "adi engineering, inc.",
"destination.macs": "00:08:a2:0d:23:0b",
"destination.port": 53,
"destination.service": "dns (UDP/53)",
"event.id": "571316607360098",
"event.interface": "eno12409",
"event.timestamp": "2025-03-28T06:17:38.142Z",
"event.type": "flow",
"network.application": "dns",
"network.bytes": 252,
"network.end": "2025-03-28T06:12:34.992Z",
"network.locality": "public",
"network.packets": 2,
"network.protocol": "UDP",
"network.start": "2025-03-28T06:12:34.984Z",
"network.transport": "UDP",
"server.bytes": 84,
"server.packets": 1,
"source.address": "192.168.1.70",
"source.asset.assetType": "unknown",
"source.asset.name": "unknown",
"source.ip": "192.168.1.70",
"source.ip_version": "IPv4",
"source.locality": "private",
"source.mac": "74:56:3c:b8:50:71",
"source.mac_oui": "Unknown",
"source.port": 60717,
"source.service": "Unknown",
"minute": 372,
"event.kind": "signal",
"kibana.alert.original_time": "2025-03-28T06:17:38.493Z",
"kibana.alert.ancestors": [
{
"id": "",
"type": "event",
"index": "",
"depth": 0
}
],
"kibana.alert.status": "active",
"kibana.alert.workflow_status": "open",
"kibana.alert.depth": 1,
"kibana.alert.reason": "event created critical alert shantanu.",
"kibana.alert.severity": "critical",
"kibana.alert.risk_score": 0,
"kibana.alert.rule.actions": [],
"kibana.alert.rule.author": [],
"kibana.alert.rule.created_at": "2025-03-05T05:06:46.033Z",
"kibana.alert.rule.created_by": "elastic",
"kibana.alert.rule.description": "testing recreation of policy 1",
"kibana.alert.rule.enabled": true,
"kibana.alert.rule.exceptions_list": [],
"kibana.alert.rule.false_positives": [],
"kibana.alert.rule.from": "now-5m",
"kibana.alert.rule.immutable": false,
"kibana.alert.rule.interval": "1m",
"kibana.alert.rule.indices": [],
"kibana.alert.rule.max_signals": 100,
"kibana.alert.rule.references": [],
"kibana.alert.rule.risk_score_mapping": [],
"kibana.alert.rule.rule_id": "ab1e5b08-64d0-4faf-9348-f3b305f71642",
"kibana.alert.rule.severity_mapping": [],
"kibana.alert.rule.threat": [],
"kibana.alert.rule.to": "now",
"kibana.alert.rule.type": "esql",
"kibana.alert.rule.updated_at": "2025-03-05T05:06:48.140Z",
"kibana.alert.rule.updated_by": "elastic",
"kibana.alert.rule.version": 1,
"kibana.alert.url":
"http://kibana-02:5601/ui/kibana/02/app/security/alerts/redirect/356924b7
4ce2273e635f03624d28cc331bdec4ea?index=.alerts-security.alerts-
default×tamp=2025-03-28T06:21:24.219Z",
"kibana.alert.uuid": "356924b74ce2273e635f03624d28cc331bdec4ea",
"kibana.alert.workflow_tags": [],
"kibana.alert.workflow_assignee_ids": [],
"kibana.alert.rule.risk_score": 0,
"kibana.alert.rule.severity": "critical",
"kibana.alert.original_event.id": "571316607360098",
"kibana.alert.original_event.interface": "eno12409",
"kibana.alert.original_event.timestamp": "2025-03-28T06:17:38.142Z",
"kibana.alert.original_event.type": "flow"
},
"fields": {
"kibana.alert.severity": [
"critical"
],
"kibana.alert.rule.updated_by": [
"elastic"
],
"signal.ancestors.depth": [
0
],
"source.mac_oui": [
"Unknown"
],
"kibana.alert.rule.tags": [
"Policy Violation"
],
"kibana.alert.reason.text": [
"event created critical alert shantanu."
],
"kibana.alert.ancestors.depth": [
0
],
"signal.rule.enabled": [
"true"
],
"signal.rule.max_signals": [
100
],
"kibana.alert.risk_score": [
0
],
"signal.rule.updated_at": [
"2025-03-05T05:06:48.140Z"
],
"source.ip": [
"192.168.1.70"
],
"destination.address": [
"8.8.8.8"
],
"kibana.alert.original_event.id": [
"571316607360098"
],
"destination.geo.continent_name": [
"North America"
],
"source.asset.assetType": [
"unknown"
],
"kibana.alert.rule.interval": [
"1m"
],
"kibana.alert.rule.type": [
"esql"
],
"event.timestamp": [
"2025-03-28T06:17:38.142Z"
],
"kibana.alert.start": [
"2025-03-28T06:21:24.496Z"
],
"kibana.alert.rule.immutable": [
"false"
],
"kibana.alert.original_event.type": [
"flow"
],
"source.port": [
60717
],
"signal.rule.from": [
"now-5m"
],
"kibana.alert.rule.enabled": [
"true"
],
"destination.geo.country_name": [
"United States"
],
"kibana.alert.rule.version": [
"1"
],
"kibana.alert.ancestors.type": [
"event"
],
"destination.port": [
53
],
"signal.ancestors.index": [
""
],
"source.mac": [
"74:56:3c:b8:50:71"
],
"network.application": [
"dns"
],
"signal.original_event.id": [
"571316607360098"
],
"network.end": [
"2025-03-28T06:12:34.992Z"
],
"signal.original_event.type": [
"flow"
],
"kibana.alert.rule.max_signals": [
100
],
"kibana.alert.rule.risk_score": [
0
],
"destination.as.organization.name.text": [
"GOOGLE"
],
"destination.ip_version": [
"IPv4"
],
"destination.ip": [
"8.8.8.8"
],
"kibana.alert.rule.consumer": [
"siem"
],
"source.locality": [
"private"
],
"destination.service": [
"dns (UDP/53)"
],
"kibana.alert.rule.category": [
"ES|QL Rule"
],
"@timestamp": [
"2025-03-28T06:21:24.219Z"
],
"signal.rule.updated_by": [
"elastic"
],
"source.ip_version": [
"IPv4"
],
"destination.geo.country_iso_code": [
"US"
],
"kibana.alert.rule.severity": [
"critical"
],
"kibana.alert.rule.execution.timestamp": [
"2025-03-28T06:21:24.496Z"
],
"kibana.alert.rule.execution.uuid": [
"ded5424e-bd37-4ee4-bdc7-150642c87338"
],
"kibana.alert.uuid": [
"356924b74ce2273e635f03624d28cc331bdec4ea"
],
"kibana.version": [
"8.15.0"
],
"source.service": [
"Unknown"
],
"event.id": [
"571316607360098"
],
"signal.ancestors.type": [
"event"
],
"event.interface": [
"eno12409"
],
"destination.as.organization.name": [
"GOOGLE"
],
"kibana.alert.rule.rule_id": [
"ab1e5b08-64d0-4faf-9348-f3b305f71642"
],
"signal.rule.type": [
"esql"
],
"kibana.alert.ancestors.id": [
""
],
"kibana.alert.url": [
"http://kibana-02:5601/ui/kibana/02/app/security/alerts/redirect/356924b7
4ce2273e635f03624d28cc331bdec4ea?index=.alerts-security.alerts-
default×tamp=2025-03-28T06:21:24.219Z"
],
"kibana.alert.rule.description": [
"testing recreation of policy 1"
],
"kibana.alert.rule.producer": [
"siem"
],
"kibana.alert.rule.to": [
"now"
],
"signal.rule.created_by": [
"elastic"
],
"signal.rule.interval": [
"1m"
],
"destination.mac": [
"00:08:a2:0d:23:0b"
],
"kibana.alert.rule.created_by": [
"elastic"
],
"signal.rule.id": [
"04e36cb7-7f20-49aa-b296-a3494780ad7b"
],
"signal.reason": [
"event created critical alert shantanu."
],
"signal.rule.risk_score": [
0
],
"kibana.alert.rule.name": [
"shantanu"
],
"signal.status": [
"open"
],
"destination.geo.timezone": [
"America/Chicago"
],
"event.kind": [
"signal"
],
"signal.rule.created_at": [
"2025-03-05T05:06:46.033Z"
],
"signal.rule.tags": [
"Policy Violation"
],
"kibana.alert.workflow_status": [
"open"
],
"kibana.alert.rule.uuid": [
"04e36cb7-7f20-49aa-b296-a3494780ad7b"
],
"network.packets": [
2
],
"kibana.alert.reason": [
"event created critical alert shantanu."
],
"signal.ancestors.id": [
""
],
"signal.original_time": [
"2025-03-28T06:17:38.493Z"
],
"signal.rule.severity": [
"critical"
],
"kibana.alert.ancestors.index": [
""
],
"kibana.alert.depth": [
1
],
"kibana.alert.original_event.timestamp": [
"2025-03-28T06:17:38.142Z"
],
"kibana.alert.rule.from": [
"now-5m"
],
"kibana.alert.rule.parameters": [
{
"description": "testing recreation of policy 1",
"risk_score": 0,
"severity": "critical",
"author": [],
"false_positives": [],
"from": "now-5m",
"rule_id": "ab1e5b08-64d0-4faf-9348-f3b305f71642",
"max_signals": 100,
"risk_score_mapping": [],
"severity_mapping": [],
"threat": [],
"to": "now",
"references": [],
"version": 1,
"exceptions_list": [],
"immutable": false,
"rule_source": {
"type": "internal"
},
"related_integrations": [],
"required_fields": [],
"setup": "",
"type": "esql",
"language": "esql",
"query": "FROM wiresense*| EVAL minute =
DATE_EXTRACT(\"minute_of_day\", network.start) | WHERE
(CIDR_MATCH(source.ip,\"192.168.3.0/24\",\"192.168.4.0/24\",\"192.168.1.
70/32\") OR
CIDR_MATCH(destination.ip,\"192.168.3.0/24\",\"192.168.4.0/24\",\"192.16
8.1.70/32\")) AND ((source.locality==\"public\" AND server.bytes>0) OR
(destination.locality==\"public\" AND client.bytes>0)) AND
network.start>= now() - 10 minute"
}
],
"kibana.alert.rule.revision": [
0
],
"signal.rule.version": [
"1"
],
"server.bytes": [
84
],
"destination.geo.continent_code": [
"NA"
],
"kibana.alert.status": [
"active"
],
"kibana.alert.last_detected": [
"2025-03-28T06:21:24.496Z"
],
"client.packets": [
1
],
"destination.macs": [
"00:08:a2:0d:23:0b"
],
"signal.depth": [
1
],
"source.address": [
"192.168.1.70"
],
"signal.rule.immutable": [
"false"
],
"kibana.alert.original_event.interface": [
"eno12409"
],
"destination.geo.location": [
{
"coordinates": [
-97.822,
37.751
],
"type": "Point"
}
],
"destination.mac_oui": [
"adi engineering, inc."
],
"kibana.alert.rule.rule_type_id": [
"siem.esqlRule"
],
"signal.rule.name": [
"shantanu"
],
"source.asset.name": [
"unknown"
],
"network.protocol": [
"UDP"
],
"signal.rule.rule_id": [
"ab1e5b08-64d0-4faf-9348-f3b305f71642"
],
"network.bytes": [
252
],
"destination.locality": [
"public"
],
"kibana.alert.rule.updated_at": [
"2025-03-05T05:06:48.140Z"
],
"signal.rule.description": [
"testing recreation of policy 1"
],
"destination.as.number": [
15169
],
"server.packets": [
1
],
"network.locality": [
"public"
],
"network.transport": [
"UDP"
],
"minute": [
372
],
"kibana.alert.rule.created_at": [
"2025-03-05T05:06:46.033Z"
],
"signal.rule.to": [
"now"
],
"client.bytes": [
168
],
"event.type": [
"flow"
],
"kibana.space_ids": [
"default"
],
"network.start": [
"2025-03-28T06:12:34.984Z"
],
"kibana.alert.original_time": [
"2025-03-28T06:17:38.493Z"
]
}
}
When a user selects X Axis = Time Range, the system should query
data grouped by the chosen interval. When Y Axis = client.bytes, the
chart should plot that data count over time. If a Breakdown is
selected, the chart should display separate series (or stacked
segments, etc.) for each breakdown category, up to the “Number of
value” limit.
7. Acceptance Criteria
1. Create Dashboard
o A user can successfully create a new dashboard with a title
and description.
o The user is navigated automatically to the new dashboard.
2. Add Metrics
o User can select an X Axis, Y Axis, optional Breakdown, chart
type, and see a live preview.
o The metric is added to the dashboard as a new card after
saving.
3. Drag & Drop
o Cards can be repositioned and resized.
o Position changes persist automatically (no manual save
required).
4. Delete Dashboard
o Confirmation modal appears.
o Dashboard is removed from the table/list upon confirmation.
o Toast message “Dashboard Deleted successfully.” appears.
5. Delete Metric
o Clicking “Delete” from the card’s “More” menu removes the
card immediately.
o No confirmation is required.
6. Error Handling
o If an API call fails, a user-friendly error message or toast is
displayed.
o The code logs errors and updates the cursor rule file with the
fix.
7. Theme Compliance
o All UI elements are from the theme library (no raw CSS or
external libraries).
8. Implementation Guidelines
1.Reuse:
src/views/dashboards/alert-summary/
AlertSummaryView.jsx for drag-and-drop/resizing.
src/views/charts/apex/ApexGradientChart.jsx for
charts.
2. Dummy API
1. Provide a mock function or endpoint: GET /api/v1/mockData
that returns a subset of the JSON fields.
2. The system transforms this data into the structure required by
ApexGradientChart.jsx.
3. State Management
1. Each dashboard can store its layout (positions, sizes) and
metrics configuration in local state or Redux (depending on
existing architecture).
2. Save to server or local storage (as per product standard).
4. Cursor Rule File
1. Each time a fix or enhancement is done, add an entry in the
rule file:
js
CopyEdit
// Cursor Rule: [Short Title of Issue]
// Explanation: [What caused the issue, how we resolved it] // Example:
"Fixed an undefined reference error when the breakdown field was empty."
```
9. Testing & QA
1. Unit Tests
o Components: test AddMetricsForm with various inputs.
o Chart rendering: ensure ApexGradientChart.jsx is called with
correct props.
2. Integration Tests
o Create dashboard → add metrics → verify chart rendering.
o Drag, drop, and resize cards → refresh the page → positions
persist.
3. End-to-End Tests
o Automated flow in a QA environment to simulate user actions:
1. Create a new dashboard.
2. Add multiple metrics with breakdown.
3. Delete one metric.
4. Delete the entire dashboard.
4. Performance
o Ensure large breakdown values (up to 10K) do not crash or
severely degrade performance.
o Validate that the chart rendering is still responsive.
Final Notes
Implementation must not break existing features. Thorough
testing is required before merging.
Documentation must be updated (e.g., README or Confluence)
with usage instructions for the new Custom Dashboard.
Cursor Rule File must be maintained diligently to prevent
repeating mistakes and to guide AI assistance in the future.