Ubidots Developer Guides
Help CenterAPI ReferenceData APICommunity
  • Welcome to our Dev Guides
  • ⚡️ Getting Started
    • What is Ubidots?
    • Devices, Variables, and Dots
    • Technical FAQs
    • Business FAQs
  • 🧩Integration Guides
    • Industrial IoT
      • Advantech
      • Amplified Engineering
      • AWS
      • Azimut
      • Balena
      • Bivocom
      • CESVA
      • Controllino
      • Digital Communications Technologies (DCT)
      • Everactive
      • Golioth
      • Kepware
      • Kunbus
      • Monnit
      • MultiTech
      • NCD.io
      • Node-RED
      • Omicron IoT
      • Red Lion
      • Robustel
      • Senquip
      • Sielco
      • Siemens
      • Strega
      • vNode
      • WAGO
      • Weintek
      • YuDash
    • Cellular
      • Blues Wireless
      • Digi International
      • Hologram
      • Monogoto
      • Particle
      • Quectel
      • Soracom
    • LoRaWAN
      • AonChip
      • Chirpstack
      • Decentlab
      • Helium
      • ioThings
      • LORIOT
      • Milesight
      • MOKOSmart
      • RAKwireless
      • Sagemcom
      • Seeed Studio
      • Senet
      • The Things Industries
        • The Things Stack
        • The Things Network
    • Sigfox
      • Digital Matter
      • McThings
      • Sigfox
      • Suntech
      • Thinxtra
      • UnaBiz
    • Satellite
      • Swarm
    • Dev Kits
      • Adafruit
      • Advantech
      • AloriumTech
      • Arduino
      • Blues Wireless
      • DFRobot
      • Dragino
      • Electric Imp
      • Espressif Systems
      • McThings
      • Microchip Technology
      • Onion
      • Particle
      • Pycom
      • RAKwireless
      • Raspberry Pi
      • Seeed Studio
      • Sodaq
      • STMicroelectronics
      • Texas Instruments
      • Thinxtra
      • Verse Technology
    • Weather
      • Weather Plugins
      • Ambient Weather
    • Tools
      • Gambit Communications
      • PubNub
  • 📊Dashboards & Widgets
    • HTML Canvas
      • 3rd party packages
      • Preload Dashboard data
      • Built-in library
        • Properties
        • Methods
        • Listening events
        • API
      • Examples
        • Basics
        • Create an LCD screen with the HTML Canvas
        • Interacting with dashboard data
        • Change header's custom style
        • Adding real time using Socket.IO
        • Delete Variable data from a Device
        • Delete Variable data from Groups or Types of Devices
        • Navigation through Dashboard
        • Using a React library
      • Code editor
        • HTML Tab
        • CSS Tab
        • JavaScript Tab
    • Custom UI
      • Paragraph
      • Input combo
        • Text
        • Numeric
        • Numeric with buttons
        • Date
        • Time
        • Toggle
        • Dropdown
        • Multiple selection dropdown
      • Button
    • Custom Style
      • Dashboards
      • Widgets
    • Line chart
    • Pages
      • Getting started
      • Development
      • API
        • Page creation
        • Publish
  • 🤖UbiFunctions
    • Getting Started
      • Creating an UbiFunction
      • Coding an UbiFunction
      • Testing an UbiFunction
      • Authentication
      • Execution Time
      • Logs
    • Runtimes
      • Python
      • NodeJS
      • Custom Runtimes
    • Invocation
      • Time-based Trigger
      • HTTPS
      • MQTT Publish
      • Ubidots Event
    • Advanced
      • Account Token
      • Execution time
      • Raw Functions
      • CORS Policy
      • Async Execution
      • DaaS (Decoder as a Service)
      • Developing and Managing UbiFunctions with Ubidots CLI
    • Examples
    • Specs and Limits
    • Storage
      • File Storage API
      • Mutiple files
  • 🧩Plugins
    • What is a plugin?
    • Public vs. Private
    • Public plugins
      • Cron
      • Webhook
    • Private Plugins
      • Cron
      • Webhook
      • Widget
      • Device
    • Plugins development
      • Getting started
      • Cron
      • Webhook
      • Widget
      • Device
      • view.xml
      • view_widget.xml
    • Plugins deployment
      • Cron and Webhook
      • Widget
      • Device
    • Using the plugins
      • Cron and Webhook
      • Widget
      • Device
  • 📈SYNTHETIC VARIABLES
    • Getting started
      • Creating synthetic variables
      • Synthetic Variables' editor
    • Expressions
      • Mathematical
      • Date range
      • Rolling
      • Special functions
    • Specs and limits
    • Examples
      • Mathematical
      • Date range
      • Rolling
      • Special functions
  • ⌨️Developer tools
    • Javascript SDK
      • Overview
      • Getting started
      • Ubidots class
        • Get methods
        • Filter methods
        • Ubidots objects
          • Entity object
          • Paginator
      • Examples
    • CLI
      • Overview
      • Installing
      • Usage
      • SDK for UbiFunctions
  • 🏗️Apps
    • App builder
      • Custom sidebar
