Getting started
Last updated
Was this helpful?
Last updated
Was this helpful?
Search the Pages module within the Data section in the Navbar:
Click the create a new page button
The page editor interface is composed of:
File Explorer: A section displaying the list of files available for editing or creating new ones.
Editor Panel: The main area for editing the content of the selected file.
Tab Bar: Displays open tabs for multiple files being edited, allowing switching between them.
Page Name: Field displaying the Page name
Page URL: A field displaying the Page's url featuring a button for copying it.
Preview Toggle: A toggle to enable or disable the live preview of Page.
Dark Mode Toggle: A toggle to switch between light and dark themes for the interface.
Save Button: A button to save the changes.
Proceed to create a folder called static
using the + button at the File Explorer:
Click the Three-Dots menu at the static
folder and then create a file within it called data.js
Paste the following contents on each of the corresponding files:
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 ;
<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>
* {
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 */
}
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();
});
[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:
Now, go to the Dashboards 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:
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: