Skip to content

Dashboard Viewer Documentation

File: src/pages/private/admin/analytics/index.svelte

Overview

The Dashboard Viewer page provides administrators with a flexible interface to view and filter various dashboards. It supports multiple dashboard viewers (currently only Metabase) and includes date range filtering capabilities.

Data Structures

Dashboard Interface

ts
interface Dashboard {
  active: boolean;
  dashboardId: string;
  name: string;
  viewer: string;
}

interface FilterData {
  startDate: string; // Format: "YYYY-MM-DD"
  endDate: string; // Format: "YYYY-MM-DD"
  dashboard: string; // Dashboard name
}

Core Functions

1. Dashboard Data Fetching

ts
async function getDashboards() {
  const { data, error } = await query<any>(`
    query {
      myDashboards {
        active
        dashboardId
        name
        viewer
      }
    }
  `);
  
  if (error) {
    return { success: false, message: error?.message || error };
  }
  return {
    success: true,
    data: data?.myDashboards || [],
  };
}

2. Event Handlers

ts
// Handle filter changes
async function handleChange({ detail }) {
  filterData = detail;
  activeViewer = "metabase"; // Currently only Metabase viewer is supported
  selectedDashboard = dashboards.find((d) => d.name === filterData.dashboard);
  renderId++; // Force re-render of the viewer component
}

// Handle form submission
function handleSubmit({ detail }) {
  const { values } = detail;
  filterData = values;
}

UI Implementation

Main Component Structure

svelte
{#if busy}
  <!-- Loading spinner -->
  <div class="absolute inset-0 flex items-center justify-center bg-gray-100">
    <div class="text-center">
      <svg class="animate-spin h-12 w-12 text-blue-500 mx-auto" ...>
        <!-- Spinner SVG -->
      </svg>
    </div>
  </div>
{:else}
  <!-- Main content -->
  <div class="min-w-full px-4 sm:px-6 lg:px-8 h-full overflow-y-hidden">
    <div class="w-full flex flex-col gap-4 h-full mt-2">
      <!-- Filters component -->
      <div>
        <Filters
          dashboards={dashboardsToShow}
          {filterData}
          on:change={handleChange}
          on:submit={handleSubmit}
        />
      </div>
      
      <!-- Dashboard viewer area -->
      <div class="flex-grow overflow-y-auto p-2 relative h-full">
        {#key renderId}
          <svelte:component 
            this={previews[activeViewer]} 
            bind:functionToCall 
          />
        {/key}
      </div>
    </div>
  </div>
{/if}

Key Features

  1. Dynamic Dashboard Loading:

    • Fetches available dashboards on mount
    • Supports multiple viewer types (currently only Metabase implemented)
  2. Filtering System:

    • Date range filtering (start date and end date)
    • Dashboard selection dropdown
    • Automatic refresh when filters change
  3. Loading States:

    • Shows spinner while loading initial data
    • Smooth transitions between dashboard views
  4. Viewer System:

    • Uses Svelte's dynamic component system to switch between viewers
    • Forces re-render with #key directive when filters change
    • Passes filter data to viewer components via functionToCall binding

Usage Notes

  1. Initialization:

    • The component automatically loads available dashboards when mounted
    • Defaults to showing the first available dashboard
  2. Filter Behavior:

    • Changing any filter automatically updates the displayed dashboard
    • The dashboard viewer component receives updated filter data through functionToCall
  3. Extensibility:

    • New dashboard viewers can be added by:
      1. Creating a viewer component
      2. Adding it to the previews object in the module script
      3. Implementing the appropriate viewer selection logic
  4. Error Handling:

    • Errors during dashboard loading are displayed using the showError utility
    • The component gracefully handles missing or invalid data

Dependencies

  • dayjs for date handling
  • Custom query function for GraphQL operations
  • showError utility for error display
  • Various viewer components (currently only MetaBase)

Released under the MIT License.