Powered by GitBook
On this page
  • Accessing the Pages module
  • Creating a new Page
  • Page editor
  • Quick example

Was this helpful?

Export as PDF
  1. Dashboards & Widgets
  2. Pages

Getting started

PreviousPagesNextDevelopment

Last updated 2 months ago

Was this helpful?

Accessing the Pages module

Search the Pages module within the Dev Center section in the Navbar:

Creating a new Page

Click the create a new page button

Page editor

The page editor interface is composed of:

  1. File Explorer: A section displaying the list of files available for editing or creating new ones.

  2. Editor Panel: The main area for editing the content of the selected file.

  3. Tab Bar: Displays open tabs for multiple files being edited, allowing switching between them.

  4. Page Name: Field displaying the Page name

  5. Page URL: A field displaying the Page's url featuring a button for copying it.

  6. Preview Toggle: A toggle to enable or disable the live preview of Page.

  7. Dark Mode Toggle: A toggle to switch between light and dark themes for the interface.

  8. Save Button: A button to save the changes.

Quick example

Proceed to create a folder called static using the + button at the File Explorer:

Click the Three-Dots menu at the staticfolder and then create a file within it called data.js

Paste the following contents on each of the corresponding files:

data.js
const fullData = {
   "categories":[
      "Oct 24",
      "Nov 24",
      "Dec 24",
      "Jan 25"
   ],
   "series":[
      {
         "stack":"total",
         "name":"AD1",
         "data":[
            null,
            null,
            37.332,
            null
         ]
      },
      {
         "stack":"total",
         "name":"AD2",
         "data":[
            9.419,
            117.572,
            76.749,
            167.505
         ]
      },
      {
         "stack":"total",
         "name":"AD5",
         "data":[
            null,
            7.659000000000001,
            32.679,
            2.929
         ]
      },
      {
         "stack":"total",
         "name":"AD7",
         "data":[
            null,
            153.884,
            110.641,
            46.781
         ]
      },
      {
         "stack":"total",
         "name":"AV2",
         "data":[
            null,
            null,
            7.651,
            null
         ]
      },
      {
         "stack":"total",
         "name":"EN1",
         "data":[
            0.821,
            null,
            null,
            null
         ]
      },
      {
         "stack":"total",
         "name":"EP5",
         "data":[
            null,
            17.772,
            0.496,
            null
         ]
      },
      {
         "stack":"total",
         "name":"PP1",
         "data":[
            1.049,
            2.021,
            111.76,
            3.8449999999999998
         ]
      },
      {
         "stack":"total",
         "name":"PP3",
         "data":[
            1.229,
            null,
            7.91,
            null
         ]
      },
      {
         "stack":"total",
         "name":"PP4",
         "data":[
            null,
            24.323,
            32.785,
            75.607
         ]
      },
      {
         "stack":"total",
         "name":"PP5",
         "data":[
            null,
            12.861,
            null,
            null
         ]
      },
      {
         "stack":"total",
         "name":"PR1",
         "data":[
            10.114,
            5.126,
            null,
            null
         ]
      },
      {
         "stack":"total",
         "name":"PR2",
         "data":[
            null,
            8.873,
            null,
            8.853
         ]
      }
   ]
};

export default fullData ;
body.html
<div id="app" class="container">
    <!-- First Chart Description -->
    <div id="chart1-info" class="content">
        <h2>Factory Production Summary</h2>
        <p>
            This chart shows the cumulative production output by each department over the last 24 hours. The data represents various production lines: AD2, AD5, AD7, PP1, PP4, and PR2.
        </p>
    </div>
    <div id="main" class="report-div"></div> <!-- First Chart -->

    <!-- Second Chart Description -->
    <div id="chart2-info" class="content">
        <h2>Factory Temperature and Environmental Monitoring</h2>
        <p>
            This chart displays temperature variations throughout the day across different monitoring points in the factory. Color bands represent specific ranges of temperatures critical for product safety.
        </p>
    </div>
    <div id="main2" class="report-div"></div> <!-- Second Chart -->
</div>
style.css
* {
  box-sizing: border-box;
  padding: 0;
  margin: 0;
}

