Compare commits

...

417 Commits

Author SHA1 Message Date
47b4ffece8 Update packages/remark-wiki-link/src/lib/remarkWikiLink.ts
Some checks failed
Release / Release (push) Failing after 1h6m8s
2025-04-08 18:12:43 +00:00
Rufus Pollock
816db6858c [site/content/docs/dms][s]: remove this directory as duplicate of content on tech.datopian.com/ especially tech.datopian.com/dms. 2025-02-09 22:59:31 +00:00
github-actions[bot]
0381f2fccf Version Packages 2025-01-22 16:37:23 +01:00
Ola Rubaj
62dbc35d3b fix(LineChart): skip lines at invalid/missing data points (don't force connect) 2025-01-22 16:23:17 +01:00
Lucas Morais Bispo
12f0d0d732
Merge pull request #1347 from datopian/feature/update-links
[md][datahub] updated links from portaljs.org to portaljs.com
2025-01-13 08:52:50 -03:00
muhammad-hassan11
d80d1f5012 removed logs 2025-01-13 16:22:01 +05:00
Anuar Ustayev (aka Anu)
af5b6b7a29
Rename/rebrand from datahub to portaljs.
DataHub.io is becoming something different, e.g., hub for data OR data market[place] while PortalJS.com is a cloud platform for creating managed data portals.
2024-12-24 10:43:26 +05:00
muhammad-hassan11
8487175f01 [md][datahub] updated links from portaljs.org to portaljs.com 2024-12-23 21:57:09 +05:00
Anuar Ustayev (aka Anu)
6551576700
Change back to PortalJS name for data portals. 2024-12-23 11:10:39 +05:00
Lucas Morais Bispo
4fccb2945f
Merge pull request #1346 from datopian/fix/dotorgmerging
[site][WIP] Seo - update title, canonical
2024-12-05 19:35:07 -03:00
lucasmbispo
a9025e5cbe [site]:seo - update title, canonical 2024-12-05 08:14:18 -03:00
github-actions[bot]
ad5a176e85 Version Packages 2024-11-11 15:52:06 +01:00
Ola Rubaj
eeb480e8cf [fix][xs]: allow yearmonth TimeUnit in LineChart 2024-11-11 15:40:07 +01:00
github-actions[bot]
30fcb256b2 Version Packages 2024-10-24 08:53:23 +02:00
Ola Rubaj
a4f8c0ed76 [chore][xs]: update package-lock 2024-10-24 08:46:51 +02:00
Ola Rubaj
829f3b1f13 [chore][xs]: fix formatting 2024-10-24 08:46:27 +02:00
Ola Rubaj
836b143a31 [fix][xs]: make tileLayerName in Map optional 2024-10-24 08:45:51 +02:00
github-actions[bot]
be38086794 Version Packages 2024-10-23 18:08:18 +02:00
Ola Rubaj
63d9e3b754
[feat,LineChart][s]: support for multiple series 2024-10-23 18:03:07 +02:00
Anuar Ustayev (aka Anu)
f86f0541eb
Merge pull request #1332 from datopian/site/fix-showcases
[portaljs site][showcases][s] Merge examples into Showcases tab
2024-10-11 09:36:16 +05:00
Lucas Morais Bispo
64bc212384
Update README.md 2024-10-09 11:46:02 -03:00
Lucas Morais Bispo
1e7daf353d
Add files via upload 2024-10-09 11:28:42 -03:00
lucasmbispo
cc69dabf80 [site][showcases] update examples 2024-10-03 21:04:06 -03:00
lucasmbispo
a5d87712e0 [site][showcases][s] Merge examples into Showcases tab 2024-10-01 11:07:33 -03:00
Rufus Pollock
86834fd1a6
Merge pull request #1317 from loleg/patch-1
Fix link to Next.js in README.md
2024-09-20 13:30:02 +02:00
Oleg Lavrovsky
8a661b1617
Fix link to Next.js in README.md 2024-09-20 11:23:06 +02:00
Rufus Pollock
1baebc3f3c
Merge pull request #1200 from rzmk/patch-1
[#1181, examples/ckan-ssg][xs]: update example generation command
2024-07-05 19:13:43 +02:00
João Demenech
bbac4954f5
Merge pull request #1202 from datopian/changeset-release/main
Version Packages
2024-06-24 17:58:02 -03:00
github-actions[bot]
be6b184884 Version Packages 2024-06-24 20:47:23 +00:00
João Demenech
64103d6488
Merge pull request #1122 from datopian/feature/custom-tile-layer
Custom Tile Layer for Map Component
2024-06-24 17:44:19 -03:00
Demenech
8e3496782c version: add changeset 2024-06-24 17:42:49 -03:00
Mueez Khan
e034503399
[examples/ckan-ssg][xs]: update command to create project 2024-06-22 00:17:49 -04:00
William Lima
93ae498ec2 Code cleanup 2024-06-19 10:10:56 -01:00
William Lima
97e43fdcba add mapbox as default basemap 2024-06-18 22:37:20 -01:00
William Lima
32f29024f8 attr replace fix 2024-06-18 22:05:41 -01:00
William Lima
134f72948c Add TileLayer Presets configuration 2024-06-18 22:01:59 -01:00
Rufus Pollock
c1f2c526a8 [#1181,site][xs]: change portaljs to datahub in github repo references. 2024-06-10 19:31:43 +02:00
João Demenech
8feb87739d
Merge pull request #1173 from datopian/changeset-release/main
Version Packages
2024-06-09 08:06:43 -03:00
github-actions[bot]
3a07267e44 Version Packages 2024-06-09 09:25:23 +00:00
Rufus Pollock
3f19ca16ed
[#1118,docs/portaljs][s 2024-06-09 11:22:25 +02:00
João Demenech
5deabac5fe
Merge pull request #1170 from datopian/fix/iframe-height
[components][iFrame] Change default height
2024-06-04 14:57:24 -03:00
lucasmbispo
96901150c6 [changesets] change major to patch 2024-06-04 09:38:47 -03:00
lucasmbispo
9ff25ed7c4 [components][iFrame] Change iFrame height 2024-06-04 09:38:12 -03:00
lucasmbispo
8f884fceab [components][iFrame] Change default height 2024-06-04 09:26:30 -03:00
Anuar Ustayev (aka Anu)
7094eded50
Merge pull request #1167 from datopian/fix/map-geojson
Fix: autoZoomConfiguration not working properly when the geojson parameter is passed
2024-06-04 14:06:45 +05:00
Rufus Pollock
30e7c6379f
Merge pull request #1069 from marcchehab/patch-2 - Add SiteToc to MobileNav.
This PR adds the SiteToc to the MobileNav. It also fixes double type declarations in MobileNav by importing the interfaces from Nav. Adding SiteToc was then just a matter of uncommenting code that was there already.
2024-05-31 17:16:42 +02:00
Ronaldo Campos
feada58932 Fix: autoZoomConfiguration not working properly when the geojson parameter is passed 2024-05-31 11:37:01 -03:00
William Lima
31406d48e3 Update Map.tsx 2024-05-31 10:29:15 -01:00
Daniellappv
d6bf344ca3
Update CONTRIBUTING.md 2024-05-31 10:55:58 +03:00
William Lima
d1a5138c6e include configs on .env vars or pass through props 2024-05-22 11:48:20 -01:00
William Lima
a6047a9341 Implements Custom Tile Layer
#1121 adds default tile layer and allows user to pass a tile object to map
2024-05-13 12:51:28 -01:00
Ola Rubaj
a4e60540ae
Merge pull request #1119 from datopian/remark-wiki-link-cleanup
## Changes

- remove unneeded tests
- do not remove "index" from the end of tile path in `getPermalinks` function
2024-05-09 02:20:45 +02:00
Ola Rubaj
e4c456c237 rm changeset file 2024-05-09 02:19:54 +02:00
Ola Rubaj
ce9ebbf41e add changeset file 2024-05-09 02:16:05 +02:00
Ola Rubaj
a8fb176bcc rm test for custom permarlink converter (irrelevant) 2024-05-09 02:12:44 +02:00
Ola Rubaj
2ac82367c5 do not remove "index" from the end of file
- should be treated as a regular file name
- it's up to the app how to interpret those paths/files later
2024-05-09 02:12:38 +02:00
Ola Rubaj
85de6f7878 replace inex.md with README.md in test fixtures 2024-05-09 02:09:52 +02:00
Ola Rubaj
539fffeb55
Merge pull request #1113 from datopian/changeset-release/main
Version Packages
2024-04-18 15:43:31 +02:00
github-actions[bot]
0d276535bd Version Packages 2024-04-18 13:42:23 +00:00
Ola Rubaj
38dd7103a3
Merge pull request #1103 from datopian/feat/portaljs-components-improvements
Components API and docs improvements
Related to: #1089
2024-04-17 16:16:27 +02:00
Ola Rubaj
48cd812a48 add changeset file 2024-04-17 16:14:00 +02:00
Ola Rubaj
7bba10714d refresh package-lock file 2024-04-17 16:13:47 +02:00
github-actions[bot]
de2c1e5b48
Version Packages (#1109)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-04-17 15:54:34 +02:00
mohamed yahia
57952e0817
[remark-wiki-link][m]: Add image size adjustment in remark-wiki-link (#1084)
* [remark-wiki-link][m]: Add image size adjustment in `remark-wiki-link`

* [remark-wiki-links][m]: Add image size feature to images
2024-04-15 18:39:27 +02:00
Demenech
df9664624f fix(LineChart): remove unused fillWidth prop 2024-04-09 17:45:12 -03:00
Demenech
2ea185b710 feat: Catalog component API and docs improvements 2024-04-09 17:41:01 -03:00
Demenech
b859d48f17 feat: Map component API and docs improvements 2024-04-09 17:30:45 -03:00
Demenech
3d73ac422e feat: Vega and Vega Lite components API and docs improvements 2024-04-09 17:13:05 -03:00
Demenech
059ffe4e34 feat: PlotlyLineChart component API and docs improvements 2024-04-09 17:08:50 -03:00
Demenech
0aed7dce77 feat: Plotly component docs improvements 2024-04-09 16:57:23 -03:00
Demenech
c202d6cfc4 feat: LineChart component API and docs improvements 2024-04-09 16:50:49 -03:00
Demenech
d9c20528c5 feat: PdfViewer component API and docs improvements 2024-04-09 16:20:01 -03:00
Demenech
b7ee5a1869 feat: Iframe component API and docs improvements 2024-04-09 16:07:12 -03:00
Demenech
4b5d549190 feat: comment out the Table component for now 2024-04-09 15:58:33 -03:00
Demenech
e6f0ab4ec8 feat: FlatUiTable component API and docs improvements 2024-04-09 15:54:03 -03:00
Demenech
22038fbd4f feat: Excel component API and docs improvements 2024-04-09 15:44:37 -03:00
Demenech
8b292a9bf2 feat: group stories in different categories 2024-04-09 15:36:48 -03:00
Demenech
cda3d335f1 feat: rename Plotly components stories so that they show up together on the storybook sidebar 2024-04-09 15:25:14 -03:00
Demenech
fe97cc87f4 fix: OpenLayers and BucketViewer were still showing up 2024-04-09 15:22:55 -03:00
Demenech
88f6199d18 feat: implement new Data interface + review PlotlyBarChart API and docs + hide BucketViewer and OpenLayers 2024-04-09 15:21:08 -03:00
Rufus Pollock
852cf60abc
[README][s]: further refinements of info re DataHub. 2024-04-05 11:50:24 +02:00
Rufus Pollock
704be0d5a7
[README][s]: update portal.js to datahub nomenclature. 2024-04-05 11:28:37 +02:00
Rufus Pollock
fb3598fa49
Delete .vscode/extensions.json
No need for vscode stuff in repo.
2024-04-01 18:18:06 +02:00
Rufus Pollock
d898b5a833
Merge pull request #1065 from marcchehab/patch-1
Fix React warning about unique "key" prop
2024-03-29 14:56:38 +01:00
github-actions[bot]
3aac4dabf9
Version Packages (#1087)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-03-22 10:42:53 -03:00
Luccas Mateus
a044f56e3c Changeset 2024-03-22 10:32:11 -03:00
Luccas Mateus
1b58c311eb Plotly components 2024-03-22 10:31:30 -03:00
Rufus Pollock
ed9ac2c263
Delete tools/tsconfig.tools.json
Remove as tools is empty folder.
2024-02-28 16:49:24 +01:00
Rufus Pollock
42c72e5afd
Delete tools/generators/.gitkeep
empty directory
2024-02-28 16:48:34 +01:00
Rufus Pollock
9e1a324fa1
[examples/fivethirtyeight][xs]: link to blog post we wrote about it. 2024-02-13 13:31:39 +01:00
Rufus Pollock
90178af8f2
[examples/fivethirtyeight][s]: add link to demo site to README. 2024-02-13 13:30:57 +01:00
Rufus Pollock
00e61e104c
[site/config][xs]: change discord server to datahub. 2024-02-09 10:27:06 +01:00
Leonardo Yuri Farias
f7f03fddca
Merge pull request #1085 from datopian/changeset-release/main
Version Packages
2024-01-31 13:20:53 -03:00
github-actions[bot]
0891dfde2d Version Packages 2024-01-31 09:31:04 +00:00
Anuar Ustayev (aka Anu)
c904e3731b
Merge pull request #1083 from datopian/feature/table-with-integration-with-datastore-api
Created integration with datastore api for table component
2024-01-31 15:28:17 +06:00
Gutts-n
86a2945ee6 Created integration with datastore api for table component 2024-01-29 14:07:42 -03:00
Leonardo Yuri Farias
09daa98b28
Merge pull request #1082 from datopian/changeset-release/main
Version Packages
2024-01-25 16:49:22 -03:00
github-actions[bot]
b511c9f71b Version Packages 2024-01-25 19:48:44 +00:00
Leonardo Yuri Farias
464cda6db8
Merge pull request #1081 from datopian/fix/changed-the-download-behavior
Fixed error to remove anchor from document
2024-01-25 16:45:58 -03:00
Gutts-n
2bbf313489 Fixed error to remove anchor from document 2024-01-25 16:45:39 -03:00
Gutts-n
c26b76368d Fixed error to remove anchor from document 2024-01-25 16:43:47 -03:00
Leonardo Yuri Farias
af11f0cfd5
Merge pull request #1080 from datopian/changeset-release/main
Version Packages
2024-01-25 16:20:34 -03:00
github-actions[bot]
9ae2b31113 Version Packages 2024-01-25 19:19:58 +00:00
Leonardo Yuri Farias
2bffd130c8
Merge pull request #1079 from datopian/fix/changed-the-download-behavior
Changed behavior of the download data bucket viewer component
2024-01-25 16:17:14 -03:00
Gutts-n
058d23678a Added changeset to the PR 2024-01-25 16:16:49 -03:00
Gutts-n
540a08934c Changed behavior of the download data bucket viewer component 2024-01-25 16:10:22 -03:00
Leonardo Yuri Farias
7d010cfee4
Merge pull request #1078 from datopian/changeset-release/main
Version Packages
2024-01-24 17:23:14 -03:00
github-actions[bot]
dd79da1c6b Version Packages 2024-01-24 20:22:57 +00:00
Leonardo Yuri Farias
a58e2b81f7
Merge pull request #1077 from datopian/feature/download-loading-message
Created property to present a component while loading the download of the file and fixed download bug on pagination
2024-01-24 17:20:09 -03:00
Gutts-n
6d7acd27ed Created property to present a component while is loading the download of the file and fixed download bug on pagination 2024-01-24 17:15:14 -03:00
Leonardo Yuri Farias
7c30842c7d
Merge pull request #1076 from datopian/changeset-release/main
Version Packages
2024-01-24 11:08:44 -03:00
github-actions[bot]
35ca1d6dfd Version Packages 2024-01-24 14:08:13 +00:00
Leonardo Yuri Farias
a7e90b64af
Merge pull request #1075 from datopian/fix/download-button-presented-on-start-of-bucket-viewer
Fixed problem presenting the download component in the first load of …
2024-01-24 11:05:18 -03:00
Gutts-n
26dcffc279 Fixed problem presenting the download component in the first load of the bucket viewer 2024-01-24 11:03:08 -03:00
Leonardo Yuri Farias
d18e3dd486
Merge pull request #1074 from datopian/changeset-release/main
Version Packages
2024-01-23 16:54:19 -03:00
github-actions[bot]
8d7059acb4 Version Packages 2024-01-23 19:53:24 +00:00
Leonardo Yuri Farias
09d5324d4e
Merge pull request #1073 from datopian/feature/search-and-pagination-for-bucket-viewer
Fixed bug on filter by startDate
2024-01-23 16:50:37 -03:00
Gutts-n
cf24042a91 Fixed bug on filter by startDate 2024-01-23 16:49:15 -03:00
Leonardo Yuri Farias
2c45da679b
Merge pull request #1072 from datopian/changeset-release/main
Version Packages
2024-01-23 14:46:42 -03:00
github-actions[bot]
0a476101e7 Version Packages 2024-01-23 17:44:30 +00:00
Leonardo Yuri Farias
1343a7a6f7
Merge pull request #1071 from datopian/feature/search-and-pagination-for-bucket-viewer
Added pagination and filter properties for the BucketViewer component
2024-01-23 14:41:44 -03:00
Gutts-n
27c99adde8 Added pagination and filter properties for the BucketViewer component 2024-01-23 14:37:03 -03:00
luzmediach
1a8e7ac06e NavMobile to use Nav interfaces and add SiteToc to sidebar 2024-01-21 12:48:10 +01:00
marcchehab
4355efe0c4
Update Nav.tsx 2024-01-21 12:36:46 +01:00
mohamed yahia
96904aef0d
Merge pull request #1068 from datopian/analytics
[core][m]: Add analytics component to the core packages
2024-01-18 23:53:27 +02:00
mohamed yahia
92a549d6a9 [core][m]: Add analytics component to the core packages 2024-01-18 23:51:01 +02:00
Leonardo Yuri Farias
1a5bbd4346
Merge pull request #1067 from datopian/changeset-release/main
Version Packages
2024-01-17 22:42:02 -03:00
github-actions[bot]
4985576183 Version Packages 2024-01-18 01:41:06 +00:00
Leonardo Yuri Farias
7049917ef7
Merge pull request #1066 from datopian/feature/iframe-component
Created Iframe component
2024-01-17 22:38:23 -03:00
Gutts-n
dd03a493be Created Iframe component 2024-01-17 22:32:56 -03:00
Gutts-n
e5b0a85e48 Created Iframe component 2024-01-17 21:54:22 -03:00
Gutts-n
a93b13f448 Component start 2024-01-17 21:08:44 -03:00
marcchehab
9e73410b17
Fix React warning about unique "key" prop
I always get a react warning: Warning: Each child in a list should have a unique "key" prop.

This fixed it and makes for warning-free development 😊
2024-01-04 14:14:49 +01:00
Leonardo Yuri Farias
8a4ec39d25
Merge pull request #1064 from datopian/changeset-release/main
Version Packages
2023-12-21 22:30:58 -03:00
github-actions[bot]
38bf06f031 Version Packages 2023-12-22 01:29:56 +00:00
Leonardo Yuri Farias
8560f165fd
Merge pull request #1063 from datopian/feature/auto-zoom-in-map-componnet
Created auto zoom configuration for the map component
2023-12-21 22:27:14 -03:00
Leonardo Farias
b13e3ade3c Created auto zoom configuration for the map component 2023-12-21 22:23:42 -03:00
Leonardo Yuri Farias
1394f02038
Merge pull request #1062 from datopian/changeset-release/main
Version Packages
2023-12-19 22:25:59 -03:00
github-actions[bot]
e687779fa6 Version Packages 2023-12-20 01:22:46 +00:00
Leonardo Yuri Farias
2ec143707d
Merge pull request #1061 from datopian/feature/style-in-map-component
Created the style property for the map component
2023-12-19 22:20:07 -03:00
Leonardo Farias
4ddfc1126a Created the style property for the map component 2023-12-19 22:16:57 -03:00
Leonardo Yuri Farias
f23d7965f2
Merge pull request #1056 from datopian/changeset-release/main
Version Packages
2023-11-26 17:56:27 -03:00
github-actions[bot]
97e4775894 Version Packages 2023-11-26 20:55:10 +00:00
Leonardo Yuri Farias
3c14ce8af7
Merge pull request #1057 from datopian/fix/exporting-bucket-viewer-component
Added the export of BucketViewer component
2023-11-26 17:52:29 -03:00
leonardo.farias
61c750b7e1 Added the export of BucketViewer component 2023-11-26 17:50:19 -03:00
Anuar Ustayev (aka Anu)
b55ec5126c
Merge pull request #1055 from datopian/feature/bucket-viewer-component
feature: Created bucket viewer component
2023-11-24 12:17:28 +06:00
leonardo.farias
712f4a3b0f Finished the development of the BucketViewer component 2023-11-23 21:41:28 -03:00
leonardo.farias
03960c8bac feature: Created bucket viewer component 2023-11-20 23:50:04 -03:00
Leonardo Yuri Farias
73c7eaf145
Merge pull request #1050 from datopian/changeset-release/main
Version Packages
2023-11-02 19:57:46 -03:00
github-actions[bot]
542f2ede9e Version Packages 2023-11-02 22:43:32 +00:00
Leonardo Yuri Farias
f17c2ed1d0
Merge pull request #1040 from datopian/fix/broken-urls-with-dashes
Support wiki links with special characters and fix links to headings
2023-11-02 19:40:53 -03:00
Demenech
f1d7e68077 fix(site,blogs): author not showing up on two posts 2023-11-02 00:09:05 -03:00
leonardo.farias
1663b09a86 Adjusts in the regex used to replace spaces with dashes in the header of wiki links and adjusted the unit tests 2023-11-01 21:50:52 -03:00
Rufus Pollock
b940c82d93
[site/blog][s]: minor updates to enhancing-geospatial-data-visualization-with-portaljs.
- Add maps to title
- Proof intro paragraphs
2023-11-01 01:05:52 +01:00
Rufus Pollock
492593dedb
[site/navbar][s]: link examples to new examples page rather than direct to github examples folder. 2023-11-01 00:25:07 +01:00
Rufus Pollock
4ae22c7411
[site/examples][s]: stub an /examples/ page. 2023-11-01 00:23:55 +01:00
leonardo.farias
85bb6cb98c Changed tests and created tests to verify the generated prefix in the HTML plugin 2023-10-27 22:35:16 -03:00
leonardo.farias
737f880036 Changed regex to permit any symbols other than # 2023-10-26 00:00:06 -03:00
leonardo.farias
1a9d64e0cf Fixing regex to not remove dashes - 2023-10-16 22:16:07 -03:00
João Demenech
3366086d87
Merge pull request #1038 from datopian/feat/site/open-spending-revamp
Blog: add new blog post about the OpenSpending revamp
2023-10-16 17:03:37 -03:00
Demenech
b12e725467 feat(site,blog): add new blog post about the OpenSpending revamp 2023-10-14 12:28:39 -03:00
Luccas Mateus
578a52a101 Change preview url 2023-10-12 13:48:50 -03:00
Ola Rubaj
48a9243b21
[site/blog][s]: markdowndb launch post (#1036) 2023-10-12 11:12:37 +02:00
João Demenech
6b3afa878b
Merge pull request #1035 from datopian/changeset-release/main
Version Packages
2023-10-10 20:48:41 -03:00
github-actions[bot]
c9a39ec421 Version Packages 2023-10-10 23:48:00 +00:00
leonardo.farias
63ad514f9e Merge branch 'main' of https://github.com/datopian/portaljs 2023-10-10 20:44:21 -03:00
leonardo.farias
e4624c35cb adding version bump to remark-wiki-link package 2023-10-10 20:44:00 -03:00
Anuar Ustayev (aka Anu)
975aaed743
Merge pull request #1034 from datopian/portal-cus
Add Link to portaljs cloud site
2023-10-10 19:03:20 +02:00
steveoni
b8b6dd662d [Hero][s]: change button style for portal cloud cta 2023-10-10 16:00:36 +01:00
steveoni
98db406793 [Navitem][s]: add insine style condition 2023-10-10 14:39:43 +01:00
steveoni
9ea045d16a [Navitem][s]: add portaljs.com to navbar 2023-10-10 14:15:39 +01:00
steveoni
6acef2be56 [Hero.tsx][s]: remove newsletter form and Portaljs cloud cta 2023-10-10 14:00:47 +01:00
github-actions[bot]
19d40db62d
Version Packages (#1033)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-10-09 19:36:54 +02:00
Ola Rubaj
c63551a54e [core][xs]: fix Navbar title not showing 2023-10-09 19:32:42 +02:00
João Demenech
c5e17810af
Merge pull request #1029 from M27afk/566-responsive-on-large-screen
Update Layout.tsx
2023-10-06 10:29:49 -03:00
Luccas Mateus
c16970fbce Update package-lock 2023-10-06 09:38:08 -03:00
Luccas Mateus
93d35e3bcd Fix build 2023-10-06 09:33:40 -03:00
Luccas Mateus
8f4c134fd8 Move missing files 2023-10-06 09:19:56 -03:00
github-actions[bot]
9482483b51
Version Packages (#1031)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-10-05 12:16:51 +02:00
Ola Rubaj
8d74fd9844 [core/Footer][xs]: minor style fixes 2023-10-05 12:12:23 +02:00
Ola Rubaj
3ae685253b [core][xs]: minor storybook setup adjstmnts 2023-10-05 12:12:23 +02:00
Manushreshta B L
5f2f0653e9 Update Layout.tsx 2023-09-27 11:08:18 +05:30
github-actions[bot]
56cb6e7912
Version Packages (#1028)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-09-26 21:33:55 +02:00
Ola Rubaj
71716ab018 [remark-wiki-link][xs]: add support youtu.be links 2023-09-26 21:23:39 +02:00
Ola Rubaj
06d39779ce
[blog][s]: Ola's Jul-Aug updates blog post (#1026) 2023-09-25 18:51:57 +02:00
Rufus Pollock
aec67de35c [site/blog,refactor][xs: move post from howtos to blog so it shows up on blog.
Move a simple catalog of anything using markdown from howtos to blog so it shows up on blog on as not showing up in blog atm (even though has filetype: 'blog').
2023-09-24 10:26:46 +02:00
github-actions[bot]
68fbf2cda6
Version Packages (#1023)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-09-20 09:56:52 -03:00
Luccas Mateus
83fd7727ba
[flatuitable][m] - add bytes + parsingConfig (#1022) 2023-09-20 08:13:19 -03:00
Anuar Ustayev (aka Anu)
083d3178cd
Merge pull request #999 from igoradamenko/igoradamenko-patch-1
Fix wiki-link regexp to match non-Latin characters
2023-09-12 00:18:23 +06:00
João Demenech
3200dc5ade fix(site,docs): missing mddb command instruction on 'Searching datasets' tutorial 2023-09-11 08:21:35 -03:00
João Demenech
32dce434eb
Merge pull request #1017 from datopian/changeset-release/main
Version Packages
2023-08-31 16:13:39 -03:00
github-actions[bot]
37ef29d9a2 Version Packages 2023-08-31 19:09:52 +00:00
João Demenech
98d62532c5
Merge pull request #1018 from datopian/ckan/feat/private-datasets
feat(ckan): makes it possible to search private datasets on the ckan api
2023-08-31 16:06:01 -03:00
João Demenech
50122cd0cb bump: new version of CKAN API 2023-08-30 18:38:35 -03:00
João Demenech
0156e72dd3 feat(ckan): makes it possible to search private datasets on the ckan api 2023-08-30 18:35:40 -03:00
Luccas Mateus
91217f3256
[packanges/ckan][xs] - fix type (#1016) 2023-08-24 16:04:44 -03:00
github-actions[bot]
11f9253709
Version Packages (#1015)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-08-24 16:03:42 -03:00
João Demenech
c09c78b015 feat(site,seo): disallow the people/* path to be crawled 2023-08-23 16:33:28 -03:00
github-actions[bot]
4a1ccd2f8d
Version Packages (#1012)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-08-21 15:26:25 -03:00
Anuar Ustayev (aka Anu)
728d5b1465
Merge pull request #1014 from datopian/feat/cloud-waitlist-form
feat(site): the newsletter form is now a cloud waitlist form
2023-08-22 00:24:23 +06:00
João Demenech
a43d4a3b86 feat(site): the newsletter form is now a cloud waitlist form
Refs: #432
2023-08-21 14:47:59 -03:00
João Demenech
4bc7ce5ce7 [site,newsletter][s]: fix hero newsletter form (broken after Brevo update) 2023-08-18 09:41:31 -03:00
João Demenech
8c5c6a2112
Merge pull request #1011 from datopian/fix-flatui
Fix flatui
2023-08-15 15:00:04 -03:00
Luccas Mateus
8e896138c6 [@portaljs/components][sm] - fix bug of multiple flatuitable with different urls 2023-08-14 16:46:15 -03:00
github-actions[bot]
b2b4fbdf12
Version Packages (#1010)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-08-14 12:06:36 -03:00
Luccas Mateus
099f3c5204
[@portaljs/ckan][sm] - fix types (#1009) 2023-08-14 11:16:51 -03:00
github-actions[bot]
17ad9558e1
Version Packages (#1008)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-08-14 16:07:19 +02:00
Luccas Mateus
88ccee6f0a [@portaljs/ckan][sm] - fix types 2023-08-14 11:02:56 -03:00
Ola Rubaj
6418dbb7e2
[#1005, remark-wiki-link]: Parse note embeds as regular wiki links (#1006) 2023-08-14 15:23:28 +02:00
Luccas Mateus
84cc6cf82b [openspending][m] - add missing resources 2023-08-14 07:34:11 -03:00
João Demenech
df395e2b70 [site,#957,seo][s]: fix build issue 2023-08-10 11:01:10 -03:00
João Demenech
ea5dade346 [site,#957,seo][s]: improves descriptions for pages 2023-08-10 10:52:23 -03:00
João Demenech
8027026399 [site,#957][s]: improves mobile reponsiveness 2023-08-10 10:35:34 -03:00
João Demenech
af7812f689
Merge pull request #1004 from datopian/custom-404
[site]: Custom 404 page + JSON-LD breadcrumbs
2023-08-09 18:01:04 -03:00
João Demenech
6a36e65b27 [site,seo][m]: add breadcrumbs json-ld to dynamic pages 2023-08-09 17:53:59 -03:00
João Demenech
38aa62fcef [404,seo][xs]: custom 404 page with noindex,nofollow meta tag 2023-08-09 16:57:01 -03:00
Ola Rubaj
ed9b575b4e
Core package storybook setup (#1003)
* [/][m]: add storybook to core package

* [/][s]: replace nx with nrwl packages for storybook

* [core][xs]: mv tsconfig.storybook.json to .storybook/tsconfig.json

* [/][s]: configure storybook with tailwind

* [core/tailwind.config.js][xs]: add basic Flowershow tailwind config

* [core][xs]: add example story

* [core][s]: darkmode storybook addon
2023-08-09 14:14:06 -03:00
Igor Adamenko
3efba6578d Fix wiki-link regexp to match non-Latin characters 2023-08-09 19:02:11 +03:00
João Demenech
8327f4efc0 [site,storybook,seo][xs]: fix duplicate user canonical issues -- refs #957 2023-08-07 15:18:12 -03:00
Ola Rubaj
d6a12e3111
Merge pull request #998 from datopian/987-tutorial4-websitey-stuff
Tutorial 4 (overview): Customising your website locally and previewing your changes locally
2023-08-04 14:55:20 +02:00
Ola Rubaj
9fc834c16d
Merge pull request #997 from datopian/985-tutorial3-collaboration
Tutorial 3 (overview): Collaborating with others on your website project
2023-08-04 14:53:24 +02:00
Ola Rubaj
1a7371f9c5 [guide/index][m]: tutorial4 overview 2023-07-28 16:33:33 +02:00
Ola Rubaj
c5ae365a20 [site/content/guide][m]: tutorial 3 overview 2023-07-28 15:55:09 +02:00
Ola Rubaj
30f7de04c7
Markdownbased repo content migration + adjustments 2023-07-28 15:40:44 +02:00
João Demenech
989d0987c6
Merge pull request #995 from datopian/site/minor-fixes
Site/minor fixes
2023-07-27 16:28:13 -03:00
João Demenech
e1014025f0 [site,docs][xs]: fix groups facet not working for a dataset on the tutorial -- refs #974 2023-07-27 16:20:37 -03:00
João Demenech
7fc69b7ce8 [site,bug][xs]: fix weird margins on pages -- refs #993 2023-07-27 15:43:14 -03:00
João Demenech
d88a23c922
Merge pull request #991 from datopian/feature/seo-improvements-ii
SEO Improvements (II) - JSON-LD
2023-07-27 13:10:33 -03:00
João Demenech
d367deaea3 [seo,json-ld][m]: implement json-ld (schema markups) 2023-07-26 18:00:12 -03:00
João Demenech
3e9eadcc69 [site,seo][xs]: merge main and fix conflict 2023-07-21 17:58:58 -03:00
Luccas Mateus de Medeiros Gomes
da226ef205 Merge branch 'main' of github.com:datopian/portaljs 2023-07-21 07:43:38 -03:00
Luccas Mateus de Medeiros Gomes
a37a31f89a [lighthouse][xs] - try ga lazyOnload 2023-07-21 07:42:36 -03:00
João Demenech
03c27df800 [site,seo][s]: alt images, description and titles fixes for multiple pages 2023-07-20 18:30:54 -03:00
João Demenech
d198130038 [site,seo][s]: add description metadata to main pages 2023-07-20 18:00:00 -03:00
Luccas Mateus
06209877ea
Lighthouse improvements (#990)
* [site][lighthouse] - increate accessibility

* [site][xs] - fix accessbiility
2023-07-20 11:11:07 -03:00
Luccas Mateus
822a3ce5ec
[site][lighthouse] - increate accessibility (#989) 2023-07-20 10:17:24 -03:00
João Demenech
1f06c67d13
[site, blog][xs]: Fix order of authors on a post 2023-07-19 16:17:56 -03:00
João Demenech
9dea140859
SEO Improvements (#983)
* [site,seo][xs]: add custom _document with lang prop, add description to meta tags, make title larger

* [site,seo][xs]: add apple touch icon, add alt props to images

* [site,seo][xs]: add icon to default seo

* [site,seo][s]: implement next-sitemap

* [site,seo][s]: review page titles

* Rebuild package-lock.json files

* Regenerate package-lock
2023-07-19 07:23:06 -03:00
João Demenech
d5899b22ab
[site,blog][xs]: Fix typo 2023-07-18 15:23:14 -03:00
João Demenech
dc895ed277
Merge pull request #984 from datopian/feature/maps-blog-post
[site]: Create new blog post about maps
2023-07-18 15:19:01 -03:00
João Demenech
7315df8a86 [site,blog][m]: create new blog post about maps 2023-07-18 14:08:33 -03:00
João Demenech
349f5bea66
Merge pull request #982 from datopian/lighthouse-improvements
[site][m] - improvements to lighthouse score
2023-07-17 15:04:25 -03:00
João Demenech
6aef860a81
Merge pull request #981 from datopian/changeset-release/main
Version Packages
2023-07-17 14:51:08 -03:00
Luccas Mateus de Medeiros Gomes
e908cb9344 [site][m] - improvements to lighthouse score 2023-07-17 14:44:29 -03:00
github-actions[bot]
1a22e54d5b Version Packages 2023-07-17 17:41:23 +00:00
João Demenech
172b4b71d4
Merge pull request #980 from datopian/bugfix/pdf-styles
Bugfix/pdf styles
2023-07-17 14:38:34 -03:00
João Demenech
3873852567 Bump version 2023-07-17 14:32:35 -03:00
João Demenech
5e349855a2 [components,pdf][xs]: add CSS styles for PDF 2023-07-17 14:29:57 -03:00
João Demenech
40bd9e0311
Merge pull request #977 from datopian/changeset-release/main
Version Packages
2023-07-14 14:44:01 -03:00
github-actions[bot]
b437b58d06 Version Packages 2023-07-14 17:31:11 +00:00
João Demenech
c3137ba1cb Regenerate package-lock.json 2023-07-14 14:28:14 -03:00
João Demenech
2e13c1b738 Release new version 2023-07-14 14:22:52 -03:00
João Demenech
122870a23e
Merge: PDF viewer component
[components][lg] - pdf viewer
2023-07-13 13:35:35 -03:00
Luccas Mateus
4e282e0d86
Update package.json 2023-07-13 13:06:42 -03:00
Luccas Mateus
6020f76adb
Merge branch 'main' into feature/pdfviewer 2023-07-13 13:03:20 -03:00
João Demenech
f3c2a2ffa7
Excel component (#973)
* [components,excel][m]: initial version of the <Excel /> component

* [components,excel][m]: add support for multiple sheets

* [components,map,excel][l]: fix leaflet map markers on prod and implement excel component

* Bump version

* [components,excel][xs]: change data for one of the stories
2023-07-13 13:02:37 -03:00
Luccas Mateus de Medeiros Gomes
11659a838b [components][lg] - pdf viewer 2023-07-12 14:50:30 -03:00
Anuar Ustayev (aka Anu)
58b7b4e753
Merge pull request #962 from datopian/tutorial-2-going-local
Tutorial 2: Edit your Flowershow website locally on your computer
2023-07-12 13:55:24 +02:00
Anuar Ustayev (aka Anu)
7cf8c31e53
Update edit-a-website-locally.md 2023-07-12 13:55:01 +02:00
João Demenech
df000b9e8f
[openspending,css][xs]: fix issues with css styles (#972) 2023-07-10 16:24:19 -03:00
Luccas Mateus de Medeiros Gomes
77e9f58899 [examples/openspending][xs] - remove css 2023-07-10 13:38:24 -03:00
github-actions[bot]
0737aaafb2
Version Packages (#971)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-07-10 10:09:37 -03:00
João Demenech
d798f402f6
Leaflet Map: multiple layers (#969)
* [components,maps][l]: leaflet map now supports multiple layers and tooltip props setting

* Remove unused var

* Update vite.config.ts

---------

Co-authored-by: Luccas Mateus <Luccasmmg@gmail.com>
2023-07-10 09:55:37 -03:00
Luccas Mateus de Medeiros Gomes
80c6221a05 [portaljs/components][lg] - map components changeset 2023-07-10 09:56:24 -03:00
Luccas Mateus
f04b86dda4
Update frankfurt-is-investing-in-education-and-your-city-should-too.mdx 2023-07-07 12:44:04 -03:00
Luccas Mateus
0fd3ee9912
Map components - Leaflet and OpenLayers (#968)
* [components,maps][l]: implements Leaflet map component -- #963

* [openspending, maps][m]: fix build for leaflet map

* Feature/openlayers map (#967)

* [maps][xl] - working with swc equals to minify

* [maps][xs] - fixing height

* [openspending][xs] - testing

* [openspending][xs] - testing

* [openspending][xs] - change order drd

* [openspending][xs] - add map

* [maps,tests][xs]: add default export to OpenLayers component

* [@portaljs/components][m] - map components

---------

Co-authored-by: João Demenech <joaommdemenech@gmail.com>
2023-07-07 11:22:34 -03:00
Luccas Mateus
cb0b9b1f14
Fix typos 2023-07-04 11:25:08 -03:00
Luccas Mateus de Medeiros Gomes
9ee4376abf [examples/ckan][sm] - fix responsiveness 2023-06-27 07:23:36 -03:00
Ola Rubaj
5a0ddd91ce [content/guide/index][s]: add overview of tutorial 2 2023-06-26 10:27:28 +02:00
Ola Rubaj
d097bc765b [blog/edit-a-website-locally][s]: improve section on markdown 2023-06-26 10:10:00 +02:00
Ola Rubaj
b283fc1e99 [content/blog/edit-a-website-locally][s]: polishing 2023-06-22 18:46:33 +02:00
Ola Rubaj
0511e00d83 [site/content][xs]: adjust tutorial title 2023-06-22 16:56:26 +02:00
Ola Rubaj
c8afa775d4 [site/content/blog][m]: tutorial on local editing 2023-06-22 16:52:45 +02:00
Ola Rubaj
7ba9b5157e [site/howtos/comments][xs]: rm unneeded link 2023-06-22 11:21:48 +02:00
Ola Rubaj
6c2a1ea125 [site/howtos][m]: mv from datopian/markdownbased 2023-06-22 11:16:12 +02:00
Ola Rubaj
343faf72cf [site/content][s]: mv /howto to /howtos 2023-06-22 11:11:06 +02:00
Ola Rubaj
1eb3f7367b [site/blog][m]: add blog "Create a catalog of anything" 2023-06-22 11:02:23 +02:00
Ola Rubaj
8cdf54397f [package.json][xs]: run mddb before dev 2023-06-22 10:47:38 +02:00
Ola Rubaj
fb94cb9ce9 [site/guide/index.md][s]: adjst tutorials overview 2023-06-22 10:42:34 +02:00
Ola Rubaj
4595cd2231 [site/content/blog][xs]: change title 2023-06-22 10:28:03 +02:00
Ola Rubaj
aa2c8aac04 [site/content/blog][s]: add tutorial on creating a flowershow website
from scratch
2023-06-22 10:20:42 +02:00
Ola Rubaj
f2e5459297 [site/lib/markdown][s]: add support for obsidian style shortened paths 2023-06-22 10:20:11 +02:00
Ola Rubaj
e111adfe73 [site/components/MDXPage][xs]: pass Hero component to mdx 2023-06-22 10:05:22 +02:00
Ola Rubaj
492c21ca4e [site/package.json][xs]: use latest portaljs/core 2023-06-22 10:04:37 +02:00
Ola Rubaj
0581357df8 [site/content][s]: add /guide with home page
- moved from markdownbased repo
2023-06-22 09:57:14 +02:00
João Demenech
15ceeec035
[openspending,stories][xs]: fix typo 2023-06-21 10:10:49 -03:00
João Demenech
1caabcf6b4 [openspending][xs]: bump @portaljs/components version 2023-06-20 19:26:42 -03:00
João Demenech
b548dfd113
Merge pull request #961 from datopian/changeset-release/main
Version Packages
2023-06-20 19:13:57 -03:00
github-actions[bot]
c5ee257d48 Version Packages 2023-06-20 20:32:15 +00:00
João Demenech
8d83f3a900
Merge pull request #960 from datopian/bugfix/linechart-width
[@portaljs/components,line chart][xs]: fix linechart width
2023-06-20 17:29:13 -03:00
João Demenech
add2f6d0f3 [@portaljs/components,line chart][xs]: fix linechart width 2023-06-20 17:12:16 -03:00
github-actions[bot]
dfab6aa318
Version Packages (#959)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-06-20 17:37:03 +02:00
Rufus Pollock
f96fb562fe
Merge pull request #958 from datopian/bespoke-hero 2023-06-20 17:32:43 +02:00
Ola Rubaj
c4bf5bd054 [core/ui/Hero][s]: create Hero component 2023-06-20 15:52:20 +02:00
Ola Rubaj
c706575ae4
Replace @flowershow/* with @portaljs/* packages in /examples (#953)
* [examples/ckan][m]: rplc @flowershow with @portaljs packages

* [examples/fivethirtyeight][m]: rplc @flowershow with @portaljs packages

* [examples/turing][m]: rplc @flowershow with @portaljs packages

* [examples/openspending][m]: rplc @flowershow with @portaljs packages

* [examples/learn][m]: rplc @flowershow with @portaljs packages

* [examples/github-backed-catalog][m]: rplc @flowershow with @portaljs packages

* [examples/github-backed-catalog][xs] - fix build

* [examples][m] - fix builds

* [examples/openspending][xs] - fix build

---------

Co-authored-by: Luccas Mateus de Medeiros Gomes <luccasmmg@gmail.com>
2023-06-16 09:13:54 -03:00
João Demenech
ed8de380a9
Merge pull request #950 from datopian/site-deps-update
Replace `@flowershow/*` with `@portaljs/*` packages in /site
2023-06-16 09:04:42 -03:00
João Demenech
33521916d6 [site,blog,#944][xs]: update titles of blog posts 2023-06-15 17:28:12 -03:00
João Demenech
04206457a4 [openspending,contributing][xs]: add link to issue tracker 2023-06-13 19:08:20 -03:00
João Demenech
8a5acb7012
Merge pull request #952 from datopian/openspending/moers-anomaly
OpenSpending: Moers Anomaly story
2023-06-13 19:03:36 -03:00
João Demenech
32493a2014 [openspending,stories][xs]: fix data url 2023-06-13 19:00:00 -03:00
Michael Polidori
b34220cac7
Merge pull request #951 from datopian/openspending/berlin-erdf-data-driven-story
OpenSpending - Berlin ERDF spendings data-driven story
2023-06-13 15:22:15 -04:00
Michael Polidori
44b37e27d9 Add Moers Anomaly story 2023-06-13 15:20:48 -04:00
João Demenech
6d3e571151 [openspending,stories][m]: fix typo 2023-06-13 12:42:01 -03:00
João Demenech
0e997f71e5 [openspending,stories][m]: add new data-driven story about Berlin 2023-06-13 12:39:02 -03:00
olayway
4a41d517ee [package.json][xs]: rm prerelease script
Handling this in projects package.json files.
2023-06-13 17:12:53 +02:00
olayway
c79b69ffe6 [site/package.json][s]: bump @portaljs packages 2023-06-13 12:33:54 +02:00
olayway
2ad6551a44 [site][s]: @flowershow/remark-wiki-link -> @portaljs/remark-wiki-link 2023-06-13 12:33:54 +02:00
olayway
5de9888c02 [site][s]: @flowershow/remark-embed -> @portaljs/remark-embed 2023-06-13 12:33:54 +02:00
olayway
5a517d714a [blog/markdowndb-basics][xs]: typo fix 2023-06-13 12:33:52 +02:00
olayway
746c77de11 [site][s]: @flowershow/markdowndb -> mddb 2023-06-13 12:32:29 +02:00
olayway
9e256b9bf1 [site][s]: @flowershow/remark-callouts -> @portaljs/remark-callouts 2023-06-13 12:32:29 +02:00
olayway
4bfcd4373b [site][s]: @flowershow/core -> @portaljs/core 2023-06-13 12:32:29 +02:00
github-actions[bot]
6649f78459
Version Packages (#949)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-06-13 12:14:38 +02:00
olayway
6f0da8c3a3 [packages][s]: fix public api of remark-* and core packages 2023-06-13 12:11:33 +02:00
olayway
5b1238cc27 [.gitignore][xs]: ignore .tgz files 2023-06-13 12:11:33 +02:00
João Demenech
17803f1f5d [site,blog,#944][m]: add Ola's author info, fix typo in blogs list 2023-06-12 15:17:18 -03:00
João Demenech
81f50bb9a2
Merge pull request #945 from datopian/openspending/frankfort-education
OpenSpending: Frankfurt Education story
2023-06-12 14:38:22 -03:00
João Demenech
f1aee6a93e [openspending,stories][xs]: update file references to point to storage and add authors 2023-06-12 14:34:40 -03:00
João Demenech
053005d784 [openspending,stories][xs]: update file references to point to storage and update story slug 2023-06-12 14:32:05 -03:00
github-actions[bot]
2f5dd4d0f7
Version Packages (#946)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-06-12 18:46:54 +02:00
olayway
fb7ce8723a [.changeset][xs]: adjst changeset message 2023-06-12 18:42:55 +02:00
olayway
7636c3d26c [package-lock][xs]: sync lock file 2023-06-12 18:35:15 +02:00
olayway
6bf6c8faf4 [core][s]: bump mdx-mermaid and mv to peers 2023-06-12 18:31:35 +02:00
Michael Polidori
095eba606e Update story 2023-06-12 11:58:26 -04:00
Michael Polidori
1097b5077d Add Frankfurt Education story 2023-06-12 11:53:55 -04:00
olayway
aa365cbb0d [blog/markdowndb-basics][xs]: rplc @flowershow/markdowndb with mddb 2023-06-12 16:42:44 +02:00
olayway
038427874a [howto/markdown][xs]: rplc @flowershow/markdowndb with mddb 2023-06-12 16:41:13 +02:00
João Demenech
bdfdb2e6a5 [openspending,drd][xs]: fix FlatUiTable error on first data-driven story 2023-06-09 19:27:45 -03:00
João Demenech
95b3fc03d3 [openspending,drd][xs]: remove sample data-driven story 2023-06-09 18:39:06 -03:00
github-actions[bot]
6aeadd71de
Version Packages (#942)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-06-09 00:16:30 +02:00
olayway
affca05058 [remark-callouts/package.json][xs]: fix export path 2023-06-09 00:12:03 +02:00
github-actions[bot]
f54d238795
Version Packages (#941)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-06-08 23:57:47 +02:00
olayway
e82e2ae021 [packages][xs]: replace prepublish with prepare 2023-06-08 23:53:42 +02:00
github-actions[bot]
c3246ee7f8
Version Packages (#940)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-06-08 23:45:12 +02:00
olayway
40d80d2282 [packages/*][s]: add prepublish script to build first 2023-06-08 23:42:17 +02:00
olayway
e0e720338f [components/package.json][xs]: add prepublish script 2023-06-08 23:33:34 +02:00
olayway
4f8b1b1e96 [ckan/package.json][xs]: add prepublish script 2023-06-08 23:32:29 +02:00
olayway
362afcc133 [package.json][xs]: rm faulty prerelease script 2023-06-08 23:29:17 +02:00
João Demenech
c165b3cc44
merge: new data story about ESIF funds
A new data story about ESIF funds
2023-06-08 17:22:27 -03:00
João Demenech
261a2a081e Fix minor typos 2023-06-08 17:21:43 -03:00
Anuar Ustayev (aka Anu)
d27857f490
Added conclusion and final tweaks. 2023-06-08 20:47:59 +07:00
Anuar Ustayev (aka Anu)
b3ba263bd8
Switch from raw csv to remote file in r2. 2023-06-08 20:35:33 +07:00
Anuar Ustayev (aka Anu)
cb774d0ad0
Added bar chart for comparison between countries. 2023-06-08 20:28:05 +07:00
Anuar Ustayev (aka Anu)
b48f71ecef
Add updated data with currency consideration. 2023-06-08 20:07:03 +07:00
Anuar Ustayev (aka Anu)
07b3235647
Create where-the-european-structural-and-investment-funds-go.mdx 2023-06-08 18:19:57 +07:00
Luccas Mateus de Medeiros Gomes
d0c2ee1e71 [examples/openspending][xs] - add contributing tab 2023-06-07 15:31:40 -03:00
João Demenech
bc180189cb Update OS sample data story 2023-06-07 11:28:31 -03:00
github-actions[bot]
39c862627d
Version Packages (#937)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-06-07 15:22:12 +02:00
olayway
b7158a5be6 add changeset file 2023-06-07 15:17:46 +02:00
olayway
ee87c4f623 [remark-embed][s]: don't include README in dist
- it will already be included by npm anyway
2023-06-07 15:06:08 +02:00
olayway
4141af0e82 [remark-embed][s]: specify folder to publish 2023-06-07 15:05:29 +02:00
olayway
7d36d22671 [remark-wiki-link][xs]: don't include README in /dist
- it is included automatically by npm, in the parent folder
2023-06-07 15:04:46 +02:00
olayway
eab2d65113 [remark-wiki-link][s]: specify folder to publish 2023-06-07 15:04:46 +02:00
olayway
51d0a7692e [remark-callouts][xs]: don't include README in /dist
- it is included automatically by npm, in the parent folder
2023-06-07 15:04:46 +02:00
olayway
cdd90ac384 [remak-callouts][s]: specify folder to publish in package.json 2023-06-07 15:04:46 +02:00
olayway
dcf6400304 [core][xs]: don't include README in /dist
- it is included automatically by npm, in the parent folder
2023-06-07 15:04:46 +02:00
olayway
247b2412d6 [core][xs]: specify folder to publish 2023-06-07 15:04:41 +02:00
olayway
1ad9b85e02 [package.json][s]: add building to prerelease 2023-06-07 13:56:32 +02:00
Ola Rubaj
af134cac8b
Integrate flowershow packages (#923)
* [packages][m]: mv @flowershow/core package here

* [packages/core][xs]: rename to @portaljs/core

* [package.json][xs]: setup npm workspaces

* [packages/core][xs]:replace deprecated rollup executor

* [core/package.json][s]: fix mermaid versions

* [core/tsconfig][xs]: rm extends

* [core/jest.config][xs]: rm coverageDirectory

* [core/package.json][xs]: install core-js

* [packages.json][s]:use same version for all nrwl packages

* [core/.eslintrc][xs]: adjust ignorePatterns

* [core/project.json][xs]: rm publish targets

* [packages][m]: mv @flowershow/remark-wiki-link here

* [packages][m]: mv @flowershow/remark-wiki-link here

* [packages][m]: mv @flowershow/remark-embed here

* [remark-callouts/project.json][xs]: adjst test pattern

* [package.json][s]: install missing deps

* [remark-callouts][xs]: adjst fields in package.json

* [remark-callouts][s]: rm pubish targets and adjst build executor

* [remark-embed/jest.config][xs]: rm unknown option coverageDirectory

* [remark-embed][xs]: rm publish targets

* [remark-embed][s]: rename to @portaljs/remark-embed

* [remark-wiki-link/eslintrc][xs]:adjst ignorePatterns

* [package.json][xs]: install missing deps

* [remark-wiki-link/test][xs]:specify format

- also temporarily force any type on htmlExtension

* [remark-wiki-link/README][xs]: replace @flowershow with @portaljs

* [remark-wiki-link][xs]:rm old changelog

* [remark-wiki-link][xs]: adjst package.json

* [remark-wiki-link/project.json][xs]: rm publish targets

* [core][s]: rm old changelog

* [core/README][xs]:correct scope name

* [remark-callouts/README][xs]: add @portaljs to pckg name

* [remark-embed/README][xs]: add @portaljs to pckg name

* [package-lock.json][xs]: refresh after rebasing on main
2023-06-07 07:21:00 -03:00
github-actions[bot]
0b8c56bcac
Version Packages (#934)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-06-06 22:33:32 -03:00
Luccas Mateus de Medeiros Gomes
20c64222c1 [examples/openspending][xs] - fix styling 2023-06-06 21:59:21 -03:00
João Demenech
683159da02
@portaljs/components improvements (#933)
* [#912,@portaljs/components][s]: create LoadingSpinner component and add that to <Table /> when using the URL parameter

* [#912,@portaljs/components][m]: refactor LineChart and add more params

* [#912,@portaljs/components][m]: possibly fixes 'loading...' size on FlatUiTable on Firefox

* [@portaljs/components][xs]: add storybook-static to .gitignore

* Add changeset
2023-06-06 21:21:31 -03:00
Luccas Mateus de Medeiros Gomes
c0681fdc7f [examples][m] - update examples to use new package version 2023-06-06 13:51:41 -03:00
Luccas Mateus de Medeiros Gomes
ec1910e016 [packages/components][xs] - update version 2023-06-06 13:02:39 -03:00
Luccas Mateus
fc70f6ec66
[examples/openspending][lg] - adding drd support (#928)
* [examples/openspending][lg] - adding drd support

* [examples/openspending][sm] - add data stories to header
2023-06-06 12:58:54 -03:00
João Demenech
8e4428e2f8
github-backed-catalog: improve documentation (#925)
* [examples/github-backed-catalog][m]: improve documentation

* [examples/github-backed-catalog][m]: add info about editing the deployment created on Vercel
2023-06-06 07:28:51 -03:00
github-actions[bot]
1292350aac
Version Packages (#926)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-06-06 07:26:45 -03:00
João Demenech
e4da3ed672
Merge pull request #924 from datopian/fix-redeclaration-of-formal-parameter-error
[packages/components][m] - fix error on build
2023-06-05 16:22:09 -03:00
Luccas Mateus de Medeiros Gomes
959fe5a588 [packages/components][m] - fix error on build 2023-06-05 14:23:57 -03:00
João Demenech
7a46a6732b [examples/openspending,footer,#897][s]: add PortalJS logo to the footer 2023-06-05 13:13:39 -03:00
Ola Rubaj
688db3e6a6
Changesets setup + auto-publish to npm (#922)
Closes #905 

## Summary

This PR sets up changesets with the aim to simplify the process of documenting changes committed to the codebase, as well as automating versioning packages and publishing them to npm.

## Changes
- initialised [changesets](https://github.com/changesets/changesets) in the repository
- (separately from this PR) installed [changesets bot](https://github.com/apps/changeset-bot) in the repository (it will check if a submitted PR includes a changeset file and inform if found or not)
- added `.github/workflows/release.yml`: The workflow creates a PR with version bumps and related changelog
files' updates, each time a commit containing changeset
file(s) is added to the main branch. After merging this auto-generated PR, this workflow will also auto-publish the released packages to npm and add git tags.
- added the following scripts to the root `package.json`:
  - `changeset`: should be run to generate changeset files, that describe changes made to the code,
  - `prerelease`: runs linting and testing on packages affected by the changes in a PR
  - `release`: runs `changeset publish` and is used by the `release` workflow then the above-mentioned auto-generated PR is merged to the main branch
2023-06-05 17:41:37 +02:00
João Demenech
fa642d8914 [examples/learn,docs][xs]: fix typo 2023-06-02 18:59:04 -03:00
João Demenech
c80b283201 [examples/learn,docs,#910][m]: add conclusions at the end of each tutorial, add page title to each tutorial page, fix hydration error re modified metadata field 2023-06-02 18:52:56 -03:00
Luccas Mateus de Medeiros Gomes
95fd8e72df [examples/openspending][sm] - 5mb to 500kb on preview 2023-06-02 09:38:13 -03:00
João Demenech
e50c76090c [examples/openspending][xs]: make year be displayed in UUTC timezone on DatasetCard 2023-06-01 15:39:15 -03:00
Luccas Mateus de Medeiros Gomes
70012d7c03 [examples/538][m] - added GA 2023-06-01 10:50:59 -03:00
Luccas Mateus de Medeiros Gomes
024c06d9cd [examples/538][xs] - change read more link 2023-06-01 10:41:43 -03:00
Luccas Mateus de Medeiros Gomes
35668c069e [examples/538][xs] - change order of datasets 2023-06-01 10:36:04 -03:00
Luccas Mateus de Medeiros Gomes
2500779499 [examples/538][m] - changes requested by anu 2023-06-01 10:30:17 -03:00
João Demenech
fc8eb95dbc
Open Spending: minor improvements (#918)
* [examples/openspending][xs]: center align footer and make file previews wider

* Run prettier

---------

Co-authored-by: deme <deme@deme>
2023-06-01 10:19:39 -03:00
Anuar Ustayev (aka Anu)
45089419da
Merge pull request #917 from datopian/fivethirtyeight-v0.2
[examples/538][m] - v0.2
2023-06-01 20:17:04 +07:00
Luccas Mateus de Medeiros Gomes
837a2d3d7a [examples/538][xs] - fix scroll 2023-06-01 09:30:48 -03:00
Luccas Mateus de Medeiros Gomes
37e36539ec [examples/538][m] - v0.2 2023-05-31 13:55:11 -03:00
Luccas Mateus
14974edcbf
[examples/openspending] - openspending v0.2 (#907)
* [examples/openspending] - openspending v0.2

* [examples/openspending][m] - fix build

* [examples/openspending][xs] - fix build

* [examples/openspending][xs] - add prebuild step

* [examples/openspending][m] - fix requested by demenech

* [examples/openspending][sm] - remove links + fix bug
2023-05-30 20:22:58 -03:00
Luccas Mateus de Medeiros Gomes
cb7d801968 [examples/turing][xs] - add more stuff to readme 2023-05-29 07:59:39 -03:00
Ola Rubaj
8fd9f00cfa
Blog post announcing our first MarkdownDB tutorial (#903)
* [site/content/blog][s]: markdowndb basics tutorial
2023-05-26 15:28:24 +02:00
deme
7696f43ff9 Merge branch 'main' of github.com:datopian/portal.js into main 2023-05-26 08:33:06 -03:00
deme
c4f447668a [examples/learn][xl]: temporarily move portaljs into learn to fix prod build 2023-05-26 08:32:48 -03:00
Anuar Ustayev (aka Anu)
b9cf1bad44
[docs][xs]: improved the title of the docs about ckan backed data portal. 2023-05-26 11:38:33 +06:00
João Demenech
a3788c7d19
Atualizar o index.md 2023-05-25 23:01:43 -03:00
deme
3a7d166c59 [examples/github-backed-catalog][m]: add datapackage 2023-05-25 21:14:43 -03:00
deme
68fa745066 Merge branch 'main' of github.com:datopian/portal.js into main 2023-05-25 14:50:51 -03:00
deme
cc50ba6223 [site,tutorial,ckan][xs]: fix typo 2023-05-25 14:50:35 -03:00
Luccas Mateus de Medeiros Gomes
3b9147bdbe [examples/github-backed-catalog][lg] - add rich data stories 2023-05-25 14:34:07 -03:00
Luccas Mateus de Medeiros Gomes
9af90ec906 [examples/ckan][xs] - fix build 2023-05-25 14:33:45 -03:00
deme
efa8732e55 [hackathon][m]: improve ckan example 2023-05-25 14:20:05 -03:00
Luccas Mateus de Medeiros Gomes
360af236e8 [examples/ckan][xs] - fix build 2023-05-25 13:56:54 -03:00
Luccas Mateus de Medeiros Gomes
f5541b5098 [examples/ckan][m] - added cors proxy + content folder + drd 2023-05-25 13:46:39 -03:00
Luccas Mateus de Medeiros Gomes
0f1d44ea61 [@portaljs/components][xs] - fix version 2023-05-25 13:30:23 -03:00
Luccas Mateus de Medeiros Gomes
de4c666f80 [@portaljs/components][m] - LineChart fix 2023-05-25 13:29:37 -03:00
Luccas Mateus de Medeiros Gomes
b1845dd2c9 [docs/examples][m] - new ckan example/blog/docs 2023-05-25 08:23:05 -03:00
Luccas Mateus de Medeiros Gomes
7849873582 [examples/openspending][m] - move back to old FlatUiTable 2023-05-24 14:35:50 -03:00
Luccas Mateus de Medeiros Gomes
58b4c1918f [éxamples] 2023-05-24 13:41:11 -03:00
Luccas Mateus de Medeiros Gomes
a2dd2dfbff [@portaljs/components][m] - add FlatUiTable component 2023-05-24 13:11:34 -03:00
Luccas Mateus de Medeiros Gomes
f22d8dc80c [examples/openspending][m] - openspending now uses @portaljs/components
The FlatUiTable component
2023-05-24 13:10:26 -03:00
Luccas Mateus de Medeiros Gomes
4dffc7aaa6 [examples/ckan-ssg][m] - use the @portaljs/ckan lib 2023-05-24 12:21:19 -03:00
Luccas Mateus de Medeiros Gomes
920146352d [examples/ckan][m] - add DMS option 2023-05-24 11:09:59 -03:00
Luccas Mateus de Medeiros Gomes
eeb40c8689 [examples/ckan][xs] - fix build 2023-05-24 08:32:02 -03:00
João Demenech
699401238e
Merge pull request #898 from datopian/ckan-package
[@portaljs/components][xl] - @portaljs/ckan package
2023-05-23 21:34:11 -03:00
Luccas Mateus de Medeiros Gomes
92ebac4a50 [ckan-ssg][m] - fix build 2023-05-23 20:23:26 -03:00
Luccas Mateus de Medeiros Gomes
5a6cf37c9e [@portaljs/ckan] - add loading state 2023-05-23 20:14:55 -03:00
Luccas Mateus de Medeiros Gomes
b8f0a9e432 [@portaljs/ckan][m] - fix build 2023-05-23 20:07:50 -03:00
Luccas Mateus de Medeiros Gomes
c82bfdd847 [@portaljs/ckan][xl] - add ckan package and example using it 2023-05-23 14:47:25 -03:00
Luccas Mateus de Medeiros Gomes
eac0a22aa8 Revert "[@portaljs/components][xl] - @portaljs/ckan package"
This reverts commit 91c76c213c833e4c0833a4d7f6bf6f83f93015f8.
2023-05-23 14:45:16 -03:00
Luccas Mateus de Medeiros Gomes
91c76c213c [@portaljs/components][xl] - @portaljs/ckan package
+ Accompaning example using said package
+ Removed the "example" from all the examples names
2023-05-23 14:13:36 -03:00
Luccas Mateus
622428a015
[examples/openspending][m]: implement analytics and update favicon (#896)
Co-authored-by: deme <joaommdemenech@gmail.com>
2023-05-19 15:13:38 -03:00
Luccas Mateus
bedc9a8d33
[examples/openspending][xl]: add table preview to showcase page, minor fixes (#895)
Co-authored-by: deme <joaommdemenech@gmail.com>
2023-05-19 14:44:34 -03:00
1451 changed files with 616854 additions and 34470 deletions

8
.changeset/README.md Normal file
View File

@ -0,0 +1,8 @@
# Changesets
Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works
with multi-package repos, or single-package repos to help you version and publish your code. You can
find the full documentation for it [in our repository](https://github.com/changesets/changesets)
We have a quick list of common questions to get you started engaging with this project in
[our documentation](https://github.com/changesets/changesets/blob/main/docs/common-questions.md)

14
.changeset/config.json Normal file
View File

@ -0,0 +1,14 @@
{
"$schema": "https://unpkg.com/@changesets/config@2.3.0/schema.json",
"changelog": [
"@changesets/changelog-github",
{ "repo": "datopian/portaljs" }
],
"commit": false,
"fixed": [],
"linked": [],
"access": "restricted",
"baseBranch": "main",
"updateInternalDependencies": "patch",
"ignore": []
}

39
.github/workflows/release.yml vendored Normal file
View File

@ -0,0 +1,39 @@
name: Release
on:
push:
branches:
- main
concurrency: release-${{ github.ref }}
jobs:
release:
name: Release
runs-on: ubuntu-latest
steps:
- name: Checkout Repo
uses: actions/checkout@v3
- name: Setup Node.js 16.x
uses: actions/setup-node@v3
with:
node-version: 16.x
- name: Install Dependencies
run: npm ci
- name: Create Release Pull Request or Publish to npm
id: changesets
uses: changesets/action@v1
with:
publish: npm run release
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
# - name: Send a Discord notification if a publish happens
# if: steps.changesets.outputs.published == 'true'
# uses: Ilshidur/action-discord@0.3.2
# with:
# args: 'The project {{ EVENT_PAYLOAD.repository.full_name }} has been deployed.'

1
.gitignore vendored
View File

@ -4,6 +4,7 @@
dist
tmp
/out-tsc
**/*.tgz
# dependencies
node_modules

View File

@ -1,8 +0,0 @@
{
"recommendations": [
"nrwl.angular-console",
"esbenp.prettier-vscode",
"firsttris.vscode-jest-runner",
"dbaeumer.vscode-eslint"
]
}

View File

@ -4,7 +4,7 @@ title: Developer docs for contributors
## Our repository
https://github.com/datopian/portaljs
https://github.com/datopian/datahub
Structure:
@ -13,11 +13,11 @@ Structure:
- **dataset-frictionless**: Example utilizing a frictionless dataset as an example
- **site**: the website for the project, with a landing page and the docs
- **packages**:
- **portaljs-components**: the library of components for creating a data portal
- **portaljs-components**: the library of components for creating a data portal
## How to contribute
You can start by checking our [issues board](https://github.com/datopian/portaljs/issues).
You can start by checking our [issues board](https://github.com/datopian/datahub/issues).
If you'd like to work on one of the issues you can:
@ -26,15 +26,16 @@ If you'd like to work on one of the issues you can:
3. Clone the forked repository to your machine.
4. Create a feature branch (e.g. `50-update-readme`, where `50` is the number of the related issue).
5. Commit your changes to the feature branch.
6. Push the feature branch to your forked repository.
7. Create a Pull Request against the original repository.
6. Add changeset file describing the changes. (See section below)
7. Push the feature branch to your forked repository.
8. Create a Pull Request against the original repository.
- add a short description of the changes included in the PR
8. Address review comments if requested by our demanding reviewers 😜.
9. Address review comments if requested by our demanding reviewers 😜.
If you have an idea for improvement, and it doesn't have a corresponding issue yet, simply submit a new one.
> [!note]
> Join our [Discord channel](https://discord.gg/rTxfCutu) do discuss existing issues and to ask for help.
> Join our [Discord channel](https://discord.gg/KZSf3FG4EZ) do discuss existing issues and to ask for help.
## Nx
@ -62,6 +63,7 @@ or you can use just:
nx <target> <project>
# e.g. npx nx serve ckan
```
if you have the `nx` binary installed globally in your machine
#### Running multiple tasks
@ -174,3 +176,23 @@ To learn more see this [offical docs page](https://nx.dev/reference/nx-json).
Each project also has it's own configuration file - `project.json`, where you can define and configure it's targets (and more).
To learn more see this [offical docs page](https://nx.dev/reference/project-configuration).
## Changesets and publishing packages
> This monorepo is set up with changesets versioning tool. See their [github repository](https://github.com/changesets/changesets) to learn more.
### What are Changesets?
Changesets are files that describe the intention of a contributor to bump a version of the package according to their changes. Changeset file holds two key bits of information: a version type (following semver), and change information to be added to a changelog.
### Adding changesets
In the root directory of the repo, run:
```
npx changeset
```
Select the package that has been changed, the semver version that should be bumped with it and a description of your changes. Please make sure to add the most accurate but also concise information.
To learn about semantic versioning standards see [this semver doc page](https://semver.org/).

View File

@ -1,31 +1,51 @@
<h1 align="center">
🌀 Portal.JS
<br />
Rapidly build rich data portals using a modern frontend framework
</h1>
<p align="center">
Bugs, issues and suggestions re PortalJS framework
<br />
<br /><a href="https://discord.gg/xfFDMPU9dC"><img src="https://dcbadge.vercel.app/api/server/xfFDMPU9dC" /></a>
</p>
* [What is Portal.JS ?](#What-is-Portal.JS)
* [Features](#Features)
* [For developers](#For-developers)
* [Docs](#Docs)
* [Community](#Community)
* [Appendix](#Appendix)
* [What happened to Recline?](#What-happened-to-Recline?)
## PortalJS framework
# What is Portal.JS
This repo and issue tracker are for
🌀 Portal.JS is a framework for rapidly building rich data portal frontends using a modern frontend approach. Portal.JS can be used to present a single dataset or build a full-scale data catalog/portal.
- PortalJS 🌀 - https://www.portaljs.com/
- DataHub Cloud ☁️ - https://datahub.io/
Built in JavaScript and React on top of the popular [Next.js](https://nextjs.com/) framework. Portal.JS 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/).
### Issues
## Features
Found a bug: 👉 https://github.com/datopian/portaljs/issues/new
### Discussions
Got a suggestion, a question, want some support or just want to shoot the breeze 🙂
Head to the discussion forum: 👉 https://github.com/datopian/portaljs/discussions
### Chat on Discord
If you would prefer to get help via live chat check out our discord 👉
[Discord](https://discord.gg/xfFDMPU9dC)
### Docs
- For PortalJS go to https://www.portaljs.com/opensource
- For DataHub Cloud https://datahub.io/docs
## PortalJS Cloud 🌀
PortalJS Cloud 🌀 is a platform for rapidly creating rich data portal and publishing systems using a modern frontend approach. PortalJS Cloud can be used to publish a single dataset or build a full-scale data catalog/portal.
PortalJS Cloud is built in JavaScript and React on top of the popular [Next.js](https://nextjs.org) framework. PortalJS Cloud 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/), GitHub, Frictionless Data Packages and more.
### Features
- 🗺️ 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 frontend tech (JavaScript, React, Next.js).
- 🔋 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.
- 📝 Well documented: full set of documentation plus the documentation of Next.js.
### For developers
@ -33,25 +53,3 @@ Built in JavaScript and React on top of the popular [Next.js](https://nextjs.com
- 🚀 Next.js framework: so everything in Next.js for free: Server Side Rendering, Static Site Generation, huge number of examples and integrations, etc.
- Server Side Rendering (SSR) => Unlimited number of pages, SEO and more whilst still using React.
- Static Site Generation (SSG) => Ultra-simple deployment, great performance, great lighthouse scores and more (good for small sites)
#### **Check out the [Portal.JS website](https://portaljs.org/) for a gallery of live portals**
___
# Docs
Access the Portal.JS documentation at:
https://portaljs.org/docs
- [Examples](https://portaljs.org/docs#examples)
# 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/EeyfGrGu4U).
# Appendix
## What happened to Recline?
Portal.JS used to be Recline(JS). If you are looking for the old Recline codebase it still exists: see the [`recline` branch](https://github.com/datopian/portal.js/tree/recline). If you want context for the rename see [this issue](https://github.com/datopian/portal.js/issues/520).

View File

@ -2,7 +2,7 @@
**🚩 UPDATE April 2023: This example is now deprecated - though still works!. Please use the [new CKAN examples](https://github.com/datopian/portaljs/tree/main/examples)**
This example shows how you can build a full data portal using a CKAN Backend with a Next.JS Frontend powered by Apollo, a full fledged guide is available as a [blog post](https://portaljs.org/blog/example-ckan-2021)
This example shows how you can build a full data portal using a CKAN Backend with a Next.JS Frontend powered by Apollo, a full fledged guide is available as a [blog post](https://portaljs.com/blog/example-ckan-2021)
## Developers

View File

@ -1 +0,0 @@
DMS=https://demo.dev.datopian.com

View File

@ -1,7 +1,7 @@
This is a repo intended to serve as an example of a data catalog that get its data from a CKAN Instance.
```
npx create-next-app <app-name> --example https://github.com/datopian/portaljs/tree/main/examples/ckan-example
npx create-next-app <app-name> --example https://github.com/datopian/datahub/tree/main/examples/ckan-ssg
cd <app-name>
```
@ -19,7 +19,7 @@ npm run dev
Congratulations, you now have something similar to this running on `http://localhost:4200`
![](https://media.discordapp.net/attachments/1069718983604977754/1098252297726865408/image.png?width=853&height=461)
If yo go to any one of those pages by clicking on `More info` you will see something similar to this
If you go to any one of those pages by clicking on `More info` you will see something similar to this
![](https://media.discordapp.net/attachments/1069718983604977754/1098252298074988595/image.png?width=853&height=461)
## Deployment

View File

@ -10,6 +10,8 @@
},
"dependencies": {
"@heroicons/react": "^2.0.17",
"@portaljs/ckan": "^0.0.2",
"@portaljs/remark-wiki-link": "^1.0.4",
"next": "13.3.1",
"next-seo": "^6.0.0",
"octokit": "^2.0.14",
@ -20,14 +22,14 @@
},
"devDependencies": {
"@tailwindcss/typography": "^0.5.9",
"autoprefixer": "^10.4.14",
"postcss": "^8.4.23",
"tailwindcss": "^3.3.1",
"eslint": "8.39.0",
"eslint-config-next": "13.3.1",
"typescript": "5.0.4",
"@types/node": "18.16.0",
"@types/react": "18.0.38",
"@types/react-dom": "18.0.11"
"@types/react-dom": "18.0.11",
"autoprefixer": "^10.4.14",
"eslint": "8.39.0",
"eslint-config-next": "13.3.1",
"postcss": "^8.4.23",
"tailwindcss": "^3.3.1",
"typescript": "5.0.4"
}
}

View File

@ -11,8 +11,9 @@ import {
ServerIcon,
UserIcon,
} from '@heroicons/react/20/solid';
import { CKAN } from '@portaljs/ckan';
const dms = getConfig().publicRuntimeConfig.DMS;
const backend_url = getConfig().publicRuntimeConfig.DMS;
const formatter = new Intl.DateTimeFormat('en-US', {
year: 'numeric',
@ -25,14 +26,12 @@ const formatter = new Intl.DateTimeFormat('en-US', {
});
export const getServerSideProps: GetServerSideProps = async (context) => {
const ckan = new CKAN(backend_url)
const { dataset } = context.query;
const response = await fetch(
`${dms}/api/3/action/package_show?id=${dataset}`
);
const _dataset = await response.json();
const _dataset = await ckan.getDatasetDetails(dataset as string)
return {
props: {
dataset: _dataset.result,
dataset: _dataset,
},
};
};

View File

@ -1,7 +1,8 @@
import getConfig from 'next/config';
import styles from './index.module.css';
import { CKAN } from '@portaljs/ckan';
const dms = getConfig().publicRuntimeConfig.DMS
const backend_url = getConfig().publicRuntimeConfig.DMS
const formatter = new Intl.DateTimeFormat('en-US', {
year: 'numeric',
@ -15,12 +16,11 @@ const formatter = new Intl.DateTimeFormat('en-US', {
export async function getServerSideProps() {
const response = await fetch(`${dms}/api/3/action/package_search`)
const datasets = await response.json()
const datasetsWithDetails = await Promise.all(datasets.result.results.map(async (dataset) => {
const response = await fetch(`${dms}/api/3/action/package_show?id=` + dataset.name)
const json = await response.json()
return json.result
const ckan = new CKAN(backend_url)
const { datasets } = await ckan.packageSearch({ limit: 1000, offset: 0, groups:[], orgs: [], tags: []})
const datasetsWithDetails = await Promise.all(datasets.map(async (dataset) => {
const _dataset = await ckan.getDatasetDetails(dataset.name)
return _dataset
}))
return {
@ -79,7 +79,7 @@ export function Index({ datasets }) {
</thead>
<tbody className="divide-y divide-gray-200">
{datasets.map((dataset) => (
<tr>
<tr key={dataset.name}>
<td className="px-3 py-4 text-sm text-gray-500">
{dataset.title}
</td>

View File

@ -0,0 +1,3 @@
{
"extends": "next/core-web-vitals"
}

35
examples/ckan/.gitignore vendored Normal file
View File

@ -0,0 +1,35 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# dependencies
/node_modules
/.pnp
.pnp.js
# testing
/coverage
# next.js
/.next/
/out/
# production
/build
# misc
.DS_Store
*.pem
# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# local env files
.env*.local
# vercel
.vercel
# typescript
*.tsbuildinfo
next-env.d.ts

38
examples/ckan/README.md Normal file
View File

@ -0,0 +1,38 @@
This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app).
## Getting Started
First, run the development server:
```bash
npm run dev
# or
yarn dev
# or
pnpm dev
```
Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
You can start editing the page by modifying `pages/index.tsx`. The page auto-updates as you edit the file.
[API routes](https://nextjs.org/docs/api-routes/introduction) can be accessed on [http://localhost:3000/api/hello](http://localhost:3000/api/hello). This endpoint can be edited in `pages/api/hello.ts`.
The `pages/api` directory is mapped to `/api/*`. Files in this directory are treated as [API routes](https://nextjs.org/docs/api-routes/introduction) instead of React pages.
This project uses [`next/font`](https://nextjs.org/docs/basic-features/font-optimization) to automatically optimize and load Inter, a custom Google Font.
## Learn More
To learn more about Next.js, take a look at the following resources:
- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome!
## Deploy on Vercel
The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.
Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details.

View File

@ -1,6 +1,6 @@
import { MDXRemote } from 'next-mdx-remote';
import dynamic from 'next/dynamic';
import { Mermaid } from '@flowershow/core';
import { Mermaid } from '@portaljs/core';
// Custom components/renderers to pass to MDX.
// Since the MDX files aren't loaded by webpack, they have no knowledge of how
@ -9,6 +9,7 @@ import { Mermaid } from '@flowershow/core';
const components = {
Table: dynamic(() => import('@portaljs/components').then(mod => mod.Table)),
Catalog: dynamic(() => import('@portaljs/components').then(mod => mod.Catalog)),
FlatUiTable: dynamic(() => import('@portaljs/components').then(mod => mod.FlatUiTable)),
mermaid: Mermaid,
Vega: dynamic(() => import('@portaljs/components').then(mod => mod.Vega)),
VegaLite: dynamic(() => import('@portaljs/components').then(mod => mod.VegaLite)),

View File

@ -0,0 +1,3 @@
# Test
Test Data Rich Stories

View File

@ -1,13 +1,13 @@
import matter from "gray-matter";
import mdxmermaid from "mdx-mermaid";
import { h } from "hastscript";
import remarkCallouts from "@flowershow/remark-callouts";
import remarkEmbed from "@flowershow/remark-embed";
import remarkCallouts from "@portaljs/remark-callouts";
import remarkEmbed from "@portaljs/remark-embed";
import remarkGfm from "remark-gfm";
import remarkMath from "remark-math";
import remarkSmartypants from "remark-smartypants";
import remarkToc from "remark-toc";
import remarkWikiLink from "@flowershow/remark-wiki-link";
import remarkWikiLink from "@portaljs/remark-wiki-link";
import rehypeAutolinkHeadings from "rehype-autolink-headings";
import rehypeKatex from "rehype-katex";
import rehypeSlug from "rehype-slug";

View File

@ -1,4 +1,4 @@
import { MarkdownDB } from "@flowershow/markdowndb";
import { MarkdownDB } from "mddb";
const dbPath = "markdown.db";

View File

@ -0,0 +1,11 @@
/** @type {import('next').NextConfig} */
const nextConfig = {
reactStrictMode: true,
publicRuntimeConfig: {
DMS: process.env.DMS
? process.env.DMS.replace(/\/?$/, '')
: 'https://demo.dev.datopian.com/',
},
};
module.exports = nextConfig;

13799
examples/ckan/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,48 @@
{
"name": "ckan",
"version": "0.1.0",
"private": true,
"scripts": {
"dev": "next dev",
"prebuild": "npm run mddb",
"build": "next build",
"start": "next start",
"lint": "next lint",
"mddb": "mddb ./content"
},
"dependencies": {
"@githubocto/flat-ui": "^0.14.1",
"@heroicons/react": "^2.0.18",
"@portaljs/ckan": "^0.0.2",
"@portaljs/components": "0.1.6",
"@portaljs/core": "^1.0.5",
"@portaljs/remark-callouts": "^1.0.5",
"@portaljs/remark-embed": "^1.0.4",
"@portaljs/remark-wiki-link": "^1.0.4",
"@tailwindcss/typography": "^0.5.9",
"@types/node": "20.2.3",
"@types/react": "18.2.6",
"@types/react-dom": "18.2.4",
"autoprefixer": "10.4.14",
"eslint": "8.41.0",
"eslint-config-next": "13.4.3",
"isomorphic-unfetch": "^4.0.2",
"mddb": "^0.1.9",
"next": "13.4.3",
"next-mdx-remote": "^4.4.1",
"papaparse": "^5.4.1",
"postcss": "8.4.23",
"react": "18.2.0",
"react-dom": "18.2.0",
"react-query": "^3.39.3",
"rehype-autolink-headings": "^6.1.1",
"rehype-katex": "^6.0.3",
"rehype-prism-plus": "^1.5.1",
"rehype-slug": "^5.1.0",
"remark-math": "^5.1.1",
"remark-smartypants": "^2.0.0",
"remark-toc": "^8.0.1",
"tailwindcss": "3.3.2",
"typescript": "5.0.4"
}
}

View File

@ -0,0 +1,179 @@
import Head from "next/head";
import { CKAN, Dataset } from "@portaljs/ckan";
import {
ChevronRightIcon,
HomeIcon,
PaperClipIcon,
} from "@heroicons/react/20/solid";
import Link from "next/link";
import getConfig from "next/config";
const backend_url = getConfig().publicRuntimeConfig.DMS
export const getServerSideProps = async (context: any) => {
try {
const datasetName = context.params?.dataset;
if (!datasetName) {
return {
notFound: true,
};
}
const ckan = new CKAN(backend_url);
const dataset = await ckan.getDatasetDetails(datasetName as string);
if (!dataset) {
return {
notFound: true,
};
}
return {
props: { dataset },
};
} catch {
return {
notFound: true,
};
}
};
export default function DatasetPage({
dataset,
}: {
dataset: Dataset;
}): JSX.Element {
return (
<>
<Head>
<title>{`${dataset.title || dataset.name} - Dataset`}</title>
<meta name="description" content="Generated by create next app" />
<link rel="icon" href="/favicon.ico" />
</Head>
<main className="flex min-h-screen flex-col items-center justify-between p-24 bg-zinc-900">
<div className="bg-white p-8 my-4 rounded-lg">
<nav className="flex px-4 py-8" aria-label="Breadcrumb">
<ol role="list" className="flex items-center space-x-4">
<li>
<div>
<Link href="/" className="text-gray-400 hover:text-gray-500">
<HomeIcon
className="h-5 w-5 flex-shrink-0"
aria-hidden="true"
/>
<span className="sr-only">Home</span>
</Link>
</div>
</li>
<li>
<div className="flex items-center">
<ChevronRightIcon
className="h-5 w-5 flex-shrink-0 text-gray-400"
aria-hidden="true"
/>
<span
className="ml-4 text-sm font-medium text-gray-500 hover:text-gray-700"
aria-current={"page"}
>
{dataset.name}
</span>
</div>
</li>
</ol>
</nav>
{dataset && (
<div>
<div className="px-4 sm:px-0">
<h3 className="text-base font-semibold leading-7 text-gray-900">
{dataset.title || dataset.name}
</h3>
<p className="mt-1 max-w-2xl text-sm leading-6 text-gray-500">
Dataset details
</p>
</div>
<div className="mt-6 border-t border-gray-100">
<dl className="divide-y divide-gray-100">
<div className="px-4 py-6 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-0">
<dt className="text-sm font-medium leading-6 text-gray-900">
Title
</dt>
<dd className="mt-1 text-sm leading-6 text-gray-700 sm:col-span-2 sm:mt-0">
{dataset.title}
</dd>
</div>
{dataset.tags && dataset.tags.length > 0 && (
<div className="px-4 py-6 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-0">
<dt className="text-sm font-medium leading-6 text-gray-900">
Tags
</dt>
<dd className="mt-1 text-sm leading-6 text-gray-700 sm:col-span-2 sm:mt-0">
{dataset.tags.map((tag) => tag.display_name).join(", ")}
</dd>
</div>
)}
{dataset.tags && dataset.tags.length > 0 && (
<div className="px-4 py-6 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-0">
<dt className="text-sm font-medium leading-6 text-gray-900">
URL
</dt>
<dd className="mt-1 text-sm leading-6 text-gray-700 sm:col-span-2 sm:mt-0">
{dataset.url}
</dd>
</div>
)}
<div className="px-4 py-6 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-0">
{dataset.notes && (
<>
<dt className="text-sm font-medium leading-6 text-gray-900">
Description
</dt>
<dd className="mt-1 text-sm leading-6 text-gray-700 sm:col-span-2 sm:mt-0">
{dataset.notes}
</dd>
</>
)}
</div>
<div className="px-4 py-6 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-0">
<dt className="text-sm font-medium leading-6 text-gray-900">
Files
</dt>
<dd className="mt-2 text-sm text-gray-900 sm:col-span-2 sm:mt-0">
<ul
role="list"
className="divide-y divide-gray-100 rounded-md border border-gray-200"
>
{dataset.resources.map((resource) => (
<li key={resource.id} className="flex items-center justify-between py-4 pl-4 pr-5 text-sm leading-6">
<div className="flex w-0 flex-1 items-center">
<PaperClipIcon
className="h-5 w-5 flex-shrink-0 text-gray-400"
aria-hidden="true"
/>
<div className="ml-4 flex min-w-0 flex-1 gap-2">
<span className="truncate font-medium">
{resource.name || resource.id}
</span>
<span className="flex-shrink-0 text-gray-400">
{resource.size}
</span>
</div>
</div>
<div className="ml-4 flex-shrink-0">
<a
href={resource.url}
className="font-medium hover:text-indigo-500 mr-4"
>
Download
</a>
</div>
</li>
))}
</ul>
</dd>
</div>
</dl>
</div>
</div>
)}
</div>
</main>
</>
);
}

View File

@ -0,0 +1,7 @@
import '@/styles/globals.css'
import '@portaljs/ckan/styles.css'
import type { AppProps } from 'next/app'
export default function App({ Component, pageProps }: AppProps) {
return <Component {...pageProps} />
}

View File

@ -0,0 +1,13 @@
import { Html, Head, Main, NextScript } from 'next/document'
export default function Document() {
return (
<Html lang="en">
<Head />
<body>
<Main />
<NextScript />
</body>
</Html>
)
}

View File

@ -0,0 +1,18 @@
import fetch from 'isomorphic-unfetch';
const Cors = async (req: any, res: any) => {
const { url } = req.query;
try {
const resProxy = await fetch(url, {
headers: {
Range: 'bytes=0-5132288',
},
});
const data = await resProxy.text();
return res.status(200).send(data);
} catch (error: any) {
res.status(400).send(error.toString());
}
};
export default Cors;

View File

@ -0,0 +1,64 @@
import {
CKAN,
DatasetSearchForm,
ListOfDatasets,
PackageSearchOptions,
Organization,
Group,
} from '@portaljs/ckan';
import getConfig from 'next/config';
import { useState } from 'react';
const backend_url = getConfig().publicRuntimeConfig.DMS;
export async function getServerSideProps() {
const ckan = new CKAN(backend_url);
const groups = await ckan.getGroupsWithDetails();
const orgs = await ckan.getOrgsWithDetails();
return {
props: {
groups,
orgs,
},
};
}
export default function Home({
orgs,
groups,
}: {
orgs: Organization[];
groups: Group[];
}) {
const ckan = new CKAN(backend_url);
const [options, setOptions] = useState<PackageSearchOptions>({
offset: 0,
limit: 5,
tags: [],
groups: [],
orgs: [],
});
return (
<div>
<main className="py-12 bg-zinc-900">
<DatasetSearchForm
options={options}
setOptions={setOptions}
groups={groups}
orgs={orgs}
/>
<div
className="bg-white p-8 mx-auto my-4 rounded-lg"
style={{ width: 'min(1100px, 95vw)' }}
>
<ListOfDatasets
options={options}
setOptions={setOptions}
ckan={ckan}
/>{' '}
</div>
</main>
</div>
);
}

View File

@ -0,0 +1,129 @@
import { existsSync, promises as fs } from 'fs';
import path from 'path';
import parse from '../../lib/markdown';
import DataRichDocument from '../../components/DataRichDocument';
import clientPromise from '../../lib/mddb';
import getConfig from 'next/config';
import { CKAN } from '@portaljs/ckan';
export const getStaticPaths = async () => {
const contentDir = path.join(process.cwd(), '/content/');
const contentFolders = await fs.readdir(contentDir, 'utf8');
const paths = contentFolders.map((folder: string) => ({
params: { path: [folder.split('.')[0]] },
}));
return {
paths,
fallback: false,
};
};
const backend_url = getConfig().publicRuntimeConfig.DMS;
export const getStaticProps = async (context) => {
const mddb = await clientPromise;
const storyFile = await mddb.getFileByUrl(context.params.path);
const md = await fs.readFile(
`${process.cwd()}/${storyFile.file_path}`,
'utf8'
);
const ckan = new CKAN(backend_url);
const datasets = storyFile.metadata.datasets ? await Promise.all(
storyFile.metadata.datasets.map(
async (datasetName: string) => await ckan.getDatasetDetails(datasetName)
)
) : [];
const orgs = storyFile.metadata.orgs ? await Promise.all(
storyFile.metadata.orgs.map(
async (orgName: string) => await ckan.getOrgDetails(orgName)
)
) : [];
let { mdxSource, frontMatter } = await parse(md, '.mdx', { datasets, orgs });
return {
props: {
mdxSource,
frontMatter: JSON.stringify(frontMatter),
},
};
};
export default function DatasetPage({ mdxSource, frontMatter }) {
frontMatter = JSON.parse(frontMatter);
return (
<main className="flex min-h-screen flex-col justify-between p-16 bg-zinc-900">
<div className="bg-white p-8 my-4 rounded-lg">
<div className="prose mx-auto py-8">
<header>
<div className="mb-6">
<>
<h1 className="mb-2">{frontMatter.title}</h1>
{frontMatter.author && (
<p className="my-0">
<span className="font-semibold">Author: </span>
<span className="my-0">{frontMatter.author}</span>
</p>
)}
{frontMatter.description && (
<p className="my-0">
<span className="font-semibold">Description: </span>
<span className="description my-0">
{frontMatter.description}
</span>
</p>
)}
{frontMatter.modified && (
<p className="my-0">
<span className="font-semibold">Modified: </span>
<span className="description my-0">
{new Date(frontMatter.modified).toLocaleDateString()}
</span>
</p>
)}
{frontMatter.files && (
<section className="py-6">
<h2 className="mt-0">Data files</h2>
<table className="table-auto">
<thead>
<tr>
<th>File</th>
<th>Format</th>
</tr>
</thead>
<tbody>
{frontMatter.files.map((f) => {
const fileName = f.split('/').slice(-1);
return (
<tr key={`resources-list-${f}`}>
<td>
<a target="_blank" href={f}>
{fileName}
</a>
</td>
<td>
{fileName[0]
.split('.')
.slice(-1)[0]
.toUpperCase()}
</td>
</tr>
);
})}
</tbody>
</table>
</section>
)}
</>
</div>
</header>
<main>
<DataRichDocument source={mdxSource} />
</main>
</div>
</div>
</main>
);
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 394 80"><path fill="#000" d="M262 0h68.5v12.7h-27.2v66.6h-13.6V12.7H262V0ZM149 0v12.7H94v20.4h44.3v12.6H94v21h55v12.6H80.5V0h68.7zm34.3 0h-17.8l63.8 79.4h17.9l-32-39.7 32-39.6h-17.9l-23 28.6-23-28.6zm18.3 56.7-9-11-27.1 33.7h17.8l18.3-22.7z"/><path fill="#000" d="M81 79.3 17 0H0v79.3h13.6V17l50.2 62.3H81Zm252.6-.4c-1 0-1.8-.4-2.5-1s-1.1-1.6-1.1-2.6.3-1.8 1-2.5 1.6-1 2.6-1 1.8.3 2.5 1a3.4 3.4 0 0 1 .6 4.3 3.7 3.7 0 0 1-3 1.8zm23.2-33.5h6v23.3c0 2.1-.4 4-1.3 5.5a9.1 9.1 0 0 1-3.8 3.5c-1.6.8-3.5 1.3-5.7 1.3-2 0-3.7-.4-5.3-1s-2.8-1.8-3.7-3.2c-.9-1.3-1.4-3-1.4-5h6c.1.8.3 1.6.7 2.2s1 1.2 1.6 1.5c.7.4 1.5.5 2.4.5 1 0 1.8-.2 2.4-.6a4 4 0 0 0 1.6-1.8c.3-.8.5-1.8.5-3V45.5zm30.9 9.1a4.4 4.4 0 0 0-2-3.3 7.5 7.5 0 0 0-4.3-1.1c-1.3 0-2.4.2-3.3.5-.9.4-1.6 1-2 1.6a3.5 3.5 0 0 0-.3 4c.3.5.7.9 1.3 1.2l1.8 1 2 .5 3.2.8c1.3.3 2.5.7 3.7 1.2a13 13 0 0 1 3.2 1.8 8.1 8.1 0 0 1 3 6.5c0 2-.5 3.7-1.5 5.1a10 10 0 0 1-4.4 3.5c-1.8.8-4.1 1.2-6.8 1.2-2.6 0-4.9-.4-6.8-1.2-2-.8-3.4-2-4.5-3.5a10 10 0 0 1-1.7-5.6h6a5 5 0 0 0 3.5 4.6c1 .4 2.2.6 3.4.6 1.3 0 2.5-.2 3.5-.6 1-.4 1.8-1 2.4-1.7a4 4 0 0 0 .8-2.4c0-.9-.2-1.6-.7-2.2a11 11 0 0 0-2.1-1.4l-3.2-1-3.8-1c-2.8-.7-5-1.7-6.6-3.2a7.2 7.2 0 0 1-2.4-5.7 8 8 0 0 1 1.7-5 10 10 0 0 1 4.3-3.5c2-.8 4-1.2 6.4-1.2 2.3 0 4.4.4 6.2 1.2 1.8.8 3.2 2 4.3 3.4 1 1.4 1.5 3 1.5 5h-5.8z"/></svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 283 64"><path fill="black" d="M141 16c-11 0-19 7-19 18s9 18 20 18c7 0 13-3 16-7l-7-5c-2 3-6 4-9 4-5 0-9-3-10-7h28v-3c0-11-8-18-19-18zm-9 15c1-4 4-7 9-7s8 3 9 7h-18zm117-15c-11 0-19 7-19 18s9 18 20 18c6 0 12-3 16-7l-8-5c-2 3-5 4-8 4-5 0-9-3-11-7h28l1-3c0-11-8-18-19-18zm-10 15c2-4 5-7 10-7s8 3 9 7h-19zm-39 3c0 6 4 10 10 10 4 0 7-2 9-5l8 5c-3 5-9 8-17 8-11 0-19-7-19-18s8-18 19-18c8 0 14 3 17 8l-8 5c-2-3-5-5-9-5-6 0-10 4-10 10zm83-29v46h-9V5h9zM37 0l37 64H0L37 0zm92 5-27 48L74 5h10l18 30 17-30h10zm59 12v10l-3-1c-6 0-10 4-10 10v15h-9V17h9v9c0-5 6-9 13-9z"/></svg>

After

Width:  |  Height:  |  Size: 629 B

View File

@ -0,0 +1,71 @@
@tailwind base;
@tailwind components;
@tailwind utilities;
@import "@portaljs/remark-callouts/styles.css";
/* mathjax */
.math-inline > mjx-container > svg {
display: inline;
align-items: center;
}
/* smooth scrolling in modern browsers */
html {
scroll-behavior: smooth !important;
}
/* tooltip fade-out clip */
.tooltip-body::after {
content: "";
position: absolute;
right: 0;
top: 3.6rem; /* multiple of $line-height used on the tooltip body (defined in tooltipBodyStyle) */
height: 1.2rem; /* ($top + $height)/$line-height is the number of lines we want to clip tooltip text at*/
width: 10rem;
background: linear-gradient(
to right,
rgba(255, 255, 255, 0),
rgba(255, 255, 255, 1) 100%
);
}
:is(h2, h3, h4, h5, h6):not(.blogitem-title) {
margin-left: -2rem !important;
padding-left: 2rem !important;
scroll-margin-top: 4.5rem;
position: relative;
}
.heading-link {
padding: 1px;
position: absolute;
left: 0;
top: 50%;
transform: translateY(-50%);
margin: auto 0;
border-radius: 5px;
background: #1e293b;
opacity: 0;
transition: opacity 0.2s;
}
.light .heading-link {
/* border: 1px solid #ab2b65; */
/* background: none; */
background: #e2e8f0;
}
:is(h2, h3, h4, h5, h6):not(.blogitem-title):hover .heading-link {
opacity: 100;
}
.heading-link svg {
transform: scale(0.75);
}
@media screen and (max-width: 640px) {
.heading-link {
visibility: hidden;
}
}

View File

@ -0,0 +1,18 @@
/** @type {import('tailwindcss').Config} */
module.exports = {
content: [
'./pages/**/*.{js,ts,jsx,tsx,mdx}',
'./components/**/*.{js,ts,jsx,tsx,mdx}',
'./app/**/*.{js,ts,jsx,tsx,mdx}',
],
theme: {
extend: {
backgroundImage: {
'gradient-radial': 'radial-gradient(var(--tw-gradient-stops))',
'gradient-conic':
'conic-gradient(from 180deg at 50% 50%, var(--tw-gradient-stops))',
},
},
},
plugins: [require('@tailwindcss/typography')],
}

View File

@ -0,0 +1,23 @@
{
"compilerOptions": {
"target": "es5",
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"skipLibCheck": true,
"strict": false,
"forceConsistentCasingInFileNames": true,
"noEmit": true,
"esModuleInterop": true,
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "preserve",
"incremental": true,
"paths": {
"@/*": ["./*"]
}
},
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"],
"exclude": ["node_modules"]
}

View File

@ -1,6 +1,6 @@
This example creates a portal/showcase for a single dataset. The dataset should be a [Frictionless dataset (data package)][fd] i.e. there should be a `datapackage.json`.
[fd]: https://frictionlessdata.io/data-packages/
[fd]: https://specs.frictionlessdata.io/data-package/
## How to use

View File

@ -1,3 +1,9 @@
# PortalJS Demo replicating the FiveThirtyEight data portal
## 👉 https://fivethirtyeight.portaljs.org 👈
Here's a blog post we wrote about it: https://www.datopian.com/blog/fivethirtyeight-replica
This is a replica of the awesome data.fivethirtyeight.com using PortalJS.
You might be asking why we did that, there are three main reasons:

View File

@ -0,0 +1,99 @@
import { useState } from 'react';
import { XMarkIcon } from '@heroicons/react/20/solid';
import { Transition } from '@headlessui/react';
export default function Layout({ children }: { children: React.ReactNode }) {
const [isShowing, setShow] = useState(true);
return (
<>
<Transition
show={isShowing}
enter="transition-opacity duration-75"
enterFrom="opacity-0"
enterTo="opacity-100"
leave="transition-opacity duration-150"
leaveFrom="opacity-100"
leaveTo="opacity-0"
>
<div className="flex items-center gap-x-6 bg-[#3c3c3c] px-6 py-2.5 sm:px-3.5 sm:before:flex-1">
<p className="text-sm leading-6 text-white">
This is a replica to the awesome{' '}
<a
className="hover:underline font-bold"
href="https://data.fivethirtyeight.com"
>
data.fivethirtyeight.com
</a>{' '}
website.{' '}
<a
className="hover:underline font-bold"
href="https://github.com/datopian/portaljs/tree/main/examples/fivethirtyeight#readme"
>
Read more here
</a>{' '}
</p>
<div className="flex flex-1 justify-end">
<button
type="button"
onClick={() => setShow(false)}
className="-m-3 p-3 focus-visible:outline-offset-[-4px]"
>
<span className="sr-only">Dismiss</span>
<XMarkIcon className="h-5 w-5 text-white" aria-hidden="true" />
</button>
</div>
</div>
</Transition>
<header className="max-w-5xl mx-auto mt-8 w-full">
<div className="border-b-2 pb-2.5 mx-2 border-zinc-800 flex justify-between">
<h1 className="flex gap-x-1 items-end">
<span className="sr-only">FiveThirtyEight</span>
<img
width="197"
height="25"
alt="FiveThirtyEight"
src="data:image/svg+xml;base64,PHN2ZyBpZD0iTGF5ZXJfMSIgZGF0YS1uYW1lPSJMYXllciAxIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0MjEgNTMuNzYiPjxkZWZzPjxzdHlsZT4uY2xzLTF7ZmlsbDojMDEwMTAxO308L3N0eWxlPjwvZGVmcz48dGl0bGU+QXJ0Ym9hcmQgOTU8L3RpdGxlPjxwYXRoIGNsYXNzPSJjbHMtMSIgZD0iTTAgMGgyNXY4SDl2MTBoMTV2OEg5djE3SDBWMHpNMzEgMzZoNVYxOGgtNXYtOGgxM3YyNmg0djdIMzF6bTUtMzZoOHY4aC04ek0xNzkgMzZoNVYxOGgtNXYtOGgxM3YyNmg0djdoLTE3em01LTM2aDh2OGgtOHpNMzE2IDM2aDVWMThoLTV2LThoMTN2MjZoNHY3aC0xN3ptNS0zNmg4djhoLTh6TTU0IDI3VjEwaDh2MTVsNCA5Ljk4aDFMNzEgMjVWMTBoOHYxN2wtNyAxNkg2MWwtNy0xNnpNMTExIDQzSDk3LjQyQzg5LjIzIDQzIDg1IDM5LjE5IDg1IDMxLjE3VjIyYzAtNy41NyA0LjMtMTMgMTMtMTMgOS4zMyAwIDEzIDUuMDcgMTMgMTR2N0g5NHYxLjc0YzAgMi42MiAxIDQuMjYgMy40MiA0LjI2SDExMXpNOTQgMjNoOHYtMS41NWMwLTIuNjItMS4wNi01LjQ1LTQuMTMtNS40NS0yLjc5IDAtMy44NyAyLjItMy44NyA1LjQ1ek0xMjUgOGgtMTBWMGgyOXY4aC0xMHYzNWgtOVY4ek0yMDIgNDNWMTBoOHY0YzEuMTQtMi40NSAzLjc1LTQgNy4yMi00SDIyMHY4aC02Yy0yLjg0IDAtNCAuOTQtNCAzLjlWNDN6TTI0NSA0M2gtNC44NEMyMzMuMDUgNDMgMjMwIDM5LjMxIDIzMCAzMS44NVYxOGgtNnYtOGg2VjNoOHY3aDd2OGgtN2wtLjA3IDEzLjkzYzAgMi4yMi45MyA0LjA3IDMuNjYgNC4wN0gyNDV6TTQyMSA0M2gtNC44NEM0MDkuMDUgNDMgNDA2IDM5LjMxIDQwNiAzMS44NVYxOGgtNnYtOGg2VjNoOHY3aDd2OGgtN2wtLjA3IDEzLjkzYzAgMi4yMi45MyA0LjA3IDMuNjYgNC4wN0g0MjF6TTI1NC4yNiA1My43Nmw0LjYxLTkuNUwyNTEgMjdWMTBoOHYxNWw0IDEwaDFsNC0xMFYxMGg4djE3bC0xMi4zIDI2Ljc2aC05LjQ0ek0yODQgMGgyNXY4aC0xNnY5aDE1djhoLTE1djEwaDE2djhoLTI1VjB6TTMzNyA0OHYtMmgxNi4xYzIgMCAyLjktLjE4IDIuOS0xLjI3di0uMzRjMC0xLjA4LS45MS0xLjM5LTIuOS0xLjM5SDM0MHYtNWw1LTVjLTUuMjktMS40OC04LTUuNDMtOC0xMXYtMWMwLTcuNTYgNC40NC0xMiAxNC0xMmEyMS45MyAyMS45MyAwIDAgMSA1Ljk1IDFMMzYxIDRsNSAzLTQgNmMxLjM3IDEuOTMgMyA0LjkzIDMgOHYxYzAgNy0zLjMgMTAuNjYtMTIgMTFsLTMgNGg2YzUuOTIgMCA5IDIuNjIgOSA3LjY4di4xMWMwIDUuMDYtMi43MSA4LjIxLTguNjIgOC4yMWgtMTNjLTQuMjkgMC02LjM4LTEuODQtNi4zOC01em0xOS0yNXYtM2MwLTMuMy0xLjMzLTQtNS00cy01IC43LTUgNHYzYzAgMy4zIDEuMzkgNCA1IDRzNS0uNyA1LTR6TTM4MCA0M2gtOFYwaDh2MTRjMS4xNC0yLjY3IDMuNC00IDctNCA2LjI2IDAgOSAzLjA4IDkgMTAuNzZWNDNoLThWMjJjMC0zLjEzLTEuMDctNS00LTVzLTQgMS44Ny00IDV6TTE1NyA0M2gtOFYwaDh2MTRjMS4xNC0yLjY3IDMuOTEtNCA3LjQ5LTQgNi4yNiAwIDguNTEgMy4xMyA4LjUxIDEwLjgxVjQzaC04VjIxYzAtMy4xMy0xLjA3LTQuNDQtNC00LjQ0cy00IDIuMjYtNCA1LjM5eiIvPjwvc3ZnPg=="
/>{' '}
<span className="-mb-0.5 text-[#3c3c3c]">replica</span>
</h1>
<div className="md:flex items-center gap-x-3 text-[#3c3c3c] -mb-1 hidden">
<a
className="hover:opacity-75 transition"
href="https://portaljs.com"
>
Built with 🌀PortalJS
</a>
<hr className="h-[80%] border border-[#3c3c3c] opacity-75 my-2"></hr>
<a
className="hover:opacity-75 transition"
href="https://github.com/datopian/portaljs/tree/main/examples/fivethirtyeight"
>
Github
</a>
</div>
</div>
<div className="mx-2 py-1.5 text-[14px] text-[#3c3c3c] md:hidden">
<ul className="flex gap-x-4">
<li>
<a
className="hover:opacity-75 transition"
href="https://portaljs.com"
>
PortalJS
</a>
</li>
<li>
<a
className="hover:opacity-75 transition"
href="https://github.com/datopian/portaljs/tree/main/examples/fivethirtyeight"
>
View on Github
</a>
</li>
</ul>
</div>
</header>
{children}
</>
);
}

View File

@ -1,33 +1,4 @@
[
{
"url": "https://github.com/fivethirtyeight/data/tree/master/polls",
"name": "polls",
"displayName": "<span class=\"lastword\">polls</span>",
"articles": [
{
"date": "2023-05-11T14:35:40.000Z",
"title": "Latest Polls",
"url": "https://projects.fivethirtyeight.com/polls/"
}
],
"files": [
"https://projects.fivethirtyeight.com/polls-page/data/president_primary_polls.csv",
"https://projects.fivethirtyeight.com/polls-page/data/president_primary_polls_historical.csv",
"https://projects.fivethirtyeight.com/polls-page/data/president_polls.csv",
"https://projects.fivethirtyeight.com/polls-page/data/president_polls_historical.csv",
"https://projects.fivethirtyeight.com/polls-page/data/senate_polls.csv",
"https://projects.fivethirtyeight.com/polls-page/data/senate_polls_historical.csv",
"https://projects.fivethirtyeight.com/polls-page/data/house_polls.csv",
"https://projects.fivethirtyeight.com/polls-page/data/house_polls_historical.csv",
"https://projects.fivethirtyeight.com/polls-page/data/governor_polls.csv",
"https://projects.fivethirtyeight.com/polls-page/data/governor_polls_historical.csv",
"https://projects.fivethirtyeight.com/polls-page/data/president_approval_polls.csv",
"https://projects.fivethirtyeight.com/polls-page/data/generic_ballot_polls.csv",
"https://projects.fivethirtyeight.com/polls-page/data/generic_ballot_polls_historical.csv",
"https://projects.fivethirtyeight.com/2020-primary-data/pres_primary_avgs_2020.csv",
"https://projects.fivethirtyeight.com/2020-general-data/presidential_poll_averages_2020.csv"
]
},
{
"url": "https://github.com/fivethirtyeight/data/tree/master/congress-generic-ballot",
"name": "congress-generic-ballot",
@ -195,6 +166,35 @@
}
]
},
{
"url": "https://github.com/fivethirtyeight/data/tree/master/polls",
"name": "polls",
"displayName": "<span class=\"lastword\">polls</span>",
"articles": [
{
"date": "2023-05-11T14:35:40.000Z",
"title": "Latest Polls",
"url": "https://projects.fivethirtyeight.com/polls/"
}
],
"files": [
"https://projects.fivethirtyeight.com/polls-page/data/president_primary_polls.csv",
"https://projects.fivethirtyeight.com/polls-page/data/president_primary_polls_historical.csv",
"https://projects.fivethirtyeight.com/polls-page/data/president_polls.csv",
"https://projects.fivethirtyeight.com/polls-page/data/president_polls_historical.csv",
"https://projects.fivethirtyeight.com/polls-page/data/senate_polls.csv",
"https://projects.fivethirtyeight.com/polls-page/data/senate_polls_historical.csv",
"https://projects.fivethirtyeight.com/polls-page/data/house_polls.csv",
"https://projects.fivethirtyeight.com/polls-page/data/house_polls_historical.csv",
"https://projects.fivethirtyeight.com/polls-page/data/governor_polls.csv",
"https://projects.fivethirtyeight.com/polls-page/data/governor_polls_historical.csv",
"https://projects.fivethirtyeight.com/polls-page/data/president_approval_polls.csv",
"https://projects.fivethirtyeight.com/polls-page/data/generic_ballot_polls.csv",
"https://projects.fivethirtyeight.com/polls-page/data/generic_ballot_polls_historical.csv",
"https://projects.fivethirtyeight.com/2020-primary-data/pres_primary_avgs_2020.csv",
"https://projects.fivethirtyeight.com/2020-general-data/presidential_poll_averages_2020.csv"
]
},
{
"url": "https://github.com/fivethirtyeight/data/tree/master/nfl-elo",
"name": "nfl-elo",
@ -1169,18 +1169,6 @@
}
]
},
{
"url": "https://github.com/fivethirtyeight/data/tree/master/undefeated-boxers",
"name": "undefeated-boxers",
"displayName": "undefeated-<span class=\"lastword\">boxers</span>",
"articles": [
{
"date": "2017-08-18T18:47:32.000Z",
"title": "Mayweather Is Defined By The Zero Next To His Name",
"url": "https://fivethirtyeight.com/features/mayweather-is-defined-by-the-zero-next-to-his-name/"
}
]
},
{
"url": "https://github.com/fivethirtyeight/data/tree/master/chess-transfers",
"name": "chess-transfers",
@ -2139,6 +2127,18 @@
}
]
},
{
"url": "https://github.com/fivethirtyeight/data/tree/master/undefeated-boxers",
"name": "undefeated-boxers",
"displayName": "undefeated-<span class=\"lastword\">boxers</span>",
"articles": [
{
"date": "2017-08-18T18:47:32.000Z",
"title": "Mayweather Is Defined By The Zero Next To His Name",
"url": "https://fivethirtyeight.com/features/mayweather-is-defined-by-the-zero-next-to-his-name/"
}
]
},
{
"url": "https://github.com/fivethirtyeight/data/tree/master/march-madness-predictions",
"name": "march-madness-predictions",

File diff suppressed because it is too large Load Diff

View File

@ -9,7 +9,11 @@
"lint": "next lint"
},
"dependencies": {
"@portaljs/components": "^0.1.0",
"@headlessui/react": "^1.7.14",
"@heroicons/react": "^2.0.18",
"@portaljs/components": "^0.1.8",
"@portaljs/core": "^1.0.5",
"@portaljs/remark-wiki-link": "^1.0.4",
"@tailwindcss/typography": "^0.5.9",
"@types/node": "20.1.1",
"@types/react": "18.2.6",
@ -26,12 +30,15 @@
"react": "18.2.0",
"react-dom": "18.2.0",
"react-markdown": "^8.0.7",
"remark": "^14.0.3",
"remark-code-frontmatter": "^1.0.0",
"remark-excerpt": "^1.0.0-beta.1",
"remark-extract-frontmatter": "^3.2.0",
"remark-frontmatter": "^4.0.1",
"remark-gfm": "^3.0.1",
"tailwindcss": "3.3.2",
"timeago.js": "^4.0.2",
"to-vfile": "^7.2.4",
"typescript": "5.0.4"
}
}

View File

@ -1,8 +1,49 @@
import '@/styles/globals.css'
import '@portaljs/components/styles.css'
import '@/styles/globals.css';
import '@portaljs/components/styles.css';
import { useEffect } from 'react';
import { pageview } from '@portaljs/core';
import Script from 'next/script';
import Head from 'next/head';
import { useRouter } from 'next/router';
import type { AppProps } from 'next/app'
import type { AppProps } from 'next/app';
export default function App({ Component, pageProps }: AppProps) {
return <Component {...pageProps} />
const router = useRouter();
useEffect(() => {
const handleRouteChange = (url: any) => {
pageview(url);
};
router.events.on('routeChangeComplete', handleRouteChange);
return () => {
router.events.off('routeChangeComplete', handleRouteChange);
};
}, [router.events]);
return (
<>
<Head>
<link rel="shortcut icon" href="/squared_logo.png" />
</Head>
<Script
strategy="afterInteractive"
src="https://www.googletagmanager.com/gtag/js?id=G-3N9SXTC7GS"
/>
<Script
id="gtag-init"
strategy="afterInteractive"
dangerouslySetInnerHTML={{
__html: `
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'G-3N9SXTC7GS', {
page_path: window.location.pathname,
});
`,
}}
/>
<Component {...pageProps} />
</>
);
}

View File

@ -19,78 +19,9 @@ export default function Document() {
/>
</Head>
<body>
<div className="px-2 max-w-5xl mx-auto pb-2">
<div className="mt-2 px-2 bg-[#3c3c3c] text-white">
<div className="p-2 text-center">
This is a replica to the awesome{' '}
<a
className="hover:underline font-bold"
href="https://data.fivethirtyeight.com"
>
data.fivethirtyeight.com
</a>{' '}
website.{' '}
<a
className="hover:underline font-bold"
href="https://github.com/datopian/portaljs/tree/main/examples/fivethirtyeight"
>
Read more here
</a>{' '}
</div>
</div>
</div>
<header className="max-w-5xl mx-auto mt-8 w-full">
<div className="border-b-2 pb-2.5 mx-2 border-zinc-800 flex justify-between">
<h1 className="flex gap-x-1 items-end">
<span className="sr-only">FiveThirtyEight</span>
<img
width="197"
height="25"
alt="FiveThirtyEight"
src="data:image/svg+xml;base64,PHN2ZyBpZD0iTGF5ZXJfMSIgZGF0YS1uYW1lPSJMYXllciAxIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0MjEgNTMuNzYiPjxkZWZzPjxzdHlsZT4uY2xzLTF7ZmlsbDojMDEwMTAxO308L3N0eWxlPjwvZGVmcz48dGl0bGU+QXJ0Ym9hcmQgOTU8L3RpdGxlPjxwYXRoIGNsYXNzPSJjbHMtMSIgZD0iTTAgMGgyNXY4SDl2MTBoMTV2OEg5djE3SDBWMHpNMzEgMzZoNVYxOGgtNXYtOGgxM3YyNmg0djdIMzF6bTUtMzZoOHY4aC04ek0xNzkgMzZoNVYxOGgtNXYtOGgxM3YyNmg0djdoLTE3em01LTM2aDh2OGgtOHpNMzE2IDM2aDVWMThoLTV2LThoMTN2MjZoNHY3aC0xN3ptNS0zNmg4djhoLTh6TTU0IDI3VjEwaDh2MTVsNCA5Ljk4aDFMNzEgMjVWMTBoOHYxN2wtNyAxNkg2MWwtNy0xNnpNMTExIDQzSDk3LjQyQzg5LjIzIDQzIDg1IDM5LjE5IDg1IDMxLjE3VjIyYzAtNy41NyA0LjMtMTMgMTMtMTMgOS4zMyAwIDEzIDUuMDcgMTMgMTR2N0g5NHYxLjc0YzAgMi42MiAxIDQuMjYgMy40MiA0LjI2SDExMXpNOTQgMjNoOHYtMS41NWMwLTIuNjItMS4wNi01LjQ1LTQuMTMtNS40NS0yLjc5IDAtMy44NyAyLjItMy44NyA1LjQ1ek0xMjUgOGgtMTBWMGgyOXY4aC0xMHYzNWgtOVY4ek0yMDIgNDNWMTBoOHY0YzEuMTQtMi40NSAzLjc1LTQgNy4yMi00SDIyMHY4aC02Yy0yLjg0IDAtNCAuOTQtNCAzLjlWNDN6TTI0NSA0M2gtNC44NEMyMzMuMDUgNDMgMjMwIDM5LjMxIDIzMCAzMS44NVYxOGgtNnYtOGg2VjNoOHY3aDd2OGgtN2wtLjA3IDEzLjkzYzAgMi4yMi45MyA0LjA3IDMuNjYgNC4wN0gyNDV6TTQyMSA0M2gtNC44NEM0MDkuMDUgNDMgNDA2IDM5LjMxIDQwNiAzMS44NVYxOGgtNnYtOGg2VjNoOHY3aDd2OGgtN2wtLjA3IDEzLjkzYzAgMi4yMi45MyA0LjA3IDMuNjYgNC4wN0g0MjF6TTI1NC4yNiA1My43Nmw0LjYxLTkuNUwyNTEgMjdWMTBoOHYxNWw0IDEwaDFsNC0xMFYxMGg4djE3bC0xMi4zIDI2Ljc2aC05LjQ0ek0yODQgMGgyNXY4aC0xNnY5aDE1djhoLTE1djEwaDE2djhoLTI1VjB6TTMzNyA0OHYtMmgxNi4xYzIgMCAyLjktLjE4IDIuOS0xLjI3di0uMzRjMC0xLjA4LS45MS0xLjM5LTIuOS0xLjM5SDM0MHYtNWw1LTVjLTUuMjktMS40OC04LTUuNDMtOC0xMXYtMWMwLTcuNTYgNC40NC0xMiAxNC0xMmEyMS45MyAyMS45MyAwIDAgMSA1Ljk1IDFMMzYxIDRsNSAzLTQgNmMxLjM3IDEuOTMgMyA0LjkzIDMgOHYxYzAgNy0zLjMgMTAuNjYtMTIgMTFsLTMgNGg2YzUuOTIgMCA5IDIuNjIgOSA3LjY4di4xMWMwIDUuMDYtMi43MSA4LjIxLTguNjIgOC4yMWgtMTNjLTQuMjkgMC02LjM4LTEuODQtNi4zOC01em0xOS0yNXYtM2MwLTMuMy0xLjMzLTQtNS00cy01IC43LTUgNHYzYzAgMy4zIDEuMzkgNCA1IDRzNS0uNyA1LTR6TTM4MCA0M2gtOFYwaDh2MTRjMS4xNC0yLjY3IDMuNC00IDctNCA2LjI2IDAgOSAzLjA4IDkgMTAuNzZWNDNoLThWMjJjMC0zLjEzLTEuMDctNS00LTVzLTQgMS44Ny00IDV6TTE1NyA0M2gtOFYwaDh2MTRjMS4xNC0yLjY3IDMuOTEtNCA3LjQ5LTQgNi4yNiAwIDguNTEgMy4xMyA4LjUxIDEwLjgxVjQzaC04VjIxYzAtMy4xMy0xLjA3LTQuNDQtNC00LjQ0cy00IDIuMjYtNCA1LjM5eiIvPjwvc3ZnPg=="
/>{' '}
<span className="-mb-0.5 text-[#3c3c3c]">replica</span>
</h1>
<div className="md:flex items-center gap-x-3 text-[#3c3c3c] -mb-1 hidden">
<a
className="hover:opacity-75 transition"
href="https://portaljs.org"
>
Built with 🌀PortalJS
</a>
<hr className="h-[80%] border border-[#3c3c3c] opacity-75 my-2"></hr>
<a
className="hover:opacity-75 transition"
href="https://github.com/datopian/portaljs/tree/main/examples/fivethirtyeight"
>
Github
</a>
</div>
</div>
<div className="mx-2 py-1.5 text-[14px] text-[#3c3c3c] md:hidden">
<ul className="flex gap-x-4">
<li>
<a
className="hover:opacity-75 transition"
href="https://portaljs.org"
>
PortalJS
</a>
</li>
<li>
<a
className="hover:opacity-75 transition"
href="https://github.com/datopian/portaljs/tree/main/examples/fivethirtyeight"
>
View on Github
</a>
</li>
</ul>
</div>
</header>
<Main />
<NextScript />
</body>
<NextScript />
</Html>
);
}

View File

@ -7,10 +7,19 @@ import remarkGfm from 'remark-gfm';
import extract from 'remark-extract-frontmatter';
import { Dataset } from '..';
import { GetStaticProps } from 'next';
import { Table } from '@portaljs/components';
import { FlatUiTable } from '@portaljs/components';
import Breadcrumbs from '@/components/Breadcrumbs';
import { ReactMarkdown } from 'react-markdown/lib/react-markdown';
import remarkFrontmatter from 'remark-frontmatter';
import Layout from '@/components/Layout';
import { format } from 'timeago.js';
// Request a weekday along with a long date
const options = {
year: 'numeric',
month: 'long',
day: 'numeric',
} as const;
export default function DatasetPage({
dataset,
@ -22,68 +31,146 @@ export default function DatasetPage({
return (
<>
<NextSeo title={`${dataset.name} page`} />
<main className="max-w-5xl px-2 prose mx-auto my-8 prose-thead:border-b-4 prose-table:max-w-5xl prose-table:overflow-scroll prose-thead:overflow-scroll prose-tbody:overflow-scroll prose-thead:pb-2 prose-thead:border-zinc-900 prose-th:uppercase prose-th:text-left prose-th:font-light prose-th:text-xs">
<Breadcrumbs links={[{ title: dataset.name, href: '' }]} />
<h1 className="uppercase mb-0 mt-16">{dataset.name}</h1>
<p className="mb-8">
<span className="font-semibold">Repository:</span>{' '}
<a target="_blank" href={dataset.url}>
{dataset.url}
</a>
</p>
<h2 className="mb-0 mt-10">FILES</h2>
<div className="inline-block min-w-full py-2 align-middle">
<table className="min-w-full divide-y divide-gray-300">
<Layout>
<main className="max-w-5xl px-2 prose mx-auto my-8 pb-8 prose-thead:border-b-4 prose-table:max-w-5xl prose-table:overflow-scroll prose-thead:overflow-scroll prose-tbody:overflow-scroll prose-thead:pb-2 prose-thead:border-zinc-900 prose-th:uppercase prose-th:text-left prose-th:font-light prose-th:text-xs prose-a:no-underline">
<Breadcrumbs links={[{ title: dataset.name, href: '' }]} />
<h1 className="uppercase mb-0 mt-16">{dataset.name}</h1>
<table className="w-full my-10 mb-8 hidden md:table">
<thead className="border-b-4 pb-2 border-zinc-900">
<tr>
<th
className="uppercase text-left font-light text-xs pb-3"
scope="col"
>
Name
<th className="uppercase text-left font-normal text-xs pb-3">
related content
</th>
<th className="uppercase text-left font-normal text-xs pb-3">
last updated
</th>
</tr>
</thead>
<tbody className="divide-y divide-gray-200">
{dataset.files?.map((file) => (
<tr key={file}>
<td className="whitespace-nowrap text-left py-4 text-sm text-gray-500">
<a href={file}>{file.split('/').slice(-1)}</a>
</td>
</tr>
))}
<tbody>
<DesktopItem key={dataset.name} dataset={dataset} />
</tbody>
</table>
</div>
{dataset.files && dataset.files.length > 0 && (
<>
<h2 className="mb-0 mt-10">DATA PREVIEWS</h2>
{dataset.files?.map((file) => (
<div key={file} className="preview-table my-8">
<h3>{file.split('/').slice(-1)}</h3>
<Table url={file} />
</div>
))}
</>
)}
{dataset.readme && (
<>
<h2 className="uppercase font-black">Readme</h2>
{dataset.readme && (
<ReactMarkdown
remarkPlugins={[
remarkFrontmatter,
remarkGfm,
[extract, { remove: true }],
]}
{dataset.readme && (
<>
{dataset.readme && (
<ReactMarkdown
remarkPlugins={[
remarkFrontmatter,
remarkGfm,
[extract, { remove: true }],
]}
>
{dataset.readme}
</ReactMarkdown>
)}
</>
)}
<h2 className="mb-0 mt-10">Files</h2>
<div className="inline-block min-w-full py-2 align-middle">
<table className="min-w-full divide-y divide-gray-300">
<thead className="border-b-4 pb-2 border-zinc-900">
<tr>
<th
className="uppercase text-left font-light text-xs pb-3"
scope="col"
>
Name
</th>
<th
className="uppercase text-left font-light text-xs pb-3"
scope="col"
>
Download
</th>
</tr>
</thead>
<tbody className="divide-y divide-gray-200">
{dataset.files?.map((file) => (
<tr key={file}>
<td className="whitespace-nowrap text-left py-4 text-sm text-gray-500">
<a href={`#${file.split('/').slice(-1)}`}>
{file.split('/').slice(-1)}
</a>
</td>
<td className="whitespace-nowrap py-4 text-sm text-gray-500">
<a href={file}>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="currentColor"
className="w-8 h-8 text-blue-400 hover:text-blue-300 transition mt-1 ml-3"
>
<path
fillRule="evenodd"
d="M12 2.25c-5.385 0-9.75 4.365-9.75 9.75s4.365 9.75 9.75 9.75 9.75-4.365 9.75-9.75S17.385 2.25 12 2.25zm-.53 14.03a.75.75 0 001.06 0l3-3a.75.75 0 10-1.06-1.06l-1.72 1.72V8.25a.75.75 0 00-1.5 0v5.69l-1.72-1.72a.75.75 0 00-1.06 1.06l3 3z"
clipRule="evenodd"
/>
</svg>
</a>
</td>
</tr>
))}
</tbody>
</table>
</div>
{dataset.files && dataset.files.length > 0 && (
<>
<h2 className="mb-0 mt-8">Data Previews</h2>
{dataset.files?.map((file) => (
<div
key={file}
id={file.split('/').slice(-1).join('')}
className="preview-table my-8"
>
<h3>{file.split('/').slice(-1)}</h3>
<FlatUiTable url={file} />
</div>
))}
</>
)}
</main>
</Layout>
</>
);
}
export function DesktopItem({ dataset }: { dataset: Dataset }) {
return (
<>
{dataset.articles.map((article, index) => (
<tr
key={article.url}
className={`${
index === dataset.articles.length - 1 ? 'border-b' : ''
} border-zinc-400`}
>
<td>
<a
className="py-8 font-bold hover:underline pr-2"
href={article.url}
>
{article.title}
</a>
</td>
<td className="py-8 font-light text-[14px] min-w-[138px] font-mono text-[#999]">
{format(article.date).includes('years')
? new Date(article.date).toLocaleString('en-US', options)
: format(article.date)}
</td>
<td className="py-8 text-end">
{index === 0 && (
<a
className="ml-auto border border-zinc-900 font-light px-[25px] py-2.5 text-sm transition hover:bg-zinc-900 hover:text-white"
href={dataset.url}
>
{dataset.readme}
</ReactMarkdown>
info
</a>
)}
</>
)}
</main>
</td>
</tr>
))}
</>
);
}
@ -101,6 +188,7 @@ export async function getStaticPaths() {
fallback: false, // can also be true or 'blocking'
};
}
// change href base check datahub-next
export const getStaticProps: GetStaticProps = async ({ params }) => {
const datasetsFile = path.join(process.cwd(), 'datasets.json');
@ -110,15 +198,20 @@ export const getStaticProps: GetStaticProps = async ({ params }) => {
(_dataset) => _dataset.name === params?.datasetName
);
const github_pat = getConfig().serverRuntimeConfig.github_pat;
const readmes = await Promise.all(['/README.md', '/readme.md', '/Readme.md'].map(async (readme) => await getProjectReadme(
'fivethirtyeight',
'data',
'master',
dataset?.name + readme,
github_pat
)));
const readme = readmes.find(item => item !== null)
if (!readme) console.log('Readme not found for ' + dataset?.name)
const readmes = await Promise.all(
['/README.md', '/readme.md', '/Readme.md'].map(
async (readme) =>
await getProjectReadme(
'fivethirtyeight',
'data',
'master',
dataset?.name + readme,
github_pat
)
)
);
const readme = readmes.find((item) => item !== null);
if (!readme) console.log('Readme not found for ' + dataset?.name);
return {
props: {
dataset: {

View File

@ -4,6 +4,7 @@ import { format } from 'timeago.js';
import { promises as fs } from 'fs';
import path from 'path';
import { NextSeo } from 'next-seo';
import Layout from '@/components/Layout';
const inter = Inter({ subsets: ['latin'] });
@ -51,21 +52,12 @@ export function MobileItem({ dataset }: { dataset: Dataset }) {
>
info
</a>
{/*
<button>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="currentColor"
className="w-12 h-12 text-blue-400 hover:text-blue-300 transition mt-1"
>
<path
fillRule="evenodd"
d="M12 2.25c-5.385 0-9.75 4.365-9.75 9.75s4.365 9.75 9.75 9.75 9.75-4.365 9.75-9.75S17.385 2.25 12 2.25zm-.53 14.03a.75.75 0 001.06 0l3-3a.75.75 0 10-1.06-1.06l-1.72 1.72V8.25a.75.75 0 00-1.5 0v5.69l-1.72-1.72a.75.75 0 00-1.06 1.06l3 3z"
clipRule="evenodd"
/>
</svg>
</button> */}
<a
className="ml-2 border border-[#3c3c3c] px-[25px] py-2.5 text-sm transition bg-[#3c3c3c] text-white hover:bg-zinc-900"
href={`/datasets/${dataset.name}`}
>
explore
</a>
</div>
</div>
);
@ -97,6 +89,16 @@ export function DesktopItem({ dataset }: { dataset: Dataset }) {
? new Date(article.date).toLocaleString('en-US', options)
: format(article.date)}
</td>
<td>
{index === 0 && (
<a
className="ml-2 border border-[#3c3c3c] px-[25px] py-2.5 text-sm transition bg-[#3c3c3c] text-white hover:bg-zinc-900"
href={`/datasets/${dataset.name}`}
>
explore
</a>
)}
</td>
<td className="py-8">
{index === 0 && (
<a
@ -107,23 +109,6 @@ export function DesktopItem({ dataset }: { dataset: Dataset }) {
</a>
)}
</td>
{/*
<td>
<button>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="currentColor"
className="w-12 h-12 text-blue-400 hover:text-blue-300 transition mt-1"
>
<path
fillRule="evenodd"
d="M12 2.25c-5.385 0-9.75 4.365-9.75 9.75s4.365 9.75 9.75 9.75 9.75-4.365 9.75-9.75S17.385 2.25 12 2.25zm-.53 14.03a.75.75 0 001.06 0l3-3a.75.75 0 10-1.06-1.06l-1.72 1.72V8.25a.75.75 0 00-1.5 0v5.69l-1.72-1.72a.75.75 0 00-1.06 1.06l3 3z"
clipRule="evenodd"
/>
</svg>
</button>
</td>*/}
</tr>
))}
</>
@ -143,6 +128,7 @@ export default function Home({ datasets }: { datasets: Dataset[] }) {
return (
<>
<NextSeo title="FiveThirtyEight tribute by PortalJS" />
<Layout>
<main
className={`flex min-h-screen flex-col items-center max-w-5xl mx-auto pt-20 px-2.5 ${inter.className}`}
>
@ -206,6 +192,7 @@ export default function Home({ datasets }: { datasets: Dataset[] }) {
.
</p>
</main>
</Layout>
</>
);
}

View File

@ -3,6 +3,9 @@
@tailwind utilities;
.preview-table > div {
overflow-x: scroll;
overflow-y: hidden;
}
.prose h1 {
font-size: 1.5em !important;
}

View File

@ -6,7 +6,7 @@ A `datasets.json` file is used to specify which datasets are going to be part of
The application contains an index page, which lists all the datasets specified in the `datasets.json` file, and users can see more information about each dataset, such as the list of data files in it and the README, by clicking the "info" button on the list.
You can read more about it on the [Data catalog with data on GitHub](https://portaljs.org/docs/examples/github-backed-catalog) blog post.
You can read more about it on the [Data catalog with data on GitHub](https://portaljs.com/docs/examples/github-backed-catalog) blog post.
## Demo

View File

@ -0,0 +1,21 @@
import { MDXRemote } from 'next-mdx-remote';
import dynamic from 'next/dynamic';
import { Mermaid } from '@portaljs/core';
// Custom components/renderers to pass to MDX.
// Since the MDX files aren't loaded by webpack, they have no knowledge of how
// to handle import statements. Instead, you must include components in scope
// here.
const components = {
Table: dynamic(() => import('@portaljs/components').then(mod => mod.Table)),
Catalog: dynamic(() => import('@portaljs/components').then(mod => mod.Catalog)),
FlatUiTable: dynamic(() => import('@portaljs/components').then(mod => mod.FlatUiTable)),
mermaid: Mermaid,
Vega: dynamic(() => import('@portaljs/components').then(mod => mod.Vega)),
VegaLite: dynamic(() => import('@portaljs/components').then(mod => mod.VegaLite)),
LineChart: dynamic(() => import('@portaljs/components').then(mod => mod.LineChart)),
} as any;
export default function DRD({ source }: { source: any }) {
return <MDXRemote {...source} components={components} />;
}

View File

@ -15,6 +15,13 @@
],
"readme": "README.md"
},
{
"owner": "luccasmmg",
"branch": "main",
"repo": "test-data-repo-1",
"files": ["data_1.csv", "data_2.csv"],
"readme": "README.md"
},
{
"owner": "datasets",
"branch": "main",

View File

@ -0,0 +1,105 @@
import matter from "gray-matter";
import mdxmermaid from "mdx-mermaid";
import { h } from "hastscript";
import remarkCallouts from "@portaljs/remark-callouts";
import remarkEmbed from "@portaljs/remark-embed";
import remarkGfm from "remark-gfm";
import remarkMath from "remark-math";
import remarkSmartypants from "remark-smartypants";
import remarkToc from "remark-toc";
import remarkWikiLink from "@portaljs/remark-wiki-link";
import rehypeAutolinkHeadings from "rehype-autolink-headings";
import rehypeKatex from "rehype-katex";
import rehypeSlug from "rehype-slug";
import rehypePrismPlus from "rehype-prism-plus";
import { serialize } from "next-mdx-remote/serialize";
/**
* Parse a markdown or MDX file to an MDX source form + front matter data
*
* @source: the contents of a markdown or mdx file
* @format: used to indicate to next-mdx-remote which format to use (md or mdx)
* @returns: { mdxSource: mdxSource, frontMatter: ...}
*/
const parse = async function (source, format, scope) {
const { content, data, excerpt } = matter(source, {
excerpt: (file, options) => {
// Generate an excerpt for the file
file.excerpt = file.content.split("\n\n")[0];
},
});
const mdxSource = await serialize(
{ value: content, path: format },
{
// Optionally pass remark/rehype plugins
mdxOptions: {
remarkPlugins: [
remarkEmbed,
remarkGfm,
[remarkSmartypants, { quotes: false, dashes: "oldschool" }],
remarkMath,
remarkCallouts,
remarkWikiLink,
[
remarkToc,
{
heading: "Table of contents",
tight: true,
},
],
[mdxmermaid, {}],
],
rehypePlugins: [
rehypeSlug,
[
rehypeAutolinkHeadings,
{
properties: { className: 'heading-link' },
test(element) {
return (
["h2", "h3", "h4", "h5", "h6"].includes(element.tagName) &&
element.properties?.id !== "table-of-contents" &&
element.properties?.className !== "blockquote-heading"
);
},
content() {
return [
h(
"svg",
{
xmlns: "http:www.w3.org/2000/svg",
fill: "#ab2b65",
viewBox: "0 0 20 20",
className: "w-5 h-5",
},
[
h("path", {
fillRule: "evenodd",
clipRule: "evenodd",
d: "M9.493 2.853a.75.75 0 00-1.486-.205L7.545 6H4.198a.75.75 0 000 1.5h3.14l-.69 5H3.302a.75.75 0 000 1.5h3.14l-.435 3.148a.75.75 0 001.486.205L7.955 14h2.986l-.434 3.148a.75.75 0 001.486.205L12.456 14h3.346a.75.75 0 000-1.5h-3.14l.69-5h3.346a.75.75 0 000-1.5h-3.14l.435-3.147a.75.75 0 00-1.486-.205L12.045 6H9.059l.434-3.147zM8.852 7.5l-.69 5h2.986l.69-5H8.852z",
}),
]
),
];
},
},
],
[rehypeKatex, { output: "mathml" }],
[rehypePrismPlus, { ignoreMissing: true }],
],
format,
},
scope,
}
);
return {
mdxSource: mdxSource,
frontMatter: data,
excerpt,
};
};
export default parse;

View File

@ -0,0 +1,14 @@
import { MarkdownDB } from "mddb";
const dbPath = "markdown.db";
const client = new MarkdownDB({
client: "sqlite3",
connection: {
filename: dbPath,
},
});
const clientPromise = client.init();
export default clientPromise;

View File

@ -39,6 +39,32 @@ export async function getProjectReadme(
}
}
export async function getProjectDatapackage(
owner: string,
repo: string,
branch: string,
github_pat?: string
) {
const octokit = new Octokit({ auth: github_pat });
try {
const response = await octokit.rest.repos.getContent({
owner,
repo,
path: "datapackage.json",
ref: branch,
});
const data = response.data as { content?: string };
const fileContent = data.content ? data.content : "";
if (fileContent === "") {
return null;
}
const decodedContent = Buffer.from(fileContent, "base64").toString();
return JSON.parse(decodedContent);
} catch (error) {
return null
}
}
export async function getLastUpdated(
owner: string,
repo: string,
@ -162,11 +188,20 @@ export async function getProject(project: GithubProject, github_pat?: string) {
projectBase,
github_pat
);
const projectDatapackage = await getProjectDatapackage(
project.owner,
project.repo,
project.branch,
github_pat
);
return {
...projectMetadata,
files: projectData,
readmeContent: projectReadme,
last_updated,
base_path: projectBase,
datapackage: projectDatapackage
};
}

File diff suppressed because it is too large Load Diff

View File

@ -10,19 +10,33 @@
"prettier": "prettier --write ."
},
"dependencies": {
"@portaljs/components": "^0.1.6",
"@portaljs/core": "^1.0.5",
"@portaljs/remark-callouts": "^1.0.5",
"@portaljs/remark-embed": "^1.0.4",
"@portaljs/remark-wiki-link": "^1.0.4",
"@types/node": "18.16.0",
"@types/react": "18.0.38",
"@types/react-dom": "18.0.11",
"eslint": "8.39.0",
"eslint-config-next": "13.3.1",
"next": "13.3.1",
"mddb": "^0.1.9",
"next": "13.4.3",
"next-mdx-remote": "^4.4.1",
"next-seo": "^6.0.0",
"octokit": "^2.0.14",
"react": "18.2.0",
"react-dom": "18.2.0",
"react-markdown": "^8.0.7",
"react-timeago": "^7.1.0",
"rehype-autolink-headings": "^6.1.1",
"rehype-katex": "^6.0.3",
"rehype-prism-plus": "^1.5.1",
"rehype-slug": "^5.1.0",
"remark-gfm": "^3.0.1",
"remark-math": "^5.1.1",
"remark-smartypants": "^2.0.0",
"remark-toc": "^8.0.1",
"typescript": "5.0.4"
},
"devDependencies": {

View File

@ -6,6 +6,8 @@ import { getProject, GithubProject } from "../../../lib/octokit";
import ReactMarkdown from "react-markdown";
import remarkGfm from "remark-gfm";
import Breadcrumbs from "../../../components/_shared/Breadcrumbs";
import parse from '../../../lib/markdown';
import DataRichDocument from '../../../components/DataRichDocument'
export default function ProjectPage({ project }) {
const repoId = `@${project.repo_config.owner}/${project.repo_config.repo}`;
@ -64,9 +66,7 @@ export default function ProjectPage({ project }) {
<hr />
<h2 className="uppercase font-black">Readme</h2>
<ReactMarkdown remarkPlugins={[remarkGfm]}>
{project.readmeContent}
</ReactMarkdown>
<DataRichDocument source={project.mdxSource} />
</main>
</>
);
@ -119,9 +119,10 @@ export async function getStaticProps({ params }) {
});
const github_pat = getConfig().serverRuntimeConfig.github_pat;
const project = await getProject(repo, github_pat);
let { mdxSource, frontMatter } = await parse(project.readmeContent, '.mdx', { project });
return {
props: {
project: { ...project, repo_config: repo },
project: { ...project, repo_config: repo, mdxSource },
},
};
}

View File

@ -40,7 +40,7 @@ export function Datasets({ projects }) {
<Link
target="_blank"
className="underline"
href="https://portaljs.org/"
href="https://portaljs.com/"
>
🌀 PortalJS
</Link>

View File

@ -78,3 +78,72 @@ pre {
color: rgba(55, 65, 81, 1);
width: 100%;
}
@import "@portaljs/remark-callouts/styles.css";
/* mathjax */
.math-inline > mjx-container > svg {
display: inline;
align-items: center;
}
/* smooth scrolling in modern browsers */
html {
scroll-behavior: smooth !important;
}
/* tooltip fade-out clip */
.tooltip-body::after {
content: "";
position: absolute;
right: 0;
top: 3.6rem; /* multiple of $line-height used on the tooltip body (defined in tooltipBodyStyle) */
height: 1.2rem; /* ($top + $height)/$line-height is the number of lines we want to clip tooltip text at*/
width: 10rem;
background: linear-gradient(
to right,
rgba(255, 255, 255, 0),
rgba(255, 255, 255, 1) 100%
);
}
:is(h2, h3, h4, h5, h6):not(.blogitem-title) {
margin-left: -2rem !important;
padding-left: 2rem !important;
scroll-margin-top: 4.5rem;
position: relative;
}
.heading-link {
padding: 1px;
position: absolute;
left: 0;
top: 50%;
transform: translateY(-50%);
margin: auto 0;
border-radius: 5px;
background: #1e293b;
opacity: 0;
transition: opacity 0.2s;
}
.light .heading-link {
/* border: 1px solid #ab2b65; */
/* background: none; */
background: #e2e8f0;
}
:is(h2, h3, h4, h5, h6):not(.blogitem-title):hover .heading-link {
opacity: 100;
}
.heading-link svg {
transform: scale(0.75);
}
@media screen and (max-width: 640px) {
.heading-link {
visibility: hidden;
}
}

View File

@ -1 +0,0 @@
PortalJS Learn Example - https://portaljs.org/docs

1
examples/learn/README.md Normal file
View File

@ -0,0 +1 @@
PortalJS Learn Example - https://portaljs.com/docs

View File

@ -0,0 +1,21 @@
import { MDXRemote } from 'next-mdx-remote';
import dynamic from 'next/dynamic';
import { Mermaid } from '@portaljs/core';
// Custom components/renderers to pass to MDX.
// Since the MDX files aren't loaded by webpack, they have no knowledge of how
// to handle import statements. Instead, you must include components in scope
// here.
const components = {
Table: dynamic(() => import('@portaljs/components').then(mod => mod.Table)),
Catalog: dynamic(() => import('@portaljs/components').then(mod => mod.Catalog)),
mermaid: Mermaid,
Vega: dynamic(() => import('@portaljs/components').then(mod => mod.Vega)),
VegaLite: dynamic(() => import('@portaljs/components').then(mod => mod.VegaLite)),
LineChart: dynamic(() => import('@portaljs/components').then(mod => mod.LineChart)),
FlatUiTable: dynamic(() => import('@portaljs/components').then(mod => mod.FlatUiTable)),
} as any;
export default function DRD({ source }: { source: any }) {
return <MDXRemote {...source} components={components} />;
}

View File

@ -0,0 +1,105 @@
import matter from "gray-matter";
import mdxmermaid from "mdx-mermaid";
import { h } from "hastscript";
import remarkCallouts from "@portaljs/remark-callouts";
import remarkEmbed from "@portaljs/remark-embed";
import remarkGfm from "remark-gfm";
import remarkMath from "remark-math";
import remarkSmartypants from "remark-smartypants";
import remarkToc from "remark-toc";
import remarkWikiLink from "@portaljs/remark-wiki-link";
import rehypeAutolinkHeadings from "rehype-autolink-headings";
import rehypeKatex from "rehype-katex";
import rehypeSlug from "rehype-slug";
import rehypePrismPlus from "rehype-prism-plus";
import { serialize } from "next-mdx-remote/serialize";
/**
* Parse a markdown or MDX file to an MDX source form + front matter data
*
* @source: the contents of a markdown or mdx file
* @format: used to indicate to next-mdx-remote which format to use (md or mdx)
* @returns: { mdxSource: mdxSource, frontMatter: ...}
*/
const parse = async function (source, format, scope) {
const { content, data, excerpt } = matter(source, {
excerpt: (file, options) => {
// Generate an excerpt for the file
file.excerpt = file.content.split("\n\n")[0];
},
});
const mdxSource = await serialize(
{ value: content, path: format },
{
// Optionally pass remark/rehype plugins
mdxOptions: {
remarkPlugins: [
remarkEmbed,
remarkGfm,
[remarkSmartypants, { quotes: false, dashes: "oldschool" }],
remarkMath,
remarkCallouts,
remarkWikiLink,
[
remarkToc,
{
heading: "Table of contents",
tight: true,
},
],
[mdxmermaid, {}],
],
rehypePlugins: [
rehypeSlug,
[
rehypeAutolinkHeadings,
{
properties: { className: 'heading-link' },
test(element) {
return (
["h2", "h3", "h4", "h5", "h6"].includes(element.tagName) &&
element.properties?.id !== "table-of-contents" &&
element.properties?.className !== "blockquote-heading"
);
},
content() {
return [
h(
"svg",
{
xmlns: "http:www.w3.org/2000/svg",
fill: "#ab2b65",
viewBox: "0 0 20 20",
className: "w-5 h-5",
},
[
h("path", {
fillRule: "evenodd",
clipRule: "evenodd",
d: "M9.493 2.853a.75.75 0 00-1.486-.205L7.545 6H4.198a.75.75 0 000 1.5h3.14l-.69 5H3.302a.75.75 0 000 1.5h3.14l-.435 3.148a.75.75 0 001.486.205L7.955 14h2.986l-.434 3.148a.75.75 0 001.486.205L12.456 14h3.346a.75.75 0 000-1.5h-3.14l.69-5h3.346a.75.75 0 000-1.5h-3.14l.435-3.147a.75.75 0 00-1.486-.205L12.045 6H9.059l.434-3.147zM8.852 7.5l-.69 5h2.986l.69-5H8.852z",
}),
]
),
];
},
},
],
[rehypeKatex, { output: "mathml" }],
[rehypePrismPlus, { ignoreMissing: true }],
],
format,
},
scope,
}
);
return {
mdxSource: mdxSource,
frontMatter: data,
excerpt,
};
};
export default parse;

View File

@ -0,0 +1,14 @@
import { MarkdownDB } from "mddb";
const dbPath = "markdown.db";
const client = new MarkdownDB({
client: "sqlite3",
connection: {
filename: dbPath,
},
});
const clientPromise = client.init();
export default clientPromise;

View File

@ -0,0 +1,5 @@
const nextConfig = {
swcMinify: false
}
module.exports = nextConfig

File diff suppressed because it is too large Load Diff

View File

@ -12,25 +12,27 @@
"mddb": "mddb ./content"
},
"dependencies": {
"@flowershow/core": "^0.4.10",
"@flowershow/markdowndb": "^0.1.1",
"@flowershow/remark-callouts": "^1.0.0",
"@flowershow/remark-embed": "^1.0.0",
"@flowershow/remark-wiki-link": "^1.1.2",
"@githubocto/flat-ui": "^0.14.1",
"@heroicons/react": "^2.0.17",
"@opentelemetry/api": "^1.4.0",
"@portaljs/components": "^0.1.0",
"@portaljs/components": "^0.1.8",
"@portaljs/core": "^1.0.5",
"@portaljs/remark-callouts": "^1.0.5",
"@portaljs/remark-embed": "^1.0.4",
"@portaljs/remark-wiki-link": "^1.0.4",
"@tanstack/react-table": "^8.8.5",
"flexsearch": "0.7.21",
"gray-matter": "^4.0.3",
"hastscript": "^7.2.0",
"mddb": "^0.1.9",
"mdx-mermaid": "2.0.0-rc7",
"next": "13.2.1",
"next-mdx-remote": "^4.4.1",
"papaparse": "^5.4.1",
"react": "18.2.0",
"react-dom": "18.2.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-hook-form": "^7.43.9",
"react-query": "^3.39.3",
"react-vega": "^7.6.0",
"rehype-autolink-headings": "^6.1.1",
"rehype-katex": "^6.0.3",
@ -40,7 +42,9 @@
"remark-math": "^5.1.1",
"remark-smartypants": "^2.0.0",
"remark-toc": "^8.0.1",
"typescript": "5.0.4"
"typescript": "5.0.4",
"vega": "5.25.0",
"vega-lite": "5.1.0"
},
"devDependencies": {
"@tailwindcss/typography": "^0.5.9",

View File

@ -81,7 +81,7 @@ export default function DatasetPage({ mdxSource, frontMatter }) {
<p className="my-0">
<span className="font-semibold">Modified: </span>
<span className="description my-0">
{new Date(frontMatter.modified).toLocaleDateString()}
{new Date(frontMatter.modified).toLocaleDateString("en-US")}
</span>
</p>
)}

View File

@ -0,0 +1,6 @@
module.exports = {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
}

View File

Before

Width:  |  Height:  |  Size: 37 KiB

After

Width:  |  Height:  |  Size: 37 KiB

View File

@ -1,7 +1,7 @@
@tailwind base;
@tailwind components;
@tailwind utilities;
@import "@flowershow/remark-callouts/styles.css";
@import "@portaljs/remark-callouts/styles.css";
.w-5 {
width: 1.25rem

View File

@ -6,7 +6,7 @@ A `datasets.json` file is used to specify which datasets are going to be part of
The application contains an index page, which lists all the datasets specified in the `datasets.json` file, and users can see more information about each dataset, such as the list of data files in it and the README, by clicking the "info" button on the list.
You can read more about it on the [Data catalog with data on GitHub](https://portaljs.org/docs/examples/github-backed-catalog) blog post.
You can read more about it on the [Data catalog with data on GitHub](https://portaljs.com/docs/examples/github-backed-catalog) blog post.
## Demo

View File

@ -2,7 +2,7 @@ import { expect, test } from 'vitest';
import { getAllProjectsFromOrg, getProjectDataPackage } from '../lib/project';
import { loadDataPackage } from '../lib/loader';
import { getProjectMetadata } from '../lib/project';
import { getCsv, parseCsv } from '../components/Table';
import { validate } from 'datapackage';
test(
'Test OS-Data',
@ -12,8 +12,24 @@ test(
'main',
process.env.VITE_GITHUB_PAT
);
if (repos.failed.length > 0) console.log(repos.failed);
expect(repos.failed.length).toBe(0);
if (repos.failed.length > 0)
console.log('Failed to get datapackage on', repos.failed);
let failedDatapackages = await Promise.all(
repos.results.map(async (item) => {
try {
const { valid, errors } = await validate(item.datapackage);
return errors.length > 0 ? item.repo.name : null;
} catch {
return item.repo.name;
}
})
);
failedDatapackages = failedDatapackages.filter((item) => item !== null);
if (failedDatapackages.length > 0) {
console.log('Failed to validate datapackage on ', failedDatapackages);
} else {
console.log('No invalid packages');
}
},
{ timeout: 100000 }
);
@ -27,7 +43,22 @@ test(
process.env.VITE_GITHUB_PAT
);
if (repos.failed.length > 0) console.log(repos.failed);
expect(repos.failed.length).toBe(0);
let failedDatapackages = await Promise.all(
repos.results.map(async (item) => {
try {
const { valid, errors } = await validate(item.datapackage);
return errors.length > 0 ? item.repo.name : null;
} catch {
return item.repo.name;
}
})
);
failedDatapackages = failedDatapackages.filter((item) => item !== null);
if (failedDatapackages.length > 0) {
console.log('Failed to validate datapackage on ', failedDatapackages);
} else {
console.log('No invalid packages');
}
},
{ timeout: 100000 }
);
@ -83,56 +114,3 @@ test(
},
{ timeout: 100000 }
);
test(
'Test getting one section of csv from R2',
async () => {
const rawCsv = await getCsv(
'https://storage.openspending.org/state-of-minas-gerais-brazil-planned-budget/__os_imported__br-mg-ppagloc.csv'
);
const parsedCsv = await parseCsv(rawCsv);
expect(parsedCsv.errors.length).toBe(1);
expect(parsedCsv.data.length).toBe(10165);
expect(parsedCsv.meta.fields).toStrictEqual([
'function_name',
'function_label',
'product_name',
'product_label',
'area_name',
'area_label',
'subaction_name',
'subaction_label',
'region_label_map',
'region_reg_map',
'region_name',
'region_label',
'municipality_map_id',
'municipality_name',
'municipality_map_code',
'municipality_label',
'municipality_map_name_simple',
'municipality_map_name',
'cofog1_label_en',
'cofog1_name',
'cofog1_label',
'amount',
'subprogramme_name',
'subprogramme_label',
'time_name',
'time_year',
'time_month',
'time_day',
'time_week',
'time_yearmonth',
'time_quarter',
'time',
'action_name',
'action_label',
'subfunction_name',
'subfunction_label',
'programme_name',
'programme_label',
]);
},
{ timeout: 100000 }
);

View File

@ -0,0 +1,29 @@
import { MDXRemote } from 'next-mdx-remote';
import dynamic from 'next/dynamic';
import { Mermaid } from '@portaljs/core';
// Custom components/renderers to pass to MDX.
// Since the MDX files aren't loaded by webpack, they have no knowledge of how
// to handle import statements. Instead, you must include components in scope
// here.
const components = {
Table: dynamic(() => import('@portaljs/components').then((mod) => mod.Table)),
Catalog: dynamic(() =>
import('@portaljs/components').then((mod) => mod.Catalog)
),
mermaid: Mermaid,
Vega: dynamic(() => import('@portaljs/components').then((mod) => mod.Vega)),
VegaLite: dynamic(() =>
import('@portaljs/components').then((mod) => mod.VegaLite)
),
LineChart: dynamic(() =>
import('@portaljs/components').then((mod) => mod.LineChart)
),
FlatUiTable: dynamic(() =>
import('@portaljs/components').then((mod) => mod.FlatUiTable)
),
} as any;
export default function DRD({ source }: { source: any }) {
return <MDXRemote {...source} components={components} />;
}

View File

@ -45,12 +45,12 @@ export default function DatasetCard({ dataset }: { dataset: Project }) {
<dt className="text-gray-500">Fiscal Period</dt>
<dd className="text-gray-700">
{dataset.fiscalPeriod?.start &&
new Date(dataset.fiscalPeriod.start).getFullYear()}
new Date(dataset.fiscalPeriod.start).getUTCFullYear()}
{dataset.fiscalPeriod?.end &&
dataset.fiscalPeriod?.start !== dataset.fiscalPeriod?.end && (
<>
{' - '}
{new Date(dataset.fiscalPeriod.end).getFullYear()}
{new Date(dataset.fiscalPeriod.end).getUTCFullYear()}
</>
)}
</dd>

View File

@ -13,9 +13,13 @@ import { useState } from 'react';
export default function DatasetsSearch({
datasets,
availableCountries,
minPeriod,
maxPeriod,
}: {
datasets: Project[];
availableCountries;
minPeriod: string;
maxPeriod: string;
}) {
const itemsPerPage = 6;
const [page, setPage] = useState(1);
@ -49,20 +53,35 @@ export default function DatasetsSearch({
? dataset.countryCode === watch().country
: true
)
// TODO: Does that really makes sense?
// What if the fiscalPeriod is 2015-2017 and inputs are
// set to 2015-2016. It's going to be filtered out but
// it shouldn't.
.filter((dataset) =>
watch().minDate && watch().minDate !== ''
? dataset.fiscalPeriod?.start >= watch().minDate
: true
)
.filter((dataset) =>
watch().maxDate && watch().maxDate !== ''
? dataset.fiscalPeriod?.end <= watch().maxDate
: true
);
.filter((dataset) => {
const filterMinDate = watch().minDate;
const filterMaxDate = watch().maxDate;
const datasetMinDate = dataset.fiscalPeriod?.start;
const datasetMaxDate = dataset.fiscalPeriod?.end;
let datasetStartOverlaps = false;
if (datasetMinDate) {
datasetStartOverlaps =
datasetMinDate >= filterMinDate && datasetMinDate <= filterMaxDate;
}
let datasetEndOverlaps = false;
if (datasetMaxDate) {
datasetEndOverlaps =
datasetMaxDate >= filterMinDate && datasetMaxDate <= filterMaxDate;
}
if (filterMinDate && filterMaxDate) {
return datasetStartOverlaps || datasetEndOverlaps;
} else if (filterMinDate) {
return datasetMinDate >= filterMinDate;
} else if (filterMaxDate) {
return datasetMinDate <= filterMaxDate;
}
return true;
});
const paginatedDatasets = filteredDatasets.slice(
(page - 1) * itemsPerPage,
@ -111,22 +130,32 @@ export default function DatasetsSearch({
</select>
</div>
<div className="sm:basis-1/6">
<label className="text-sm text-gray-600 font-medium">Min. date</label>
<label className="text-sm text-gray-600 font-medium">
Fiscal Period Start
</label>
<div className="relative">
<input
aria-label="Min. date"
type="date"
type="text"
placeholder={minPeriod}
onFocus={(e) => (e.target.type = 'date')}
onBlur={(e) => (e.target.type = 'text')}
{...register('minDate', { onChange: () => setPage(1) })}
className="h-[3em] w-full rounded-lg bg-white py-2 pl-3 pr-10 text-left shadow-md focus:outline-none focus-visible:border-emerald-500 focus-visible:ring-2 focus-visible:ring-white focus-visible:ring-opacity-75 focus-visible:ring-offset-2 focus-visible:ring-offset-emerald-400 sm:text-sm"
/>
</div>
</div>
<div className="sm:basis-1/6">
<label className="text-sm text-gray-600 font-medium">Max. date</label>
<label className="text-sm text-gray-600 font-medium">
Fiscal Period End
</label>
<div className="relative">
<input
aria-label="Max. date"
type="date"
type="text"
placeholder={maxPeriod}
onFocus={(e) => (e.target.type = 'date')}
onBlur={(e) => (e.target.type = 'text')}
{...register('maxDate', { onChange: () => setPage(1) })}
className="h-[3em] w-full rounded-lg bg-white py-2 pl-3 pr-10 text-left shadow-md focus:outline-none focus-visible:border-emerald-500 focus-visible:ring-2 focus-visible:ring-white focus-visible:ring-opacity-75 focus-visible:ring-offset-2 focus-visible:ring-offset-emerald-400 sm:text-sm"
/>
@ -196,9 +225,9 @@ const CloseIcon = () => {
id="Vector"
d="M18 18L12 12M12 12L6 6M12 12L18 6M12 12L6 18"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
/>
</g>
</svg>

View File

@ -1,18 +1,16 @@
import {
QueryClient,
QueryClientProvider,
useQuery,
useQueryClient,
} from 'react-query';
import { QueryClient, QueryClientProvider, useQuery } from 'react-query';
import Papa from 'papaparse';
import { Grid } from '@githubocto/flat-ui';
const queryClient = new QueryClient();
export async function getCsv(url: string) {
export async function getCsv(url: string, corsProxy?: string, range?: string) {
if (corsProxy) {
url = corsProxy + url
}
const response = await fetch(url, {
headers: {
Range: 'bytes=0-5132288',
Range: range ? `bytes=0-${range}` : 'bytes=0-512000',
},
});
const data = await response.text();
@ -62,24 +60,45 @@ const Spinning = () => {
);
};
export const Table: React.FC<{ url: string }> = ({ url }) => {
export interface FlatUiTableProps {
url?: string;
data?: { [key: string]: number | string }[];
rawCsv?: string;
range?: string;
corsProxy?: string;
}
export const FlatUiTable: React.FC<FlatUiTableProps> = ({
url,
data,
rawCsv,
corsProxy,
range
}) => {
return (
// Provide the client to your App
<QueryClientProvider client={queryClient}>
<TableInner url={url} />
<TableInner range={range} corsProxy={corsProxy} url={url} data={data} rawCsv={rawCsv} />
</QueryClientProvider>
);
};
const TableInner: React.FC<{ url: string }> = ({ url }) => {
const TableInner: React.FC<FlatUiTableProps> = ({ url, data, rawCsv, corsProxy, range }) => {
if (data) {
return (
<div className="w-full" style={{height: '500px'}}>
<Grid data={data} />
</div>
);
}
const { data: csvString, isLoading: isDownloadingCSV } = useQuery(
['dataCsv', url],
() => getCsv(url)
() => getCsv(url as string, corsProxy, range),
{ enabled: !!url }
);
const { data: parsedData, isLoading: isParsing } = useQuery(
['dataPreview', csvString],
() => parseCsv(csvString),
{ enabled: !!csvString }
() => parseCsv(rawCsv ? rawCsv as string : csvString as string),
{ enabled: rawCsv ? true : !!csvString }
);
if (isParsing || isDownloadingCSV)
<div className="w-full">
@ -87,8 +106,10 @@ const TableInner: React.FC<{ url: string }> = ({ url }) => {
</div>;
if (parsedData)
return (
<div className="h-[500px] overflow-scroll">
<div className="w-full" style={{height: '500px'}}>
<Grid data={parsedData.data} />
</div>
);
return <Spinning />
};

View File

@ -5,6 +5,9 @@ import Link from 'next/link';
import { useRouter } from 'next/router';
import { Bars3Icon } from '@heroicons/react/24/outline';
import { useState } from 'react';
import { Fragment } from 'react';
import { Menu, Transition } from '@headlessui/react';
import { ChevronDownIcon } from '@heroicons/react/20/solid';
export function Header() {
const [menuOpen, setMenuOpen] = useState<boolean>(false);
@ -16,42 +19,85 @@ export function Header() {
};
const navLinks = [
{
title: 'Home',
href: '/',
},
{
title: 'Datasets',
href: '/#datasets',
},
// {
// title: "Community",
// href: "https://community.openspending.org/"
// }
{
title: 'Data Stories',
href: '/stories',
},
{
title: 'Blog',
href: '/blog',
},
{
title: 'About',
href: '/about',
children: [
{
title: 'Fiscal Data Package',
href: '/about/fiscaldatapackage/',
},
{
title: 'Tools',
href: '/about/tools/',
},
{
title: 'Funders',
href: '/about/funders/',
},
{
title: 'Presentations',
href: '/about/presentations/',
},
],
},
{
title: 'Contributing',
href: '/contributing',
},
{
title: 'Help',
href: '/help',
},
{
title: 'Resources',
href: '/resources',
children: [
{
title: 'Follow the money',
href: '/resources/journo',
},
{
title: 'Map of Spending Projects',
href: '/resources/map-of-spending-projects/',
},
{
title: 'Working Group On Open Spending Data',
href: '/resources/wg/',
},
{
title: 'UK Departamental Spending',
href: '/resources/gb-spending',
},
],
},
];
return (
<header className="relative z-50 pb-11 lg:pt-11">
<Container className="flex flex-wrap items-center justify-between lg:flex-nowrap mt-10 lg:mt-0">
<Container className="flex flex-wrap justify-between lg:flex-nowrap mt-10 lg:mt-0">
<Link href="/" className="lg:mt-0 lg:grow lg:basis-0 flex items-center">
<Image src={logo} alt="OpenSpending" className="h-12 w-auto" />
</Link>
<ul className="hidden list-none sm:flex gap-x-5 text-base font-medium">
{navLinks.map((link, i) => (
<li key={`nav-link-${i}`}>
<Link
className={`text-emerald-900 hover:text-emerald-600 ${
isActive(link) ? 'text-emerald-600' : ''
}`}
href={link.href}
scroll={false}
>
{link.title}
</Link>
<Dropdown navItem={link} />
</li>
))}
</ul>
<div className="hidden xl:block xl:grow"></div>
<div className="sm:hidden sm:mt-10 lg:mt-0 lg:grow lg:basis-0 lg:justify-end">
<button onClick={() => setMenuOpen(!menuOpen)}>
<Bars3Icon className="w-8 h-8" />
@ -80,3 +126,77 @@ export function Header() {
</header>
);
}
function classNames(...classes) {
return classes.filter(Boolean).join(' ');
}
function Dropdown({ navItem }: { navItem: any }) {
const [showDropDown, setShowDropDown] = useState(false);
return (
<Menu as="div" className="relative inline-block text-left">
{({ open }) => (
<>
<div>
<Menu.Button
onMouseEnter={() => setShowDropDown(true)}
onMouseLeave={() => setShowDropDown(false)}
className="text-emerald-900 hover:text-emerald-600 inline-flex w-full justify-center gap-x-1.5 px-3 py-2 text-sm font-semibold"
>
<Link href={navItem.href}>{navItem.title}</Link>
{navItem.children && (
<ChevronDownIcon
className="-mr-1 h-5 w-5 text-gray-400"
aria-hidden="true"
/>
)}
</Menu.Button>
</div>
{navItem.children && (
<Transition
as={Fragment}
show={showDropDown}
enter="transition ease-out duration-100"
enterFrom="transform opacity-0 scale-95"
enterTo="transform opacity-100 scale-100"
leave="transition ease-in duration-75"
leaveFrom="transform opacity-100 scale-100"
leaveTo="transform opacity-0 scale-95"
>
<div>
<Menu.Items
static
onMouseEnter={() => setShowDropDown(true)}
onMouseLeave={() => setShowDropDown(false)}
className="absolute right-0 z-10 w-56 origin-top-right rounded-md bg-white shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none"
>
<div className="py-1">
{navItem.children.map((item) => (
<Menu.Item key={item.href}>
{({ active }) => (
<a
key={item.href}
href={item.href}
className={classNames(
active
? 'bg-gray-100 text-emerald-900 hover:text-emerald-600'
: 'text-gray-700',
'block px-4 py-2 text-sm'
)}
>
{item.title}
</a>
)}
</Menu.Item>
))}
</div>
</Menu.Items>
</div>
</Transition>
)}
</>
)}
</Menu>
);
}

View File

@ -27,7 +27,7 @@ export function Hero({ countriesCount, datasetsCount, filesCount }) {
<Button href="#datasets" className="mt-10">
Search datasets
</Button>
<dl className="mt-10 grid grid-cols-2 gap-x-10 gap-y-6 sm:mt-16 sm:gap-x-16 sm:gap-y-10 sm:text-center lg:auto-cols-auto lg:grid-flow-col lg:grid-cols-none lg:justify-start lg:text-left">
<dl className="mt-10 grid grid-cols-1 sm:grid-cols-3 gap-x-10 gap-y-6 sm:mt-16 sm:gap-x-16 sm:gap-y-10 sm:text-center lg:auto-cols-auto lg:grid-flow-col lg:grid-cols-none lg:justify-start lg:text-left">
{[
// Added the plus sign because some datasets do not
// contain defined countries
@ -36,10 +36,18 @@ export function Hero({ countriesCount, datasetsCount, filesCount }) {
['Files', filesCount],
].map(([name, value]) => (
<div key={name}>
<dt className="font-mono text-sm text-emerald-600">{name}</dt>
<dd className="mt-0.5 text-2xl font-semibold tracking-tight text-emerald-900">
{value}
</dd>
<div className='flex gap-x-2 items-center sm:hidden' key={name}>
<dd className="mt-0.5 text-2xl font-semibold tracking-tight text-emerald-900">
{value}
</dd>
<dt className="font-mono text-sm text-emerald-600">{name}</dt>
</div>
<div className='hidden sm:block' key={name}>
<dt className="font-mono text-sm text-emerald-600">{name}</dt>
<dd className="mt-0.5 text-2xl font-semibold tracking-tight text-emerald-900">
{value}
</dd>
</div>
</div>
))}
</dl>

Some files were not shown because too many files have changed in this diff Show More