Merge branch 'feature/nextjs-inspired-docs' of github.com:datopian/portaljs into feature/nextjs-inspired-docs
@ -48,7 +48,7 @@ https://portaljs.org/docs
|
||||
|
||||
# Community
|
||||
|
||||
If you have questions about anything related to Portal.JS, you're always welcome to ask our community on [GitHub Discussions](https://github.com/datopian/portal.js/discussions) or on our [Discord server](https://discord.gg/An7Bu5x8).
|
||||
If you have questions about anything related to Portal.JS, you're always welcome to ask our community on [GitHub Discussions](https://github.com/datopian/portal.js/discussions) or on our [Discord server](https://discord.gg/EeyfGrGu4U).
|
||||
|
||||
# Appendix
|
||||
|
||||
|
||||
@ -15,7 +15,7 @@ export default function LineChart({
|
||||
const spec = {
|
||||
$schema: "https://vega.github.io/schema/vega-lite/v5.json",
|
||||
title,
|
||||
width: "container",
|
||||
width: 500,
|
||||
height: 300,
|
||||
mark: {
|
||||
type: "line",
|
||||
|
||||
11
examples/basic-example/content/my-dataset/README.md
Normal file
@ -0,0 +1,11 @@
|
||||
# Data
|
||||
|
||||
This is the README.md this project.
|
||||
|
||||
## Table
|
||||
|
||||
<Table url="data_1.csv" />
|
||||
|
||||
## Vega Lite Line Chart from URL
|
||||
|
||||
<VegaLite spec={ { "$schema": "https://vega.github.io/schema/vega-lite/v5.json", "data": {"url": "data_2.csv"}, "width": 550, "height": 250, "mark": "line", "encoding": { "x": {"field": "Time", "type": "temporal"}, "y": {"field": "Anomaly (deg C)", "type": "quantitative"}, "tooltip": {"field": "Anomaly (deg C)", "type": "quantitative"} } } } />
|
||||
20
examples/basic-example/pages/api/get-data-file.ts
Normal file
@ -0,0 +1,20 @@
|
||||
// Next.js API route support: https://nextjs.org/docs/api-routes/introduction
|
||||
import type { NextApiRequest, NextApiResponse } from 'next'
|
||||
import { promises as fs } from 'fs';
|
||||
import path from 'path';
|
||||
|
||||
export default async function handler(
|
||||
req: NextApiRequest,
|
||||
res: NextApiResponse<string>
|
||||
) {
|
||||
const contentDir = path.join(process.cwd(), '/content');
|
||||
const datasets = await fs.readdir(contentDir);
|
||||
const query = req.query;
|
||||
const { fileName } = query;
|
||||
const dataFile = path.join(
|
||||
process.cwd(),
|
||||
'/content/' + datasets[0] + '/' + fileName
|
||||
);
|
||||
const data = await fs.readFile(dataFile, 'utf8');
|
||||
res.status(200).send(data)
|
||||
}
|
||||
@ -4,7 +4,7 @@ import path from 'path';
|
||||
import parse from '../lib/markdown';
|
||||
import DRD from '../components/DRD';
|
||||
|
||||
export const getServerSideProps = async (context) => {
|
||||
export const getStaticProps = async (context) => {
|
||||
const indexFile = path.join(process.cwd(), '/content/index.md');
|
||||
const readme = await fs.readFile(indexFile, 'utf8');
|
||||
let { mdxSource, frontMatter } = await parse(readme, '.mdx');
|
||||
|
||||
173
examples/basic-example/public/data_2.csv
Normal file
@ -0,0 +1,173 @@
|
||||
Time,Anomaly (deg C),Lower confidence limit (2.5%),Upper confidence limit (97.5%)
|
||||
1850,-0.41765878,-0.589203,-0.24611452
|
||||
1851,-0.2333498,-0.41186792,-0.054831687
|
||||
1852,-0.22939907,-0.40938243,-0.04941572
|
||||
1853,-0.27035445,-0.43000934,-0.110699534
|
||||
1854,-0.29163003,-0.43282393,-0.15043613
|
||||
1855,-0.2969512,-0.43935776,-0.15454465
|
||||
1856,-0.32035372,-0.46809322,-0.1726142
|
||||
1857,-0.46723005,-0.61632216,-0.31813794
|
||||
1858,-0.3887657,-0.53688604,-0.24064532
|
||||
1859,-0.28119546,-0.42384982,-0.13854107
|
||||
1860,-0.39016518,-0.5389766,-0.24135375
|
||||
1861,-0.42927712,-0.5972301,-0.26132414
|
||||
1862,-0.53639776,-0.7037096,-0.36908585
|
||||
1863,-0.3443432,-0.5341645,-0.1545219
|
||||
1864,-0.4654367,-0.6480974,-0.282776
|
||||
1865,-0.33258784,-0.5246526,-0.14052312
|
||||
1866,-0.34126064,-0.52183825,-0.16068307
|
||||
1867,-0.35696334,-0.55306214,-0.16086453
|
||||
1868,-0.35196072,-0.52965826,-0.17426313
|
||||
1869,-0.31657043,-0.47642276,-0.15671812
|
||||
1870,-0.32789087,-0.46867347,-0.18710826
|
||||
1871,-0.3685807,-0.5141493,-0.22301209
|
||||
1872,-0.32804197,-0.4630833,-0.19300064
|
||||
1873,-0.34133235,-0.4725396,-0.21012507
|
||||
1874,-0.3732512,-0.5071426,-0.2393598
|
||||
1875,-0.37562594,-0.514041,-0.23721085
|
||||
1876,-0.42410994,-0.56287116,-0.28534868
|
||||
1877,-0.101108834,-0.22982001,0.027602348
|
||||
1878,-0.011315193,-0.13121258,0.10858219
|
||||
1879,-0.30363432,-0.43406433,-0.1732043
|
||||
1880,-0.31583208,-0.44015095,-0.19151321
|
||||
1881,-0.23224552,-0.35793498,-0.10655605
|
||||
1882,-0.29553008,-0.4201501,-0.17091006
|
||||
1883,-0.3464744,-0.4608177,-0.23213111
|
||||
1884,-0.49232006,-0.6026686,-0.38197154
|
||||
1885,-0.47112358,-0.5830682,-0.35917896
|
||||
1886,-0.42090362,-0.5225382,-0.31926903
|
||||
1887,-0.49878576,-0.61655986,-0.3810117
|
||||
1888,-0.37937889,-0.49332377,-0.265434
|
||||
1889,-0.24989556,-0.37222093,-0.12757017
|
||||
1890,-0.50685817,-0.6324095,-0.3813068
|
||||
1891,-0.40131494,-0.5373699,-0.26525995
|
||||
1892,-0.5075585,-0.64432853,-0.3707885
|
||||
1893,-0.49461925,-0.6315314,-0.35770702
|
||||
1894,-0.48376393,-0.6255681,-0.34195974
|
||||
1895,-0.4487516,-0.58202064,-0.3154826
|
||||
1896,-0.28400728,-0.4174015,-0.15061308
|
||||
1897,-0.25980017,-0.39852425,-0.12107607
|
||||
1898,-0.48579213,-0.6176492,-0.35393503
|
||||
1899,-0.35543364,-0.48639694,-0.22447036
|
||||
1900,-0.23447904,-0.3669676,-0.10199049
|
||||
1901,-0.29342857,-0.42967388,-0.15718324
|
||||
1902,-0.43898427,-0.5754281,-0.30254042
|
||||
1903,-0.5333264,-0.66081935,-0.40583345
|
||||
1904,-0.5975614,-0.7288325,-0.46629035
|
||||
1905,-0.40775132,-0.5350291,-0.28047356
|
||||
1906,-0.3191393,-0.45052385,-0.18775477
|
||||
1907,-0.5041577,-0.6262818,-0.38203365
|
||||
1908,-0.5138707,-0.63748026,-0.3902612
|
||||
1909,-0.5357649,-0.6526296,-0.41890016
|
||||
1910,-0.5310242,-0.6556868,-0.40636164
|
||||
1911,-0.5392051,-0.66223973,-0.4161705
|
||||
1912,-0.47567302,-0.5893311,-0.36201498
|
||||
1913,-0.46715254,-0.5893755,-0.34492958
|
||||
1914,-0.2625924,-0.38276345,-0.1424214
|
||||
1915,-0.19184391,-0.32196194,-0.06172589
|
||||
1916,-0.42020997,-0.5588941,-0.28152588
|
||||
1917,-0.54301953,-0.6921192,-0.3939199
|
||||
1918,-0.42458433,-0.58198184,-0.26718682
|
||||
1919,-0.32551822,-0.48145813,-0.1695783
|
||||
1920,-0.2985808,-0.44860035,-0.14856121
|
||||
1921,-0.24067703,-0.38175339,-0.09960067
|
||||
1922,-0.33922812,-0.46610323,-0.21235302
|
||||
1923,-0.31793055,-0.444173,-0.1916881
|
||||
1924,-0.3120622,-0.4388317,-0.18529275
|
||||
1925,-0.28242525,-0.4147755,-0.15007503
|
||||
1926,-0.12283547,-0.25264767,0.006976739
|
||||
1927,-0.22940508,-0.35135695,-0.10745319
|
||||
1928,-0.20676155,-0.33881804,-0.074705064
|
||||
1929,-0.39275664,-0.52656746,-0.25894582
|
||||
1930,-0.1768054,-0.29041144,-0.06319936
|
||||
1931,-0.10339768,-0.2126916,0.0058962475
|
||||
1932,-0.14546166,-0.25195515,-0.0389682
|
||||
1933,-0.32234442,-0.4271004,-0.21758842
|
||||
1934,-0.17433685,-0.27400395,-0.07466974
|
||||
1935,-0.20605922,-0.30349734,-0.10862111
|
||||
1936,-0.16952093,-0.26351926,-0.07552261
|
||||
1937,-0.01919893,-0.11975875,0.08136089
|
||||
1938,-0.012200732,-0.11030374,0.08590227
|
||||
1939,-0.040797167,-0.14670466,0.065110326
|
||||
1940,0.07593584,-0.04194966,0.19382134
|
||||
1941,0.038129337,-0.16225387,0.23851255
|
||||
1942,0.0014060909,-0.1952124,0.19802457
|
||||
1943,0.0064140745,-0.19959097,0.21241911
|
||||
1944,0.14410514,-0.054494828,0.3427051
|
||||
1945,0.043088365,-0.15728289,0.24345961
|
||||
1946,-0.1188128,-0.2659574,0.028331792
|
||||
1947,-0.091205545,-0.23179041,0.04937931
|
||||
1948,-0.12466127,-0.25913337,0.009810844
|
||||
1949,-0.14380224,-0.2540775,-0.033526987
|
||||
1950,-0.22662179,-0.33265698,-0.12058662
|
||||
1951,-0.06115397,-0.15035024,0.028042298
|
||||
1952,0.015354565,-0.08293597,0.11364509
|
||||
1953,0.07763074,-0.020529618,0.1757911
|
||||
1954,-0.11675021,-0.20850271,-0.024997713
|
||||
1955,-0.19730993,-0.28442997,-0.1101899
|
||||
1956,-0.2631656,-0.33912563,-0.18720557
|
||||
1957,-0.035334926,-0.10056862,0.029898768
|
||||
1958,-0.017632553,-0.083074555,0.04780945
|
||||
1959,-0.048004825,-0.11036375,0.0143540995
|
||||
1960,-0.115487024,-0.17416587,-0.056808177
|
||||
1961,-0.019997388,-0.07078052,0.030785747
|
||||
1962,-0.06405444,-0.11731443,-0.010794453
|
||||
1963,-0.03680589,-0.09057008,0.016958294
|
||||
1964,-0.30586675,-0.34949213,-0.26224136
|
||||
1965,-0.2043879,-0.25357357,-0.15520222
|
||||
1966,-0.14888458,-0.19839221,-0.09937696
|
||||
1967,-0.11751631,-0.16062479,-0.07440783
|
||||
1968,-0.1686323,-0.21325313,-0.124011464
|
||||
1969,-0.031366713,-0.07186544,0.009132013
|
||||
1970,-0.08510657,-0.12608096,-0.04413217
|
||||
1971,-0.20593274,-0.24450706,-0.16735843
|
||||
1972,-0.0938271,-0.13171694,-0.05593726
|
||||
1973,0.04993336,0.013468528,0.086398184
|
||||
1974,-0.17253734,-0.21022376,-0.1348509
|
||||
1975,-0.11075424,-0.15130512,-0.07020335
|
||||
1976,-0.21586166,-0.25588378,-0.17583954
|
||||
1977,0.10308852,0.060056705,0.14612034
|
||||
1978,0.0052557723,-0.034576867,0.04508841
|
||||
1979,0.09085813,0.062358618,0.119357646
|
||||
1980,0.19607207,0.162804,0.22934014
|
||||
1981,0.25001204,0.21939126,0.28063282
|
||||
1982,0.034263328,-0.005104665,0.07363132
|
||||
1983,0.22383861,0.18807402,0.2596032
|
||||
1984,0.04800471,0.011560736,0.08444869
|
||||
1985,0.04972978,0.015663471,0.08379609
|
||||
1986,0.09568697,0.064408,0.12696595
|
||||
1987,0.2430264,0.21218552,0.27386728
|
||||
1988,0.28215173,0.2470353,0.31726816
|
||||
1989,0.17925027,0.14449838,0.21400215
|
||||
1990,0.36056247,0.32455227,0.39657268
|
||||
1991,0.33889654,0.30403617,0.3737569
|
||||
1992,0.124896795,0.09088206,0.15891153
|
||||
1993,0.16565846,0.12817313,0.2031438
|
||||
1994,0.23354977,0.19841294,0.2686866
|
||||
1995,0.37686616,0.34365577,0.41007656
|
||||
1996,0.2766894,0.24318004,0.31019878
|
||||
1997,0.4223085,0.39009082,0.4545262
|
||||
1998,0.57731646,0.54304415,0.6115888
|
||||
1999,0.32448497,0.29283476,0.35613516
|
||||
2000,0.3310848,0.29822788,0.36394167
|
||||
2001,0.48928034,0.4580683,0.5204924
|
||||
2002,0.5434665,0.51278186,0.57415116
|
||||
2003,0.5441702,0.5112426,0.5770977
|
||||
2004,0.46737072,0.43433833,0.5004031
|
||||
2005,0.60686255,0.5757053,0.6380198
|
||||
2006,0.5725527,0.541973,0.60313237
|
||||
2007,0.5917013,0.56135315,0.6220495
|
||||
2008,0.46564984,0.43265733,0.49864236
|
||||
2009,0.5967817,0.56525564,0.6283077
|
||||
2010,0.68037146,0.649076,0.7116669
|
||||
2011,0.53769773,0.5060012,0.5693943
|
||||
2012,0.5776071,0.5448553,0.6103589
|
||||
2013,0.6235754,0.5884838,0.6586669
|
||||
2014,0.67287165,0.63890487,0.7068384
|
||||
2015,0.82511437,0.79128706,0.8589417
|
||||
2016,0.93292713,0.90176356,0.96409065
|
||||
2017,0.84517425,0.81477475,0.87557375
|
||||
2018,0.762654,0.731052,0.79425603
|
||||
2019,0.8910726,0.85678726,0.92535794
|
||||
2020,0.9227938,0.8882121,0.9573755
|
||||
2021,0.6640137,0.5372486,0.79077876
|
||||
|
BIN
examples/basic-example/public/favicon.ico
Normal file
|
After Width: | Height: | Size: 25 KiB |
4
examples/basic-example/public/vercel.svg
Normal file
@ -0,0 +1,4 @@
|
||||
<svg width="283" height="64" viewBox="0 0 283 64" fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M141.04 16c-11.04 0-19 7.2-19 18s8.96 18 20 18c6.67 0 12.55-2.64 16.19-7.09l-7.65-4.42c-2.02 2.21-5.09 3.5-8.54 3.5-4.79 0-8.86-2.5-10.37-6.5h28.02c.22-1.12.35-2.28.35-3.5 0-10.79-7.96-17.99-19-17.99zm-9.46 14.5c1.25-3.99 4.67-6.5 9.45-6.5 4.79 0 8.21 2.51 9.45 6.5h-18.9zM248.72 16c-11.04 0-19 7.2-19 18s8.96 18 20 18c6.67 0 12.55-2.64 16.19-7.09l-7.65-4.42c-2.02 2.21-5.09 3.5-8.54 3.5-4.79 0-8.86-2.5-10.37-6.5h28.02c.22-1.12.35-2.28.35-3.5 0-10.79-7.96-17.99-19-17.99zm-9.45 14.5c1.25-3.99 4.67-6.5 9.45-6.5 4.79 0 8.21 2.51 9.45 6.5h-18.9zM200.24 34c0 6 3.92 10 10 10 4.12 0 7.21-1.87 8.8-4.92l7.68 4.43c-3.18 5.3-9.14 8.49-16.48 8.49-11.05 0-19-7.2-19-18s7.96-18 19-18c7.34 0 13.29 3.19 16.48 8.49l-7.68 4.43c-1.59-3.05-4.68-4.92-8.8-4.92-6.07 0-10 4-10 10zm82.48-29v46h-9V5h9zM36.95 0L73.9 64H0L36.95 0zm92.38 5l-27.71 48L73.91 5H84.3l17.32 30 17.32-30h10.39zm58.91 12v9.69c-1-.29-2.06-.49-3.2-.49-5.81 0-10 4-10 10V51h-9V17h9v9.2c0-5.08 5.91-9.2 13.2-9.2z" fill="#000"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
BIN
site/content/assets/docs/editing-the-page-1.png
Normal file
|
After Width: | Height: | Size: 23 KiB |
BIN
site/content/assets/docs/tutorial-1-img-1.png
Normal file
|
After Width: | Height: | Size: 204 KiB |
BIN
site/content/assets/docs/tutorial-1-img-2.png
Normal file
|
After Width: | Height: | Size: 56 KiB |
BIN
site/content/assets/docs/tutorial-1-img-3.png
Normal file
|
After Width: | Height: | Size: 72 KiB |
BIN
site/content/assets/docs/tutorial-1-img-4.png
Normal file
|
After Width: | Height: | Size: 60 KiB |
BIN
site/content/assets/docs/tutorial-1-img-5.png
Normal file
|
After Width: | Height: | Size: 66 KiB |
BIN
site/content/assets/docs/tutorial-1-img-6.png
Normal file
|
After Width: | Height: | Size: 204 KiB |
BIN
site/content/assets/examples/basic-example.png
Normal file
|
After Width: | Height: | Size: 19 KiB |
@ -2,7 +2,7 @@
|
||||
<h1>Datopian Tech</h1>
|
||||
|
||||
<a href="https://datopian.com/">
|
||||
<img src="/static/img/datopian-logo.png" style={{maxWidth: "280px", display: "block", margin: "3rem auto 1.5rem"}} />
|
||||
<img src="/images/datopian-light-logotype.svg" style={{maxWidth: "250px", display: "block", margin: "3rem auto 1.5rem"}} />
|
||||
</a>
|
||||
|
||||
<p className="description" style={{fontSize: "1.6rem", lineHeight: 1.3}}>
|
||||
@ -51,7 +51,6 @@ A DMS has a variety of features. This section provides an overview and links to
|
||||
|
||||
> [!tip] There are many ways to break down features and this is just one framing. We are thinking about others and if you have thoughts please get in touch.
|
||||
|
||||
|
||||
- [Discovering and showcasing data (catalog and presenting)](/docs/dms/frontend)
|
||||
- [Views on data](/docs/dms/views) including visualizing and previewing data as well [Data Explorers][explorer] and [Dashboards][]
|
||||
- [Publishing data](/docs/dms/publish)
|
||||
|
||||
@ -1,53 +1,52 @@
|
||||
# 🌀 PortalJS: The JavaScript framework for data portals
|
||||
# Getting Started
|
||||
|
||||
🌀 PortalJS is a framework for rapidly building rich data portal frontends using a modern frontend approach. PortalJS can be used to present a single dataset or build a full-scale data catalog/portal.
|
||||
Welcome to the PortalJS documentation!
|
||||
|
||||
Built in JavaScript and React on top of the popular [Next.js](https://nextjs.com/) framework. PortalJS assumes a "decoupled" approach where the frontend is a separate service from the backend and interacts with backend(s) via an API. It can be used with any backend and has out of the box support for [CKAN](https://ckan.org/).
|
||||
If you have questions about anything related to PortalJS, you're always welcome to ask our community on [GitHub Discussions](https://github.com/datopian/portaljs/discussions) or on [our chat channel on Discord](https://discord.gg/EeyfGrGu4U).
|
||||
|
||||
PortalJS offers a variety of examples (templates) to bootstrap your own data portal in just a few minutes. [Get started now!](#getting-started)
|
||||
## Setup
|
||||
|
||||
## Features
|
||||
### Prerequisites
|
||||
|
||||
- 🗺️ Unified sites: present data and content in one seamless site, pulling datasets from a DMS (e.g. CKAN) and content from a CMS (e.g. Wordpress) with a common internal API.
|
||||
- 👩💻 Developer friendly: built with familiar and modern frontend tech such as JavaScript, React and Next.js, so you can take advantage of everything these technologies have to offer: Server Side Rendering, Static Site Generation, huge number of examples and more!
|
||||
- 🔋 Batteries included: full set of portal components out of the box e.g. catalog search, dataset showcase, blog, etc.
|
||||
- 🎨 Easy to theme and customize: installable themes, use standard CSS and React+CSS tooling. Add new routes quickly.
|
||||
- 🧱 Extensible: quickly extend and develop/import your own React components
|
||||
- 📝 Well documented: full set of documentation plus the documentation of Next.js and Apollo.
|
||||
- Node.js 14.18.0 or newer
|
||||
- MacOS, Windows (including WSL), and Linux are supported
|
||||
|
||||
## What is a data portal?
|
||||
### Create a PortalJS app
|
||||
|
||||
A Data Portal is a gateway to data. That gateway can be big or small, open or restricted. For example, data.gov is open to everyone, whilst an enterprise "intra" data portal is restricted to that enterprise (and perhaps even to certain people within it).
|
||||
To create a PortalJS app, open your terminal, cd into the directory you’d like to create the app in, and run the following command:
|
||||
|
||||
A Data Portal's core purpose is to enable the rapid discovery and use of data. However, as a flexible, central point of truth on an organizations data assets, a Data Portal can become essential data infrastructure and be extended or integrated to provide many additional features:
|
||||
```bash
|
||||
npx create-next-app my-data-portal --example https://github.com/datopian/portaljs/tree/main/examples/basic-example
|
||||
```
|
||||
|
||||
- Data storage and APIs
|
||||
- Data visualization and exploration
|
||||
- Data validation and schemas
|
||||
- Orchestration and integration of data
|
||||
- Data Lake coordination and organization
|
||||
> [!tip]
|
||||
> You may have noticed we used the command create-next-app. That’s because PortalJS is built on the awesome NextJS react javascript framework. That’s mean you can do everything you do with NextJS with PortalJS. Check out their docs to learn more.
|
||||
|
||||
The rise of Data Portals reflect the rapid growth in the volume and variety of data that organizations hold and use. With so much data available internally (and externally) it is hard for users to discover and access the data they need. And with so many potential users and use-cases it is hard to anticipate what data will be needed, when.
|
||||
### Run the development server
|
||||
|
||||
**[Read more about data portals](/docs/dms/data-portals)**
|
||||
You now have a new directory called `my-data-portal`. Let’s cd into it and then run the following command:
|
||||
|
||||
## Getting started
|
||||
```bash
|
||||
npm run dev
|
||||
```
|
||||
|
||||
To get started creating your own data portal with PortalJS, take a look at the examples below and analyze which one best suits your needs:
|
||||
This starts the NextJS (and hence PortalJS) "development server" on port 3000.
|
||||
|
||||
### Examples
|
||||
Let's check it's working and what we have! Open http://localhost:3000 from your browser.
|
||||
|
||||
* [Data catalog with data coming from CKAN](/docs/example-ckan)
|
||||
* [Simple data catalog](/docs/example-data-catalog)
|
||||
You should see a page like this when you access http://localhost:3000. This is the starter template page which shows the most simple data portal you could have: a simple README plus csv file.
|
||||
|
||||
Then, simply follow the instructions on the given example page to use it as the template of your project.
|
||||
<img src="/assets/examples/basic-example.png" />
|
||||
|
||||
## Tutorials and guides
|
||||
### Editing the Page
|
||||
|
||||
We are working on that! Tutorials coming out soon.
|
||||
Let’s try editing the starter page.
|
||||
|
||||
## Getting Help
|
||||
|
||||
If you have questions about anything related to PortalJS, you're always welcome to ask our community on [GitHub Discussions](https://github.com/datopian/portaljs/discussions) or on our [Discord server](https://discord.gg/EeyfGrGu4U).
|
||||
- Make sure the development server is still running.
|
||||
- Open content/index.md with your text editor.
|
||||
- Find the text that says “My Dataset” and change it to “My Awesome Dataset”.
|
||||
- Save the file.
|
||||
|
||||
As soon as you save the file, the browser automatically updates the page with the new text:
|
||||
|
||||
<img src="/assets/docs/editing-the-page-1.png" />
|
||||
|
||||
374
site/content/docs/tutorial-create-data-portal-singe-dataset.md
Normal file
@ -0,0 +1,374 @@
|
||||
## Create a data portal with a single dataset
|
||||
|
||||
Welcome to the PortalJS tutorials series. In this first tutorial, we are going to take a look at a simple data portal example built with PortalJS, understand its structure and learn how we can customize it, specially with data components.
|
||||
|
||||
The resulting data portal is our _Hello World_ equivalent: a single dataset, and it looks like this:
|
||||
|
||||
<img src="/assets/docs/tutorial-1-img-1.png" />
|
||||
|
||||
This tutorials series is sequential, so the next tutorials starts from where this one left, don't forget to save your progress, and, finally, let's get started!
|
||||
|
||||
### Create a new PortalJS project
|
||||
|
||||
First step is to create a new PortalJS project. To do that, please follow the instructions on the [Getting Started](#getting-started) section of the docs.
|
||||
|
||||
Now, make sure you have the project running on your local environment (`npm run dev`) and access http://localhost:3000 on your browser. As you can see, the new project is not empty, it already contains some content which we will use as a base in this tutorial. Here's what the page looks like:
|
||||
|
||||
<img src="/assets/docs/tutorial-1-img-2.png" />
|
||||
|
||||
|
||||
### Basics
|
||||
|
||||
As you can see, the page is very generic, and consists of a header, some text, a table and a line chart (built with Vega). Soon we are going to make it more interesting, but first, how did we end up with this?
|
||||
|
||||
#### The content routing system
|
||||
|
||||
Let's start by analyzing the main components of the folder strucutre of the project:
|
||||
|
||||
```bash
|
||||
content/
|
||||
my-dataset/
|
||||
README.md
|
||||
public/
|
||||
data_1.csv
|
||||
data_2.csv
|
||||
```
|
||||
|
||||
You see that `README.md` file inside the content folder? That's exactly what's being rendered on your browser. PortalJS uses a filesystem approach to content routing, this means that the folder structure inside the content folder determines the routes used to access the pages in the application, a page being a `.md` (Markdown) file, analogously to a HTML document. When the file is named "README.md", it means that it's an index file. Take a look at the following example:
|
||||
|
||||
```bash
|
||||
content/
|
||||
README.md # => Page rendered at /
|
||||
folder-1/
|
||||
README.md # => Page rendered at /folder-1
|
||||
folder-2/
|
||||
README.md # => Page rendered at /folder-2
|
||||
folder-2-1/
|
||||
README.md # => Page rendered at /folder-2/folder-2-1
|
||||
```
|
||||
|
||||
INTERNAL NOTE: let's change that to index.md instead of README.md. Add examples of non-index pages? The MDX pipeline should be handling other .md files but it's not doing that rn. Maybe remove next paragraph
|
||||
|
||||
Note that it's also possible to create non-index pages, but this is not going to be demonstrated on this tutorial for the sake of simplicity.
|
||||
|
||||
#### The pages
|
||||
|
||||
_Cool, a Markdown file becomes a page, but what is a Markdown file :thinking_face:?_
|
||||
|
||||
Without getting into much detail, Markdown is a markup language which allows users to write structured and formatted text using a very simple syntax, with the beauty of not leaving the realm of plain text and keeping the document completely human-readable (opposite of, for instance, HTML, in which the document might get messy and very hard to read when it's not being rendered on a browser).
|
||||
|
||||
It's not the intent of this tutorial to guide the user throught Markdown, but it's a requirement to understand it, so if you are not familiar with it we encourage you to take a look at [this guide](https://www.datopian.com/playbook/markdown) written by Datopian (Markdown is going to take over the world, seriously, you won't regret it!).
|
||||
|
||||
Now that you are aware of Markdown documents and their application on PortalJS, let's hop to how this page you were seeing on your browser looks like behind the scenes. You probably noticed the cool chart and table on the page. Plain Markdown cannot do that, but the extended Markdown on PortalJS can.
|
||||
|
||||
If you open `content/README.md` on your IDE or any text editor, you are going to come across the following content:
|
||||
|
||||
```markdown
|
||||
# Data
|
||||
|
||||
This is the README.md this project.
|
||||
|
||||
## Table
|
||||
|
||||
<Table url="data_1.csv" />
|
||||
|
||||
## Vega Lite Line Chart from URL
|
||||
|
||||
<VegaLite spec={ { "$schema": "https://vega.github.io/schema/vega-lite/v5.json", "data": {"url": "data_2.csv"}, "width": 550, "height": 250, "mark": "line", "encoding": { "x": {"field": "Time", "type": "temporal"}, "y": {"field": "Anomaly (deg C)", "type": "quantitative"}, "tooltip": {"field": "Anomaly (deg C)", "type": "quantitative"} } } } />
|
||||
|
||||
```
|
||||
|
||||
Note the `<Table />` and the `<VegaLite />` components, that's how data components are used on PortalJS, similar to tags on HTML documents. Each data component will have it's own set of attributes. These two are not the only data components that are supported, but it's interesting to note that data components can be used in a way as simple as the table pointing to a CSV file, or as flexible and complex as a chart built using a VegaLite spec.
|
||||
|
||||
One other very interesting point to notice here is that both data components are getting its data from the data files inside the public folder. When a relative URL is provided as the data source for a data component, PortalJS will look for the given file in the public folder.
|
||||
|
||||
We now have the basics, let's build something.
|
||||
|
||||
### Making the dataset page more interesting
|
||||
|
||||
It's time to start playing around with the project. Let's say we want to create a dataset page to present the data about the TV series Breaking Bad (or feel free choose a different theme and be creative!). Here are some sites with data that we can use:
|
||||
|
||||
- [Openpsychometrics.com Test](https://openpsychometrics.org/tests/characters/stats/BB/)
|
||||
- [Rotten Tomatoes Page](https://www.rottentomatoes.com/tv/breaking_bad)
|
||||
|
||||
Open the `content/my-dataset/README.md` file and delete the content inside it. Now, let's start with a heading and description:
|
||||
|
||||
```markdown
|
||||
# Breaking Bad Statistics
|
||||
|
||||
**Data source:** https://openpsychometrics.org/tests/characters/stats/BB/
|
||||
|
||||
Visualizations about the public perception of the Breaking Bad TV series and its characters.
|
||||
|
||||
```
|
||||
|
||||
Cool, with that, our intention with this page is now clear. Time to add some visualizations.
|
||||
|
||||
#### Tables
|
||||
|
||||
Let's start with a table. There's an interesting table in the dataset about the notability of 10 of the characters on the [Openpsychometrics.com Test](https://openpsychometrics.org/tests/characters/stats/BB/), let's reproduce that in our page. Here's the data in CSV format:
|
||||
|
||||
```bash
|
||||
Notability,Name
|
||||
91.3,Walter White
|
||||
88.9,Jesse Pinkman
|
||||
82.5,Mike Ehrmantraut
|
||||
79.6,Gus Fring
|
||||
74.8,Hank Schrader
|
||||
73.8,Saul Goodman
|
||||
61.3,Jane Margolis
|
||||
55.4,Skyler White
|
||||
46.8,Flynn White
|
||||
27.9,Marie Schrader
|
||||
```
|
||||
|
||||
Tables can be created from different data sources on PortalJs, these being:
|
||||
|
||||
##### URL
|
||||
|
||||
The URL can be either internal (relative) or external. To create a table from a URL, use the following syntax:
|
||||
|
||||
```jsx
|
||||
<Table url="data.csv" /> // Internal, file at /public/data.csv
|
||||
|
||||
// Or
|
||||
|
||||
<Table url="https://people.sc.fsu.edu/~jburkardt/data/csv/addresses.csv" />
|
||||
```
|
||||
|
||||
##### Inline CSV
|
||||
|
||||
To create a table using inline CSV, use the following syntax:
|
||||
|
||||
```jsx
|
||||
<Table csv={`
|
||||
Year,Cost
|
||||
2018,50345.50
|
||||
2019,65272.20
|
||||
2020,48413.80
|
||||
2021,76213.50
|
||||
2022,71653.60
|
||||
`} />
|
||||
```
|
||||
|
||||
##### Columns and rows
|
||||
|
||||
|
||||
Finally, you can also provide the data in the form of columns and rows using the following syntax:
|
||||
|
||||
```jsx
|
||||
<Table cols={[
|
||||
{ key: 'id', name: 'ID' },
|
||||
{ key: 'firstName', name: 'First name' },
|
||||
{ key: 'lastName', name: 'Last name' },
|
||||
{ key: 'age', name: 'Age' }
|
||||
]} data={[
|
||||
{ id: 1, lastName: 'Snow', firstName: 'Jon', age: 35 },
|
||||
{ id: 2, lastName: 'Lannister', firstName: 'Cersei', age: 42 },
|
||||
{ id: 3, lastName: 'Lannister', firstName: 'Jaime', age: 45 },
|
||||
{ id: 4, lastName: 'Stark', firstName: 'Arya', age: 16 },
|
||||
{ id: 7, lastName: 'Clifford', firstName: 'Ferrara', age: 44 },
|
||||
{ id: 8, lastName: 'Frances', firstName: 'Rossini', age: 36 },
|
||||
{ id: 9, lastName: 'Roxie', firstName: 'Harvey', age: 65 },
|
||||
]}
|
||||
/>
|
||||
```
|
||||
|
||||
___
|
||||
|
||||
Now that you are more familiar with the table data component, let's go ahead and add the table to the page. Since there are only a few rows in the data, inline CSV might be a good option for this table, but feel free to create a CSV file or to convert the data to columns and rows if you want. Add that to the end of the file:
|
||||
|
||||
```markdown
|
||||
## Character Notability
|
||||
|
||||
<Table csv={`
|
||||
Notability,Name
|
||||
91.3,Walter White
|
||||
88.9,Jesse Pinkman
|
||||
82.5,Mike Ehrmantraut
|
||||
79.6,Gus Fring
|
||||
74.8,Hank Schrader
|
||||
73.8,Saul Goodman
|
||||
61.3,Jane Margolis
|
||||
55.4,Skyler White
|
||||
46.8,Flynn White
|
||||
27.9,Marie Schrader
|
||||
`} />
|
||||
|
||||
_Isn't it interesting that Saul is so below in the ranking? There's even a spin-off about him._
|
||||
|
||||
```
|
||||
|
||||
Here's how it's going to look like on the page:
|
||||
|
||||
<img src="/assets/docs/tutorial-1-img-3.png" />
|
||||
|
||||
#### Simple line charts
|
||||
|
||||
Let's use the `<LineChart />` data component and the ratings on Rotten Tomatoes to create a rating by year line chart (note that each season was released in a diffent year).
|
||||
|
||||
INTERNAL NOTE: LineChart is not working properly on the example, the width is not right. Can't we make numeric X work as well instead of having just years? We still have that bug in which the X is offsetted by -1.
|
||||
|
||||
First, here's the data of the rating by season in CSV format:
|
||||
|
||||
```bash
|
||||
Year,Rating
|
||||
2008,86
|
||||
2009,97
|
||||
2010,100
|
||||
2011,100
|
||||
2012,97
|
||||
```
|
||||
|
||||
The `<LineChart />` data component expects two attributes: `title` and `data`, so let's add the following to the end of the file:
|
||||
|
||||
```markdown
|
||||
## Rating x Season
|
||||
|
||||
<LineChart title="Rating x Season" data={
|
||||
[
|
||||
["2008",86],
|
||||
["2009",97],
|
||||
["2010",100],
|
||||
["2011",100],
|
||||
["2012",97]
|
||||
]
|
||||
}
|
||||
/>
|
||||
|
||||
_Consistently well received by critics_
|
||||
|
||||
```
|
||||
|
||||
Here are the results:
|
||||
|
||||
<img src="/assets/docs/tutorial-1-img-4.png" />
|
||||
|
||||
#### Complex charts
|
||||
|
||||
Finally, PortalJS also supports the creation of visualizations with [Vega and VegaLite](https://vega.github.io/). This becomes specially interesting when it's desired to create more complex and custom visualizations. To demonstrate this, let's add a bar chart that compares Breaking Bad to Better Call Saul, a spin-off of the series, based on the data on Rotten Tomatoes. Here's the data in CSV format:
|
||||
|
||||
```bash
|
||||
TV Show,Average Tomatometer,Average Audience Score
|
||||
Breaking Bad,0.96,0.97
|
||||
Better Call Saul,0.98,0.96
|
||||
```
|
||||
|
||||
Add that to the file:
|
||||
|
||||
```jsx=
|
||||
## Breaking Bad x Better Call Saul
|
||||
|
||||
<VegaLite spec={
|
||||
{
|
||||
"width": 150,
|
||||
"data": {
|
||||
"values": [
|
||||
{"TV Show": "Breaking Bad", "Rating": "Average Tomatometer", "Value":0.96},
|
||||
{"TV Show":"Breaking Bad", "Rating": "Average Audience Score", "Value":0.97},
|
||||
{"TV Show":"Better Call Saul", "Rating": "Average Tomatometer", "Value":0.98},
|
||||
{"TV Show":"Better Call Saul", "Rating": "Average Audience Score", "Value":0.96}
|
||||
]
|
||||
},
|
||||
"mark": "bar",
|
||||
"encoding": {
|
||||
"column": {"field": "TV Show","header": {"orient": "bottom"}},
|
||||
"y": {"field": "Value", "type": "quantitative"},
|
||||
"x": {"field": "Rating", "axis": null},
|
||||
"color": {"field": "Rating"}
|
||||
},
|
||||
"config": {
|
||||
"view": {"stroke": "transparent"}
|
||||
}
|
||||
}
|
||||
} />
|
||||
|
||||
_The producers were able to successfully expand the success of the original series to the spin-off_
|
||||
|
||||
```
|
||||
|
||||
It's going to look like this when you navigate to the page again:
|
||||
|
||||
<img src="/assets/docs/tutorial-1-img-5.png" />
|
||||
|
||||
### Final results
|
||||
|
||||
Here's the whole source code of the dataset page we built:
|
||||
|
||||
```markdown
|
||||
# Breaking Bad Statistics
|
||||
|
||||
**Data source:** https://openpsychometrics.org/tests/characters/stats/BB/
|
||||
|
||||
Visualizations about the public perception of the Breaking Bad TV series and its characters.
|
||||
|
||||
## Character Notability
|
||||
|
||||
<Table csv={`
|
||||
Notability,Name
|
||||
91.3,Walter White
|
||||
88.9,Jesse Pinkman
|
||||
82.5,Mike Ehrmantraut
|
||||
79.6,Gus Fring
|
||||
74.8,Hank Schrader
|
||||
73.8,Saul Goodman
|
||||
61.3,Jane Margolis
|
||||
55.4,Skyler White
|
||||
46.8,Flynn White
|
||||
27.9,Marie Schrader
|
||||
`} />
|
||||
|
||||
_Isn't it interesting that Saul is so below in the ranking? There's even a spin-off about him._
|
||||
|
||||
## Rating x Season
|
||||
|
||||
<LineChart title="Rating x Season" data={
|
||||
[
|
||||
["2008",86],
|
||||
["2009",97],
|
||||
["2010",100],
|
||||
["2011",100],
|
||||
["2012",97]
|
||||
]
|
||||
}
|
||||
/>
|
||||
|
||||
_Consistently well received by critics_
|
||||
|
||||
## Breaking Bad x Better Call Saul
|
||||
|
||||
<VegaLite spec={
|
||||
{
|
||||
"width": 150,
|
||||
"data": {
|
||||
"values": [
|
||||
{"TV Show": "Breaking Bad", "Rating": "Average Tomatometer", "Value":0.96},
|
||||
{"TV Show":"Breaking Bad", "Rating": "Average Audience Score", "Value":0.97},
|
||||
{"TV Show":"Better Call Saul", "Rating": "Average Tomatometer", "Value":0.98},
|
||||
{"TV Show":"Better Call Saul", "Rating": "Average Audience Score", "Value":0.96}
|
||||
]
|
||||
},
|
||||
"mark": "bar",
|
||||
"encoding": {
|
||||
"column": {"field": "TV Show","header": {"orient": "bottom"}},
|
||||
"y": {"field": "Value", "type": "quantitative"},
|
||||
"x": {"field": "Rating", "axis": null},
|
||||
"color": {"field": "Rating"}
|
||||
},
|
||||
"config": {
|
||||
"view": {"stroke": "transparent"}
|
||||
}
|
||||
}
|
||||
} />
|
||||
|
||||
_The producers were able to successfully expand the success of the original series to the spin-off_
|
||||
```
|
||||
And here's a screenshot of what it looks like:
|
||||
|
||||
<img src="/assets/docs/tutorial-1-img-6.png" />
|
||||
|
||||
### Next steps
|
||||
|
||||
Now that you already know how to create pages and render data components, we encourage you to play around with this project. You can try adding new visualizations, changing values, or creating a new page about something you find interesting.
|
||||
|
||||
Finally, proceed to the next tutorial in the series.
|
||||
@ -4,7 +4,8 @@
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "next dev",
|
||||
"build": "npm run mddb && next build",
|
||||
"build": "next build",
|
||||
"prebuild": "npm run mddb && node ./scripts/fix-symlinks.mjs",
|
||||
"start": "next start",
|
||||
"mddb": "mddb content"
|
||||
},
|
||||
|
||||
BIN
site/public/static/img/docs/dms/ckan-register.png
Normal file
|
After Width: | Height: | Size: 118 KiB |
BIN
site/public/static/img/docs/dms/data-explorer/chart-builder.png
Normal file
|
After Width: | Height: | Size: 46 KiB |
BIN
site/public/static/img/docs/dms/data-explorer/data-explorer.png
Normal file
|
After Width: | Height: | Size: 298 KiB |
|
After Width: | Height: | Size: 154 KiB |
BIN
site/public/static/img/docs/dms/data-explorer/date-picker.png
Normal file
|
After Width: | Height: | Size: 61 KiB |
BIN
site/public/static/img/docs/dms/data-explorer/i18n-cookie.png
Normal file
|
After Width: | Height: | Size: 154 KiB |
BIN
site/public/static/img/docs/dms/data-explorer/map-builder.png
Normal file
|
After Width: | Height: | Size: 33 KiB |
BIN
site/public/static/img/docs/dms/data-explorer/query-builder.png
Normal file
|
After Width: | Height: | Size: 18 KiB |
BIN
site/public/static/img/docs/dms/dx/DX_architecture.jpg
Normal file
|
After Width: | Height: | Size: 280 KiB |
BIN
site/public/static/img/docs/dms/dx/GitOps_Workflow.jpg
Normal file
|
After Width: | Height: | Size: 37 KiB |
BIN
site/public/static/img/docs/dms/dx/logging-dashboard.png
Normal file
|
After Width: | Height: | Size: 125 KiB |
BIN
site/public/static/img/docs/dms/dx/logging-query.png
Normal file
|
After Width: | Height: | Size: 365 KiB |
BIN
site/public/static/img/docs/dms/dx/logging-service.png
Normal file
|
After Width: | Height: | Size: 306 KiB |
BIN
site/public/static/img/docs/dms/dx/monitoring-console.png
Normal file
|
After Width: | Height: | Size: 85 KiB |
BIN
site/public/static/img/docs/dms/dx/monitoring-create-alert.png
Normal file
|
After Width: | Height: | Size: 164 KiB |
BIN
site/public/static/img/docs/dms/dx/monitoring-create-uptime.png
Normal file
|
After Width: | Height: | Size: 141 KiB |
BIN
site/public/static/img/docs/dms/dx/monitoring-dashboard.png
Normal file
|
After Width: | Height: | Size: 318 KiB |
|
After Width: | Height: | Size: 230 KiB |
BIN
site/public/static/img/docs/dms/frontend-sequence-1.png
Normal file
|
After Width: | Height: | Size: 152 KiB |
15
site/scripts/fix-symlinks.mjs
Normal file
@ -0,0 +1,15 @@
|
||||
// Script executed before builds
|
||||
|
||||
import { exec } from "child_process";
|
||||
import fs from "fs";
|
||||
|
||||
// If Vercel environment is detected
|
||||
if (process.env.VERCEL_ENV) {
|
||||
console.log(
|
||||
"[scripts/fix-symlinks.mjs] Vercel environment detected. Fixing symlinks..."
|
||||
);
|
||||
|
||||
// fs.unlinkSync('public/assets')
|
||||
exec('cp -r ./content/assets ./public/')
|
||||
|
||||
}
|
||||