body {
    overflow: hidden; /* Prevent body from scrolling */
}

/* Overall container for charts and descriptions */
.container {
    overflow-y: auto; /* Allow vertical scrolling only on the #app container */
    height: 100vh; /* Ensure the container fills the entire viewport */
    width: 100%;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    font-family: 'Nunito', sans-serif;
    font-size: 1rem;
    color: rgb(94, 94, 94); /* Text color */
}

/* Styling for description blocks */
.content {
    width: 100%;
    text-align: center; /* Center-align text */
    padding: 0; /* Add padding for spacing */
    background-color: white; /* Light background */
    border-bottom: none; /* Remove the subtle line */
}

/* Heading styling */
.content h2 {
    font-size: 20px; /* Larger font size for headings */
    font-weight: 700; /* Bold headings */
    margin: 0; /* Space below the heading */
    color: #2c3e50; /* Darker heading color */
    padding-top: 20px; /* Add padding for spacing */
    
}

/* Paragraph styling */
.content p {
    font-size: 14px; /* Slightly smaller text */
    font-weight: 400; /* Regular weight */
    margin: 0;
    line-height: 1.6; /* Improve readability */
    color: rgb(148, 148, 148); /* Light gray text */
    padding: 0; /* Add padding for spacing */
}

/* Styling for the chart containers */
.report-div {
    width: 100%; /* Full width */
    height: 50vh; /* Half of the viewport height for each chart */
    display: flex;
    justify-content: center;
    align-items: center;
    background-color: white; /* White background for charts */
    border-bottom: none; /* Remove the subtle line */
}
script.js
import fullData from './static/data.js';


// First chart setup
var chartDom1 = document.getElementById('main');
var myChart1 = echarts.init(chartDom1, null, {
  renderer: 'canvas',
  useDirtyRect: false
});

// Second chart setup
var chartDom2 = document.getElementById('main2');
var myChart2 = echarts.init(chartDom2, null, {
  renderer: 'canvas',
  useDirtyRect: false
});

const ubidots = new Ubidots();
const COLUMN_PREFIX = ""; 

ubidots.on("ready", () => {
    render();

    ubidots.on('dashboardRefreshed', function () {
        render();
    });
});

function render() {
    // First Chart (Original Data)
    let series1 = buildEchartsSeries(fullData.series);
    let options1 = setOptionsEcharts(series1, fullData.categories);
    myChart1.setOption(options1);

    // Second Chart (Desired Configuration)
    let series2 = buildEchartsSeriesForSecondChart();
    let options2 = setDesiredChartOptions(series2);
    myChart2.setOption(options2);
}

function buildEchartsSeries(series) {
    series.forEach(element => {
        element["type"] = "bar";
        if (COLUMN_PREFIX !== "") {
            element.stack = `${COLUMN_PREFIX} ${element.stack}`;
        }
        element["emphasis"] = {
            focus: "self"
        };
        let dataLength = element.data.length;
        let newData = Array(dataLength);
        for (let i = 0; i < dataLength; i++) {
            if (element.data[i] != null) {
                newData[i] = element.data[i];
            }
        }
        element.data = newData;
    });
    return series;
}

function buildEchartsSeriesForSecondChart() {
    const dummyData = generateDummyData();

    return [
        {
            name: "Sample Series",
            type: "line",
            data: dummyData,
            areaStyle: {},
            itemStyle: {
                color: "#5470C6",
                opacity: 0.8,
                borderColor: "#5470C6"
            },
            lineStyle: {
                width: 2
            },
            showSymbol: false,
            symbolSize: 8,
            connectNulls: true
        }
    ];
}

function setOptionsEcharts(series, categories) {
    return {
        tooltip: {
            trigger: 'axis',
            textStyle: {},
            axisPointer: {
                type: 'shadow' // 'shadow' as default; can also be 'line' or 'shadow'
            },
            formatter: function (params) {
                var tooltip = params[0].name + '<br>'; // Category name
                params.forEach(function (item) {
                    if (item.data != null) {
                        tooltip += item.marker + item.seriesName + ':   ' + `<b>${formatHours(item.data)}</b>` + '<br>';
                    }
                });
                return tooltip; // Return the customized tooltip content
            }
        },
        legend: {},
        grid: {
            left: '3%',
            right: '4%',
            bottom: '3%',
            containLabel: true
        },
        xAxis: {
            type: 'category',
            data: categories
        },
        yAxis: {
            type: 'value'
        },
        series: series
    };
}

