DEV Community

Cover image for Using External Weather Data In A Custom Panel Extension
Kevin Lewis for Directus

Posted on • Originally published at docs.directus.io

Using External Weather Data In A Custom Panel Extension

In this post, you will learn how to fetch data from an external data source and display it in a custom panel extension for Directus Insights.

Panels can only talk to internal Directus services, and can't reliably make external web requests because browser security protections prevent these cross-origin requests from being made. To create a panel that can interact with external APIs, you will create bundle including an endpoint (that can make external requests) and a panel (that uses the endpoint).

Add an Extensions Volume

Follow our Directus Self-Hosted Quickstart, adding a volume for extensions:

volumes:
  - ./database:/directus/database
  - ./uploads:/directus/uploads
  - ./extensions:/directus/extensions // [!code ++]
Enter fullscreen mode Exit fullscreen mode

Create a Bundle

Once you have run docker compose up for the first time, local directories for the volumes will be created. Navigate to the extensions directory and use the Directus Extensions CLI to create a bundle:

npx create-directus-extension@latest
├ type: bundle
├ name: directus-extension-bundle-weather
└ language: javascript
Enter fullscreen mode Exit fullscreen mode

Then, navigate to the newly-created extension directory.

Create an Endpoint

Use npm run add to add a new extension to the bundle:

npm run add
├ type: endpoint
├ name: weather-endpoint
└ language: javascript
Enter fullscreen mode Exit fullscreen mode

Navigate to the new weather-endpoint/index.js file and replace it with the following:

export default {
    id: 'weather',
    handler: (router) => {
        router.get('/', async (req, res) => {
            try {
                const response = await fetch(`https://api.open-meteo.com/v1/forecast?current_weather=true&${req._parsedUrl.query}`);

                if (response.ok) {
                    res.json(await response.json());
                } else { 
                    res.status(response.status).send(response.statusText);
                }
            } catch(error) {
                res.status(500).send(error.message);
            }
        })
    }
}
Enter fullscreen mode Exit fullscreen mode

From the directus-extension-bundle-weather directory, run npm run build. Restart your Directus project, and you should now be able to access http://localhost:8055/weather?longitude=0&latitude=0.

The Open-Meteo API requires a longitude and latitude, so they must always be provided.

Create a Panel

Use npm run add to add a new extension to the bundle:

npm run add
├ type: panel
├ name: weather-panel
└ language: javascript
Enter fullscreen mode Exit fullscreen mode

Navigate to the new weather-panel/index.js file, update the id to weather-panel and the name to Weather.

In the options array, remove the text field, and add two new fields for longitude and latitude:

options: [
    {
        field: 'longitude',
        name: 'Longitude',
        type: 'string',
        meta: {
            interface: 'input',
            width: 'half',
        },
    },
    {
        field: 'latitude',
        name: 'Latitude',
        type: 'string',
        meta: {
            interface: 'input',
            width: 'half',
        },
    },
],
Enter fullscreen mode Exit fullscreen mode

Open panel.vue, and at the top of the <script>, import useApi and Vue's ref:

import { useApi } from '@directus/extensions-sdk'; // [!code ++]
import { ref } from 'vue'; // [!code ++]

export default {
Enter fullscreen mode Exit fullscreen mode

Then, add longitude and latitude props:

props: {
    showHeader: {
        type: Boolean,
        default: false,
    },
    longitude: { // [!code ++]
        type: String,  // [!code ++]
        default: '0',  // [!code ++]
    },  // [!code ++]
    latitude: {  // [!code ++]
        type: String,  // [!code ++]
        default: '0',  // [!code ++]
    },  // [!code ++]
},
Enter fullscreen mode Exit fullscreen mode

Create a setup method which will run when the panel is loaded:

setup(props) {
    const api = useApi();
    const weather = ref({});

    async function fetchData() {
        const response = await api.get(`/weather?longitude=${props.longitude}&latitude=${props.latitude}`);
        weather.value = response.data;
    }
    fetchData();

    return { weather };
}
Enter fullscreen mode Exit fullscreen mode

This code will immediately fetch weather data using the new internal endpoint, and then make it available as weather to the template.

Finally, update the template:

<template>
    <div class="text" :class="{ 'has-header': showHeader }">
        {{ text }}  // [!code --]
        {{ weather }}  // [!code ++]
    </div>
</template>
Enter fullscreen mode Exit fullscreen mode

Run npm run build from the bundle directory, and restart Directus.

Use the Panel

Create a new Insights Dashboard and add a Weather panel. Add coordinates, and you should see external data displayed in the panel.

Panel configutation showing a longitude and latitude input field

A panel showing a JSON payload of weather data

You can now create panels using external data. If you have any questions at all, feel free to join our Discord community.

Top comments (0)