External API (USGS Earthquakes)

Static content

This example demonstrates how to fetch data from the USGS Earthquake Hazards Program API. This service supports server-side date filtering, which aligns perfectly with the widget’s Period Filter.

Function Explanation

  1. Date Filtering: The code checks the filters.period object.
    • If from and to are present, they are formatted to ISO 8601 strings (YYYY-MM-DD) and sent as starttime and endtime parameters.
    • If no period is selected, it defaults to the last 24 hours.
  2. Name/Text Filtering: The filters.generic (search text) is used to filter the results client-side (searching within the place field), as the API does not support a direct “text search” parameter for this endpoint.

Code

// Main function executed by the Custom Table widget
// parameters: entityData, filters, page, pageElements, callback

// Base URL for USGS Earthquake API (GeoJSON format)
let url = 'https://earthquake.usgs.gov/fdsnws/event/1/query?format=geojson&limit=200';

// 1. Handle Date Filters (Server-Side)
if (filters && filters.period && filters.period.from && filters.period.to) {
  // Helper to format date as YYYY-MM-DD
  const formatDate = (dateStr) => new Date(dateStr).toISOString().split('T')[0];
  
  const start = formatDate(filters.period.from);
  const end = formatDate(filters.period.to);
  
  url += `&starttime=${start}&endtime=${end}`;
} else {
  // Default to 'now' if no filter (API defaults to last 30 days usually, let's limit to recent)
  // Actually, let's explicitely ask for last 2 days to keep data manageable if no filter
  // But for simplicity, we rely on the API defaults or a 'limit' param already added above.
}

try {
  // 2. Fetch Data
  const response = await http(url);
  
  let features = [];
  if (response && response.features) {
      features = response.features;
  } else if (response && response.json) {
      const json = await response.json();
      features = json.features || [];
  }

  // 3. Handle Name/Text Filter (Client-Side)
  // filtering by 'place' property
  if (filters && filters.generic && filters.generic.length > 0) {
    const search = filters.generic.toLowerCase();
    features = features.filter(f => 
      f.properties.place && f.properties.place.toLowerCase().includes(search)
    );
  }

  // 4. Map to Table Columns
  // Configured Columns hint: 'place', 'magnitude', 'time', 'status'
  const tableData = features.map(f => {
    const props = f.properties;
    const dateObj = new Date(props.time);
    
    // Determine color based on magnitude
    let magColor = 'green';
    if (props.mag >= 5) magColor = 'red';
    else if (props.mag >= 3) magColor = 'orange';

    return {
      place: props.place,
      magnitude: {
          value: props.mag ? props.mag.toFixed(1) : '0.0',
          _style: `font-weight:bold; color: ${magColor};`
      },
      time: dateObj.toLocaleString(),
      status: `<a href="${props.url}" target="_blank">Ver Detalles</a>`
    };
  });

  callback(tableData);

} catch (error) {
  console.error("Error fetching earthquake data:", error);
  callback([]);
}