function setDesiredChartOptions(series) {
    return {
        yAxis: [
            {
                type: "value",
                axisLine: {
                    lineStyle: {
                        color: "#5e5e5e40"
                    }
                },
                axisLabel: {
                    color: "#5E5E5E",
                    fontSize: 11,
                    show: false
                },
                splitLine: {
                    lineStyle: {
                        color: ["#5e5e5e"],
                        opacity: 0.1
                    }
                },
                min: "dataMin",
                max: "dataMax",
                name: "",
                nameLocation: "center",
                nameGap: 70,
                nameTextStyle: {
                    color: "#5E5E5E"
                },
                position: "left",
                show: true,
                offset: 0,
                lineStyle: {
                    color: "#5470C6",
                    width: 3
                }
            }
        ],
        xAxis: [
            {
                type: "time",
                axisLine: {
                    lineStyle: {
                        color: "#5e5e5e40"
                    }
                },
                axisLabel: {
                    color: "#5E5E5E",
                    fontSize: 11,
                    show: false
                },
                splitLine: {
                    lineStyle: {
                        color: ["#5e5e5e"],
                        opacity: 0.1
                    }
                }
            }
        ],
        dataZoom: [
            {
                show: true,
                filterMode: "none",
                xAxisIndex: 0,
                realtime: false,
                textStyle: {
                    color: "#5E5E5E",
                    fontSize: 11
                },
                dataBackground: {
                    areaStyle: {
                        color: "#5E5E5E"
                    }
                },
                right: 45,
                left: 45
            }
        ],
        series: series,
        tooltip: {
            confine: true,
            trigger: "axis"
        },
        visualMap: {
            show: false,
            type: "piecewise",
            pieces: [
                { gt: 0, lt: 18, color: "#1e13e8" },
                { gt: 18, lt: 22, color: "#e8dd13" },
                { gt: 22, lt: 26, color: "#e85a13" },
                { gt: 26, lt: 28, color: "#ed2005" },
                { gt: 28, color: "#ed2005" }
            ],
            dimension: 1,
            seriesIndex: 0
        }
    };
}

function generateDummyData() {
    const now = new Date();
    const data = [];
    for (let i = 0; i < 50; i++) {
        const timestamp = new Date(now.getTime() - i * 3600000); // Subtract i hours
        const value = Math.random() * 30; // Random values
        data.push([timestamp, value]); // Push [timestamp, value]
    }
    return data.reverse(); // Ensure chronological order
}

function formatHours(hours) {
    if (hours < 1) {
        return Math.floor(hours * 60) + 'm';
    }
    var duration = moment.duration(hours, 'hours');
    var months = Math.floor(duration.asMonths());
    duration.subtract(months, 'months');
    var days = Math.floor(duration.asDays());
    duration.subtract(days, 'days');
    var remainingHours = Math.floor(duration.asHours());
    duration.subtract(hours, 'hours');
    var minutes = Math.floor(duration.asMinutes());
    var result = '';
    if (months > 0) result += months + 'M ';
    if (days > 0) result += days + 'd ';
    if (remainingHours > 0) result += remainingHours + 'h ';
    if (minutes > 0) result += minutes + 'm';
    return result.trim();
}

window.addEventListener('resize', function () {
    myChart1.resize();
    myChart2.resize();
});
manifest.toml
[page]
keywords = "test,validation"
description = "Page for testing purposes."
static_paths = ["static"]
js_libraries = [
    {src="script.js", type="module", defer="", crossorigin="", referrerpolicy="no-referrer"}
    {src="static/data.js", type="module", defer="", crossorigin="", referrerpolicy="no-referrer"}
]
js_thirdparty_libraries = [
    {src="https://cdnjs.cloudflare.com/ajax/libs/echarts/5.4.3/echarts.min.js"},
    {src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.1/moment.min.js"}
]

css_libraries = [{href="style.css", crossorigin="", referrerpolicy="no-referrer"}]
css_thirdparty_libraries = [
    {href="https://fonts.googleapis.com/css2?family=Nunito:wght@400;600;700&display=swap", type="font", crossorigin=""}
]
link_thirdparty_libraries = [
    {href="https://fonts.googleapis.com/css?family=Roboto:310i,410&display=swap", type="font", crossorigin=""}
]

Then click the Save button to save the page. You'll be prompted for a name:

Upon giving a name to your page, you'll be able to copy its URL:

When you reload the dashboard, the page created will be displayed:

That's it! You've just developed your first Page. Head to the next section to learn more about developing Pages in Ubidots in greater detail:

Now, go to the module and create a new dashboard to use it for displaying the recently created Page. Once you've created said dashboard, go to its settings and change Dashboard type to Default and then paste the previously copied URL in the Custom Page URL field:

📊
Dashboards