Last 4 digits formula
I am an ESO user and am trying to create a widget that will show only the final 4 digits of an incident number. The beginning of the incident numbers are not always the same but the last 4 are what I need. In excel I use =right(A2,4). I then use this list in excel with an =if formula (=if(c3-c2=1,"","missing") to show me any incident numbers that were not reported. If there is a way to make this part of the widget also, it would make my job that much easier. Thank you.69Views0likes5CommentsFiltering Orders by Grouped Filter Criteria with Optional Nulls
Afternoon SS community, We need a filtering mechanism in our business where users can apply filter groups to retrieve specific orders. Each filter group consists of three fields: location_id, category_id, and client_id. When a filter value is NULL, it should behave as a wildcard and match all values for that field. The goal is for users to select one or more filter groups at a time and retrieve all matching orders — without returning duplicates, even if the same order matches multiple groups. Currently, I can filter by individual fields, but I’m unsure how to structure things to support grouped filters like this without requiring users to select each field individually. The business requirement is to let users select entire filter groups, not individual filters. Sample Data: order_id location_id category_id client_id 1 1 1 1 2 1 1 2 3 2 2 3 4 2 3 4 5 2 1 4 Filter Group Examples: Group 1 location_id: 1 category_id: 1 client_id: 1 Expected Result: Order 1 only Group 2 location_id: 1 category_id: 1 client_id: NULL Expected Result: Orders 1 and 2 Group 3 location_id: 2 category_id: NULL client_id: NULL Expected Result: Orders 3, 4, and 5 How can I design a filtering logic that: Accepts multiple filter groups (with NULLs acting as wildcards) Returns all matching orders Avoids duplicate orders if they match more than one group Any guidance or sample query structure would be greatly appreciated! Thanks in advance.173Views0likes6CommentsSeeking Best Practice for Live Detail Reporting in Sisense (Replacing SSRS)
Afternoon Sisense community, Our team is looking to replicate the functionality of a crucial SSRS report within Sisense. This report is used by a department to obtain a detailed list of jobs for a specific month. The workflow involves: Running the report for a selected month (typically the current or previous month). Reviewing the output for discrepancies. Updating the source system based on the review. Re-running the report immediately to verify the changes (requiring live data). Current Sisense Implementation & Performance Issue I've attempted to recreate this report's dataset using a Live Model connected to a Redshift SQL View. The view is complex: It contains approximately 50 columns of detailed data. It involves JOINs across 15 different tables to consolidate all necessary dimensions and metrics. The Issue: The performance of this Live Model is unacceptable. Users are accustomed to the SSRS report running a stored procedure and returning the filtered data in under 30 seconds. My Sisense Live Model is timing out. Constraints & Goal Requirement: The data must be live (no ElastiCube, as users need immediate reflection of system changes after updates). Target Performance: Sub-30-second return for monthly filtered data. Request for Guidance Given the high number of columns, multiple joins, and the strict requirement for live data with fast filtering (specifically by month), what would be the recommended best practice for implementing this detailed report in Sisense? Are there specific Sisense configurations, data modeling techniques for live connections that would address this performance bottleneck while meeting the "live" requirement? Thank you for your insights!125Views0likes6CommentsDashboard not auto-refreshing for mobile app performance data
Hi everyone, I’m using Sisense to track performance metrics from my mobile entertainment app — like daily active users, watch duration, and session time. Lately, I’ve noticed that some dashboards don’t refresh automatically, and I have to manually reload them to see updated results. I’ve already checked the data connector and refresh schedule, but everything looks fine there. Could this delay be due to caching, or maybe a dashboard setting I’m missing? Would appreciate any suggestions or settings to look into — thanks in advance!50Views1like4CommentsCASE WHEN Statements
We are using CASE WHEN statements for our customers looking to create their own booleans. We use live connection so these cannot be added to the elasticube. We are looking to complete the following: CASE WHEN [Timeline Type] = "emergency department" AND [Vital Systolic Blood Pressure] < 90 THEN 1 ELSE 0 END Additionally, customers would like to know the percentage of time the above is yes. Can this be completed in the function area or do we need to handle this in our transformation pipeline?752Views0likes1CommentHow to hide a row in a pivot table?
Hello. I am looking to hide (not filter out) a row based on its content in a pivot table widget. I haven't been able to find a native functionality for that, but I assume there's javascript to do that. Can anyone assist? I've only been able to find column masking, but that isn't helpful.117Views0likes6CommentsDashboard (fire unit time limit)
Hello, I am currently working in ESO (insights), and I wondered if anyone had any luck with making a dashboard that would display information like the one attached? It would be for certain apparatus that go lights-and-sirens to an incident, but are over a time limit. I am having issues getting the filters to function for me. Thanks46Views0likes4CommentsHow to filter a table/pivot table: Filter one column that does not equal another column?
Hi DRay Liliia_DevX , I am trying to see if there is logic where I have a pivot table and I want to filter one column based on another column that do not equal, so getting all the results that match within a widget filter or maybe a formula filter.86Views0likes3CommentsWidget Error
I’m working on integrating a few Sisense dashboards into my project, but I’m running into this error. import React, { useMemo, useEffect, useState } from 'react'; import { useApi, configApiRef } from '@backstage/core-plugin-api'; import { SisenseContextProvider, WidgetById } from '@sisense/sdk-ui'; import { filterFactory } from '@sisense/sdk-data'; import SisenseDashboard from './SisenseDashboard'; import solutionSisenseOrg from '../../solution-sisense-org-mapping.json'; const SISENSE_URL = ''; const SISENSE_TOKEN = ''; type SisenseOrgMapping = Record<string, Record<string, any>>; type SisenseChartProps = { dashboardOid: string; tab: string; widgetLists?: []; isWidgetRequired?: boolean; }; const centerStyle = { minHeight: '40vh', display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', fontSize: '1.1rem', background: 'none', }; export const SisenseChart: React.FC<SisenseChartProps> = ({ dashboardOid, tab, widgetLists = [], isWidgetRequired = true, }) => { const config = useApi(configApiRef); const { sisenseUrl, sisenseToken } = useMemo( () => ({ sisenseUrl: config.getOptionalString('sisense.url') ?? SISENSE_URL, sisenseToken: config.getOptionalString('sisense.token') ?? SISENSE_TOKEN, }), [config], ); // Extract current org from URL const currentUrl = window.location.href; const solutionOrg = useMemo(() => { const match = currentUrl.match(/\/system\/([^/]+)/); return match?.[1] ?? ''; }, [currentUrl]); // Map to Sisense org const mappedSisenseOrg = useMemo(() => { if (!solutionSisenseOrg || typeof solutionSisenseOrg !== 'object') return undefined; return (solutionSisenseOrg as SisenseOrgMapping)[solutionOrg]; }, [solutionOrg]); // State for dashboard filters const [filters, setFilters] = useState<any[]>([]); const [isLoading, setLoading] = useState(true); const [error, setError] = useState<string | null>(null); // Reset filters/loading when dashboardOid or tab changes useEffect(() => { setFilters([]); setLoading(true); setError(null); }, [dashboardOid, tab]); // Fetch dashboard filters useEffect(() => { if (!dashboardOid || !sisenseUrl || !sisenseToken) return; const fetchDashboard = async () => { try { const response = await fetch( `${sisenseUrl}/api/v1/dashboards/${dashboardOid}`, { headers: { Authorization: `Bearer ${sisenseToken}` } }, ); if (!response.ok) throw new Error('Failed to fetch dashboard'); const data = await response.json(); setFilters(data.filters || []); setLoading(false); } catch (err: any) { setError('Failed to load dashboard filters.'); setLoading(false); } }; fetchDashboard(); }, [dashboardOid, sisenseUrl, sisenseToken]); console.log('Fetched filters:', filters); // Memoize jaqlFilters const jaqlFilters = useMemo(() => { // Extract filters from levels const levelFilters = filters.flatMap( (filter: any) => filter.levels?.filter( (level: any) => level.table === 'projects' || level.table === 'products' || // (level.table === 'Business_Unit_Sols' && level.column === 'solution') || (level.table === 'rca_all_issues' && (level.column === 'solutions' || level.column === 'incident_date' || level.column === 'incident_date (Calendar)')) || (level.table === 'defect_metrics' && level.column === 'project_name') || (level.table === 'quality_scorecard' && level.column === 'filter_solution'), ) || [], ) || []; // Extract root jaql filters const rootJaqlFilters = filters .filter((filter: any) => filter.jaql) .map((filter: any) => filter.jaql) .filter( (jaql: any) => (jaql.table === 'rca_all_issues' && (jaql.column === 'solutions' || jaql.column === 'incident_date' || jaql.column === 'incident_date (Calendar)')) || (jaql.table === 'Business_Unit_Sols' && jaql.column === 'solution') || (jaql.table === 'projects') || (jaql.table === 'products') ); return [...levelFilters, ...rootJaqlFilters]; }, [filters]); // Memoize jaql, attribute, filterquery (always called, never conditionally) let hasValidFilter = null; let members = null; if (mappedSisenseOrg && mappedSisenseOrg[tab]) { if (typeof mappedSisenseOrg[tab] === 'string') { members = [mappedSisenseOrg[tab]]; hasValidFilter = Boolean( jaqlFilters.length && jaqlFilters[0]?.dim && mappedSisenseOrg && mappedSisenseOrg[tab], ); } else if (typeof mappedSisenseOrg[tab] === 'object') { hasValidFilter = Boolean( jaqlFilters.length && jaqlFilters[0]?.dim && mappedSisenseOrg && mappedSisenseOrg[tab] && mappedSisenseOrg[tab][dashboardOid], ); members = [mappedSisenseOrg[tab][dashboardOid]]; } } const jaql = useMemo( () => hasValidFilter ? { dim: jaqlFilters[0]?.dim, datatype: jaqlFilters[0]?.datatype || 'text', isDashboardFilter: jaqlFilters[0]?.isDashboardFilter || false, title: jaqlFilters[0]?.title, collapsed: jaqlFilters[0]?.collapsed || false, filter: { explicit: true, multiSelection: true, members: members ? members : [], }, } : null, [members, hasValidFilter, jaqlFilters], ); const attribute = useMemo( () => hasValidFilter ? { jaql: () => ({ jaql: { dim: jaqlFilters[0]?.dim, datatype: jaqlFilters[0]?.datatype || 'text', isDashboardFilter: jaqlFilters[0]?.isDashboardFilter || false, title: jaqlFilters[0]?.title, collapsed: jaqlFilters[0]?.collapsed || false, filter: { explicit: true, multiSelection: true, members: members ? members : [], }, }, }), serialize: () => ({ dim: jaqlFilters[0]?.dim, datatype: jaqlFilters[0]?.datatype || 'text', title: jaqlFilters[0]?.title, }), id: jaqlFilters[0]?.dim, } : null, [members, hasValidFilter, jaqlFilters], ); const filterquery: any = useMemo(() => { if (!hasValidFilter || !attribute || !jaql) return null; return filterFactory.customFilter(attribute as any, jaql as any, { disabled: false, }); }, [hasValidFilter, attribute, jaql]); if (!sisenseUrl || !sisenseToken) return null; if (!solutionOrg) return ( <div style={centerStyle as React.CSSProperties}> Could not determine organization from URL. </div> ); if (!mappedSisenseOrg) return ( <div style={centerStyle as React.CSSProperties}> No Sisense organization mapping found for "{solutionOrg}". </div> ); if (error) return <div style={centerStyle as React.CSSProperties}>{error}</div>; if (isLoading) return ( <div style={centerStyle as React.CSSProperties}> <div className="sisense-loader" style={{ marginBottom: 12 }}> {' '} Loading...{' '} </div> </div> ); if (!hasValidFilter || !filterquery) { return ( <div style={centerStyle as React.CSSProperties}> No valid filter found for this {tab} dashboard. </div> ); } const renderWidgets = () => ( <div> {widgetLists.map((widgetOid, idx) => ( <WidgetById key={widgetOid || idx} // Ensure key is never null widgetOid={widgetOid} dashboardOid={dashboardOid} includeDashboardFilters={false} filters={[filterquery]} /> ))} </div> ); let contentToShow: React.ReactNode = null; if (isWidgetRequired && widgetLists.length > 0) { contentToShow = renderWidgets(); } else if (!isWidgetRequired && widgetLists.length === 0) { contentToShow = null; } else { contentToShow = ( <SisenseDashboard filterquery={filterquery} dashboardOid={dashboardOid} /> ); } return ( <SisenseContextProvider url={sisenseUrl} token={sisenseToken}> {contentToShow} </SisenseContextProvider> ); }; --------------------- import React from 'react'; import { Dashboard, dashboardModelTranslator, useGetDashboardModel, useCustomWidgets, } from '@sisense/sdk-ui'; import CustomHistogramWidget from './CustomHistogramWidget'; interface SisenseDashboardProps { filterquery: any[]; dashboardOid: string; } const SisenseDashboard: React.FC<SisenseDashboardProps> = ({ filterquery, dashboardOid, }) => { const { dashboard } = useGetDashboardModel({ dashboardOid, includeFilters: false, includeWidgets: true, }); const { registerCustomWidget } = useCustomWidgets(); if (!dashboard) return null; const { title, widgets, layoutOptions, styleOptions, widgetsOptions } = dashboardModelTranslator.toDashboardProps(dashboard); registerCustomWidget('histogramwidget', CustomHistogramWidget); // console.log('Dashboard Props:widgets', widgets); // Add a non-null key property to each widget using its id console.log('Dashboard Widgets:', layoutOptions); const widgetsWithValidId = Array.isArray(widgets) ? widgets.map((widget: any, idx: number) => { let id = typeof widget?.id === 'string' && widget.id.trim() ? widget.id.trim() : `widget-${idx}`; if (!id) { console.warn('Widget missing id:', widget); id = `widget-${idx}`; } const widgetType = widget.widgetType || widget.type || widget.kind || widget.category || ''; const widgetProps: any = { ...widget, id, key: id}; if ( widgetType !== 'text' && widgetType !== 'TextWidget' && widgetType !== 'TEXT' ) { widgetProps.filters = filterquery; } else { delete widgetProps.filters; } return widgetProps; }) : []; return ( <div style={{ marginBottom: '24px' }}> <Dashboard id={dashboardOid} title={title} layoutOptions={layoutOptions} widgets={widgetsWithValidId} filters={filterquery} config={{ filtersPanel: { visible: false } }} styleOptions={styleOptions} widgetsOptions={widgetsOptions} /> </div> ); }; export default SisenseDashboard; ERROR: 1. dimension, [rca_all_issues.incident_date (Calendar)], was not found. rcas_and_related_actions {"dimension":"[rca_all_issues.incident_date (Calendar)]"} 2. Value cannot be null. (Parameter 'key') rcas_and_related_action145Views0likes7Comments