Sisense Community logo
    • Community Feedback
    • Chapters
    • Events
    • Forums
      • Help and How To
      • Product Feedback Forum
      • Strategy & Use Cases
    • Blogs
    • KB Docs
      • KB Docs
      • Add-Ons & Plug-Ins
      • APIs
      • Best Practices
      • Blox
      • CDT
      • Cloud Managed Service
      • Data Models
      • Data Sources
      • Embedding Analytics
      • How-Tos & FAQs
      • Onboarding
      • PySisense
      • Security
      • Sisense Administration
      • Sisense Intelligence & AI
      • Troubleshooting
      • Widget & Dashboard Scripts
    • Support
    • Learning
      • Sisense Academy: Free Courses and Certifications
      • Official Developer Documentation
      • Official Product Documentation
      • Official Sisense Youtube Channel
      • Sisense Compose SDK Playground
      • Official Sisense Discord
    • Use Case Gallery
    Discussions
    •                    
    •                    
    •                    
    •                    
    •                    
    •                    
    •                    
    •                    
    •                    
    •                    
    •                    
    •                    
    •                    
    •                    
    •                    
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   
    Discussions
    • TagsChevronRightIcon
    React
    • kundankumar
      • Help and How-To
               
      kundankumar
      Widget 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_action

      9 months agolast reply 7 months ago
      7
               
    • Francois van Vuuren
      • Help and How-To
               
      Francois van Vuuren
      Get a list of Datasets in an elasticube with ComposeSDK
                               

      I want to create a dropdown containing all the tables/datasets within a specific elasticube with React.  I created a dropwdown that I can populate all the elasticubes in my instance with, but I want to be able to see the list of datasets from that elasticubes but I am struggling to find the api end-point or if there is another way.  Ideally would then also like to be able to build a table, containing all the data from that table, once selected, but trying to take it one step at a time 🙂   Any advise would be greatly appreciated.

      1 year agolast reply 1 year ago
      7
               
    • apillai
      • Help and How-To
               
      apillai
      compose sdk aggregated Table widget expand collapse feature
               

      Hi Team , Is there an option in compose sdk to build an aggregated table with expand collapse button for certain columns Thanks, Aneesh

      1 year agolast reply 1 year ago
      2
               
      • Help and How-ToChevronRightIcon
                       
      Custom Widget Script Styling Not Coming Through on sdk-ui Chart Component
      ewoytowitz
      ewoytowitz
      Posted 2 years ago • Last reply 1 year ago
      11
               
      • Embedding AnalyticsChevronRightIcon

      Supercharging Your Tabular Views: AG Grid Powered by Sisense Compose SDK

                                               

      Supercharging Your Tabular Views: AG Grid Powered by Sisense Compose SDK   How to Build a Tabular View with Sisense Compose SDK and AG Grid   This guide walks through how to use Sisense Compose SDK's query hooks to power an AG Grid table component in React. We'll break down the steps, explain the code, and highlight the key functionalities of AG Grid. Introduction Tables are essential in BI applications for summarizing large datasets and providing users with a simple way to navigate, filter, and analyze data. AG Grid is an ideal solution for tabular views, offering robust capabilities like sorting, filtering, grouping, and data exporting. When combined with the Sisense Compose SDK, you can power real-time, data-driven applications that provide users with seamless, customizable data interactions. In this example, we are using a sample eCommerce dataset, available through the Sisense Compose SDK free trial, to demonstrate how powerful this combination can be. Users can explore product sales by country, age range, and time period in a fully interactive grid. AG Grid's advanced tabular capabilities include features like multi-level row grouping, custom value formatting, pivot mode for creating complex data hierarchies, and the ability to export data to formats like CSV. These features, when integrated with Sisense's query hooks and real-time data, enable developers to create highly dynamic dashboards where users can manipulate large datasets with ease. This combination of Sisense Compose SDK and AG Grid empowers developers to create rich, interactive data experiences, allowing users to filter and manipulate data at granular levels, all while leveraging real-time querying powered by Sisense. Step-by-Step Breakdown of the Code Setting Up the Project packages used: npm install ag-grid-react ag-grid-community @mui/material @sisense/sdk-ui @sisense/sdk-data   Register AG Grid Modules AG Grid uses modules to enable functionality like client-side row models, and sorting and filtering. We register the modules to be used within AG Grid: import { AgGridReact } from "ag-grid-react"; import "ag-grid-community/styles/ag-grid.css"; import "ag-grid-community/styles/ag-theme-alpine.css";   These imports ensure that AG Grid is properly styled and functional. Setting Up the Query with Sisense SDK Sisense Compose SDK’s `useExecuteQuery` is used to fetch data from your data sources. The query can include dimensions and measures which AG Grid will render.   const queryProps = useMemo(() => ({ dataSource: DM.DataSource, dimensions: [DM.Country.Country, DM.Commerce.AgeRange, DM.Commerce.Date.Years], measures: [ measureFactory.sum(DM.Commerce.Revenue, "Total Revenue"), measureFactory.sum(DM.Commerce.Quantity, "Total Quantity"), ], }), []);   Here, `useExecuteQuery` executes the query based on the defined data source (`DM.DataSource`), dimensions (e.g., country, age range), and measures (e.g., revenue, quantity). Fetching and Displaying Data We leverage React's `useEffect` hook to update the state of `rowData` once data is fetched. This ensures AG Grid displays up-to-date information.   const { data, isLoading, isError } = useExecuteQuery(queryProps); useEffect(() => { if (!isLoading && !isError && data) { const rows = data.rows.map((row) => ({ country: row[0]?.text || "N/A", ageRange: row[1]?.text || "N/A", year: row[2]?.text || "N/A", revenue: row[3]?.data || 0, quantity: row[4]?.data || 0, })); setRowData(rows); } }, [data, isLoading, isError]);   This block processes the raw data returned from the query and formats it for use in the AG Grid. Column Definitions AG Grid requires column definitions that define how each field should be displayed.   const columnDefs = useMemo(() => [ { field: "country", headerName: "Country" }, { field: "ageRange", headerName: "Age Range" }, { field: "year", headerName: "Year" }, { field: "revenue", headerName: "Total Revenue", valueFormatter: (params) => abbreviateNumber(params.value), // Helper function for number formatting }, { field: "quantity", headerName: "Total Quantity", valueFormatter: (params) => abbreviateNumber(params.value), }, ], []);   We define five columns: country, age range, year, revenue, and quantity. The `valueFormatter` function ensures that numbers are displayed in an abbreviated format (e.g., "1.2K" for thousands). AG Grid Configuration The grid configuration includes `defaultColDef` for common properties across all columns (like filtering and sorting), and `animateRows` for smoother transitions.   const defaultColDef = useMemo(() => ({ flex: 1, minWidth: 100, sortable: true, filter: true, resizable: true, }), []);   Here, all columns are set to be sortable, filterable, and resizable by default. Exporting Data AG Grid’s API allows exporting table data to CSV. We use a button to trigger the export functionality:   const onBtnExport = useCallback(() => { gridRef.current.api.exportDataAsCsv(); }, []);   Rendering the Grid Finally, we render the AG Grid component, passing the `rowData`, `columnDefs`, and `defaultColDef` as props:   <AgGridReact ref={gridRef} rowData={rowData} columnDefs={columnDefs} defaultColDef={defaultColDef} animateRows={true} />   This sets up the AG Grid to dynamically render data retrieved via Sisense Compose SDK. Value of Tabular Views Tabular views are crucial for presenting structured data, providing an easy way to explore, filter, and analyze datasets. AG Grid’s built-in features like sorting, filtering, and exporting make it a perfect fit for visualizing data-rich tables in BI environments. Features of AG Grid - Sorting and Filtering: Users can sort and filter data by column. - Grouping: Group rows by common fields. - Customization: Full flexibility in column definitions and row configurations. - Exporting: Allows exporting table data to CSV format. - Performance: Handles large datasets efficiently. Using Sisense Compose SDK to Power Components Sisense Compose SDK is an API-first approach to data querying, which powers the `useExecuteQuery` hook in this component. By combining it with AG Grid, you can easily visualize dynamic, real-time data in table format. Here is a functional example in Github  https://github.com/sisensers/ag-grid-compose-sdk.git

      Sisense User
      Sisense UserPosted 1 year ago
      0
               
      • Embedding AnalyticsChevronRightIcon

      Using Compose SDK with D3 Packed Bubble Charts

                                       

      Using Compose SDK with D3 Packed Bubble Charts How to Build a Packed Bubble Chart Using D3.js and the Sisense Compose SDK D3 Packed Bubble Git Repo   What Is D3.js? D3.js (Data-Driven Documents) is a popular JavaScript library used to create complex, data-driven visualizations in the web browser. D3 allows developers to bind data to a Document Object Model (DOM) and apply transformations to the data using SVG, HTML, and CSS. Its flexibility makes it the go-to library for building everything from bar charts to complex network diagrams. Why Use D3.js? - Customizability: You have full control over how elements are drawn and interact on the page. - Scalability: D3 can handle large datasets efficiently and supports dynamic updates as data changes. - Community: It has a robust ecosystem and large  developer community. What Is Sisense Compose SDK? Sisense Compose SDK is a powerful developer toolkit that compartmentalizes Sisense's APIs into JavaScript packages, allowing developers to build custom data products within their preferred IDE. With the Compose SDK, developers can embed pre-existing Sisense Fusion Embed charts or build custom visualizations from the ground up using query and chart components. This flexibility empowers developers to integrate custom chart libraries powered by Sisense, all while adhering to the platform's robust data security protocols. The SDK enables seamless interaction with Sisense's data layer, allowing you to query data, execute complex analytics workflows, and retrieve results programmatically, making it an essential tool for embedding advanced analytics into your applications. Why Use the Sisense Compose SDK? -   Flexibility: You can embed pre-existing Sisense Fusion Embed charts or build fully custom visualizations using your preferred tools, such as D3.js. The SDK provides the flexibility to create tailor-made analytics experiences that fit your unique requirements. -   Customization: Developers can leverage the SDK to execute, filter, and transform data, and even power custom chart libraries like D3.js, while still ensuring that Sisense’s data security protocols are adhered to. The SDK also allows for building visualizations from the ground up, giving you full control over every aspect of the charting process. Integrating D3.js with the Sisense Compose SDK In this tutorial, we’ll walk through how to combine the strengths of D3.js for visualization with the Sisense Compose SDK for querying and managing data, allowing you to build a packed bubble chart that is both highly customizable and secure. Setting Up the Project First, you need to install the required dependencies: ```bash npm install react react-dom npm install d3 npm install @sisense/sdk-ui @sisense/sdk-data ``` You’ll also need to set up a `.env` file with your Sisense instance URL and API Token: ```bash REACT_APP_SISENSE_INSTANCE_URL=https://your-sisense-instance-url.com REACT_APP_SISENSE_API_TOKEN=your-api-token ``` These variables will be used to authenticate with your Sisense instance. Querying Data with Sisense Compose SDK The Sisense Compose SDK allows you to query your data models directly. Here’s an example of querying for age range, total cost, and total revenue: ``` const { data, isLoading, isError } = useExecuteQuery({ dataSource: DM.DataSource, dimensions: [DM.Commerce.AgeRange], measures: [ measureFactory.sum(DM.Commerce.Cost, 'Total Cost'), measureFactory.sum(DM.Commerce.Revenue, 'Total Revenue'), ], }); ``` This query fetches the age range of customers, along with the total cost and total revenue for each age group. The `useExecuteQuery` hook makes it easy to execute the query and retrieve the results. Visualizing Data with D3.js Once the data is fetched, we can map it to D3.js to visualize it as a packed bubble chart: ``` const bubbleData = data.rows.map(row => ({ ageRange: row[0].data, totalCost: row[1].data ?? 0, totalRevenue: row[2].data ?? 0, })); // Define the bubble chart using D3 svg.selectAll('circle') .data(bubbleData) .enter() .append('circle') .attr('cx', d => xScale(d.ageRange)) .attr('cy', d => yScale(d.totalRevenue)) .attr('r', d => radiusScale(d.totalCost)) .attr('fill', 'steelblue') .attr('opacity', 0.7); ``` Here, `xScale` and `yScale` are used to position the bubbles, and `radiusScale` controls the size of the bubbles based on the `totalCost`. Each bubble represents an age range, and its size reflects the total cost associated with that range. Enhancing the User Experience By leveraging the Sisense Compose SDK and D3.js, you can build highly interactive and customizable visualizations. This packed bubble chart will resize and reposition the bubbles in real-time as new data is queried or filters are applied. You can further extend this by adding hover tooltips, click events, or dynamic filters using D3.js transitions. Conclusion Combining D3.js with the Sisense Compose SDK allows you to create dynamic, real-time data visualizations that not only look great but also provide meaningful insights. This packed bubble chart offers a visually compelling way to represent comparative data, such as cost and revenue across different age groups. Whether you’re building dashboards or embedding analytics into a product, this integration delivers powerful visualizations tailored to your needs. If you’re not already using Sisense, try it out with their free trial   here .

      Sisense User
      Sisense UserPosted 1 year ago
      0
               
    • Padrickk
      • Help and How-To
               
      Padrickk
      I need some guidance as in what category should I post into?
                               

      Hello there, This is my first post after just joining this discussion, so please forgive me and provide kind assistance if I have posted to the wrong subsection. I am new here but a real enthusiast and loving this community so far. I have a background in teaching coding and in education and feel I could help with documentation, at least for starters. As a new member in this forum and wish to share and gain some knowledge. I am looking forward to create my own discussion to resolve my query and gain some knowledge though I have taken part in various discussion which is definitely helped me a lot. Also in what category should be taken depends on what factors? Thank you in advance.  

      1 year agolast reply 1 year ago
      2
               
    • Abenezer
      • Help and How-To
               
      Abenezer
      I received an error: "The dimension was not found," even though I have it in my data model.
                       

      React component < Indicator title = "Total Revenue" imeasure = { measureFactory . sum ( DM . Attendees . PricePaid ) } dataSource = { DM . DataSource } color = { theme . palette . primary . main } filters = { all_filters } primaryValueFormat = "Currency" ShowSecondaryValue /> Data Model PricePaid : createAttribute ({ name : 'PricePaid' , type : 'numeric-attribute' , expression : '[Attendees .PricePaid]' , }),

      1 year agolast reply 1 year ago
      3
               
      • Help and How-ToChevronRightIcon
                       
      Sorting Chart By Different Field Than The One Displayed
      ewoytowitz
      ewoytowitz
      Posted 2 years ago • Last reply 2 years ago
      4
               
      • Help and How-ToChevronRightIcon
                       
      Help with filterFactory.dateRange
      ewoytowitz
      ewoytowitz
      Posted 2 years ago • Last reply 2 years ago
      2