Skip to content

Dashboard Viewer Component Documentation

File: src/pages/private/admin/analytics/partial/metaBase.svelte

Overview

This component displays a dashboard in an iframe, handling loading states, errors, and initial empty states. It communicates with a GraphQL API to fetch dashboard URLs and manages the display lifecycle.

Module Script (GraphQL Query)

ts
async function getDashboard(startDate: string, endDate: string, dashboardId: number) {
  const { data, error } = await query<any>(`
    query dashboardUrl(
      $dashboardId: Long!
      $expirySeconds: Int!
      $parameters: String!
    ) {
      dashboardUrl(
        expirySeconds: $expirySeconds
        dashboardId: $dashboardId
        parameters: $parameters
      )
    }
  `, {
    _id: uniqueId("q"),
    dashboardId,
    expirySeconds: 3000, // 50 minutes expiry
    parameters: JSON.stringify({
      start_date: startDate,
      end_date: endDate
    })
  });

  if (error) {
    return { success: false, message: error?.message || error };
  }
  return {
    success: true,
    data: data?.dashboardUrl
  };
}

Component Script

Props

ts
export let filterData = {
  startDate: string | null,
  endDate: string | null,
  dashboard: string | null
};

export let functionToCall: (() => {
  startDate: string,
  endDate: string,
  dashboardId: number
}) | null;

State Variables

ts
let src: string = ""; // iframe source URL
let isLoading: boolean = false;
let hasError: boolean = false;
let isInitialized: boolean = true;

Methods

ts
async function loadData(startDate: string, endDate: string, dashboardId: number) {
  try {
    isInitialized = false;
    isLoading = true;
    hasError = false;
    
    const ret = await getDashboard(startDate, endDate, dashboardId);
    if (!ret.success) {
      hasError = true;
      isLoading = false;
      return;
    }
    
    src = ret.data;
    hasError = false;
  } catch (error) {
    console.error("Error setting iframe source:", error);
    hasError = true;
  } finally {
    functionToCall = null; // Reset after loading
    isLoading = false;
  }
}

UI States

1. Loading State

svelte
<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">...</svg>
    <p class="mt-4 text-gray-600">Loading dashboard...</p>
  </div>
</div>

2. Error State

svelte
<div class="absolute inset-0 flex items-center justify-center bg-gray-100">
  <div class="text-center p-4 bg-red-50 rounded-lg">
    <svg class="h-12 w-12 text-red-500 mx-auto">...</svg>
    <p class="mt-4 text-red-600">Failed to load dashboard</p>
    <button 
      on:click={() => (isLoading = true)}
      class="mt-4 px-4 py-2 bg-blue-500 text-white rounded hover:bg-blue-600"
    >
      Retry
    </button>
  </div>
</div>

3. Initial State (No Filters Selected)

svelte
<div class="flex flex-col items-center justify-center h-full bg-gray-50 rounded-lg shadow-md p-8">
  <svg class="h-14 w-14 text-blue-400 mb-4">...</svg>
  <p class="text-gray-600 text-lg font-medium text-center">
    Please select filters to view the dashboard.
  </p>
  <p class="text-gray-400 text-sm mt-2 text-center">
    Choose a date range to get started.
  </p>
</div>

4. Dashboard Display

svelte
<iframe
  {src}
  frameborder="0"
  class="w-full h-full"
  title="Dashboard"
  on:load={() => (isLoading = false)}
  on:error={() => {
    hasError = true;
    isLoading = false;
  }}
/>

Lifecycle Management

  1. Initialization:

    • Starts in isInitialized state showing placeholder content
    • Waits for functionToCall to be set by parent component
  2. Data Loading:

    • Triggered in afterUpdate when functionToCall is available
    • Shows loading spinner during API request
    • Handles success/error cases appropriately
  3. Error Recovery:

    • Provides retry button in error state
    • Resets loading state on iframe load/error events

Usage Example

svelte
<script>
  import MetaBase from "./metaBase.svelte";
  
  let filterData = {
    startDate: "2023-01-01",
    endDate: "2023-12-31",
    dashboard: "sales"
  };
  
  function getDashboardParams() {
    return {
      startDate: filterData.startDate,
      endDate: filterData.endDate,
      dashboardId: 123 // Would typically map from filterData.dashboard
    };
  }
</script>

<MetaBase 
  {filterData} 
  functionToCall={getDashboardParams} 
/>

Dependencies

  • lodash/fp for uniqueId function
  • Custom query function for GraphQL operations
  • Svelte lifecycle functions (afterUpdate)

Error Handling

  1. GraphQL Errors:

    • Catches and displays API errors
    • Sets error state for UI feedback
  2. Loading Errors:

    • Handles iframe loading errors
    • Provides retry mechanism
  3. Validation:

    • Requires both dates to be set before loading
    • Maintains clean state transitions

Accessibility Features

  1. Loading States:

    • Clear visual feedback during loading
    • Accessible spinner animation
  2. Error States:

    • High contrast error display
    • Clear error message and recovery option
  3. Iframe:

    • Proper title attribute
    • Handles load/error events

Released under the MIT License.