Lofty idea: reproduce a dashboard outside of Sugar

We would like to "copy" some Sugar Dashboards leveraging the APIs that can be used to retrieve the metadata from the Dashboard.

We don't need full Dashboard functionality with filters etc, we just need to give a handful of non-Sugar users the ability to look at a specific Dashboard as a snapshot in time, on occasion.

We can use an api call to /Dashboards/<dashboardID> to get the dashboard metadata, including the ReportIDs for each of the dashlets included, but we can't use the /Reports API for stacked histogram reports (they are not simple Rows and Columns).

I attempted to use the reportIDs to get the metadata for each dashlet from the /Reports/<reportID>/chart API but I am having a lot of trouble interpreting and mapping the resulting metadata.

Is there an easier way that I'm missing or some "Rosetta Stone" for interpreting the metadata that I can refer to?

Thanks,

Francesca

Parents
  • Hi  ,

    If you’re planning to use a live data report (which may not actually be necessary based on your ask here), you would need to interpret the JSON results and render them using the ChartJS engine (there's no shortcuts on this).

    Another option is to leverage the existing “Download chart” functionality in the report dashlet. This is a client-side trigger that outputs a base64-encoded PNG of the chart currently being displayed. In theory, you could use that output to download the image and save to your external service and serve it. That said, this approach would unfortunately require a manual step.

    Elaborating, on the previous alternative with a more auto approach, you could extend
    clients/base/views/report-dashlet/report-dashlet.js
    by adding a listener for the report:data:chart:loaded event and triggering the downloadReport function. This would generate the base64 PNG automatically, which you could then capture, send to an API, store, and make available to other users later.

    The main advantage of this approach is that you’d get the full chart exactly as rendered in Sugar. The downside is that the dashboard would need to remain open, since the dashlet would effectively be “publishing” the image every X minutes or hours.

    Let me know if you want to explore any of these options in more detail.

    Rafael Fernandes

    Staff Developer Advocate | SugarCRM

  • Thanks for the tips  

    We have tools in Wolfram Language to create charts of all sorts.

    The idea is to run the APIs from a Wolfram Notebook, retrieve the data, and build the charts in Wolfram Language.

    I'm 99% of the way there, I'm missing a few labels... I was just hoping to find more guidance for building the interpreter of the dashboard and chart metadata to translate it into Wolfram Language, ideally the code would be generic enough that I could pass any dashboardID and reproduce its current state on demand inside Wolfram Language presentations.

    All in the spirit of "drink your own Prosecco" Smile (I'm Italian no Champagne)

Reply
  • Thanks for the tips  

    We have tools in Wolfram Language to create charts of all sorts.

    The idea is to run the APIs from a Wolfram Notebook, retrieve the data, and build the charts in Wolfram Language.

    I'm 99% of the way there, I'm missing a few labels... I was just hoping to find more guidance for building the interpreter of the dashboard and chart metadata to translate it into Wolfram Language, ideally the code would be generic enough that I could pass any dashboardID and reproduce its current state on demand inside Wolfram Language presentations.

    All in the spirit of "drink your own Prosecco" Smile (I'm Italian no Champagne)

Children
  • Does this help  ?

    Here is a line-by-line explanation of how the provided JSON data can be consumed to generate a chart, independent of the SugarCRM framework:

    1. Extract Chart Properties


    - chartData.properties[0]` contains metadata for the chart:
    - title, subtitle: Chart title and subtitle.
    - type: Chart type (e.g., stacked group by).
    - legend, labels, print` Display options.
    - groupName, seriesName: X-axis and series labels.
    - xDataType, yDataType: Data types for axes.

    Usage:
    Use these properties to configure the chart's appearance, axes, and legend.

    2. Prepare Series Labels
    - `chartData.label`: Array of series labels.
    - Example: `["", "Existing Business", "New Business"]`

    **Usage:**
    Ignore the first empty string. The rest are used as legend entries and to label each data series (e.g., bar or line).

    3. Assign Colors
    - `chartData.color`: Array of color hex codes.

    Usage:
    Assign these colors to each series for visual distinction.

    4. Prepare Data Points
    - `chartData.values`: Array of objects, each representing a data point (e.g., a quarter).
    - `label`: X-axis value (e.g., "Q1 2025").
    - `gvalue`: Total value for the group (e.g., sum for the quarter).
    - `gvaluelabel`: Formatted total value (e.g., "$867.00").
    - `values`: Array of values for each series for this group.
    - `valuelabels`: Formatted values for each series.
    - `links`: Optional drill-down links for each series.

    Usage:
    For each data point:
    - Use `label` for the X-axis.
    - For each series, use the corresponding value in `values` for the Y-axis.
    - Use `valuelabels` for tooltips or data labels.
    - Optionally, use `links` for interactive drill-down.

    5. Map Series to Data
    - The index of each value in `values` matches the index in `chartData.label` (excluding the first empty string).

    Usage:
    For each series (e.g., "Existing Business", "New Business"), plot the value at the corresponding index for each data point.

    6. Configure Axes
    - X-axis: Use `label` from each value object (e.g., "Q1 2025").
    - Y-axis: Use `values` for each series.
    - Axis labels: Use `groupName` and `seriesName` from `properties`.

    7. Apply Filters (Optional)
    - `reportData.filters_def`: Contains filter definitions used to generate the report.

    Usage:
    If you want to replicate the report, apply these filters to your data source before aggregating.

    8. Summary and Grouping
    - `reportData.summary_columns` and `group_defs`: Define how data is grouped and summarized.

    Usage:
    Group your data by the fields in `group_defs` and aggregate using the functions in `summary_columns` (e.g., sum of `amount`).

    9. Final Chart Construction
    - For each group (quarter), plot a stacked bar (or other chart type) with each series value.
    - Use colors, labels, and tooltips as described above.

    Example Pseudocode

    // 1. Get series labels (skip first empty string)
    const seriesLabels = chartData.label.slice(1);
    
    // 2. Get colors for each series
    const seriesColors = chartData.color.slice(0, seriesLabels.length);
    
    // 3. Prepare data for charting library
    const chartSeries = seriesLabels.map((label, idx) => ({
    name: label,
    color: seriesColors[idx],
    data: chartData.values.map(point => ({
    x: point.label,
    y: point.values[idx],
    label: point.valuelabels[idx],
    link: point.links[idx]
    }))
    }));
    
    // 4. Configure chart options using chartData.properties[0]
    const chartOptions = {
    title: chartData.properties[0].title,
    xAxis: { title: chartData.properties[0].groupName },
    yAxis: { title: chartData.properties[0].seriesName, type: chartData.properties[0].yDataType },
    legend: { enabled: chartData.properties[0].legend === "on" }
    };
    
    // 5. Render chart using your preferred library (e.g., Chart.js, Highcharts, etc.)
    


    Summary:
    - Use `properties` for chart configuration.
    - Use `label` for series names.
    - Use `color` for series colors.
    - Use `values` for data points per group.
    - Map each value to its series and group.
    - Use `summary_columns` and `group_defs` for grouping and aggregation logic.
    - Apply filters as needed.

    Rafael Fernandes

    Staff Developer Advocate | SugarCRM

  • This might be of further help...

    The manner in which we render the reports based charts can be described as follows...

    - Reports object is instantiated and report definition is retrieved (stored as JSON object in saved_reports->content)  

    - Reports object executes run_query() to retrieve its corresponding data

    - Data is used to then create a JSON object whose format matches that expected by the chart (it will vary based on chart type, etc.), the JSON typically also includes some of the settings for the chart attributes Rafael mentions

    - JSON object is passed to chart object and the chart is then rendered  

    I would think you should be able to mimic this behavior by retrieving the report definition (to get the report labels, etc) then retrieving the data via run_query(). It sounds like the Wolfram engine you mention would have a predefined format it expects for the input, so you would then just need to massage the result set a bit to map it accordingly.