Compare commits
8 Commits
main
...
905-change
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3366016c43 | ||
|
|
0e3d6ee262 | ||
|
|
b6539eac2a | ||
|
|
2bfc1f7e18 | ||
|
|
20fd1b3b97 | ||
|
|
013b9072c9 | ||
|
|
1da0c3823d | ||
|
|
03fd120bcd |
1
.gitignore
vendored
1
.gitignore
vendored
@ -4,7 +4,6 @@
|
|||||||
dist
|
dist
|
||||||
tmp
|
tmp
|
||||||
/out-tsc
|
/out-tsc
|
||||||
**/*.tgz
|
|
||||||
|
|
||||||
# dependencies
|
# dependencies
|
||||||
node_modules
|
node_modules
|
||||||
|
|||||||
8
.vscode/extensions.json
vendored
Normal file
8
.vscode/extensions.json
vendored
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"recommendations": [
|
||||||
|
"nrwl.angular-console",
|
||||||
|
"esbenp.prettier-vscode",
|
||||||
|
"firsttris.vscode-jest-runner",
|
||||||
|
"dbaeumer.vscode-eslint"
|
||||||
|
]
|
||||||
|
}
|
||||||
@ -4,7 +4,7 @@ title: Developer docs for contributors
|
|||||||
|
|
||||||
## Our repository
|
## Our repository
|
||||||
|
|
||||||
https://github.com/datopian/datahub
|
https://github.com/datopian/portaljs
|
||||||
|
|
||||||
Structure:
|
Structure:
|
||||||
|
|
||||||
@ -17,7 +17,7 @@ Structure:
|
|||||||
|
|
||||||
## How to contribute
|
## How to contribute
|
||||||
|
|
||||||
You can start by checking our [issues board](https://github.com/datopian/datahub/issues).
|
You can start by checking our [issues board](https://github.com/datopian/portaljs/issues).
|
||||||
|
|
||||||
If you'd like to work on one of the issues you can:
|
If you'd like to work on one of the issues you can:
|
||||||
|
|
||||||
@ -35,7 +35,7 @@ If you'd like to work on one of the issues you can:
|
|||||||
If you have an idea for improvement, and it doesn't have a corresponding issue yet, simply submit a new one.
|
If you have an idea for improvement, and it doesn't have a corresponding issue yet, simply submit a new one.
|
||||||
|
|
||||||
> [!note]
|
> [!note]
|
||||||
> Join our [Discord channel](https://discord.gg/KZSf3FG4EZ) do discuss existing issues and to ask for help.
|
> Join our [Discord channel](https://discord.gg/rTxfCutu) do discuss existing issues and to ask for help.
|
||||||
|
|
||||||
## Nx
|
## Nx
|
||||||
|
|
||||||
|
|||||||
76
README.md
76
README.md
@ -1,51 +1,31 @@
|
|||||||
<p align="center">
|
<h1 align="center">
|
||||||
Bugs, issues and suggestions re PortalJS framework
|
🌀 Portal.JS
|
||||||
<br />
|
<br />
|
||||||
<br /><a href="https://discord.gg/xfFDMPU9dC"><img src="https://dcbadge.vercel.app/api/server/xfFDMPU9dC" /></a>
|
Rapidly build rich data portals using a modern frontend framework
|
||||||
</p>
|
</h1>
|
||||||
|
|
||||||
## PortalJS framework
|
* [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?)
|
||||||
|
|
||||||
This repo and issue tracker are for
|
# What is Portal.JS
|
||||||
|
|
||||||
- PortalJS 🌀 - https://www.portaljs.com/
|
🌀 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.
|
||||||
- DataHub Cloud ☁️ - https://datahub.io/
|
|
||||||
|
|
||||||
### Issues
|
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/).
|
||||||
|
|
||||||
Found a bug: 👉 https://github.com/datopian/portaljs/issues/new
|
## Features
|
||||||
|
|
||||||
### 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.
|
- 🗺️ 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).
|
- 👩💻 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.
|
- 🔋 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.
|
- 🎨 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
|
- 🧱 Extensible: quickly extend and develop/import your own React components
|
||||||
- 📝 Well documented: full set of documentation plus the documentation of Next.js.
|
- 📝 Well documented: full set of documentation plus the documentation of Next.js and Apollo.
|
||||||
|
|
||||||
### For developers
|
### For developers
|
||||||
|
|
||||||
@ -53,3 +33,25 @@ PortalJS Cloud is built in JavaScript and React on top of the popular [Next.js](
|
|||||||
- 🚀 Next.js framework: so everything in Next.js for free: Server Side Rendering, Static Site Generation, huge number of examples and integrations, etc.
|
- 🚀 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.
|
- 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)
|
- 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).
|
||||||
|
|||||||
@ -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)**
|
**🚩 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.com/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.org/blog/example-ckan-2021)
|
||||||
|
|
||||||
## Developers
|
## Developers
|
||||||
|
|
||||||
|
|||||||
@ -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.
|
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/datahub/tree/main/examples/ckan-ssg
|
npx create-next-app <app-name> --example https://github.com/datopian/portaljs/tree/main/examples/ckan-example
|
||||||
cd <app-name>
|
cd <app-name>
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -19,7 +19,7 @@ npm run dev
|
|||||||
|
|
||||||
Congratulations, you now have something similar to this running on `http://localhost:4200`
|
Congratulations, you now have something similar to this running on `http://localhost:4200`
|
||||||

|

|
||||||
If you go to any one of those pages by clicking on `More info` you will see something similar to this
|
If yo go to any one of those pages by clicking on `More info` you will see something similar to this
|
||||||

|

|
||||||
|
|
||||||
## Deployment
|
## Deployment
|
||||||
|
|||||||
160
examples/ckan-ssg/package-lock.json
generated
160
examples/ckan-ssg/package-lock.json
generated
@ -10,7 +10,6 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@heroicons/react": "^2.0.17",
|
"@heroicons/react": "^2.0.17",
|
||||||
"@portaljs/ckan": "^0.0.2",
|
"@portaljs/ckan": "^0.0.2",
|
||||||
"@portaljs/remark-wiki-link": "^1.0.4",
|
|
||||||
"next": "13.3.1",
|
"next": "13.3.1",
|
||||||
"next-seo": "^6.0.0",
|
"next-seo": "^6.0.0",
|
||||||
"octokit": "^2.0.14",
|
"octokit": "^2.0.14",
|
||||||
@ -36,6 +35,7 @@
|
|||||||
"version": "7.21.0",
|
"version": "7.21.0",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.21.0.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.21.0.tgz",
|
||||||
"integrity": "sha512-xwII0//EObnq89Ji5AKYQaRYiW/nZ3llSv29d49IuxPhKbtJoLP+9QUUZ4nVragQVtaVGeZrpB+ZtG/Pdy/POw==",
|
"integrity": "sha512-xwII0//EObnq89Ji5AKYQaRYiW/nZ3llSv29d49IuxPhKbtJoLP+9QUUZ4nVragQVtaVGeZrpB+ZtG/Pdy/POw==",
|
||||||
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"regenerator-runtime": "^0.13.11"
|
"regenerator-runtime": "^0.13.11"
|
||||||
},
|
},
|
||||||
@ -732,16 +732,6 @@
|
|||||||
"react-dom": "^18.2.0"
|
"react-dom": "^18.2.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@portaljs/remark-wiki-link": {
|
|
||||||
"version": "1.0.4",
|
|
||||||
"resolved": "https://registry.npmjs.org/@portaljs/remark-wiki-link/-/remark-wiki-link-1.0.4.tgz",
|
|
||||||
"integrity": "sha512-cp6vlssDAPawcBI0vUPRpcPdORql3RbK1Q+t1LuRvMQ+yiRb+9DnSPBUviDXKqwsBMOOXP/ePAdYohaeXGt0lQ==",
|
|
||||||
"dependencies": {
|
|
||||||
"mdast-util-to-markdown": "^1.5.0",
|
|
||||||
"mdast-util-wiki-link": "^0.0.2",
|
|
||||||
"micromark-util-symbol": "^1.0.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@rushstack/eslint-patch": {
|
"node_modules/@rushstack/eslint-patch": {
|
||||||
"version": "1.2.0",
|
"version": "1.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.2.0.tgz",
|
||||||
@ -1430,24 +1420,6 @@
|
|||||||
"url": "https://github.com/sponsors/wooorm"
|
"url": "https://github.com/sponsors/wooorm"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/character-entities-legacy": {
|
|
||||||
"version": "1.1.4",
|
|
||||||
"resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-1.1.4.tgz",
|
|
||||||
"integrity": "sha512-3Xnr+7ZFS1uxeiUDvV02wQ+QDbc55o97tIV5zHScSPJpcLm/r0DFPcoY3tYRp+VZukxuMeKgXYmsXQHO05zQeA==",
|
|
||||||
"funding": {
|
|
||||||
"type": "github",
|
|
||||||
"url": "https://github.com/sponsors/wooorm"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/character-reference-invalid": {
|
|
||||||
"version": "1.1.4",
|
|
||||||
"resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-1.1.4.tgz",
|
|
||||||
"integrity": "sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg==",
|
|
||||||
"funding": {
|
|
||||||
"type": "github",
|
|
||||||
"url": "https://github.com/sponsors/wooorm"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/chokidar": {
|
"node_modules/chokidar": {
|
||||||
"version": "3.5.3",
|
"version": "3.5.3",
|
||||||
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz",
|
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz",
|
||||||
@ -2916,28 +2888,6 @@
|
|||||||
"node": ">= 0.4"
|
"node": ">= 0.4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/is-alphabetical": {
|
|
||||||
"version": "1.0.4",
|
|
||||||
"resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-1.0.4.tgz",
|
|
||||||
"integrity": "sha512-DwzsA04LQ10FHTZuL0/grVDk4rFoVH1pjAToYwBrHSxcrBIGQuXrQMtD5U1b0U2XVgKZCTLLP8u2Qxqhy3l2Vg==",
|
|
||||||
"funding": {
|
|
||||||
"type": "github",
|
|
||||||
"url": "https://github.com/sponsors/wooorm"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/is-alphanumerical": {
|
|
||||||
"version": "1.0.4",
|
|
||||||
"resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-1.0.4.tgz",
|
|
||||||
"integrity": "sha512-UzoZUr+XfVz3t3v4KyGEniVL9BDRoQtY7tOyrRybkVNjDFWyo1yhXNGrrBTQxp3ib9BLAWs7k2YKBQsFRkZG9A==",
|
|
||||||
"dependencies": {
|
|
||||||
"is-alphabetical": "^1.0.0",
|
|
||||||
"is-decimal": "^1.0.0"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"type": "github",
|
|
||||||
"url": "https://github.com/sponsors/wooorm"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/is-arguments": {
|
"node_modules/is-arguments": {
|
||||||
"version": "1.1.1",
|
"version": "1.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz",
|
||||||
@ -3069,15 +3019,6 @@
|
|||||||
"url": "https://github.com/sponsors/ljharb"
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/is-decimal": {
|
|
||||||
"version": "1.0.4",
|
|
||||||
"resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-1.0.4.tgz",
|
|
||||||
"integrity": "sha512-RGdriMmQQvZ2aqaQq3awNA6dCGtKpiDFcOzrTWrDAT2MiWrKQVPmxLGHl7Y2nNu6led0kEyoX0enY0qXYsv9zw==",
|
|
||||||
"funding": {
|
|
||||||
"type": "github",
|
|
||||||
"url": "https://github.com/sponsors/wooorm"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/is-docker": {
|
"node_modules/is-docker": {
|
||||||
"version": "2.2.1",
|
"version": "2.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz",
|
||||||
@ -3114,15 +3055,6 @@
|
|||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/is-hexadecimal": {
|
|
||||||
"version": "1.0.4",
|
|
||||||
"resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-1.0.4.tgz",
|
|
||||||
"integrity": "sha512-gyPJuv83bHMpocVYoqof5VDiZveEoGoFL8m3BXNb2VW8Xs+rz9kqO8LOQ5DH6EsuvilT1ApazU0pyl+ytbPtlw==",
|
|
||||||
"funding": {
|
|
||||||
"type": "github",
|
|
||||||
"url": "https://github.com/sponsors/wooorm"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/is-map": {
|
"node_modules/is-map": {
|
||||||
"version": "2.0.2",
|
"version": "2.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.2.tgz",
|
||||||
@ -3795,59 +3727,6 @@
|
|||||||
"url": "https://opencollective.com/unified"
|
"url": "https://opencollective.com/unified"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/mdast-util-wiki-link": {
|
|
||||||
"version": "0.0.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/mdast-util-wiki-link/-/mdast-util-wiki-link-0.0.2.tgz",
|
|
||||||
"integrity": "sha512-lSsR10/dPuYIxzjGZIGA4oYzsnEnqcsD6DTXL0pqdbBzNB9teKVZB2aIzZcUsdg31v/NoHOstkVwzbN6VrQLtw==",
|
|
||||||
"dependencies": {
|
|
||||||
"@babel/runtime": "^7.12.1",
|
|
||||||
"mdast-util-to-markdown": "^0.6.5"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/mdast-util-wiki-link/node_modules/longest-streak": {
|
|
||||||
"version": "2.0.4",
|
|
||||||
"resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-2.0.4.tgz",
|
|
||||||
"integrity": "sha512-vM6rUVCVUJJt33bnmHiZEvr7wPT78ztX7rojL+LW51bHtLh6HTjx84LA5W4+oa6aKEJA7jJu5LR6vQRBpA5DVg==",
|
|
||||||
"funding": {
|
|
||||||
"type": "github",
|
|
||||||
"url": "https://github.com/sponsors/wooorm"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/mdast-util-wiki-link/node_modules/mdast-util-to-markdown": {
|
|
||||||
"version": "0.6.5",
|
|
||||||
"resolved": "https://registry.npmjs.org/mdast-util-to-markdown/-/mdast-util-to-markdown-0.6.5.tgz",
|
|
||||||
"integrity": "sha512-XeV9sDE7ZlOQvs45C9UKMtfTcctcaj/pGwH8YLbMHoMOXNNCn2LsqVQOqrF1+/NU8lKDAqozme9SCXWyo9oAcQ==",
|
|
||||||
"dependencies": {
|
|
||||||
"@types/unist": "^2.0.0",
|
|
||||||
"longest-streak": "^2.0.0",
|
|
||||||
"mdast-util-to-string": "^2.0.0",
|
|
||||||
"parse-entities": "^2.0.0",
|
|
||||||
"repeat-string": "^1.0.0",
|
|
||||||
"zwitch": "^1.0.0"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"type": "opencollective",
|
|
||||||
"url": "https://opencollective.com/unified"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/mdast-util-wiki-link/node_modules/mdast-util-to-string": {
|
|
||||||
"version": "2.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-2.0.0.tgz",
|
|
||||||
"integrity": "sha512-AW4DRS3QbBayY/jJmD8437V1Gombjf8RSOUCMFBuo5iHi58AGEgVCKQ+ezHkZZDpAQS75hcBMpLqjpJTjtUL7w==",
|
|
||||||
"funding": {
|
|
||||||
"type": "opencollective",
|
|
||||||
"url": "https://opencollective.com/unified"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/mdast-util-wiki-link/node_modules/zwitch": {
|
|
||||||
"version": "1.0.5",
|
|
||||||
"resolved": "https://registry.npmjs.org/zwitch/-/zwitch-1.0.5.tgz",
|
|
||||||
"integrity": "sha512-V50KMwwzqJV0NpZIZFwfOD5/lyny3WlSzRiXgA0G7VUnRlqttta1L6UQIHzd6EuBY/cHGfwTIck7w1yH6Q5zUw==",
|
|
||||||
"funding": {
|
|
||||||
"type": "github",
|
|
||||||
"url": "https://github.com/sponsors/wooorm"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/merge2": {
|
"node_modules/merge2": {
|
||||||
"version": "1.4.1",
|
"version": "1.4.1",
|
||||||
"resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
|
"resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
|
||||||
@ -4835,32 +4714,6 @@
|
|||||||
"node": ">=6"
|
"node": ">=6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/parse-entities": {
|
|
||||||
"version": "2.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-2.0.0.tgz",
|
|
||||||
"integrity": "sha512-kkywGpCcRYhqQIchaWqZ875wzpS/bMKhz5HnN3p7wveJTkTtyAB/AlnS0f8DFSqYW1T82t6yEAkEcB+A1I3MbQ==",
|
|
||||||
"dependencies": {
|
|
||||||
"character-entities": "^1.0.0",
|
|
||||||
"character-entities-legacy": "^1.0.0",
|
|
||||||
"character-reference-invalid": "^1.0.0",
|
|
||||||
"is-alphanumerical": "^1.0.0",
|
|
||||||
"is-decimal": "^1.0.0",
|
|
||||||
"is-hexadecimal": "^1.0.0"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"type": "github",
|
|
||||||
"url": "https://github.com/sponsors/wooorm"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/parse-entities/node_modules/character-entities": {
|
|
||||||
"version": "1.2.4",
|
|
||||||
"resolved": "https://registry.npmjs.org/character-entities/-/character-entities-1.2.4.tgz",
|
|
||||||
"integrity": "sha512-iBMyeEHxfVnIakwOuDXpVkc54HijNgCyQB2w0VfGQThle6NXn50zU6V/u+LDhxHcDUPojn6Kpga3PTAD8W1bQw==",
|
|
||||||
"funding": {
|
|
||||||
"type": "github",
|
|
||||||
"url": "https://github.com/sponsors/wooorm"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/path-exists": {
|
"node_modules/path-exists": {
|
||||||
"version": "4.0.0",
|
"version": "4.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
|
||||||
@ -5230,7 +5083,8 @@
|
|||||||
"node_modules/regenerator-runtime": {
|
"node_modules/regenerator-runtime": {
|
||||||
"version": "0.13.11",
|
"version": "0.13.11",
|
||||||
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz",
|
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz",
|
||||||
"integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg=="
|
"integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==",
|
||||||
|
"dev": true
|
||||||
},
|
},
|
||||||
"node_modules/regexp.prototype.flags": {
|
"node_modules/regexp.prototype.flags": {
|
||||||
"version": "1.5.0",
|
"version": "1.5.0",
|
||||||
@ -5293,14 +5147,6 @@
|
|||||||
"url": "https://opencollective.com/unified"
|
"url": "https://opencollective.com/unified"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/repeat-string": {
|
|
||||||
"version": "1.6.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz",
|
|
||||||
"integrity": "sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w==",
|
|
||||||
"engines": {
|
|
||||||
"node": ">=0.10"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/resolve": {
|
"node_modules/resolve": {
|
||||||
"version": "1.22.2",
|
"version": "1.22.2",
|
||||||
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.2.tgz",
|
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.2.tgz",
|
||||||
|
|||||||
@ -11,7 +11,6 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@heroicons/react": "^2.0.17",
|
"@heroicons/react": "^2.0.17",
|
||||||
"@portaljs/ckan": "^0.0.2",
|
"@portaljs/ckan": "^0.0.2",
|
||||||
"@portaljs/remark-wiki-link": "^1.0.4",
|
|
||||||
"next": "13.3.1",
|
"next": "13.3.1",
|
||||||
"next-seo": "^6.0.0",
|
"next-seo": "^6.0.0",
|
||||||
"octokit": "^2.0.14",
|
"octokit": "^2.0.14",
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
import { MDXRemote } from 'next-mdx-remote';
|
import { MDXRemote } from 'next-mdx-remote';
|
||||||
import dynamic from 'next/dynamic';
|
import dynamic from 'next/dynamic';
|
||||||
import { Mermaid } from '@portaljs/core';
|
import { Mermaid } from '@flowershow/core';
|
||||||
|
|
||||||
// Custom components/renderers to pass to MDX.
|
// Custom components/renderers to pass to MDX.
|
||||||
// Since the MDX files aren't loaded by webpack, they have no knowledge of how
|
// Since the MDX files aren't loaded by webpack, they have no knowledge of how
|
||||||
|
|||||||
@ -1,13 +1,13 @@
|
|||||||
import matter from "gray-matter";
|
import matter from "gray-matter";
|
||||||
import mdxmermaid from "mdx-mermaid";
|
import mdxmermaid from "mdx-mermaid";
|
||||||
import { h } from "hastscript";
|
import { h } from "hastscript";
|
||||||
import remarkCallouts from "@portaljs/remark-callouts";
|
import remarkCallouts from "@flowershow/remark-callouts";
|
||||||
import remarkEmbed from "@portaljs/remark-embed";
|
import remarkEmbed from "@flowershow/remark-embed";
|
||||||
import remarkGfm from "remark-gfm";
|
import remarkGfm from "remark-gfm";
|
||||||
import remarkMath from "remark-math";
|
import remarkMath from "remark-math";
|
||||||
import remarkSmartypants from "remark-smartypants";
|
import remarkSmartypants from "remark-smartypants";
|
||||||
import remarkToc from "remark-toc";
|
import remarkToc from "remark-toc";
|
||||||
import remarkWikiLink from "@portaljs/remark-wiki-link";
|
import remarkWikiLink from "@flowershow/remark-wiki-link";
|
||||||
import rehypeAutolinkHeadings from "rehype-autolink-headings";
|
import rehypeAutolinkHeadings from "rehype-autolink-headings";
|
||||||
import rehypeKatex from "rehype-katex";
|
import rehypeKatex from "rehype-katex";
|
||||||
import rehypeSlug from "rehype-slug";
|
import rehypeSlug from "rehype-slug";
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import { MarkdownDB } from "mddb";
|
import { MarkdownDB } from "@flowershow/markdowndb";
|
||||||
|
|
||||||
const dbPath = "markdown.db";
|
const dbPath = "markdown.db";
|
||||||
|
|
||||||
|
|||||||
1099
examples/ckan/package-lock.json
generated
1099
examples/ckan/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -11,14 +11,14 @@
|
|||||||
"mddb": "mddb ./content"
|
"mddb": "mddb ./content"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@flowershow/core": "^0.4.13",
|
||||||
|
"@flowershow/markdowndb": "^0.1.5",
|
||||||
|
"@flowershow/remark-callouts": "^1.0.0",
|
||||||
|
"@flowershow/remark-embed": "^1.0.0",
|
||||||
"@githubocto/flat-ui": "^0.14.1",
|
"@githubocto/flat-ui": "^0.14.1",
|
||||||
"@heroicons/react": "^2.0.18",
|
"@heroicons/react": "^2.0.18",
|
||||||
"@portaljs/ckan": "^0.0.2",
|
"@portaljs/ckan": "^0.0.2",
|
||||||
"@portaljs/components": "0.1.6",
|
"@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",
|
"@tailwindcss/typography": "^0.5.9",
|
||||||
"@types/node": "20.2.3",
|
"@types/node": "20.2.3",
|
||||||
"@types/react": "18.2.6",
|
"@types/react": "18.2.6",
|
||||||
@ -27,7 +27,6 @@
|
|||||||
"eslint": "8.41.0",
|
"eslint": "8.41.0",
|
||||||
"eslint-config-next": "13.4.3",
|
"eslint-config-next": "13.4.3",
|
||||||
"isomorphic-unfetch": "^4.0.2",
|
"isomorphic-unfetch": "^4.0.2",
|
||||||
"mddb": "^0.1.9",
|
|
||||||
"next": "13.4.3",
|
"next": "13.4.3",
|
||||||
"next-mdx-remote": "^4.4.1",
|
"next-mdx-remote": "^4.4.1",
|
||||||
"papaparse": "^5.4.1",
|
"papaparse": "^5.4.1",
|
||||||
|
|||||||
@ -40,25 +40,16 @@ export default function Home({
|
|||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<main className="flex min-h-screen flex-col items-center p-24 bg-zinc-900">
|
||||||
<main className="py-12 bg-zinc-900">
|
<DatasetSearchForm
|
||||||
<DatasetSearchForm
|
options={options}
|
||||||
options={options}
|
setOptions={setOptions}
|
||||||
setOptions={setOptions}
|
groups={groups}
|
||||||
groups={groups}
|
orgs={orgs}
|
||||||
orgs={orgs}
|
/>
|
||||||
/>
|
<div className="bg-white p-8 my-4 rounded-lg">
|
||||||
<div
|
<ListOfDatasets options={options} setOptions={setOptions} ckan={ckan} />{' '}
|
||||||
className="bg-white p-8 mx-auto my-4 rounded-lg"
|
</div>
|
||||||
style={{ width: 'min(1100px, 95vw)' }}
|
</main>
|
||||||
>
|
|
||||||
<ListOfDatasets
|
|
||||||
options={options}
|
|
||||||
setOptions={setOptions}
|
|
||||||
ckan={ckan}
|
|
||||||
/>{' '}
|
|
||||||
</div>
|
|
||||||
</main>
|
|
||||||
</div>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
@tailwind components;
|
@tailwind components;
|
||||||
@tailwind utilities;
|
@tailwind utilities;
|
||||||
|
|
||||||
@import "@portaljs/remark-callouts/styles.css";
|
@import "@flowershow/remark-callouts/styles.css";
|
||||||
|
|
||||||
/* mathjax */
|
/* mathjax */
|
||||||
.math-inline > mjx-container > svg {
|
.math-inline > mjx-container > svg {
|
||||||
|
|||||||
@ -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`.
|
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://specs.frictionlessdata.io/data-package/
|
[fd]: https://frictionlessdata.io/data-packages/
|
||||||
|
|
||||||
## How to use
|
## How to use
|
||||||
|
|
||||||
|
|||||||
@ -1,9 +1,3 @@
|
|||||||
# 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.
|
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:
|
You might be asking why we did that, there are three main reasons:
|
||||||
|
|||||||
@ -1,99 +0,0 @@
|
|||||||
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}
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@ -1,4 +1,33 @@
|
|||||||
[
|
[
|
||||||
|
{
|
||||||
|
"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",
|
"url": "https://github.com/fivethirtyeight/data/tree/master/congress-generic-ballot",
|
||||||
"name": "congress-generic-ballot",
|
"name": "congress-generic-ballot",
|
||||||
@ -166,35 +195,6 @@
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"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",
|
"url": "https://github.com/fivethirtyeight/data/tree/master/nfl-elo",
|
||||||
"name": "nfl-elo",
|
"name": "nfl-elo",
|
||||||
@ -1169,6 +1169,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/chess-transfers",
|
"url": "https://github.com/fivethirtyeight/data/tree/master/chess-transfers",
|
||||||
"name": "chess-transfers",
|
"name": "chess-transfers",
|
||||||
@ -2127,18 +2139,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/march-madness-predictions",
|
"url": "https://github.com/fivethirtyeight/data/tree/master/march-madness-predictions",
|
||||||
"name": "march-madness-predictions",
|
"name": "march-madness-predictions",
|
||||||
|
|||||||
6984
examples/fivethirtyeight/package-lock.json
generated
6984
examples/fivethirtyeight/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -9,11 +9,7 @@
|
|||||||
"lint": "next lint"
|
"lint": "next lint"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@headlessui/react": "^1.7.14",
|
"@portaljs/components": "^0.1.0",
|
||||||
"@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",
|
"@tailwindcss/typography": "^0.5.9",
|
||||||
"@types/node": "20.1.1",
|
"@types/node": "20.1.1",
|
||||||
"@types/react": "18.2.6",
|
"@types/react": "18.2.6",
|
||||||
@ -30,15 +26,12 @@
|
|||||||
"react": "18.2.0",
|
"react": "18.2.0",
|
||||||
"react-dom": "18.2.0",
|
"react-dom": "18.2.0",
|
||||||
"react-markdown": "^8.0.7",
|
"react-markdown": "^8.0.7",
|
||||||
"remark": "^14.0.3",
|
|
||||||
"remark-code-frontmatter": "^1.0.0",
|
"remark-code-frontmatter": "^1.0.0",
|
||||||
"remark-excerpt": "^1.0.0-beta.1",
|
|
||||||
"remark-extract-frontmatter": "^3.2.0",
|
"remark-extract-frontmatter": "^3.2.0",
|
||||||
"remark-frontmatter": "^4.0.1",
|
"remark-frontmatter": "^4.0.1",
|
||||||
"remark-gfm": "^3.0.1",
|
"remark-gfm": "^3.0.1",
|
||||||
"tailwindcss": "3.3.2",
|
"tailwindcss": "3.3.2",
|
||||||
"timeago.js": "^4.0.2",
|
"timeago.js": "^4.0.2",
|
||||||
"to-vfile": "^7.2.4",
|
|
||||||
"typescript": "5.0.4"
|
"typescript": "5.0.4"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,49 +1,8 @@
|
|||||||
import '@/styles/globals.css';
|
import '@/styles/globals.css'
|
||||||
import '@portaljs/components/styles.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) {
|
export default function App({ Component, pageProps }: AppProps) {
|
||||||
const router = useRouter();
|
return <Component {...pageProps} />
|
||||||
|
|
||||||
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} />
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -19,9 +19,78 @@ export default function Document() {
|
|||||||
/>
|
/>
|
||||||
</Head>
|
</Head>
|
||||||
<body>
|
<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 />
|
<Main />
|
||||||
|
<NextScript />
|
||||||
</body>
|
</body>
|
||||||
<NextScript />
|
|
||||||
</Html>
|
</Html>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,19 +7,10 @@ import remarkGfm from 'remark-gfm';
|
|||||||
import extract from 'remark-extract-frontmatter';
|
import extract from 'remark-extract-frontmatter';
|
||||||
import { Dataset } from '..';
|
import { Dataset } from '..';
|
||||||
import { GetStaticProps } from 'next';
|
import { GetStaticProps } from 'next';
|
||||||
import { FlatUiTable } from '@portaljs/components';
|
import { Table } from '@portaljs/components';
|
||||||
import Breadcrumbs from '@/components/Breadcrumbs';
|
import Breadcrumbs from '@/components/Breadcrumbs';
|
||||||
import { ReactMarkdown } from 'react-markdown/lib/react-markdown';
|
import { ReactMarkdown } from 'react-markdown/lib/react-markdown';
|
||||||
import remarkFrontmatter from 'remark-frontmatter';
|
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({
|
export default function DatasetPage({
|
||||||
dataset,
|
dataset,
|
||||||
@ -31,146 +22,68 @@ export default function DatasetPage({
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<NextSeo title={`${dataset.name} page`} />
|
<NextSeo title={`${dataset.name} page`} />
|
||||||
<Layout>
|
<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">
|
||||||
<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: '' }]} />
|
||||||
<Breadcrumbs links={[{ title: dataset.name, href: '' }]} />
|
<h1 className="uppercase mb-0 mt-16">{dataset.name}</h1>
|
||||||
<h1 className="uppercase mb-0 mt-16">{dataset.name}</h1>
|
<p className="mb-8">
|
||||||
<table className="w-full my-10 mb-8 hidden md:table">
|
<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">
|
||||||
<thead className="border-b-4 pb-2 border-zinc-900">
|
<thead className="border-b-4 pb-2 border-zinc-900">
|
||||||
<tr>
|
<tr>
|
||||||
<th className="uppercase text-left font-normal text-xs pb-3">
|
<th
|
||||||
related content
|
className="uppercase text-left font-light text-xs pb-3"
|
||||||
</th>
|
scope="col"
|
||||||
<th className="uppercase text-left font-normal text-xs pb-3">
|
>
|
||||||
last updated
|
Name
|
||||||
</th>
|
</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody className="divide-y divide-gray-200">
|
||||||
<DesktopItem key={dataset.name} dataset={dataset} />
|
{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>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
</div>
|
||||||
{dataset.readme && (
|
{dataset.files && dataset.files.length > 0 && (
|
||||||
<>
|
<>
|
||||||
{dataset.readme && (
|
<h2 className="mb-0 mt-10">DATA PREVIEWS</h2>
|
||||||
<ReactMarkdown
|
{dataset.files?.map((file) => (
|
||||||
remarkPlugins={[
|
<div key={file} className="preview-table my-8">
|
||||||
remarkFrontmatter,
|
<h3>{file.split('/').slice(-1)}</h3>
|
||||||
remarkGfm,
|
<Table url={file} />
|
||||||
[extract, { remove: true }],
|
</div>
|
||||||
]}
|
))}
|
||||||
>
|
</>
|
||||||
{dataset.readme}
|
)}
|
||||||
</ReactMarkdown>
|
{dataset.readme && (
|
||||||
)}
|
<>
|
||||||
</>
|
<h2 className="uppercase font-black">Readme</h2>
|
||||||
)}
|
{dataset.readme && (
|
||||||
|
<ReactMarkdown
|
||||||
<h2 className="mb-0 mt-10">Files</h2>
|
remarkPlugins={[
|
||||||
<div className="inline-block min-w-full py-2 align-middle">
|
remarkFrontmatter,
|
||||||
<table className="min-w-full divide-y divide-gray-300">
|
remarkGfm,
|
||||||
<thead className="border-b-4 pb-2 border-zinc-900">
|
[extract, { remove: true }],
|
||||||
<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}
|
|
||||||
>
|
>
|
||||||
info
|
{dataset.readme}
|
||||||
</a>
|
</ReactMarkdown>
|
||||||
)}
|
)}
|
||||||
</td>
|
</>
|
||||||
</tr>
|
)}
|
||||||
))}
|
</main>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -188,7 +101,6 @@ export async function getStaticPaths() {
|
|||||||
fallback: false, // can also be true or 'blocking'
|
fallback: false, // can also be true or 'blocking'
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
// change href base check datahub-next
|
|
||||||
|
|
||||||
export const getStaticProps: GetStaticProps = async ({ params }) => {
|
export const getStaticProps: GetStaticProps = async ({ params }) => {
|
||||||
const datasetsFile = path.join(process.cwd(), 'datasets.json');
|
const datasetsFile = path.join(process.cwd(), 'datasets.json');
|
||||||
@ -198,20 +110,15 @@ export const getStaticProps: GetStaticProps = async ({ params }) => {
|
|||||||
(_dataset) => _dataset.name === params?.datasetName
|
(_dataset) => _dataset.name === params?.datasetName
|
||||||
);
|
);
|
||||||
const github_pat = getConfig().serverRuntimeConfig.github_pat;
|
const github_pat = getConfig().serverRuntimeConfig.github_pat;
|
||||||
const readmes = await Promise.all(
|
const readmes = await Promise.all(['/README.md', '/readme.md', '/Readme.md'].map(async (readme) => await getProjectReadme(
|
||||||
['/README.md', '/readme.md', '/Readme.md'].map(
|
'fivethirtyeight',
|
||||||
async (readme) =>
|
'data',
|
||||||
await getProjectReadme(
|
'master',
|
||||||
'fivethirtyeight',
|
dataset?.name + readme,
|
||||||
'data',
|
github_pat
|
||||||
'master',
|
)));
|
||||||
dataset?.name + readme,
|
const readme = readmes.find(item => item !== null)
|
||||||
github_pat
|
if (!readme) console.log('Readme not found for ' + dataset?.name)
|
||||||
)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
const readme = readmes.find((item) => item !== null);
|
|
||||||
if (!readme) console.log('Readme not found for ' + dataset?.name);
|
|
||||||
return {
|
return {
|
||||||
props: {
|
props: {
|
||||||
dataset: {
|
dataset: {
|
||||||
|
|||||||
@ -4,7 +4,6 @@ import { format } from 'timeago.js';
|
|||||||
import { promises as fs } from 'fs';
|
import { promises as fs } from 'fs';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import { NextSeo } from 'next-seo';
|
import { NextSeo } from 'next-seo';
|
||||||
import Layout from '@/components/Layout';
|
|
||||||
|
|
||||||
const inter = Inter({ subsets: ['latin'] });
|
const inter = Inter({ subsets: ['latin'] });
|
||||||
|
|
||||||
@ -52,12 +51,21 @@ export function MobileItem({ dataset }: { dataset: Dataset }) {
|
|||||||
>
|
>
|
||||||
info
|
info
|
||||||
</a>
|
</a>
|
||||||
<a
|
{/*
|
||||||
className="ml-2 border border-[#3c3c3c] px-[25px] py-2.5 text-sm transition bg-[#3c3c3c] text-white hover:bg-zinc-900"
|
<button>
|
||||||
href={`/datasets/${dataset.name}`}
|
<svg
|
||||||
>
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
explore
|
viewBox="0 0 24 24"
|
||||||
</a>
|
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> */}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
@ -89,16 +97,6 @@ export function DesktopItem({ dataset }: { dataset: Dataset }) {
|
|||||||
? new Date(article.date).toLocaleString('en-US', options)
|
? new Date(article.date).toLocaleString('en-US', options)
|
||||||
: format(article.date)}
|
: format(article.date)}
|
||||||
</td>
|
</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">
|
<td className="py-8">
|
||||||
{index === 0 && (
|
{index === 0 && (
|
||||||
<a
|
<a
|
||||||
@ -109,6 +107,23 @@ export function DesktopItem({ dataset }: { dataset: Dataset }) {
|
|||||||
</a>
|
</a>
|
||||||
)}
|
)}
|
||||||
</td>
|
</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>
|
</tr>
|
||||||
))}
|
))}
|
||||||
</>
|
</>
|
||||||
@ -128,7 +143,6 @@ export default function Home({ datasets }: { datasets: Dataset[] }) {
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<NextSeo title="FiveThirtyEight tribute by PortalJS" />
|
<NextSeo title="FiveThirtyEight tribute by PortalJS" />
|
||||||
<Layout>
|
|
||||||
<main
|
<main
|
||||||
className={`flex min-h-screen flex-col items-center max-w-5xl mx-auto pt-20 px-2.5 ${inter.className}`}
|
className={`flex min-h-screen flex-col items-center max-w-5xl mx-auto pt-20 px-2.5 ${inter.className}`}
|
||||||
>
|
>
|
||||||
@ -192,7 +206,6 @@ export default function Home({ datasets }: { datasets: Dataset[] }) {
|
|||||||
.
|
.
|
||||||
</p>
|
</p>
|
||||||
</main>
|
</main>
|
||||||
</Layout>
|
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,9 +3,6 @@
|
|||||||
@tailwind utilities;
|
@tailwind utilities;
|
||||||
|
|
||||||
.preview-table > div {
|
.preview-table > div {
|
||||||
|
overflow-x: scroll;
|
||||||
overflow-y: hidden;
|
overflow-y: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
.prose h1 {
|
|
||||||
font-size: 1.5em !important;
|
|
||||||
}
|
|
||||||
|
|||||||
@ -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.
|
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.com/docs/examples/github-backed-catalog) blog post.
|
You can read more about it on the [Data catalog with data on GitHub](https://portaljs.org/docs/examples/github-backed-catalog) blog post.
|
||||||
|
|
||||||
## Demo
|
## Demo
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
import { MDXRemote } from 'next-mdx-remote';
|
import { MDXRemote } from 'next-mdx-remote';
|
||||||
import dynamic from 'next/dynamic';
|
import dynamic from 'next/dynamic';
|
||||||
import { Mermaid } from '@portaljs/core';
|
import { Mermaid } from '@flowershow/core';
|
||||||
|
|
||||||
// Custom components/renderers to pass to MDX.
|
// Custom components/renderers to pass to MDX.
|
||||||
// Since the MDX files aren't loaded by webpack, they have no knowledge of how
|
// Since the MDX files aren't loaded by webpack, they have no knowledge of how
|
||||||
|
|||||||
@ -1,13 +1,13 @@
|
|||||||
import matter from "gray-matter";
|
import matter from "gray-matter";
|
||||||
import mdxmermaid from "mdx-mermaid";
|
import mdxmermaid from "mdx-mermaid";
|
||||||
import { h } from "hastscript";
|
import { h } from "hastscript";
|
||||||
import remarkCallouts from "@portaljs/remark-callouts";
|
import remarkCallouts from "@flowershow/remark-callouts";
|
||||||
import remarkEmbed from "@portaljs/remark-embed";
|
import remarkEmbed from "@flowershow/remark-embed";
|
||||||
import remarkGfm from "remark-gfm";
|
import remarkGfm from "remark-gfm";
|
||||||
import remarkMath from "remark-math";
|
import remarkMath from "remark-math";
|
||||||
import remarkSmartypants from "remark-smartypants";
|
import remarkSmartypants from "remark-smartypants";
|
||||||
import remarkToc from "remark-toc";
|
import remarkToc from "remark-toc";
|
||||||
import remarkWikiLink from "@portaljs/remark-wiki-link";
|
import remarkWikiLink from "@flowershow/remark-wiki-link";
|
||||||
import rehypeAutolinkHeadings from "rehype-autolink-headings";
|
import rehypeAutolinkHeadings from "rehype-autolink-headings";
|
||||||
import rehypeKatex from "rehype-katex";
|
import rehypeKatex from "rehype-katex";
|
||||||
import rehypeSlug from "rehype-slug";
|
import rehypeSlug from "rehype-slug";
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import { MarkdownDB } from "mddb";
|
import { MarkdownDB } from "@flowershow/markdowndb";
|
||||||
|
|
||||||
const dbPath = "markdown.db";
|
const dbPath = "markdown.db";
|
||||||
|
|
||||||
|
|||||||
586
examples/github-backed-catalog/package-lock.json
generated
586
examples/github-backed-catalog/package-lock.json
generated
@ -8,17 +8,16 @@
|
|||||||
"name": "my-app",
|
"name": "my-app",
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@flowershow/core": "^0.4.13",
|
||||||
|
"@flowershow/markdowndb": "^0.1.5",
|
||||||
|
"@flowershow/remark-callouts": "^1.0.0",
|
||||||
|
"@flowershow/remark-embed": "^1.0.0",
|
||||||
"@portaljs/components": "^0.1.6",
|
"@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/node": "18.16.0",
|
||||||
"@types/react": "18.0.38",
|
"@types/react": "18.0.38",
|
||||||
"@types/react-dom": "18.0.11",
|
"@types/react-dom": "18.0.11",
|
||||||
"eslint": "8.39.0",
|
"eslint": "8.39.0",
|
||||||
"eslint-config-next": "13.3.1",
|
"eslint-config-next": "13.3.1",
|
||||||
"mddb": "^0.1.9",
|
|
||||||
"next": "13.4.3",
|
"next": "13.4.3",
|
||||||
"next-mdx-remote": "^4.4.1",
|
"next-mdx-remote": "^4.4.1",
|
||||||
"next-seo": "^6.0.0",
|
"next-seo": "^6.0.0",
|
||||||
@ -46,31 +45,19 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@algolia/autocomplete-core": {
|
"node_modules/@algolia/autocomplete-core": {
|
||||||
"version": "1.9.2",
|
"version": "1.8.2",
|
||||||
"resolved": "https://registry.npmjs.org/@algolia/autocomplete-core/-/autocomplete-core-1.9.2.tgz",
|
"resolved": "https://registry.npmjs.org/@algolia/autocomplete-core/-/autocomplete-core-1.8.2.tgz",
|
||||||
"integrity": "sha512-hkG80c9kx9ClVAEcUJbTd2ziVC713x9Bji9Ty4XJfKXlxlsx3iXsoNhAwfeR4ulzIUg7OE5gez0UU1zVDdG7kg==",
|
"integrity": "sha512-mTeshsyFhAqw/ebqNsQpMtbnjr+qVOSKXArEj4K0d7sqc8It1XD0gkASwecm9mF/jlOQ4Z9RNg1HbdA8JPdRwQ==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@algolia/autocomplete-plugin-algolia-insights": "1.9.2",
|
"@algolia/autocomplete-shared": "1.8.2"
|
||||||
"@algolia/autocomplete-shared": "1.9.2"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@algolia/autocomplete-plugin-algolia-insights": {
|
|
||||||
"version": "1.9.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/@algolia/autocomplete-plugin-algolia-insights/-/autocomplete-plugin-algolia-insights-1.9.2.tgz",
|
|
||||||
"integrity": "sha512-2LVsf4W66hVHQ3Ua/8k15oPlxjELCztbAkQm/hP42Sw+GLkHAdY1vaVRYziaWq64+Oljfg6FKkZHCdgXH+CGIA==",
|
|
||||||
"dependencies": {
|
|
||||||
"@algolia/autocomplete-shared": "1.9.2"
|
|
||||||
},
|
|
||||||
"peerDependencies": {
|
|
||||||
"search-insights": ">= 1 < 3"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@algolia/autocomplete-preset-algolia": {
|
"node_modules/@algolia/autocomplete-preset-algolia": {
|
||||||
"version": "1.9.2",
|
"version": "1.8.2",
|
||||||
"resolved": "https://registry.npmjs.org/@algolia/autocomplete-preset-algolia/-/autocomplete-preset-algolia-1.9.2.tgz",
|
"resolved": "https://registry.npmjs.org/@algolia/autocomplete-preset-algolia/-/autocomplete-preset-algolia-1.8.2.tgz",
|
||||||
"integrity": "sha512-pqgIm2GNqtCT59Y1ICctIPrYTi34+wNPiNWEclD/yDzp5uDUUsyGe5XrUjCNyQRTKonAlmYxoaEHOn8FWgmBHA==",
|
"integrity": "sha512-J0oTx4me6ZM9kIKPuL3lyU3aB8DEvpVvR6xWmHVROx5rOYJGQcZsdG4ozxwcOyiiu3qxMkIbzntnV1S1VWD8yA==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@algolia/autocomplete-shared": "1.9.2"
|
"@algolia/autocomplete-shared": "1.8.2"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@algolia/client-search": ">= 4.9.1 < 6",
|
"@algolia/client-search": ">= 4.9.1 < 6",
|
||||||
@ -78,127 +65,123 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@algolia/autocomplete-shared": {
|
"node_modules/@algolia/autocomplete-shared": {
|
||||||
"version": "1.9.2",
|
"version": "1.8.2",
|
||||||
"resolved": "https://registry.npmjs.org/@algolia/autocomplete-shared/-/autocomplete-shared-1.9.2.tgz",
|
"resolved": "https://registry.npmjs.org/@algolia/autocomplete-shared/-/autocomplete-shared-1.8.2.tgz",
|
||||||
"integrity": "sha512-XxX6YDn+7LG+SmdpXEOnj7fc3TjiVpQ0CbGhjLwrd2tYr6LVY2D4Iiu/iuYJ4shvVDWWnpwArSk0uIWC/8OPUA==",
|
"integrity": "sha512-b6Z/X4MczChMcfhk6kfRmBzPgjoPzuS9KGR4AFsiLulLNRAAqhP+xZTKtMnZGhLuc61I20d5WqlId02AZvcO6g=="
|
||||||
"peerDependencies": {
|
|
||||||
"@algolia/client-search": ">= 4.9.1 < 6",
|
|
||||||
"algoliasearch": ">= 4.9.1 < 6"
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
"node_modules/@algolia/cache-browser-local-storage": {
|
"node_modules/@algolia/cache-browser-local-storage": {
|
||||||
"version": "4.17.2",
|
"version": "4.17.1",
|
||||||
"resolved": "https://registry.npmjs.org/@algolia/cache-browser-local-storage/-/cache-browser-local-storage-4.17.2.tgz",
|
"resolved": "https://registry.npmjs.org/@algolia/cache-browser-local-storage/-/cache-browser-local-storage-4.17.1.tgz",
|
||||||
"integrity": "sha512-ZkVN7K/JE+qMQbpR6h3gQOGR6yCJpmucSBCmH5YDxnrYbp2CbrVCu0Nr+FGVoWzMJNznj1waShkfQ9awERulLw==",
|
"integrity": "sha512-e91Jpu93X3t3mVdQwF3ZDjSFMFIfzSc+I76G4EX8nl9RYXgqcjframoL05VTjcD2YCsI18RIHAWVCBoCXVZnrw==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@algolia/cache-common": "4.17.2"
|
"@algolia/cache-common": "4.17.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@algolia/cache-common": {
|
"node_modules/@algolia/cache-common": {
|
||||||
"version": "4.17.2",
|
"version": "4.17.1",
|
||||||
"resolved": "https://registry.npmjs.org/@algolia/cache-common/-/cache-common-4.17.2.tgz",
|
"resolved": "https://registry.npmjs.org/@algolia/cache-common/-/cache-common-4.17.1.tgz",
|
||||||
"integrity": "sha512-fojbhYIS8ovfYs6hwZpy1O4mBfVRxNgAaZRqsdVQd54hU4MxYDYFCxagYX28lOBz7btcDHld6BMoWXvjzkx6iQ=="
|
"integrity": "sha512-fvi1WT8aSiGAKrcTw8Qg3RYgcwW8GZMHcqEm4AyDBEy72JZlFBSY80cTQ75MslINjCHXLDT+9EN8AGI9WVY7uA=="
|
||||||
},
|
},
|
||||||
"node_modules/@algolia/cache-in-memory": {
|
"node_modules/@algolia/cache-in-memory": {
|
||||||
"version": "4.17.2",
|
"version": "4.17.1",
|
||||||
"resolved": "https://registry.npmjs.org/@algolia/cache-in-memory/-/cache-in-memory-4.17.2.tgz",
|
"resolved": "https://registry.npmjs.org/@algolia/cache-in-memory/-/cache-in-memory-4.17.1.tgz",
|
||||||
"integrity": "sha512-UYQcMzPurNi+cPYkuPemTZkjKAjdgAS1hagC5irujKbrYnN4yscK4TkOI5tX+O8/KegtJt3kOK07OIrJ2QDAAw==",
|
"integrity": "sha512-NbBt6eBWlsXc5geSpfPRC5dkIB/0Ptthw8r0yM5Z7D3sPlYdnTZSO9y9XWXIptRMwmZe4cM8iBMN8y0tzbcBkA==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@algolia/cache-common": "4.17.2"
|
"@algolia/cache-common": "4.17.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@algolia/client-account": {
|
"node_modules/@algolia/client-account": {
|
||||||
"version": "4.17.2",
|
"version": "4.17.1",
|
||||||
"resolved": "https://registry.npmjs.org/@algolia/client-account/-/client-account-4.17.2.tgz",
|
"resolved": "https://registry.npmjs.org/@algolia/client-account/-/client-account-4.17.1.tgz",
|
||||||
"integrity": "sha512-doSk89pBPDpDyKJSHFADIGa2XSGrBCj3QwPvqtRJXDADpN+OjW+eTR8r4hEs/7X4GGfjfAOAES8JgDx+fZntYw==",
|
"integrity": "sha512-3rL/6ofJvyL+q8TiWM3qoM9tig+SY4gB1Vbsj+UeJPnJm8Khm+7OS+r+mFraqR6pTehYqN8yGYoE7x4diEn4aA==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@algolia/client-common": "4.17.2",
|
"@algolia/client-common": "4.17.1",
|
||||||
"@algolia/client-search": "4.17.2",
|
"@algolia/client-search": "4.17.1",
|
||||||
"@algolia/transporter": "4.17.2"
|
"@algolia/transporter": "4.17.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@algolia/client-analytics": {
|
"node_modules/@algolia/client-analytics": {
|
||||||
"version": "4.17.2",
|
"version": "4.17.1",
|
||||||
"resolved": "https://registry.npmjs.org/@algolia/client-analytics/-/client-analytics-4.17.2.tgz",
|
"resolved": "https://registry.npmjs.org/@algolia/client-analytics/-/client-analytics-4.17.1.tgz",
|
||||||
"integrity": "sha512-V+DcXbOtD/hKwAR3qGQrtlrJ3q2f9OKfx843q744o4m3xHv5ueCAvGXB1znPsdaUrVDNAImcgEgqwI9x7EJbDw==",
|
"integrity": "sha512-Bepr2w249vODqeBtM7i++tPmUsQ9B81aupUGbDWmjA/FX+jzQqOdhW8w1CFO5kWViNKTbz2WBIJ9U3x8hOa4bA==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@algolia/client-common": "4.17.2",
|
"@algolia/client-common": "4.17.1",
|
||||||
"@algolia/client-search": "4.17.2",
|
"@algolia/client-search": "4.17.1",
|
||||||
"@algolia/requester-common": "4.17.2",
|
"@algolia/requester-common": "4.17.1",
|
||||||
"@algolia/transporter": "4.17.2"
|
"@algolia/transporter": "4.17.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@algolia/client-common": {
|
"node_modules/@algolia/client-common": {
|
||||||
"version": "4.17.2",
|
"version": "4.17.1",
|
||||||
"resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-4.17.2.tgz",
|
"resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-4.17.1.tgz",
|
||||||
"integrity": "sha512-gKBUnjxi0ukJYIJxVREYGt1Dmj1B3RBYbfGWi0dIPp1BC1VvQm+BOuNwsIwmq/x3MPO+sGuK978eKiP3tZDvag==",
|
"integrity": "sha512-+r7kg4EgbFnGsDnoGSVNtXZO8xvZ0vzf1WAOV7sqV9PMf1bp6cpJP/3IuPrSk4t5w2KVl+pC8jfTM7HcFlfBEQ==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@algolia/requester-common": "4.17.2",
|
"@algolia/requester-common": "4.17.1",
|
||||||
"@algolia/transporter": "4.17.2"
|
"@algolia/transporter": "4.17.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@algolia/client-personalization": {
|
"node_modules/@algolia/client-personalization": {
|
||||||
"version": "4.17.2",
|
"version": "4.17.1",
|
||||||
"resolved": "https://registry.npmjs.org/@algolia/client-personalization/-/client-personalization-4.17.2.tgz",
|
"resolved": "https://registry.npmjs.org/@algolia/client-personalization/-/client-personalization-4.17.1.tgz",
|
||||||
"integrity": "sha512-wc4UgOWxSYWz5wpuelNmlt895jA9twjZWM2ms17Ws8qCvBHF7OVGdMGgbysPB8790YnfvvDnSsWOv3CEj26Eow==",
|
"integrity": "sha512-gJku9DG/THJpfsSlG/az0a3QIn+VVff9kKh8PG8+7ZfxOHS+C+Y5YSeZVsC+c2cfoKLPo3CuHIiJ/p86erR3bA==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@algolia/client-common": "4.17.2",
|
"@algolia/client-common": "4.17.1",
|
||||||
"@algolia/requester-common": "4.17.2",
|
"@algolia/requester-common": "4.17.1",
|
||||||
"@algolia/transporter": "4.17.2"
|
"@algolia/transporter": "4.17.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@algolia/client-search": {
|
"node_modules/@algolia/client-search": {
|
||||||
"version": "4.17.2",
|
"version": "4.17.1",
|
||||||
"resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-4.17.2.tgz",
|
"resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-4.17.1.tgz",
|
||||||
"integrity": "sha512-FUjIs+gRe0upJC++uVs4sdxMw15JxfkT86Gr/kqVwi9kcqaZhXntSbW/Fw959bIYXczjmeVQsilYvBWW4YvSZA==",
|
"integrity": "sha512-Q5YfT5gVkx60PZDQBqp/zH9aUbBdC7HVvxupiHUgnCKqRQsRZjOhLest7AI6FahepuZLBZS62COrO7v+JvKY7w==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@algolia/client-common": "4.17.2",
|
"@algolia/client-common": "4.17.1",
|
||||||
"@algolia/requester-common": "4.17.2",
|
"@algolia/requester-common": "4.17.1",
|
||||||
"@algolia/transporter": "4.17.2"
|
"@algolia/transporter": "4.17.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@algolia/logger-common": {
|
"node_modules/@algolia/logger-common": {
|
||||||
"version": "4.17.2",
|
"version": "4.17.1",
|
||||||
"resolved": "https://registry.npmjs.org/@algolia/logger-common/-/logger-common-4.17.2.tgz",
|
"resolved": "https://registry.npmjs.org/@algolia/logger-common/-/logger-common-4.17.1.tgz",
|
||||||
"integrity": "sha512-EfXuweUE+1HiSMsQidaDWA5Lv4NnStYIlh7PO5pLkI+sdhbMX0e5AO5nUAMIFM1VkEANes70RA8fzhP6OqCqQQ=="
|
"integrity": "sha512-Us28Ot+fLEmX9M96sa65VZ8EyEEzhYPxfhV9aQyKDjfXbUdJlJxKt6wZpoEg9RAPSdO8IjK9nmuW2P8au3rRsg=="
|
||||||
},
|
},
|
||||||
"node_modules/@algolia/logger-console": {
|
"node_modules/@algolia/logger-console": {
|
||||||
"version": "4.17.2",
|
"version": "4.17.1",
|
||||||
"resolved": "https://registry.npmjs.org/@algolia/logger-console/-/logger-console-4.17.2.tgz",
|
"resolved": "https://registry.npmjs.org/@algolia/logger-console/-/logger-console-4.17.1.tgz",
|
||||||
"integrity": "sha512-JuG8HGVlJ+l/UEDK4h2Y8q/IEmRjQz1J0aS9tf6GPNbGYiSvMr1DDdZ+hqV3bb1XE6wU8Ypex56HisWMSpnG0A==",
|
"integrity": "sha512-iKGQTpOjHiE64W3JIOu6dmDvn+AfYIElI9jf/Nt6umRPmP/JI9rK+OHUoW4pKrBtdG0DPd62ppeNXzSnLxY6/g==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@algolia/logger-common": "4.17.2"
|
"@algolia/logger-common": "4.17.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@algolia/requester-browser-xhr": {
|
"node_modules/@algolia/requester-browser-xhr": {
|
||||||
"version": "4.17.2",
|
"version": "4.17.1",
|
||||||
"resolved": "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-4.17.2.tgz",
|
"resolved": "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-4.17.1.tgz",
|
||||||
"integrity": "sha512-FKI2lYWwksALfRt2OETFmGb5+P7WVc4py2Ai3H7k8FSfTLwVvs9WVVmtlx6oANQ8RFEK4B85h8DQJTJ29TDfmA==",
|
"integrity": "sha512-W5mGfGDsyfVR+r4pUFrYLGBEM18gs38+GNt5PE5uPULy4uVTSnnVSkJkWeRkmLBk9zEZ/Nld8m4zavK6dtEuYg==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@algolia/requester-common": "4.17.2"
|
"@algolia/requester-common": "4.17.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@algolia/requester-common": {
|
"node_modules/@algolia/requester-common": {
|
||||||
"version": "4.17.2",
|
"version": "4.17.1",
|
||||||
"resolved": "https://registry.npmjs.org/@algolia/requester-common/-/requester-common-4.17.2.tgz",
|
"resolved": "https://registry.npmjs.org/@algolia/requester-common/-/requester-common-4.17.1.tgz",
|
||||||
"integrity": "sha512-Rfim23ztAhYpE9qm+KCfCRo+YLJCjiiTG+IpDdzUjMpYPhUtirQT0A35YEd/gKn86YNyydxS9w8iRSjwKh+L0A=="
|
"integrity": "sha512-HggXdjvVFQR0I5l7hM5WdHgQ1tqcRWeyXZz8apQ7zPWZhirmY2E9D6LVhDh/UnWQNEm7nBtM+eMFONJ3bZccIQ=="
|
||||||
},
|
},
|
||||||
"node_modules/@algolia/requester-node-http": {
|
"node_modules/@algolia/requester-node-http": {
|
||||||
"version": "4.17.2",
|
"version": "4.17.1",
|
||||||
"resolved": "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-4.17.2.tgz",
|
"resolved": "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-4.17.1.tgz",
|
||||||
"integrity": "sha512-E0b0kyCDMvUIhQmDNd/mH4fsKJdEEX6PkMKrYJjzm6moo+rP22tqpq4Rfe7DZD8OB6/LsDD3zs3Kvd+L+M5wwQ==",
|
"integrity": "sha512-NzFWecXT6d0PPsQY9L+/qoK2deF74OLcpvqCH+Vh3mh+QzPsFafcBExdguAjZsAWDn1R6JEeFW7/fo/p0SE57w==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@algolia/requester-common": "4.17.2"
|
"@algolia/requester-common": "4.17.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@algolia/transporter": {
|
"node_modules/@algolia/transporter": {
|
||||||
"version": "4.17.2",
|
"version": "4.17.1",
|
||||||
"resolved": "https://registry.npmjs.org/@algolia/transporter/-/transporter-4.17.2.tgz",
|
"resolved": "https://registry.npmjs.org/@algolia/transporter/-/transporter-4.17.1.tgz",
|
||||||
"integrity": "sha512-m8pXlz5OnNzjD1rcw+duCN4jG4yEzkJBsvKYMoN22Oq6rQwy1AY5muZ+IQUs4dL+A364CYkRMLRWhvXpCZ1x+g==",
|
"integrity": "sha512-ZM+qhX47Vh46mWH8/U9ihvy98HdTYpYQDSlqBD7IbiUbbyoCMke+qmdSX2MGhR2FCcXBSxejsJKKVAfbpaLVgg==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@algolia/cache-common": "4.17.2",
|
"@algolia/cache-common": "4.17.1",
|
||||||
"@algolia/logger-common": "4.17.2",
|
"@algolia/logger-common": "4.17.1",
|
||||||
"@algolia/requester-common": "4.17.2"
|
"@algolia/requester-common": "4.17.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@babel/code-frame": {
|
"node_modules/@babel/code-frame": {
|
||||||
@ -370,18 +353,18 @@
|
|||||||
"integrity": "sha512-Tbsj02wXCbqGmzdnXNk0SOF19ChhRU70BsroIi4Pm6Ehp56in6vch94mfbdQ17DozxkL3BAVjbZ4Qc1a0HFRAg=="
|
"integrity": "sha512-Tbsj02wXCbqGmzdnXNk0SOF19ChhRU70BsroIi4Pm6Ehp56in6vch94mfbdQ17DozxkL3BAVjbZ4Qc1a0HFRAg=="
|
||||||
},
|
},
|
||||||
"node_modules/@docsearch/css": {
|
"node_modules/@docsearch/css": {
|
||||||
"version": "3.5.0",
|
"version": "3.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/@docsearch/css/-/css-3.5.0.tgz",
|
"resolved": "https://registry.npmjs.org/@docsearch/css/-/css-3.4.0.tgz",
|
||||||
"integrity": "sha512-Ob5FQLubplcBNihAVtriR59FRBeP8u69F6mu4L4yIr60KfsPc10bOV0DoPErJw0zF9IBN2cNLW9qdmt8zWPxyg=="
|
"integrity": "sha512-Hg8Xfma+rFwRi6Y/pfei4FJoQ1hdVURmmNs/XPoMTCPAImU+d5yxj+M+qdLtNjWRpfWziU4dQcqY94xgFBn2dg=="
|
||||||
},
|
},
|
||||||
"node_modules/@docsearch/react": {
|
"node_modules/@docsearch/react": {
|
||||||
"version": "3.5.0",
|
"version": "3.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/@docsearch/react/-/react-3.5.0.tgz",
|
"resolved": "https://registry.npmjs.org/@docsearch/react/-/react-3.4.0.tgz",
|
||||||
"integrity": "sha512-3IG8mmSMzSHNGy2S1VuPyYU9tFCxFpj5Ov8SYwsSHM4yMvFsaO9oFxXocA5lSenliIELhuOuS5+BdxHa/Qlf2A==",
|
"integrity": "sha512-ufrp5879XYGojgS30ZAp8H4qIMbahRHB9M85VDBP36Xgz5QjYM54i1URKj5e219F7gqTtOivfztFTij6itc0MQ==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@algolia/autocomplete-core": "1.9.2",
|
"@algolia/autocomplete-core": "1.8.2",
|
||||||
"@algolia/autocomplete-preset-algolia": "1.9.2",
|
"@algolia/autocomplete-preset-algolia": "1.8.2",
|
||||||
"@docsearch/css": "3.5.0",
|
"@docsearch/css": "3.4.0",
|
||||||
"algoliasearch": "^4.0.0"
|
"algoliasearch": "^4.0.0"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
@ -590,16 +573,16 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@floating-ui/core": {
|
"node_modules/@floating-ui/core": {
|
||||||
"version": "1.3.0",
|
"version": "1.2.6",
|
||||||
"resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.2.6.tgz",
|
||||||
"integrity": "sha512-vX1WVAdPjZg9DkDkC+zEx/tKtnST6/qcNpwcjeBgco3XRNHz5PUA+ivi/yr6G3o0kMR60uKBJcfOdfzOFI7PMQ=="
|
"integrity": "sha512-EvYTiXet5XqweYGClEmpu3BoxmsQ4hkj3QaYA6qEnigCWffTP3vNRwBReTdrwDwo7OoJ3wM8Uoe9Uk4n+d4hfg=="
|
||||||
},
|
},
|
||||||
"node_modules/@floating-ui/dom": {
|
"node_modules/@floating-ui/dom": {
|
||||||
"version": "1.3.0",
|
"version": "1.2.8",
|
||||||
"resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.2.8.tgz",
|
||||||
"integrity": "sha512-qIAwejE3r6NeA107u4ELDKkH8+VtgRKdXqtSPaKflL2S2V+doyN+Wt9s5oHKXPDo4E8TaVXaHT3+6BbagH31xw==",
|
"integrity": "sha512-XLwhYV90MxiHDq6S0rzFZj00fnDM+A1R9jhSioZoMsa7G0Q0i+Q4x40ajR8FHSdYDE1bgjG45mIWe6jtv9UPmg==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@floating-ui/core": "^1.3.0"
|
"@floating-ui/core": "^1.2.6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@floating-ui/react-dom": {
|
"node_modules/@floating-ui/react-dom": {
|
||||||
@ -629,6 +612,103 @@
|
|||||||
"react-dom": ">=16.8.0"
|
"react-dom": ">=16.8.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@flowershow/core": {
|
||||||
|
"version": "0.4.13",
|
||||||
|
"resolved": "https://registry.npmjs.org/@flowershow/core/-/core-0.4.13.tgz",
|
||||||
|
"integrity": "sha512-UeDb70pjUGgILUXGQKFkytKL9ilwsTIM3jYsNNi55PKHXAaHEQA480Y+m2yNPgC5SzFlGj0FIP/zhH0JfBdNiw==",
|
||||||
|
"dependencies": {
|
||||||
|
"@docsearch/react": "^3.3.3",
|
||||||
|
"@floating-ui/react-dom": "^1.3.0",
|
||||||
|
"@floating-ui/react-dom-interactions": "^0.13.3",
|
||||||
|
"@giscus/react": "^2.2.6",
|
||||||
|
"@headlessui/react": "^1.7.12",
|
||||||
|
"clsx": "^1.2.1",
|
||||||
|
"disqus-react": "^1.1.5",
|
||||||
|
"framer-motion": "^10.0.1",
|
||||||
|
"kbar": "0.1.0-beta.40",
|
||||||
|
"mdx-mermaid": "2.0.0-rc7",
|
||||||
|
"mermaid": "10.0.1-rc.2",
|
||||||
|
"prop-types": "^15.8.1"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"next": "^13.2.1",
|
||||||
|
"next-themes": "^0.2.1",
|
||||||
|
"react": "^18.2.0",
|
||||||
|
"react-dom": "^18.2.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@flowershow/core/node_modules/dagre-d3-es": {
|
||||||
|
"version": "7.0.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/dagre-d3-es/-/dagre-d3-es-7.0.8.tgz",
|
||||||
|
"integrity": "sha512-eykdoYQ4FwCJinEYS0gPL2f2w+BPbSLvnQSJ3Ye1vAoPjdkq6xIMKBv+UkICd3qZE26wBKIn3p+6n0QC7R1LyA==",
|
||||||
|
"dependencies": {
|
||||||
|
"d3": "^7.8.2",
|
||||||
|
"lodash-es": "^4.17.21"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@flowershow/core/node_modules/dompurify": {
|
||||||
|
"version": "2.4.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/dompurify/-/dompurify-2.4.3.tgz",
|
||||||
|
"integrity": "sha512-q6QaLcakcRjebxjg8/+NP+h0rPfatOgOzc46Fst9VAA3jF2ApfKBNKMzdP4DYTqtUMXSCd5pRS/8Po/OmoCHZQ=="
|
||||||
|
},
|
||||||
|
"node_modules/@flowershow/core/node_modules/mermaid": {
|
||||||
|
"version": "10.0.1-rc.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/mermaid/-/mermaid-10.0.1-rc.2.tgz",
|
||||||
|
"integrity": "sha512-THnhraO9F6pQZY9Nv91QuWv35QdmZy/UW2FpadRN/1cLuqCyihNKIEOxuVLEPrgtFawt2nL+BpUoJKC4div3UQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"@braintree/sanitize-url": "^6.0.0",
|
||||||
|
"cytoscape": "^3.23.0",
|
||||||
|
"cytoscape-cose-bilkent": "^4.1.0",
|
||||||
|
"cytoscape-fcose": "^2.1.0",
|
||||||
|
"d3": "^7.4.0",
|
||||||
|
"dagre-d3-es": "7.0.8",
|
||||||
|
"dompurify": "2.4.3",
|
||||||
|
"elkjs": "^0.8.2",
|
||||||
|
"khroma": "^2.0.0",
|
||||||
|
"lodash-es": "^4.17.21",
|
||||||
|
"moment-mini": "^2.29.4",
|
||||||
|
"non-layered-tidy-tree-layout": "^2.0.2",
|
||||||
|
"stylis": "^4.1.2",
|
||||||
|
"ts-dedent": "^2.2.0",
|
||||||
|
"uuid": "^9.0.0",
|
||||||
|
"web-worker": "^1.2.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@flowershow/markdowndb": {
|
||||||
|
"version": "0.1.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/@flowershow/markdowndb/-/markdowndb-0.1.5.tgz",
|
||||||
|
"integrity": "sha512-AfmkvgitNb7z150bTcCn/1lqwUhPRD3IhCbIwYxE5IXtL57+WwewJUNOU3SOKXNWg6eDVlfEq0H2GICSLAC4bw==",
|
||||||
|
"dependencies": {
|
||||||
|
"@flowershow/remark-wiki-link": "^1.1.2",
|
||||||
|
"gray-matter": "^4.0.3",
|
||||||
|
"knex": "^2.4.2",
|
||||||
|
"remark-gfm": "^3.0.1",
|
||||||
|
"remark-parse": "^10.0.1",
|
||||||
|
"sqlite3": "^5.1.6",
|
||||||
|
"unist-util-select": "^4.0.3"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"mddb": "src/bin/index.js"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@flowershow/remark-callouts": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@flowershow/remark-callouts/-/remark-callouts-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-zzHDpw1bswTTf+cbhNh2Bogf4ghpIcxAypFxYZxZ/afeGdN3NNSQwnamL8StY9uu6aQ/miq4Egbuof3xk2ksWA==",
|
||||||
|
"dependencies": {
|
||||||
|
"mdast-util-from-markdown": "^1.2.0",
|
||||||
|
"svg-parser": "^2.0.4",
|
||||||
|
"unist-util-visit": "^4.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@flowershow/remark-embed": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@flowershow/remark-embed/-/remark-embed-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-tADovIrhbmNWJj72C+pgT921+BuApmO6xxKU3HlWciRHkD6S4KqsikLjsopalK+VJmqluoHhhST0kf0S6xUKIA==",
|
||||||
|
"dependencies": {
|
||||||
|
"unist-util-visit": "^4.1.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@flowershow/remark-wiki-link": {
|
"node_modules/@flowershow/remark-wiki-link": {
|
||||||
"version": "1.2.0",
|
"version": "1.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/@flowershow/remark-wiki-link/-/remark-wiki-link-1.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/@flowershow/remark-wiki-link/-/remark-wiki-link-1.2.0.tgz",
|
||||||
@ -1621,9 +1701,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@headlessui/react": {
|
"node_modules/@headlessui/react": {
|
||||||
"version": "1.7.15",
|
"version": "1.7.14",
|
||||||
"resolved": "https://registry.npmjs.org/@headlessui/react/-/react-1.7.15.tgz",
|
"resolved": "https://registry.npmjs.org/@headlessui/react/-/react-1.7.14.tgz",
|
||||||
"integrity": "sha512-OTO0XtoRQ6JPB1cKNFYBZv2Q0JMqMGNhYP1CjPvcJvjz8YGokz8oAj89HIYZGN0gZzn/4kk9iUpmMF4Q21Gsqw==",
|
"integrity": "sha512-znzdq9PG8rkwcu9oQ2FwIy0ZFtP9Z7ycS+BAqJ3R5EIqC/0bJGvhT7193rFf+45i9nnPsYvCQVW4V/bB9Xc+gA==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"client-only": "^0.0.1"
|
"client-only": "^0.0.1"
|
||||||
},
|
},
|
||||||
@ -1727,9 +1807,9 @@
|
|||||||
"integrity": "sha512-kXOeFbfCm4fFf2A3WwVEeQj55tMZa8c8/f9AKHMobQMkzNUfUj+antR3fRPaZJawsa1aZiP/Da3ndpZrwEe4rQ=="
|
"integrity": "sha512-kXOeFbfCm4fFf2A3WwVEeQj55tMZa8c8/f9AKHMobQMkzNUfUj+antR3fRPaZJawsa1aZiP/Da3ndpZrwEe4rQ=="
|
||||||
},
|
},
|
||||||
"node_modules/@lit/reactive-element": {
|
"node_modules/@lit/reactive-element": {
|
||||||
"version": "1.6.2",
|
"version": "1.6.1",
|
||||||
"resolved": "https://registry.npmjs.org/@lit/reactive-element/-/reactive-element-1.6.2.tgz",
|
"resolved": "https://registry.npmjs.org/@lit/reactive-element/-/reactive-element-1.6.1.tgz",
|
||||||
"integrity": "sha512-rDfl+QnCYjuIGf5xI2sVJWdYIi56CTCwWa+nidKYX6oIuBYwUbT/vX4qbUDlHiZKJ/3FRNQ/tWJui44p6/stSA==",
|
"integrity": "sha512-va15kYZr7KZNNPZdxONGQzpUr+4sxVu7V/VG7a8mRfPPXUyhEYj5RzXCQmGrlP3tAh0L3HHm5AjBMFYRqlM9SA==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@lit-labs/ssr-dom-shim": "^1.0.0"
|
"@lit-labs/ssr-dom-shim": "^1.0.0"
|
||||||
}
|
}
|
||||||
@ -2364,60 +2444,6 @@
|
|||||||
"react-dom": "^18.2.0"
|
"react-dom": "^18.2.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@portaljs/core": {
|
|
||||||
"version": "1.0.5",
|
|
||||||
"resolved": "https://registry.npmjs.org/@portaljs/core/-/core-1.0.5.tgz",
|
|
||||||
"integrity": "sha512-HJ3eYjyKL7wrPlBwcEHzNd/SW2PwLu49nAsRTz8r7tgyRINDVkHTLVjZ5V6jCSYtuX7LSlxk0WMIZ9aDOocXDA==",
|
|
||||||
"dependencies": {
|
|
||||||
"@docsearch/react": "^3.3.3",
|
|
||||||
"@floating-ui/react-dom": "^1.3.0",
|
|
||||||
"@floating-ui/react-dom-interactions": "^0.13.3",
|
|
||||||
"@giscus/react": "^2.2.6",
|
|
||||||
"@headlessui/react": "^1.7.12",
|
|
||||||
"clsx": "^1.2.1",
|
|
||||||
"core-js": "^3.30.2",
|
|
||||||
"disqus-react": "^1.1.5",
|
|
||||||
"framer-motion": "^10.0.1",
|
|
||||||
"kbar": "0.1.0-beta.40",
|
|
||||||
"mermaid": "^10.2.2",
|
|
||||||
"prop-types": "^15.8.1"
|
|
||||||
},
|
|
||||||
"peerDependencies": {
|
|
||||||
"mdx-mermaid": "2.0.0-rc7",
|
|
||||||
"next": "^13.2.1",
|
|
||||||
"next-themes": "^0.2.1",
|
|
||||||
"react": "^18.2.0",
|
|
||||||
"react-dom": "^18.2.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@portaljs/remark-callouts": {
|
|
||||||
"version": "1.0.5",
|
|
||||||
"resolved": "https://registry.npmjs.org/@portaljs/remark-callouts/-/remark-callouts-1.0.5.tgz",
|
|
||||||
"integrity": "sha512-KMjr44isEvQzpNBBCP3s5/3TCmI/ce4xRvbOk6h9xicVZqE6BPTH9rhfOGvop9cchyAWgj9gmJXhQk+Bd+t5bg==",
|
|
||||||
"dependencies": {
|
|
||||||
"mdast-util-from-markdown": "^1.2.0",
|
|
||||||
"svg-parser": "^2.0.4",
|
|
||||||
"unist-util-visit": "^4.1.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@portaljs/remark-embed": {
|
|
||||||
"version": "1.0.4",
|
|
||||||
"resolved": "https://registry.npmjs.org/@portaljs/remark-embed/-/remark-embed-1.0.4.tgz",
|
|
||||||
"integrity": "sha512-BvRMC1iBd5M93u9WS0mvunHoBMWgQQTCR7RdqSS9sRav5pqquiNG7il12Yza4vFpFBXwLkzEG0NwIVXzzutT8w==",
|
|
||||||
"dependencies": {
|
|
||||||
"unist-util-visit": "^4.1.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@portaljs/remark-wiki-link": {
|
|
||||||
"version": "1.0.4",
|
|
||||||
"resolved": "https://registry.npmjs.org/@portaljs/remark-wiki-link/-/remark-wiki-link-1.0.4.tgz",
|
|
||||||
"integrity": "sha512-cp6vlssDAPawcBI0vUPRpcPdORql3RbK1Q+t1LuRvMQ+yiRb+9DnSPBUviDXKqwsBMOOXP/ePAdYohaeXGt0lQ==",
|
|
||||||
"dependencies": {
|
|
||||||
"mdast-util-to-markdown": "^1.5.0",
|
|
||||||
"mdast-util-wiki-link": "^0.0.2",
|
|
||||||
"micromark-util-symbol": "^1.0.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@primer/octicons-react": {
|
"node_modules/@primer/octicons-react": {
|
||||||
"version": "12.1.0",
|
"version": "12.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/@primer/octicons-react/-/octicons-react-12.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/@primer/octicons-react/-/octicons-react-12.1.0.tgz",
|
||||||
@ -2448,43 +2474,27 @@
|
|||||||
"integrity": "sha512-Z8R0kdAZui8eYTuGY5oQUA0SU4jYq43m4bZW6Dw0B35fUp+U3r+pCrkj0EADJAPv1UaKNskSv/lrfRdC7719Rg=="
|
"integrity": "sha512-Z8R0kdAZui8eYTuGY5oQUA0SU4jYq43m4bZW6Dw0B35fUp+U3r+pCrkj0EADJAPv1UaKNskSv/lrfRdC7719Rg=="
|
||||||
},
|
},
|
||||||
"node_modules/@radix-ui/react-compose-refs": {
|
"node_modules/@radix-ui/react-compose-refs": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.0.0.tgz",
|
||||||
"integrity": "sha512-fDSBgd44FKHa1FRMU59qBMPFcl2PZE+2nmqunj+BWFyYYjnhIDWL2ItDs3rrbJDQOtzt5nIebLCQc4QRfz6LJw==",
|
"integrity": "sha512-0KaSv6sx787/hK3eF53iOkiSLwAGlFMx5lotrqD2pTjB18KbybKoEIgkNZTKC60YECDQTKGTRcDBILwZVqVKvA==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/runtime": "^7.13.10"
|
"@babel/runtime": "^7.13.10"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@types/react": "*",
|
|
||||||
"react": "^16.8 || ^17.0 || ^18.0"
|
"react": "^16.8 || ^17.0 || ^18.0"
|
||||||
},
|
|
||||||
"peerDependenciesMeta": {
|
|
||||||
"@types/react": {
|
|
||||||
"optional": true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@radix-ui/react-portal": {
|
"node_modules/@radix-ui/react-portal": {
|
||||||
"version": "1.0.3",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.0.2.tgz",
|
||||||
"integrity": "sha512-xLYZeHrWoPmA5mEKEfZZevoVRK/Q43GfzRXkWV6qawIWWK8t6ifIiLQdd7rmQ4Vk1bmI21XhqF9BN3jWf+phpA==",
|
"integrity": "sha512-swu32idoCW7KA2VEiUZGBSu9nB6qwGdV6k6HYhUoOo3M1FFpD+VgLzUqtt3mwL1ssz7r2x8MggpLSQach2Xy/Q==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/runtime": "^7.13.10",
|
"@babel/runtime": "^7.13.10",
|
||||||
"@radix-ui/react-primitive": "1.0.3"
|
"@radix-ui/react-primitive": "1.0.2"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@types/react": "*",
|
|
||||||
"@types/react-dom": "*",
|
|
||||||
"react": "^16.8 || ^17.0 || ^18.0",
|
"react": "^16.8 || ^17.0 || ^18.0",
|
||||||
"react-dom": "^16.8 || ^17.0 || ^18.0"
|
"react-dom": "^16.8 || ^17.0 || ^18.0"
|
||||||
},
|
|
||||||
"peerDependenciesMeta": {
|
|
||||||
"@types/react": {
|
|
||||||
"optional": true
|
|
||||||
},
|
|
||||||
"@types/react-dom": {
|
|
||||||
"optional": true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@radix-ui/react-presence": {
|
"node_modules/@radix-ui/react-presence": {
|
||||||
@ -2507,44 +2517,28 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@radix-ui/react-primitive": {
|
"node_modules/@radix-ui/react-primitive": {
|
||||||
"version": "1.0.3",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-1.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-1.0.2.tgz",
|
||||||
"integrity": "sha512-yi58uVyoAcK/Nq1inRY56ZSjKypBNKTa/1mcL8qdl6oJeEaDbOldlzrGn7P6Q3Id5d+SYNGc5AJgc4vGhjs5+g==",
|
"integrity": "sha512-zY6G5Qq4R8diFPNwtyoLRZBxzu1Z+SXMlfYpChN7Dv8gvmx9X3qhDqiLWvKseKVJMuedFeU/Sa0Sy/Ia+t06Dw==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/runtime": "^7.13.10",
|
"@babel/runtime": "^7.13.10",
|
||||||
"@radix-ui/react-slot": "1.0.2"
|
"@radix-ui/react-slot": "1.0.1"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@types/react": "*",
|
|
||||||
"@types/react-dom": "*",
|
|
||||||
"react": "^16.8 || ^17.0 || ^18.0",
|
"react": "^16.8 || ^17.0 || ^18.0",
|
||||||
"react-dom": "^16.8 || ^17.0 || ^18.0"
|
"react-dom": "^16.8 || ^17.0 || ^18.0"
|
||||||
},
|
|
||||||
"peerDependenciesMeta": {
|
|
||||||
"@types/react": {
|
|
||||||
"optional": true
|
|
||||||
},
|
|
||||||
"@types/react-dom": {
|
|
||||||
"optional": true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@radix-ui/react-slot": {
|
"node_modules/@radix-ui/react-slot": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.0.1.tgz",
|
||||||
"integrity": "sha512-YeTpuq4deV+6DusvVUW4ivBgnkHwECUu0BiN43L5UCDFgdhsRUWAghhTF5MbvNTPzmiFOx90asDSUjWuCNapwg==",
|
"integrity": "sha512-avutXAFL1ehGvAXtPquu0YK5oz6ctS474iM3vNGQIkswrVhdrS52e3uoMQBzZhNRAIE0jBnUyXWNmSjGHhCFcw==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/runtime": "^7.13.10",
|
"@babel/runtime": "^7.13.10",
|
||||||
"@radix-ui/react-compose-refs": "1.0.1"
|
"@radix-ui/react-compose-refs": "1.0.0"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@types/react": "*",
|
|
||||||
"react": "^16.8 || ^17.0 || ^18.0"
|
"react": "^16.8 || ^17.0 || ^18.0"
|
||||||
},
|
|
||||||
"peerDependenciesMeta": {
|
|
||||||
"@types/react": {
|
|
||||||
"optional": true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@radix-ui/rect": {
|
"node_modules/@radix-ui/rect": {
|
||||||
@ -2868,7 +2862,6 @@
|
|||||||
"resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.0.tgz",
|
"resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.0.tgz",
|
||||||
"integrity": "sha512-Cn6WYCm0tXv8p6k+A8PvbDG763EDpBoTzHdA+Q/MF6H3sapGjCm9NzoaJncJS9tUKSuCoDs9XHxYYsQDgxR6kw==",
|
"integrity": "sha512-Cn6WYCm0tXv8p6k+A8PvbDG763EDpBoTzHdA+Q/MF6H3sapGjCm9NzoaJncJS9tUKSuCoDs9XHxYYsQDgxR6kw==",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/node": "*"
|
"@types/node": "*"
|
||||||
}
|
}
|
||||||
@ -3085,24 +3078,24 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/algoliasearch": {
|
"node_modules/algoliasearch": {
|
||||||
"version": "4.17.2",
|
"version": "4.17.1",
|
||||||
"resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-4.17.2.tgz",
|
"resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-4.17.1.tgz",
|
||||||
"integrity": "sha512-VFu43JJNYIW74awp7oeQcQsPcxOhd8psqBDTfyNO2Zt6L1NqnNMTVnaIdQ+8dtKqUDBqQZp0szPxECvX8CK2Fg==",
|
"integrity": "sha512-4GDQ1RhP2qUR3x8PevFRbEdqZqIARNViZYjgTJmA1T7wRNtFA3W4Aqc/RsODqa1J8IO/QDla5x4tWuUS8NV8wA==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@algolia/cache-browser-local-storage": "4.17.2",
|
"@algolia/cache-browser-local-storage": "4.17.1",
|
||||||
"@algolia/cache-common": "4.17.2",
|
"@algolia/cache-common": "4.17.1",
|
||||||
"@algolia/cache-in-memory": "4.17.2",
|
"@algolia/cache-in-memory": "4.17.1",
|
||||||
"@algolia/client-account": "4.17.2",
|
"@algolia/client-account": "4.17.1",
|
||||||
"@algolia/client-analytics": "4.17.2",
|
"@algolia/client-analytics": "4.17.1",
|
||||||
"@algolia/client-common": "4.17.2",
|
"@algolia/client-common": "4.17.1",
|
||||||
"@algolia/client-personalization": "4.17.2",
|
"@algolia/client-personalization": "4.17.1",
|
||||||
"@algolia/client-search": "4.17.2",
|
"@algolia/client-search": "4.17.1",
|
||||||
"@algolia/logger-common": "4.17.2",
|
"@algolia/logger-common": "4.17.1",
|
||||||
"@algolia/logger-console": "4.17.2",
|
"@algolia/logger-console": "4.17.1",
|
||||||
"@algolia/requester-browser-xhr": "4.17.2",
|
"@algolia/requester-browser-xhr": "4.17.1",
|
||||||
"@algolia/requester-common": "4.17.2",
|
"@algolia/requester-common": "4.17.1",
|
||||||
"@algolia/requester-node-http": "4.17.2",
|
"@algolia/requester-node-http": "4.17.1",
|
||||||
"@algolia/transporter": "4.17.2"
|
"@algolia/transporter": "4.17.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/ansi-regex": {
|
"node_modules/ansi-regex": {
|
||||||
@ -3409,8 +3402,7 @@
|
|||||||
"url": "https://feross.org/support"
|
"url": "https://feross.org/support"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"optional": true,
|
"optional": true
|
||||||
"peer": true
|
|
||||||
},
|
},
|
||||||
"node_modules/before-after-hook": {
|
"node_modules/before-after-hook": {
|
||||||
"version": "2.2.3",
|
"version": "2.2.3",
|
||||||
@ -3438,7 +3430,6 @@
|
|||||||
"resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz",
|
||||||
"integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==",
|
"integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"buffer": "^5.5.0",
|
"buffer": "^5.5.0",
|
||||||
"inherits": "^2.0.4",
|
"inherits": "^2.0.4",
|
||||||
@ -3541,7 +3532,6 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"base64-js": "^1.3.1",
|
"base64-js": "^1.3.1",
|
||||||
"ieee754": "^1.1.13"
|
"ieee754": "^1.1.13"
|
||||||
@ -3552,7 +3542,6 @@
|
|||||||
"resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz",
|
"resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz",
|
||||||
"integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==",
|
"integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"peer": true,
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "*"
|
"node": "*"
|
||||||
}
|
}
|
||||||
@ -3916,16 +3905,6 @@
|
|||||||
"toggle-selection": "^1.0.6"
|
"toggle-selection": "^1.0.6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/core-js": {
|
|
||||||
"version": "3.31.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.31.0.tgz",
|
|
||||||
"integrity": "sha512-NIp2TQSGfR6ba5aalZD+ZQ1fSxGhDo/s1w0nx3RYzf2pnJxt7YynxFlFScP6eV7+GZsKO95NSjGxyJsU3DZgeQ==",
|
|
||||||
"hasInstallScript": true,
|
|
||||||
"funding": {
|
|
||||||
"type": "opencollective",
|
|
||||||
"url": "https://opencollective.com/core-js"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/cose-base": {
|
"node_modules/cose-base": {
|
||||||
"version": "1.0.3",
|
"version": "1.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/cose-base/-/cose-base-1.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/cose-base/-/cose-base-1.0.3.tgz",
|
||||||
@ -3954,7 +3933,6 @@
|
|||||||
"resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.5.tgz",
|
"resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.5.tgz",
|
||||||
"integrity": "sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw==",
|
"integrity": "sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw==",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"node-fetch": "2.6.7"
|
"node-fetch": "2.6.7"
|
||||||
}
|
}
|
||||||
@ -3964,7 +3942,6 @@
|
|||||||
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz",
|
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz",
|
||||||
"integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==",
|
"integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"whatwg-url": "^5.0.0"
|
"whatwg-url": "^5.0.0"
|
||||||
},
|
},
|
||||||
@ -4103,9 +4080,9 @@
|
|||||||
"integrity": "sha512-dp3s92+uNI1hWIpPGH3jK2kxE2lMjdXdr+DH8ynZHpd6PUlH6x6cbuXnoMmiNumznqaNO31xu9e79F0uuZ0JFg=="
|
"integrity": "sha512-dp3s92+uNI1hWIpPGH3jK2kxE2lMjdXdr+DH8ynZHpd6PUlH6x6cbuXnoMmiNumznqaNO31xu9e79F0uuZ0JFg=="
|
||||||
},
|
},
|
||||||
"node_modules/d3": {
|
"node_modules/d3": {
|
||||||
"version": "7.8.5",
|
"version": "7.8.4",
|
||||||
"resolved": "https://registry.npmjs.org/d3/-/d3-7.8.5.tgz",
|
"resolved": "https://registry.npmjs.org/d3/-/d3-7.8.4.tgz",
|
||||||
"integrity": "sha512-JgoahDG51ncUfJu6wX/1vWQEqOflgXyl4MaHqlcSruTez7yhaRKR9i8VjjcQGeS2en/jnFivXuaIMnseMMt0XA==",
|
"integrity": "sha512-q2WHStdhiBtD8DMmhDPyJmXUxr6VWRngKyiJ5EfXMxPw+tqT6BhNjhJZ4w3BHsNm3QoVfZLY8Orq/qPFczwKRA==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"d3-array": "3",
|
"d3-array": "3",
|
||||||
"d3-axis": "3",
|
"d3-axis": "3",
|
||||||
@ -4512,6 +4489,7 @@
|
|||||||
"version": "7.0.10",
|
"version": "7.0.10",
|
||||||
"resolved": "https://registry.npmjs.org/dagre-d3-es/-/dagre-d3-es-7.0.10.tgz",
|
"resolved": "https://registry.npmjs.org/dagre-d3-es/-/dagre-d3-es-7.0.10.tgz",
|
||||||
"integrity": "sha512-qTCQmEhcynucuaZgY5/+ti3X/rnszKZhEQH/ZdWdtP1tA/y3VoHJzcVrO9pjjJCNpigfscAtoUB5ONcd2wNn0A==",
|
"integrity": "sha512-qTCQmEhcynucuaZgY5/+ti3X/rnszKZhEQH/ZdWdtP1tA/y3VoHJzcVrO9pjjJCNpigfscAtoUB5ONcd2wNn0A==",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"d3": "^7.8.2",
|
"d3": "^7.8.2",
|
||||||
"lodash-es": "^4.17.21"
|
"lodash-es": "^4.17.21"
|
||||||
@ -4538,9 +4516,10 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/dayjs": {
|
"node_modules/dayjs": {
|
||||||
"version": "1.11.8",
|
"version": "1.11.7",
|
||||||
"resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.8.tgz",
|
"resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.7.tgz",
|
||||||
"integrity": "sha512-LcgxzFoWMEPO7ggRv1Y2N31hUf2R0Vj7fuy/m+Bg1K8rr+KAs1AEy4y9jd5DXe8pbHgX+srkHNS7TH6Q6ZhYeQ=="
|
"integrity": "sha512-+Yw9U6YO5TQohxLcIkrXBeY73WP3ejHWVvx8XCk3gxvQDCTEmS48ZrSZCKciI7Bhl/uCMyxYtE9UqRILmFphkQ==",
|
||||||
|
"peer": true
|
||||||
},
|
},
|
||||||
"node_modules/debug": {
|
"node_modules/debug": {
|
||||||
"version": "4.3.4",
|
"version": "4.3.4",
|
||||||
@ -4706,8 +4685,7 @@
|
|||||||
"version": "0.0.1045489",
|
"version": "0.0.1045489",
|
||||||
"resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1045489.tgz",
|
"resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1045489.tgz",
|
||||||
"integrity": "sha512-D+PTmWulkuQW4D1NTiCRCFxF7pQPn0hgp4YyX4wAQ6xYXKOadSWPR3ENGDQ47MW/Ewc9v2rpC/UEEGahgBYpSQ==",
|
"integrity": "sha512-D+PTmWulkuQW4D1NTiCRCFxF7pQPn0hgp4YyX4wAQ6xYXKOadSWPR3ENGDQ47MW/Ewc9v2rpC/UEEGahgBYpSQ==",
|
||||||
"optional": true,
|
"optional": true
|
||||||
"peer": true
|
|
||||||
},
|
},
|
||||||
"node_modules/didyoumean": {
|
"node_modules/didyoumean": {
|
||||||
"version": "1.2.2",
|
"version": "1.2.2",
|
||||||
@ -4761,7 +4739,8 @@
|
|||||||
"node_modules/dompurify": {
|
"node_modules/dompurify": {
|
||||||
"version": "3.0.3",
|
"version": "3.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.0.3.tgz",
|
||||||
"integrity": "sha512-axQ9zieHLnAnHh0sfAamKYiqXMJAVwu+LM/alQ7WDagoWessyWvMSFyW65CqF3owufNu8HBcE4cM2Vflu7YWcQ=="
|
"integrity": "sha512-axQ9zieHLnAnHh0sfAamKYiqXMJAVwu+LM/alQ7WDagoWessyWvMSFyW65CqF3owufNu8HBcE4cM2Vflu7YWcQ==",
|
||||||
|
"peer": true
|
||||||
},
|
},
|
||||||
"node_modules/downshift": {
|
"node_modules/downshift": {
|
||||||
"version": "6.1.12",
|
"version": "6.1.12",
|
||||||
@ -4828,7 +4807,6 @@
|
|||||||
"resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz",
|
"resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz",
|
||||||
"integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==",
|
"integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"once": "^1.4.0"
|
"once": "^1.4.0"
|
||||||
}
|
}
|
||||||
@ -5543,7 +5521,6 @@
|
|||||||
"resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz",
|
||||||
"integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==",
|
"integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"debug": "^4.1.1",
|
"debug": "^4.1.1",
|
||||||
"get-stream": "^5.1.0",
|
"get-stream": "^5.1.0",
|
||||||
@ -5638,7 +5615,6 @@
|
|||||||
"resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz",
|
||||||
"integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==",
|
"integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"pend": "~1.2.0"
|
"pend": "~1.2.0"
|
||||||
}
|
}
|
||||||
@ -5773,8 +5749,7 @@
|
|||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz",
|
||||||
"integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==",
|
"integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==",
|
||||||
"optional": true,
|
"optional": true
|
||||||
"peer": true
|
|
||||||
},
|
},
|
||||||
"node_modules/fs-extra": {
|
"node_modules/fs-extra": {
|
||||||
"version": "10.1.0",
|
"version": "10.1.0",
|
||||||
@ -5909,7 +5884,6 @@
|
|||||||
"resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz",
|
||||||
"integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==",
|
"integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"pump": "^3.0.0"
|
"pump": "^3.0.0"
|
||||||
},
|
},
|
||||||
@ -6482,8 +6456,7 @@
|
|||||||
"url": "https://feross.org/support"
|
"url": "https://feross.org/support"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"optional": true,
|
"optional": true
|
||||||
"peer": true
|
|
||||||
},
|
},
|
||||||
"node_modules/ignore": {
|
"node_modules/ignore": {
|
||||||
"version": "5.2.4",
|
"version": "5.2.4",
|
||||||
@ -7377,9 +7350,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/lit": {
|
"node_modules/lit": {
|
||||||
"version": "2.7.5",
|
"version": "2.7.4",
|
||||||
"resolved": "https://registry.npmjs.org/lit/-/lit-2.7.5.tgz",
|
"resolved": "https://registry.npmjs.org/lit/-/lit-2.7.4.tgz",
|
||||||
"integrity": "sha512-i/cH7Ye6nBDUASMnfwcictBnsTN91+aBjXoTHF2xARghXScKxpD4F4WYI+VLXg9lqbMinDfvoI7VnZXjyHgdfQ==",
|
"integrity": "sha512-cgD7xrZoYr21mbrkZIuIrj98YTMw/snJPg52deWVV4A8icLyNHI3bF70xsJeAgwTuiq5Kkd+ZR8gybSJDCPB7g==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@lit/reactive-element": "^1.6.0",
|
"@lit/reactive-element": "^1.6.0",
|
||||||
"lit-element": "^3.3.0",
|
"lit-element": "^3.3.0",
|
||||||
@ -8020,23 +7993,6 @@
|
|||||||
"url": "https://github.com/sponsors/wooorm"
|
"url": "https://github.com/sponsors/wooorm"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/mddb": {
|
|
||||||
"version": "0.1.9",
|
|
||||||
"resolved": "https://registry.npmjs.org/mddb/-/mddb-0.1.9.tgz",
|
|
||||||
"integrity": "sha512-d3B5zArnWDqKN1Blq6hGtfr3HTHUKK/GS95b4OZqcyDPvUP4JnYuWHDjyoJ0tSgDKH6ybB6WdnnI3tcHQvRTyw==",
|
|
||||||
"dependencies": {
|
|
||||||
"@flowershow/remark-wiki-link": "^1.1.2",
|
|
||||||
"gray-matter": "^4.0.3",
|
|
||||||
"knex": "^2.4.2",
|
|
||||||
"remark-gfm": "^3.0.1",
|
|
||||||
"remark-parse": "^10.0.1",
|
|
||||||
"sqlite3": "^5.1.6",
|
|
||||||
"unist-util-select": "^4.0.3"
|
|
||||||
},
|
|
||||||
"bin": {
|
|
||||||
"mddb": "dist/src/bin/index.js"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/mdn-data": {
|
"node_modules/mdn-data": {
|
||||||
"version": "2.0.14",
|
"version": "2.0.14",
|
||||||
"resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.14.tgz",
|
"resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.14.tgz",
|
||||||
@ -8046,7 +8002,6 @@
|
|||||||
"version": "2.0.0-rc7",
|
"version": "2.0.0-rc7",
|
||||||
"resolved": "https://registry.npmjs.org/mdx-mermaid/-/mdx-mermaid-2.0.0-rc7.tgz",
|
"resolved": "https://registry.npmjs.org/mdx-mermaid/-/mdx-mermaid-2.0.0-rc7.tgz",
|
||||||
"integrity": "sha512-AMy3138EsvcGwE4cGqUVytj4mLpJ3TJ2nek82+67Qi4GSOXoelAqmQudHSk26IsP091c3qX4d/4wi9CqLwFl9Q==",
|
"integrity": "sha512-AMy3138EsvcGwE4cGqUVytj4mLpJ3TJ2nek82+67Qi4GSOXoelAqmQudHSk26IsP091c3qX4d/4wi9CqLwFl9Q==",
|
||||||
"peer": true,
|
|
||||||
"optionalDependencies": {
|
"optionalDependencies": {
|
||||||
"estree-util-to-js": "^1.1.0",
|
"estree-util-to-js": "^1.1.0",
|
||||||
"estree-util-visit": "^1.2.0",
|
"estree-util-visit": "^1.2.0",
|
||||||
@ -8077,9 +8032,10 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/mermaid": {
|
"node_modules/mermaid": {
|
||||||
"version": "10.2.3",
|
"version": "10.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/mermaid/-/mermaid-10.2.3.tgz",
|
"resolved": "https://registry.npmjs.org/mermaid/-/mermaid-10.2.0.tgz",
|
||||||
"integrity": "sha512-cMVE5s9PlQvOwfORkyVpr5beMsLdInrycAosdr+tpZ0WFjG4RJ/bUHST7aTgHNJbujHkdBRAm+N50P3puQOfPw==",
|
"integrity": "sha512-mYKXlH9ngKdMsJ87VYMdlDZXS+MXDAGKPf3XzDf2vvAPnmRoFm7GFebemOAOWYI1bWSECDyoWTGwesWe6mW1Cw==",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@braintree/sanitize-url": "^6.0.2",
|
"@braintree/sanitize-url": "^6.0.2",
|
||||||
"cytoscape": "^3.23.0",
|
"cytoscape": "^3.23.0",
|
||||||
@ -8943,8 +8899,7 @@
|
|||||||
"version": "0.5.3",
|
"version": "0.5.3",
|
||||||
"resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz",
|
"resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz",
|
||||||
"integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==",
|
"integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==",
|
||||||
"optional": true,
|
"optional": true
|
||||||
"peer": true
|
|
||||||
},
|
},
|
||||||
"node_modules/modern-normalize": {
|
"node_modules/modern-normalize": {
|
||||||
"version": "1.1.0",
|
"version": "1.1.0",
|
||||||
@ -8957,6 +8912,11 @@
|
|||||||
"url": "https://github.com/sponsors/sindresorhus"
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/moment-mini": {
|
||||||
|
"version": "2.29.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/moment-mini/-/moment-mini-2.29.4.tgz",
|
||||||
|
"integrity": "sha512-uhXpYwHFeiTbY9KSgPPRoo1nt8OxNVdMVoTBYHfSEKeRkIkwGpO+gERmhuhBtzfaeOyTkykSrm2+noJBgqt3Hg=="
|
||||||
|
},
|
||||||
"node_modules/mri": {
|
"node_modules/mri": {
|
||||||
"version": "1.2.0",
|
"version": "1.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz",
|
||||||
@ -9681,8 +9641,7 @@
|
|||||||
"version": "1.2.0",
|
"version": "1.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz",
|
||||||
"integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==",
|
"integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==",
|
||||||
"optional": true,
|
"optional": true
|
||||||
"peer": true
|
|
||||||
},
|
},
|
||||||
"node_modules/periscopic": {
|
"node_modules/periscopic": {
|
||||||
"version": "3.1.0",
|
"version": "3.1.0",
|
||||||
@ -9891,7 +9850,6 @@
|
|||||||
"resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz",
|
||||||
"integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==",
|
"integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"peer": true,
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=0.4.0"
|
"node": ">=0.4.0"
|
||||||
}
|
}
|
||||||
@ -9938,15 +9896,13 @@
|
|||||||
"version": "1.1.0",
|
"version": "1.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
|
||||||
"integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==",
|
"integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==",
|
||||||
"optional": true,
|
"optional": true
|
||||||
"peer": true
|
|
||||||
},
|
},
|
||||||
"node_modules/pump": {
|
"node_modules/pump": {
|
||||||
"version": "3.0.0",
|
"version": "3.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz",
|
||||||
"integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==",
|
"integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"end-of-stream": "^1.1.0",
|
"end-of-stream": "^1.1.0",
|
||||||
"once": "^1.3.1"
|
"once": "^1.3.1"
|
||||||
@ -9967,7 +9923,6 @@
|
|||||||
"deprecated": "< 19.4.0 is no longer supported",
|
"deprecated": "< 19.4.0 is no longer supported",
|
||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"https-proxy-agent": "5.0.1",
|
"https-proxy-agent": "5.0.1",
|
||||||
"progress": "2.0.3",
|
"progress": "2.0.3",
|
||||||
@ -9983,7 +9938,6 @@
|
|||||||
"resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-18.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-18.2.1.tgz",
|
||||||
"integrity": "sha512-MRtTAZfQTluz3U2oU/X2VqVWPcR1+94nbA2V6ZrSZRVEwLqZ8eclZ551qGFQD/vD2PYqHJwWOW/fpC721uznVw==",
|
"integrity": "sha512-MRtTAZfQTluz3U2oU/X2VqVWPcR1+94nbA2V6ZrSZRVEwLqZ8eclZ551qGFQD/vD2PYqHJwWOW/fpC721uznVw==",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"cross-fetch": "3.1.5",
|
"cross-fetch": "3.1.5",
|
||||||
"debug": "4.3.4",
|
"debug": "4.3.4",
|
||||||
@ -10850,15 +10804,6 @@
|
|||||||
"url": "https://github.com/sponsors/sindresorhus"
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/search-insights": {
|
|
||||||
"version": "2.6.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/search-insights/-/search-insights-2.6.0.tgz",
|
|
||||||
"integrity": "sha512-vU2/fJ+h/Mkm/DJOe+EaM5cafJv/1rRTZpGJTuFPf/Q5LjzgMDsqPdSaZsAe+GAWHHsfsu+rQSAn6c8IGtBEVw==",
|
|
||||||
"peer": true,
|
|
||||||
"engines": {
|
|
||||||
"node": ">=8.16.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/section-matter": {
|
"node_modules/section-matter": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/section-matter/-/section-matter-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/section-matter/-/section-matter-1.0.0.tgz",
|
||||||
@ -11458,7 +11403,6 @@
|
|||||||
"resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz",
|
||||||
"integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==",
|
"integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"chownr": "^1.1.1",
|
"chownr": "^1.1.1",
|
||||||
"mkdirp-classic": "^0.5.2",
|
"mkdirp-classic": "^0.5.2",
|
||||||
@ -11470,15 +11414,13 @@
|
|||||||
"version": "1.1.4",
|
"version": "1.1.4",
|
||||||
"resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz",
|
"resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz",
|
||||||
"integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==",
|
"integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==",
|
||||||
"optional": true,
|
"optional": true
|
||||||
"peer": true
|
|
||||||
},
|
},
|
||||||
"node_modules/tar-stream": {
|
"node_modules/tar-stream": {
|
||||||
"version": "2.2.0",
|
"version": "2.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz",
|
||||||
"integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==",
|
"integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"bl": "^4.0.3",
|
"bl": "^4.0.3",
|
||||||
"end-of-stream": "^1.4.1",
|
"end-of-stream": "^1.4.1",
|
||||||
@ -11542,8 +11484,7 @@
|
|||||||
"version": "2.3.8",
|
"version": "2.3.8",
|
||||||
"resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
|
"resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
|
||||||
"integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==",
|
"integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==",
|
||||||
"optional": true,
|
"optional": true
|
||||||
"peer": true
|
|
||||||
},
|
},
|
||||||
"node_modules/tildify": {
|
"node_modules/tildify": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
@ -11926,7 +11867,6 @@
|
|||||||
"resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz",
|
"resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz",
|
||||||
"integrity": "sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg==",
|
"integrity": "sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg==",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"buffer": "^5.2.1",
|
"buffer": "^5.2.1",
|
||||||
"through": "^2.3.8"
|
"through": "^2.3.8"
|
||||||
@ -12940,7 +12880,6 @@
|
|||||||
"resolved": "https://registry.npmjs.org/ws/-/ws-8.9.0.tgz",
|
"resolved": "https://registry.npmjs.org/ws/-/ws-8.9.0.tgz",
|
||||||
"integrity": "sha512-Ja7nszREasGaYUYCI2k4lCKIRTt+y7XuqVoHR44YpI49TtryyqbqvDMn5eqfW7e6HzTukDRIsXqzVHScqRcafg==",
|
"integrity": "sha512-Ja7nszREasGaYUYCI2k4lCKIRTt+y7XuqVoHR44YpI49TtryyqbqvDMn5eqfW7e6HzTukDRIsXqzVHScqRcafg==",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"peer": true,
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=10.0.0"
|
"node": ">=10.0.0"
|
||||||
},
|
},
|
||||||
@ -13016,7 +12955,6 @@
|
|||||||
"resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz",
|
"resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz",
|
||||||
"integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==",
|
"integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"buffer-crc32": "~0.2.3",
|
"buffer-crc32": "~0.2.3",
|
||||||
"fd-slicer": "~1.1.0"
|
"fd-slicer": "~1.1.0"
|
||||||
|
|||||||
@ -10,17 +10,16 @@
|
|||||||
"prettier": "prettier --write ."
|
"prettier": "prettier --write ."
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@flowershow/core": "^0.4.13",
|
||||||
|
"@flowershow/markdowndb": "^0.1.5",
|
||||||
|
"@flowershow/remark-callouts": "^1.0.0",
|
||||||
|
"@flowershow/remark-embed": "^1.0.0",
|
||||||
"@portaljs/components": "^0.1.6",
|
"@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/node": "18.16.0",
|
||||||
"@types/react": "18.0.38",
|
"@types/react": "18.0.38",
|
||||||
"@types/react-dom": "18.0.11",
|
"@types/react-dom": "18.0.11",
|
||||||
"eslint": "8.39.0",
|
"eslint": "8.39.0",
|
||||||
"eslint-config-next": "13.3.1",
|
"eslint-config-next": "13.3.1",
|
||||||
"mddb": "^0.1.9",
|
|
||||||
"next": "13.4.3",
|
"next": "13.4.3",
|
||||||
"next-mdx-remote": "^4.4.1",
|
"next-mdx-remote": "^4.4.1",
|
||||||
"next-seo": "^6.0.0",
|
"next-seo": "^6.0.0",
|
||||||
|
|||||||
@ -40,7 +40,7 @@ export function Datasets({ projects }) {
|
|||||||
<Link
|
<Link
|
||||||
target="_blank"
|
target="_blank"
|
||||||
className="underline"
|
className="underline"
|
||||||
href="https://portaljs.com/"
|
href="https://portaljs.org/"
|
||||||
>
|
>
|
||||||
🌀 PortalJS
|
🌀 PortalJS
|
||||||
</Link>
|
</Link>
|
||||||
|
|||||||
@ -79,7 +79,7 @@ pre {
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
@import "@portaljs/remark-callouts/styles.css";
|
@import "@flowershow/remark-callouts/styles.css";
|
||||||
|
|
||||||
/* mathjax */
|
/* mathjax */
|
||||||
.math-inline > mjx-container > svg {
|
.math-inline > mjx-container > svg {
|
||||||
|
|||||||
@ -1 +1 @@
|
|||||||
PortalJS Learn Example - https://portaljs.com/docs
|
PortalJS Learn Example - https://portaljs.org/docs
|
||||||
@ -1,19 +1,19 @@
|
|||||||
import { MDXRemote } from 'next-mdx-remote';
|
import { MDXRemote } from 'next-mdx-remote';
|
||||||
import dynamic from 'next/dynamic';
|
import dynamic from 'next/dynamic';
|
||||||
import { Mermaid } from '@portaljs/core';
|
import { Mermaid } from '@flowershow/core';
|
||||||
|
|
||||||
// Custom components/renderers to pass to MDX.
|
// Custom components/renderers to pass to MDX.
|
||||||
// Since the MDX files aren't loaded by webpack, they have no knowledge of how
|
// 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
|
// to handle import statements. Instead, you must include components in scope
|
||||||
// here.
|
// here.
|
||||||
const components = {
|
const components = {
|
||||||
Table: dynamic(() => import('@portaljs/components').then(mod => mod.Table)),
|
Table: dynamic(() => import('../portaljs/components/Table').then(mod => mod.Table)),
|
||||||
Catalog: dynamic(() => import('@portaljs/components').then(mod => mod.Catalog)),
|
Catalog: dynamic(() => import('../portaljs/components/Catalog').then(mod => mod.Catalog)),
|
||||||
mermaid: Mermaid,
|
mermaid: Mermaid,
|
||||||
Vega: dynamic(() => import('@portaljs/components').then(mod => mod.Vega)),
|
Vega: dynamic(() => import('../portaljs/components/Vega').then(mod => mod.Vega)),
|
||||||
VegaLite: dynamic(() => import('@portaljs/components').then(mod => mod.VegaLite)),
|
VegaLite: dynamic(() => import('../portaljs/components/VegaLite').then(mod => mod.VegaLite)),
|
||||||
LineChart: dynamic(() => import('@portaljs/components').then(mod => mod.LineChart)),
|
LineChart: dynamic(() => import('../portaljs/components/LineChart').then(mod => mod.LineChart)),
|
||||||
FlatUiTable: dynamic(() => import('@portaljs/components').then(mod => mod.FlatUiTable)),
|
FlatUiTable: dynamic(() => import('../portaljs/components/FlatUiTable').then(mod => mod.FlatUiTable)),
|
||||||
} as any;
|
} as any;
|
||||||
|
|
||||||
export default function DRD({ source }: { source: any }) {
|
export default function DRD({ source }: { source: any }) {
|
||||||
|
|||||||
@ -1,13 +1,13 @@
|
|||||||
import matter from "gray-matter";
|
import matter from "gray-matter";
|
||||||
import mdxmermaid from "mdx-mermaid";
|
import mdxmermaid from "mdx-mermaid";
|
||||||
import { h } from "hastscript";
|
import { h } from "hastscript";
|
||||||
import remarkCallouts from "@portaljs/remark-callouts";
|
import remarkCallouts from "@flowershow/remark-callouts";
|
||||||
import remarkEmbed from "@portaljs/remark-embed";
|
import remarkEmbed from "@flowershow/remark-embed";
|
||||||
import remarkGfm from "remark-gfm";
|
import remarkGfm from "remark-gfm";
|
||||||
import remarkMath from "remark-math";
|
import remarkMath from "remark-math";
|
||||||
import remarkSmartypants from "remark-smartypants";
|
import remarkSmartypants from "remark-smartypants";
|
||||||
import remarkToc from "remark-toc";
|
import remarkToc from "remark-toc";
|
||||||
import remarkWikiLink from "@portaljs/remark-wiki-link";
|
import remarkWikiLink from "@flowershow/remark-wiki-link";
|
||||||
import rehypeAutolinkHeadings from "rehype-autolink-headings";
|
import rehypeAutolinkHeadings from "rehype-autolink-headings";
|
||||||
import rehypeKatex from "rehype-katex";
|
import rehypeKatex from "rehype-katex";
|
||||||
import rehypeSlug from "rehype-slug";
|
import rehypeSlug from "rehype-slug";
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import { MarkdownDB } from "mddb";
|
import { MarkdownDB } from "@flowershow/markdowndb";
|
||||||
|
|
||||||
const dbPath = "markdown.db";
|
const dbPath = "markdown.db";
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +0,0 @@
|
|||||||
const nextConfig = {
|
|
||||||
swcMinify: false
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = nextConfig
|
|
||||||
2636
examples/learn/package-lock.json
generated
2636
examples/learn/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -12,28 +12,17 @@
|
|||||||
"mddb": "mddb ./content"
|
"mddb": "mddb ./content"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@githubocto/flat-ui": "^0.14.1",
|
"@flowershow/core": "^0.4.10",
|
||||||
"@heroicons/react": "^2.0.17",
|
"@flowershow/markdowndb": "^0.1.1",
|
||||||
|
"@flowershow/remark-callouts": "^1.0.0",
|
||||||
|
"@flowershow/remark-embed": "^1.0.0",
|
||||||
|
"@flowershow/remark-wiki-link": "^1.1.2",
|
||||||
"@opentelemetry/api": "^1.4.0",
|
"@opentelemetry/api": "^1.4.0",
|
||||||
"@portaljs/components": "^0.1.8",
|
"@portaljs/components": "^0.1.0",
|
||||||
"@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",
|
"gray-matter": "^4.0.3",
|
||||||
"hastscript": "^7.2.0",
|
"hastscript": "^7.2.0",
|
||||||
"mddb": "^0.1.9",
|
|
||||||
"mdx-mermaid": "2.0.0-rc7",
|
"mdx-mermaid": "2.0.0-rc7",
|
||||||
"next": "13.2.1",
|
"next": "13.2.1",
|
||||||
"next-mdx-remote": "^4.4.1",
|
|
||||||
"papaparse": "^5.4.1",
|
|
||||||
"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-autolink-headings": "^6.1.1",
|
||||||
"rehype-katex": "^6.0.3",
|
"rehype-katex": "^6.0.3",
|
||||||
"rehype-prism-plus": "^1.5.1",
|
"rehype-prism-plus": "^1.5.1",
|
||||||
@ -43,6 +32,17 @@
|
|||||||
"remark-smartypants": "^2.0.0",
|
"remark-smartypants": "^2.0.0",
|
||||||
"remark-toc": "^8.0.1",
|
"remark-toc": "^8.0.1",
|
||||||
"typescript": "5.0.4",
|
"typescript": "5.0.4",
|
||||||
|
"@githubocto/flat-ui": "^0.14.1",
|
||||||
|
"@heroicons/react": "^2.0.17",
|
||||||
|
"@tanstack/react-table": "^8.8.5",
|
||||||
|
"flexsearch": "0.7.21",
|
||||||
|
"next-mdx-remote": "^4.4.1",
|
||||||
|
"papaparse": "^5.4.1",
|
||||||
|
"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",
|
||||||
"vega": "5.25.0",
|
"vega": "5.25.0",
|
||||||
"vega-lite": "5.1.0"
|
"vega-lite": "5.1.0"
|
||||||
},
|
},
|
||||||
|
|||||||
@ -81,7 +81,7 @@ export default function DatasetPage({ mdxSource, frontMatter }) {
|
|||||||
<p className="my-0">
|
<p className="my-0">
|
||||||
<span className="font-semibold">Modified: </span>
|
<span className="font-semibold">Modified: </span>
|
||||||
<span className="description my-0">
|
<span className="description my-0">
|
||||||
{new Date(frontMatter.modified).toLocaleDateString("en-US")}
|
{new Date(frontMatter.modified).toLocaleDateString()}
|
||||||
</span>
|
</span>
|
||||||
</p>
|
</p>
|
||||||
)}
|
)}
|
||||||
|
|||||||
119
examples/learn/portaljs/components/Catalog.tsx
Normal file
119
examples/learn/portaljs/components/Catalog.tsx
Normal file
@ -0,0 +1,119 @@
|
|||||||
|
import { Index } from 'flexsearch';
|
||||||
|
import { useState } from 'react';
|
||||||
|
import DebouncedInput from './DebouncedInput';
|
||||||
|
import { useForm } from 'react-hook-form';
|
||||||
|
|
||||||
|
export function Catalog({
|
||||||
|
datasets,
|
||||||
|
facets,
|
||||||
|
}: {
|
||||||
|
datasets: any[];
|
||||||
|
facets: string[];
|
||||||
|
}) {
|
||||||
|
const [indexFilter, setIndexFilter] = useState('');
|
||||||
|
const index = new Index({ tokenize: 'full' });
|
||||||
|
datasets.forEach((dataset) =>
|
||||||
|
index.add(
|
||||||
|
dataset._id,
|
||||||
|
//This will join every metadata value + the url_path into one big string and index that
|
||||||
|
Object.entries(dataset.metadata).reduce(
|
||||||
|
(acc, curr) => acc + ' ' + curr[1].toString(),
|
||||||
|
''
|
||||||
|
) +
|
||||||
|
' ' +
|
||||||
|
dataset.url_path
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
const facetValues = facets
|
||||||
|
? facets.reduce((acc, facet) => {
|
||||||
|
const possibleValues = datasets.reduce((acc, curr) => {
|
||||||
|
const facetValue = curr.metadata[facet];
|
||||||
|
if (facetValue) {
|
||||||
|
return Array.isArray(facetValue)
|
||||||
|
? acc.concat(facetValue)
|
||||||
|
: acc.concat([facetValue]);
|
||||||
|
}
|
||||||
|
return acc;
|
||||||
|
}, []);
|
||||||
|
acc[facet] = {
|
||||||
|
possibleValues: [...new Set(possibleValues)],
|
||||||
|
selectedValue: null,
|
||||||
|
};
|
||||||
|
return acc;
|
||||||
|
}, {})
|
||||||
|
: [];
|
||||||
|
|
||||||
|
const { register, watch } = useForm(facetValues);
|
||||||
|
|
||||||
|
const filteredDatasets = datasets
|
||||||
|
// First filter by flex search
|
||||||
|
.filter((dataset) =>
|
||||||
|
indexFilter !== ''
|
||||||
|
? index.search(indexFilter).includes(dataset._id)
|
||||||
|
: true
|
||||||
|
)
|
||||||
|
//Then check if the selectedValue for the given facet is included in the dataset metadata
|
||||||
|
.filter((dataset) => {
|
||||||
|
//Avoids a server rendering breakage
|
||||||
|
if (!watch() || Object.keys(watch()).length === 0) return true
|
||||||
|
//This will filter only the key pairs of the metadata values that were selected as facets
|
||||||
|
const datasetFacets = Object.entries(dataset.metadata).filter((entry) =>
|
||||||
|
facets.includes(entry[0])
|
||||||
|
);
|
||||||
|
//Check if the value present is included in the selected value in the form
|
||||||
|
return datasetFacets.every((elem) =>
|
||||||
|
watch()[elem[0]].selectedValue
|
||||||
|
? (elem[1] as string | string[]).includes(
|
||||||
|
watch()[elem[0]].selectedValue
|
||||||
|
)
|
||||||
|
: true
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<DebouncedInput
|
||||||
|
value={indexFilter ?? ''}
|
||||||
|
onChange={(value) => setIndexFilter(String(value))}
|
||||||
|
className="p-2 text-sm shadow border border-block mr-1"
|
||||||
|
placeholder="Search all datasets..."
|
||||||
|
/>
|
||||||
|
{Object.entries(facetValues).map((elem) => (
|
||||||
|
<select
|
||||||
|
key={elem[0]}
|
||||||
|
defaultValue=""
|
||||||
|
className="p-2 ml-1 text-sm shadow border border-block"
|
||||||
|
{...register(elem[0] + '.selectedValue')}
|
||||||
|
>
|
||||||
|
<option value="">
|
||||||
|
Filter by {elem[0]}
|
||||||
|
</option>
|
||||||
|
{(elem[1] as { possibleValues: string[] }).possibleValues.map(
|
||||||
|
(val) => (
|
||||||
|
<option
|
||||||
|
key={val}
|
||||||
|
className="dark:bg-white dark:text-black"
|
||||||
|
value={val}
|
||||||
|
>
|
||||||
|
{val}
|
||||||
|
</option>
|
||||||
|
)
|
||||||
|
)}
|
||||||
|
</select>
|
||||||
|
))}
|
||||||
|
<ul className='mb-5 pl-6 mt-5 list-disc'>
|
||||||
|
{filteredDatasets.map((dataset) => (
|
||||||
|
<li className='py-2' key={dataset._id}>
|
||||||
|
<a className='font-medium underline' href={dataset.url_path}>
|
||||||
|
{dataset.metadata.title
|
||||||
|
? dataset.metadata.title
|
||||||
|
: dataset.url_path}
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
32
examples/learn/portaljs/components/DebouncedInput.tsx
Normal file
32
examples/learn/portaljs/components/DebouncedInput.tsx
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
import { useEffect, useState } from "react";
|
||||||
|
|
||||||
|
const DebouncedInput = ({
|
||||||
|
value: initialValue,
|
||||||
|
onChange,
|
||||||
|
debounce = 500,
|
||||||
|
...props
|
||||||
|
}) => {
|
||||||
|
const [value, setValue] = useState(initialValue);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setValue(initialValue);
|
||||||
|
}, [initialValue]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const timeout = setTimeout(() => {
|
||||||
|
onChange(value);
|
||||||
|
}, debounce);
|
||||||
|
|
||||||
|
return () => clearTimeout(timeout);
|
||||||
|
}, [value]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<input
|
||||||
|
{...props}
|
||||||
|
value={value}
|
||||||
|
onChange={(e) => setValue(e.target.value)}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default DebouncedInput;
|
||||||
113
examples/learn/portaljs/components/FlatUiTable.tsx
Normal file
113
examples/learn/portaljs/components/FlatUiTable.tsx
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
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, corsProxy?: string) {
|
||||||
|
if (corsProxy) {
|
||||||
|
url = corsProxy + url
|
||||||
|
}
|
||||||
|
const response = await fetch(url, {
|
||||||
|
headers: {
|
||||||
|
Range: 'bytes=0-5132288',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const data = await response.text();
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function parseCsv(file: string): Promise<any> {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
Papa.parse(file, {
|
||||||
|
header: true,
|
||||||
|
dynamicTyping: true,
|
||||||
|
skipEmptyLines: true,
|
||||||
|
transform: (value: string): string => {
|
||||||
|
return value.trim();
|
||||||
|
},
|
||||||
|
complete: (results: any) => {
|
||||||
|
return resolve(results);
|
||||||
|
},
|
||||||
|
error: (error: any) => {
|
||||||
|
return reject(error);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const Spinning = () => {
|
||||||
|
return (
|
||||||
|
<div role="status w-fit mx-auto">
|
||||||
|
<svg
|
||||||
|
aria-hidden="true"
|
||||||
|
className="w-8 h-8 mr-2 text-gray-200 animate-spin dark:text-gray-600 fill-emerald-600"
|
||||||
|
viewBox="0 0 100 101"
|
||||||
|
fill="none"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M100 50.5908C100 78.2051 77.6142 100.591 50 100.591C22.3858 100.591 0 78.2051 0 50.5908C0 22.9766 22.3858 0.59082 50 0.59082C77.6142 0.59082 100 22.9766 100 50.5908ZM9.08144 50.5908C9.08144 73.1895 27.4013 91.5094 50 91.5094C72.5987 91.5094 90.9186 73.1895 90.9186 50.5908C90.9186 27.9921 72.5987 9.67226 50 9.67226C27.4013 9.67226 9.08144 27.9921 9.08144 50.5908Z"
|
||||||
|
fill="currentColor"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
d="M93.9676 39.0409C96.393 38.4038 97.8624 35.9116 97.0079 33.5539C95.2932 28.8227 92.871 24.3692 89.8167 20.348C85.8452 15.1192 80.8826 10.7238 75.2124 7.41289C69.5422 4.10194 63.2754 1.94025 56.7698 1.05124C51.7666 0.367541 46.6976 0.446843 41.7345 1.27873C39.2613 1.69328 37.813 4.19778 38.4501 6.62326C39.0873 9.04874 41.5694 10.4717 44.0505 10.1071C47.8511 9.54855 51.7191 9.52689 55.5402 10.0491C60.8642 10.7766 65.9928 12.5457 70.6331 15.2552C75.2735 17.9648 79.3347 21.5619 82.5849 25.841C84.9175 28.9121 86.7997 32.2913 88.1811 35.8758C89.083 38.2158 91.5421 39.6781 93.9676 39.0409Z"
|
||||||
|
fill="currentFill"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
<span className="sr-only">Loading...</span>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export interface FlatUiTableProps {
|
||||||
|
url?: string;
|
||||||
|
data?: { [key: string]: number | string }[];
|
||||||
|
rawCsv?: string;
|
||||||
|
corsProxy?: string;
|
||||||
|
}
|
||||||
|
export const FlatUiTable: React.FC<FlatUiTableProps> = ({
|
||||||
|
url,
|
||||||
|
data,
|
||||||
|
rawCsv,
|
||||||
|
corsProxy,
|
||||||
|
}) => {
|
||||||
|
return (
|
||||||
|
// Provide the client to your App
|
||||||
|
<QueryClientProvider client={queryClient}>
|
||||||
|
<TableInner corsProxy={corsProxy} url={url} data={data} rawCsv={rawCsv} />
|
||||||
|
</QueryClientProvider>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const TableInner: React.FC<FlatUiTableProps> = ({ url, data, rawCsv, corsProxy }) => {
|
||||||
|
if (data) {
|
||||||
|
return (
|
||||||
|
<div className="w-full" style={{height: '500px'}}>
|
||||||
|
<Grid data={data} />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
const { data: csvString, isLoading: isDownloadingCSV } = useQuery(
|
||||||
|
['dataCsv', url],
|
||||||
|
() => getCsv(url as string, corsProxy),
|
||||||
|
{ enabled: !!url }
|
||||||
|
);
|
||||||
|
const { data: parsedData, isLoading: isParsing } = useQuery(
|
||||||
|
['dataPreview', csvString],
|
||||||
|
() => parseCsv(rawCsv ? rawCsv as string : csvString as string),
|
||||||
|
{ enabled: rawCsv ? true : !!csvString }
|
||||||
|
);
|
||||||
|
if (isParsing || isDownloadingCSV)
|
||||||
|
<div className="w-full">
|
||||||
|
<Spinning />
|
||||||
|
</div>;
|
||||||
|
if (parsedData)
|
||||||
|
return (
|
||||||
|
<div className="w-full" style={{height: '500px'}}>
|
||||||
|
<Grid data={parsedData.data} />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
return <Spinning />
|
||||||
|
};
|
||||||
|
|
||||||
63
examples/learn/portaljs/components/LineChart.tsx
Normal file
63
examples/learn/portaljs/components/LineChart.tsx
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
import { VegaLite } from './VegaLite';
|
||||||
|
|
||||||
|
export type LineChartProps = {
|
||||||
|
data: Array<Array<string | number>> | string | { x: string; y: number }[];
|
||||||
|
title?: string;
|
||||||
|
xAxis?: string;
|
||||||
|
yAxis?: string;
|
||||||
|
fullWidth?: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
export function LineChart({
|
||||||
|
data = [],
|
||||||
|
fullWidth = false,
|
||||||
|
title = '',
|
||||||
|
xAxis = 'x',
|
||||||
|
yAxis = 'y',
|
||||||
|
}: LineChartProps) {
|
||||||
|
var tmp = data;
|
||||||
|
if (Array.isArray(data)) {
|
||||||
|
tmp = data.map((r) => {
|
||||||
|
return { x: r[0], y: r[1] };
|
||||||
|
});
|
||||||
|
}
|
||||||
|
const vegaData = { table: tmp };
|
||||||
|
const spec = {
|
||||||
|
$schema: 'https://vega.github.io/schema/vega-lite/v5.json',
|
||||||
|
title,
|
||||||
|
width: 600,
|
||||||
|
height: 300,
|
||||||
|
mark: {
|
||||||
|
type: 'line',
|
||||||
|
color: 'black',
|
||||||
|
strokeWidth: 1,
|
||||||
|
tooltip: true,
|
||||||
|
},
|
||||||
|
data: {
|
||||||
|
name: 'table',
|
||||||
|
},
|
||||||
|
selection: {
|
||||||
|
grid: {
|
||||||
|
type: 'interval',
|
||||||
|
bind: 'scales',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
encoding: {
|
||||||
|
x: {
|
||||||
|
field: xAxis,
|
||||||
|
timeUnit: 'year',
|
||||||
|
type: 'temporal',
|
||||||
|
},
|
||||||
|
y: {
|
||||||
|
field: yAxis,
|
||||||
|
type: 'quantitative',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
if (typeof data === 'string') {
|
||||||
|
spec.data = { url: data } as any;
|
||||||
|
return <VegaLite fullWidth={fullWidth} spec={spec} />;
|
||||||
|
}
|
||||||
|
|
||||||
|
return <VegaLite fullWidth={fullWidth} data={vegaData} spec={spec} />;
|
||||||
|
}
|
||||||
195
examples/learn/portaljs/components/Table.tsx
Normal file
195
examples/learn/portaljs/components/Table.tsx
Normal file
@ -0,0 +1,195 @@
|
|||||||
|
import {
|
||||||
|
createColumnHelper,
|
||||||
|
FilterFn,
|
||||||
|
flexRender,
|
||||||
|
getCoreRowModel,
|
||||||
|
getFilteredRowModel,
|
||||||
|
getPaginationRowModel,
|
||||||
|
getSortedRowModel,
|
||||||
|
useReactTable,
|
||||||
|
} from '@tanstack/react-table';
|
||||||
|
|
||||||
|
import {
|
||||||
|
ArrowDownIcon,
|
||||||
|
ArrowUpIcon,
|
||||||
|
ChevronDoubleLeftIcon,
|
||||||
|
ChevronDoubleRightIcon,
|
||||||
|
ChevronLeftIcon,
|
||||||
|
ChevronRightIcon,
|
||||||
|
} from '@heroicons/react/24/solid';
|
||||||
|
|
||||||
|
import React, { useEffect, useMemo, useState } from 'react';
|
||||||
|
|
||||||
|
import parseCsv from '../lib/parseCsv';
|
||||||
|
import DebouncedInput from './DebouncedInput';
|
||||||
|
import loadData from '../lib/loadData';
|
||||||
|
|
||||||
|
export type TableProps = {
|
||||||
|
data?: Array<{ [key: string]: number | string }>;
|
||||||
|
cols?: Array<{ [key: string]: string }>;
|
||||||
|
csv?: string;
|
||||||
|
url?: string;
|
||||||
|
fullWidth?: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const Table = ({
|
||||||
|
data: ogData = [],
|
||||||
|
cols: ogCols = [],
|
||||||
|
csv = '',
|
||||||
|
url = '',
|
||||||
|
fullWidth = false,
|
||||||
|
}: TableProps) => {
|
||||||
|
if (csv) {
|
||||||
|
const out = parseCsv(csv);
|
||||||
|
ogData = out.rows;
|
||||||
|
ogCols = out.fields;
|
||||||
|
}
|
||||||
|
|
||||||
|
const [data, setData] = React.useState(ogData);
|
||||||
|
const [cols, setCols] = React.useState(ogCols);
|
||||||
|
// const [error, setError] = React.useState(""); // TODO: add error handling
|
||||||
|
|
||||||
|
const tableCols = useMemo(() => {
|
||||||
|
const columnHelper = createColumnHelper();
|
||||||
|
return cols.map((c) =>
|
||||||
|
columnHelper.accessor<any, string>(c.key, {
|
||||||
|
header: () => c.name,
|
||||||
|
cell: (info) => info.getValue(),
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}, [data, cols]);
|
||||||
|
|
||||||
|
const [globalFilter, setGlobalFilter] = useState('');
|
||||||
|
|
||||||
|
const table = useReactTable({
|
||||||
|
data,
|
||||||
|
columns: tableCols,
|
||||||
|
getCoreRowModel: getCoreRowModel(),
|
||||||
|
state: {
|
||||||
|
globalFilter,
|
||||||
|
},
|
||||||
|
globalFilterFn: globalFilterFn,
|
||||||
|
onGlobalFilterChange: setGlobalFilter,
|
||||||
|
getFilteredRowModel: getFilteredRowModel(),
|
||||||
|
getPaginationRowModel: getPaginationRowModel(),
|
||||||
|
getSortedRowModel: getSortedRowModel(),
|
||||||
|
});
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (url) {
|
||||||
|
loadData(url).then((data) => {
|
||||||
|
const { rows, fields } = parseCsv(data);
|
||||||
|
setData(rows);
|
||||||
|
setCols(fields);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, [url]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={`${fullWidth ? 'w-[90vw] ml-[calc(50%-45vw)]' : 'w-full'}`}>
|
||||||
|
<DebouncedInput
|
||||||
|
value={globalFilter ?? ''}
|
||||||
|
onChange={(value: any) => setGlobalFilter(String(value))}
|
||||||
|
className="p-2 text-sm shadow border border-block"
|
||||||
|
placeholder="Search all columns..."
|
||||||
|
/>
|
||||||
|
<table className="w-full mt-10">
|
||||||
|
<thead className="text-left border-b border-b-slate-300">
|
||||||
|
{table.getHeaderGroups().map((hg) => (
|
||||||
|
<tr key={hg.id}>
|
||||||
|
{hg.headers.map((h) => (
|
||||||
|
<th key={h.id} className="pr-2 pb-2">
|
||||||
|
<div
|
||||||
|
{...{
|
||||||
|
className: h.column.getCanSort()
|
||||||
|
? 'cursor-pointer select-none'
|
||||||
|
: '',
|
||||||
|
onClick: h.column.getToggleSortingHandler(),
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{flexRender(h.column.columnDef.header, h.getContext())}
|
||||||
|
{{
|
||||||
|
asc: (
|
||||||
|
<ArrowUpIcon className="inline-block ml-2 h-4 w-4" />
|
||||||
|
),
|
||||||
|
desc: (
|
||||||
|
<ArrowDownIcon className="inline-block ml-2 h-4 w-4" />
|
||||||
|
),
|
||||||
|
}[h.column.getIsSorted() as string] ?? (
|
||||||
|
<div className="inline-block ml-2 h-4 w-4" />
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</th>
|
||||||
|
))}
|
||||||
|
</tr>
|
||||||
|
))}
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{table.getRowModel().rows.map((r) => (
|
||||||
|
<tr key={r.id} className="border-b border-b-slate-200">
|
||||||
|
{r.getVisibleCells().map((c) => (
|
||||||
|
<td key={c.id} className="py-2">
|
||||||
|
{flexRender(c.column.columnDef.cell, c.getContext())}
|
||||||
|
</td>
|
||||||
|
))}
|
||||||
|
</tr>
|
||||||
|
))}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<div className="flex gap-2 items-center justify-center mt-10">
|
||||||
|
<button
|
||||||
|
className={`w-6 h-6 ${
|
||||||
|
!table.getCanPreviousPage() ? 'opacity-25' : 'opacity-100'
|
||||||
|
}`}
|
||||||
|
onClick={() => table.setPageIndex(0)}
|
||||||
|
disabled={!table.getCanPreviousPage()}
|
||||||
|
>
|
||||||
|
<ChevronDoubleLeftIcon />
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
className={`w-6 h-6 ${
|
||||||
|
!table.getCanPreviousPage() ? 'opacity-25' : 'opacity-100'
|
||||||
|
}`}
|
||||||
|
onClick={() => table.previousPage()}
|
||||||
|
disabled={!table.getCanPreviousPage()}
|
||||||
|
>
|
||||||
|
<ChevronLeftIcon />
|
||||||
|
</button>
|
||||||
|
<span className="flex items-center gap-1">
|
||||||
|
<div>Page</div>
|
||||||
|
<strong>
|
||||||
|
{table.getState().pagination.pageIndex + 1} of{' '}
|
||||||
|
{table.getPageCount()}
|
||||||
|
</strong>
|
||||||
|
</span>
|
||||||
|
<button
|
||||||
|
className={`w-6 h-6 ${
|
||||||
|
!table.getCanNextPage() ? 'opacity-25' : 'opacity-100'
|
||||||
|
}`}
|
||||||
|
onClick={() => table.nextPage()}
|
||||||
|
disabled={!table.getCanNextPage()}
|
||||||
|
>
|
||||||
|
<ChevronRightIcon />
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
className={`w-6 h-6 ${
|
||||||
|
!table.getCanNextPage() ? 'opacity-25' : 'opacity-100'
|
||||||
|
}`}
|
||||||
|
onClick={() => table.setPageIndex(table.getPageCount() - 1)}
|
||||||
|
disabled={!table.getCanNextPage()}
|
||||||
|
>
|
||||||
|
<ChevronDoubleRightIcon />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const globalFilterFn: FilterFn<any> = (row, columnId, filterValue: string) => {
|
||||||
|
const search = filterValue.toLowerCase();
|
||||||
|
|
||||||
|
let value = row.getValue(columnId) as string;
|
||||||
|
if (typeof value === 'number') value = String(value);
|
||||||
|
|
||||||
|
return value?.toLowerCase().includes(search);
|
||||||
|
};
|
||||||
6
examples/learn/portaljs/components/Vega.tsx
Normal file
6
examples/learn/portaljs/components/Vega.tsx
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
// Wrapper for the Vega component
|
||||||
|
import { Vega as VegaOg } from "react-vega";
|
||||||
|
|
||||||
|
export function Vega(props) {
|
||||||
|
return <VegaOg {...props} />;
|
||||||
|
}
|
||||||
9
examples/learn/portaljs/components/VegaLite.tsx
Normal file
9
examples/learn/portaljs/components/VegaLite.tsx
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
// Wrapper for the Vega Lite component
|
||||||
|
import { VegaLite as VegaLiteOg } from "react-vega";
|
||||||
|
import applyFullWidthDirective from "../lib/applyFullWidthDirective";
|
||||||
|
|
||||||
|
export function VegaLite(props) {
|
||||||
|
const Component = applyFullWidthDirective({ Component: VegaLiteOg });
|
||||||
|
|
||||||
|
return <Component {...props} />;
|
||||||
|
}
|
||||||
21
examples/learn/portaljs/lib/applyFullWidthDirective.tsx
Normal file
21
examples/learn/portaljs/lib/applyFullWidthDirective.tsx
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
export default function applyFullWidthDirective({
|
||||||
|
Component,
|
||||||
|
defaultWFull = true,
|
||||||
|
}) {
|
||||||
|
return (props) => {
|
||||||
|
const newProps = { ...props };
|
||||||
|
|
||||||
|
let newClassName = newProps.className || "";
|
||||||
|
if (newProps.fullWidth === true) {
|
||||||
|
newClassName += " w-[90vw] ml-[calc(50%-45vw)] max-w-none";
|
||||||
|
} else if (defaultWFull) {
|
||||||
|
// So that charts and tables will have the
|
||||||
|
// same width as the text content, but images
|
||||||
|
// can have its width set using the width prop
|
||||||
|
newClassName += " w-full";
|
||||||
|
}
|
||||||
|
newProps.className = newClassName;
|
||||||
|
|
||||||
|
return <Component {...newProps} />;
|
||||||
|
};
|
||||||
|
}
|
||||||
5
examples/learn/portaljs/lib/loadData.tsx
Normal file
5
examples/learn/portaljs/lib/loadData.tsx
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
export default async function loadData(url: string) {
|
||||||
|
const response = await fetch(url)
|
||||||
|
const data = await response.text()
|
||||||
|
return data
|
||||||
|
}
|
||||||
20
examples/learn/portaljs/lib/parseCsv.ts
Normal file
20
examples/learn/portaljs/lib/parseCsv.ts
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
import papa from "papaparse";
|
||||||
|
|
||||||
|
const parseCsv = (csv: string) => {
|
||||||
|
csv = csv.trim();
|
||||||
|
const rawdata = papa.parse(csv, { header: true });
|
||||||
|
|
||||||
|
let cols: any[] = [];
|
||||||
|
if(rawdata.meta.fields) {
|
||||||
|
cols = rawdata.meta.fields.map((r: string) => {
|
||||||
|
return { key: r, name: r };
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
rows: rawdata.data as any,
|
||||||
|
fields: cols,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export default parseCsv;
|
||||||
@ -1,7 +1,7 @@
|
|||||||
@tailwind base;
|
@tailwind base;
|
||||||
@tailwind components;
|
@tailwind components;
|
||||||
@tailwind utilities;
|
@tailwind utilities;
|
||||||
@import "@portaljs/remark-callouts/styles.css";
|
@import "@flowershow/remark-callouts/styles.css";
|
||||||
|
|
||||||
.w-5 {
|
.w-5 {
|
||||||
width: 1.25rem
|
width: 1.25rem
|
||||||
|
|||||||
@ -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.
|
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.com/docs/examples/github-backed-catalog) blog post.
|
You can read more about it on the [Data catalog with data on GitHub](https://portaljs.org/docs/examples/github-backed-catalog) blog post.
|
||||||
|
|
||||||
## Demo
|
## Demo
|
||||||
|
|
||||||
|
|||||||
@ -2,7 +2,7 @@ import { expect, test } from 'vitest';
|
|||||||
import { getAllProjectsFromOrg, getProjectDataPackage } from '../lib/project';
|
import { getAllProjectsFromOrg, getProjectDataPackage } from '../lib/project';
|
||||||
import { loadDataPackage } from '../lib/loader';
|
import { loadDataPackage } from '../lib/loader';
|
||||||
import { getProjectMetadata } from '../lib/project';
|
import { getProjectMetadata } from '../lib/project';
|
||||||
import { validate } from 'datapackage';
|
import { getCsv, parseCsv } from '../components/Table';
|
||||||
|
|
||||||
test(
|
test(
|
||||||
'Test OS-Data',
|
'Test OS-Data',
|
||||||
@ -12,24 +12,8 @@ test(
|
|||||||
'main',
|
'main',
|
||||||
process.env.VITE_GITHUB_PAT
|
process.env.VITE_GITHUB_PAT
|
||||||
);
|
);
|
||||||
if (repos.failed.length > 0)
|
if (repos.failed.length > 0) console.log(repos.failed);
|
||||||
console.log('Failed to get datapackage on', 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 }
|
{ timeout: 100000 }
|
||||||
);
|
);
|
||||||
@ -43,22 +27,7 @@ test(
|
|||||||
process.env.VITE_GITHUB_PAT
|
process.env.VITE_GITHUB_PAT
|
||||||
);
|
);
|
||||||
if (repos.failed.length > 0) console.log(repos.failed);
|
if (repos.failed.length > 0) console.log(repos.failed);
|
||||||
let failedDatapackages = await Promise.all(
|
expect(repos.failed.length).toBe(0);
|
||||||
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 }
|
{ timeout: 100000 }
|
||||||
);
|
);
|
||||||
@ -114,3 +83,56 @@ test(
|
|||||||
},
|
},
|
||||||
{ timeout: 100000 }
|
{ 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 }
|
||||||
|
);
|
||||||
|
|||||||
@ -1,29 +0,0 @@
|
|||||||
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} />;
|
|
||||||
}
|
|
||||||
@ -45,12 +45,12 @@ export default function DatasetCard({ dataset }: { dataset: Project }) {
|
|||||||
<dt className="text-gray-500">Fiscal Period</dt>
|
<dt className="text-gray-500">Fiscal Period</dt>
|
||||||
<dd className="text-gray-700">
|
<dd className="text-gray-700">
|
||||||
{dataset.fiscalPeriod?.start &&
|
{dataset.fiscalPeriod?.start &&
|
||||||
new Date(dataset.fiscalPeriod.start).getUTCFullYear()}
|
new Date(dataset.fiscalPeriod.start).getFullYear()}
|
||||||
{dataset.fiscalPeriod?.end &&
|
{dataset.fiscalPeriod?.end &&
|
||||||
dataset.fiscalPeriod?.start !== dataset.fiscalPeriod?.end && (
|
dataset.fiscalPeriod?.start !== dataset.fiscalPeriod?.end && (
|
||||||
<>
|
<>
|
||||||
{' - '}
|
{' - '}
|
||||||
{new Date(dataset.fiscalPeriod.end).getUTCFullYear()}
|
{new Date(dataset.fiscalPeriod.end).getFullYear()}
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</dd>
|
</dd>
|
||||||
|
|||||||
@ -13,13 +13,9 @@ import { useState } from 'react';
|
|||||||
export default function DatasetsSearch({
|
export default function DatasetsSearch({
|
||||||
datasets,
|
datasets,
|
||||||
availableCountries,
|
availableCountries,
|
||||||
minPeriod,
|
|
||||||
maxPeriod,
|
|
||||||
}: {
|
}: {
|
||||||
datasets: Project[];
|
datasets: Project[];
|
||||||
availableCountries;
|
availableCountries;
|
||||||
minPeriod: string;
|
|
||||||
maxPeriod: string;
|
|
||||||
}) {
|
}) {
|
||||||
const itemsPerPage = 6;
|
const itemsPerPage = 6;
|
||||||
const [page, setPage] = useState(1);
|
const [page, setPage] = useState(1);
|
||||||
@ -136,10 +132,7 @@ export default function DatasetsSearch({
|
|||||||
<div className="relative">
|
<div className="relative">
|
||||||
<input
|
<input
|
||||||
aria-label="Min. date"
|
aria-label="Min. date"
|
||||||
type="text"
|
type="date"
|
||||||
placeholder={minPeriod}
|
|
||||||
onFocus={(e) => (e.target.type = 'date')}
|
|
||||||
onBlur={(e) => (e.target.type = 'text')}
|
|
||||||
{...register('minDate', { onChange: () => setPage(1) })}
|
{...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"
|
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"
|
||||||
/>
|
/>
|
||||||
@ -152,10 +145,7 @@ export default function DatasetsSearch({
|
|||||||
<div className="relative">
|
<div className="relative">
|
||||||
<input
|
<input
|
||||||
aria-label="Max. date"
|
aria-label="Max. date"
|
||||||
type="text"
|
type="date"
|
||||||
placeholder={maxPeriod}
|
|
||||||
onFocus={(e) => (e.target.type = 'date')}
|
|
||||||
onBlur={(e) => (e.target.type = 'text')}
|
|
||||||
{...register('maxDate', { onChange: () => setPage(1) })}
|
{...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"
|
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"
|
||||||
/>
|
/>
|
||||||
|
|||||||
@ -4,13 +4,10 @@ import { Grid } from '@githubocto/flat-ui';
|
|||||||
|
|
||||||
const queryClient = new QueryClient();
|
const queryClient = new QueryClient();
|
||||||
|
|
||||||
export async function getCsv(url: string, corsProxy?: string, range?: string) {
|
export async function getCsv(url: string) {
|
||||||
if (corsProxy) {
|
|
||||||
url = corsProxy + url
|
|
||||||
}
|
|
||||||
const response = await fetch(url, {
|
const response = await fetch(url, {
|
||||||
headers: {
|
headers: {
|
||||||
Range: range ? `bytes=0-${range}` : 'bytes=0-512000',
|
Range: 'bytes=0-5132288',
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
const data = await response.text();
|
const data = await response.text();
|
||||||
@ -64,25 +61,21 @@ export interface FlatUiTableProps {
|
|||||||
url?: string;
|
url?: string;
|
||||||
data?: { [key: string]: number | string }[];
|
data?: { [key: string]: number | string }[];
|
||||||
rawCsv?: string;
|
rawCsv?: string;
|
||||||
range?: string;
|
|
||||||
corsProxy?: string;
|
|
||||||
}
|
}
|
||||||
export const FlatUiTable: React.FC<FlatUiTableProps> = ({
|
export const FlatUiTable: React.FC<FlatUiTableProps> = ({
|
||||||
url,
|
url,
|
||||||
data,
|
data,
|
||||||
rawCsv,
|
rawCsv,
|
||||||
corsProxy,
|
|
||||||
range
|
|
||||||
}) => {
|
}) => {
|
||||||
return (
|
return (
|
||||||
// Provide the client to your App
|
// Provide the client to your App
|
||||||
<QueryClientProvider client={queryClient}>
|
<QueryClientProvider client={queryClient}>
|
||||||
<TableInner range={range} corsProxy={corsProxy} url={url} data={data} rawCsv={rawCsv} />
|
<TableInner url={url} data={data} rawCsv={rawCsv} />
|
||||||
</QueryClientProvider>
|
</QueryClientProvider>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const TableInner: React.FC<FlatUiTableProps> = ({ url, data, rawCsv, corsProxy, range }) => {
|
const TableInner: React.FC<FlatUiTableProps> = ({ url, data, rawCsv }) => {
|
||||||
if (data) {
|
if (data) {
|
||||||
return (
|
return (
|
||||||
<div className="w-full" style={{height: '500px'}}>
|
<div className="w-full" style={{height: '500px'}}>
|
||||||
@ -92,12 +85,12 @@ const TableInner: React.FC<FlatUiTableProps> = ({ url, data, rawCsv, corsProxy,
|
|||||||
}
|
}
|
||||||
const { data: csvString, isLoading: isDownloadingCSV } = useQuery(
|
const { data: csvString, isLoading: isDownloadingCSV } = useQuery(
|
||||||
['dataCsv', url],
|
['dataCsv', url],
|
||||||
() => getCsv(url as string, corsProxy, range),
|
() => getCsv(url),
|
||||||
{ enabled: !!url }
|
{ enabled: !!url }
|
||||||
);
|
);
|
||||||
const { data: parsedData, isLoading: isParsing } = useQuery(
|
const { data: parsedData, isLoading: isParsing } = useQuery(
|
||||||
['dataPreview', csvString],
|
['dataPreview', csvString],
|
||||||
() => parseCsv(rawCsv ? rawCsv as string : csvString as string),
|
() => parseCsv(rawCsv ? rawCsv : csvString),
|
||||||
{ enabled: rawCsv ? true : !!csvString }
|
{ enabled: rawCsv ? true : !!csvString }
|
||||||
);
|
);
|
||||||
if (isParsing || isDownloadingCSV)
|
if (isParsing || isDownloadingCSV)
|
||||||
@ -110,6 +103,4 @@ const TableInner: React.FC<FlatUiTableProps> = ({ url, data, rawCsv, corsProxy,
|
|||||||
<Grid data={parsedData.data} />
|
<Grid data={parsedData.data} />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
return <Spinning />
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -5,9 +5,6 @@ import Link from 'next/link';
|
|||||||
import { useRouter } from 'next/router';
|
import { useRouter } from 'next/router';
|
||||||
import { Bars3Icon } from '@heroicons/react/24/outline';
|
import { Bars3Icon } from '@heroicons/react/24/outline';
|
||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import { Fragment } from 'react';
|
|
||||||
import { Menu, Transition } from '@headlessui/react';
|
|
||||||
import { ChevronDownIcon } from '@heroicons/react/20/solid';
|
|
||||||
|
|
||||||
export function Header() {
|
export function Header() {
|
||||||
const [menuOpen, setMenuOpen] = useState<boolean>(false);
|
const [menuOpen, setMenuOpen] = useState<boolean>(false);
|
||||||
@ -19,85 +16,42 @@ export function Header() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const navLinks = [
|
const navLinks = [
|
||||||
|
{
|
||||||
|
title: 'Home',
|
||||||
|
href: '/',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
title: 'Datasets',
|
title: 'Datasets',
|
||||||
href: '/#datasets',
|
href: '/#datasets',
|
||||||
},
|
},
|
||||||
{
|
// {
|
||||||
title: 'Data Stories',
|
// title: "Community",
|
||||||
href: '/stories',
|
// href: "https://community.openspending.org/"
|
||||||
},
|
// }
|
||||||
{
|
|
||||||
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 (
|
return (
|
||||||
<header className="relative z-50 pb-11 lg:pt-11">
|
<header className="relative z-50 pb-11 lg:pt-11">
|
||||||
<Container className="flex flex-wrap justify-between lg:flex-nowrap mt-10 lg:mt-0">
|
<Container className="flex flex-wrap items-center justify-between lg:flex-nowrap mt-10 lg:mt-0">
|
||||||
<Link href="/" className="lg:mt-0 lg:grow lg:basis-0 flex items-center">
|
<Link href="/" className="lg:mt-0 lg:grow lg:basis-0 flex items-center">
|
||||||
<Image src={logo} alt="OpenSpending" className="h-12 w-auto" />
|
<Image src={logo} alt="OpenSpending" className="h-12 w-auto" />
|
||||||
</Link>
|
</Link>
|
||||||
<ul className="hidden list-none sm:flex gap-x-5 text-base font-medium">
|
<ul className="hidden list-none sm:flex gap-x-5 text-base font-medium">
|
||||||
{navLinks.map((link, i) => (
|
{navLinks.map((link, i) => (
|
||||||
<li key={`nav-link-${i}`}>
|
<li key={`nav-link-${i}`}>
|
||||||
<Dropdown navItem={link} />
|
<Link
|
||||||
|
className={`text-emerald-900 hover:text-emerald-600 ${
|
||||||
|
isActive(link) ? 'text-emerald-600' : ''
|
||||||
|
}`}
|
||||||
|
href={link.href}
|
||||||
|
scroll={false}
|
||||||
|
>
|
||||||
|
{link.title}
|
||||||
|
</Link>
|
||||||
</li>
|
</li>
|
||||||
))}
|
))}
|
||||||
</ul>
|
</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">
|
<div className="sm:hidden sm:mt-10 lg:mt-0 lg:grow lg:basis-0 lg:justify-end">
|
||||||
<button onClick={() => setMenuOpen(!menuOpen)}>
|
<button onClick={() => setMenuOpen(!menuOpen)}>
|
||||||
<Bars3Icon className="w-8 h-8" />
|
<Bars3Icon className="w-8 h-8" />
|
||||||
@ -126,77 +80,3 @@ export function Header() {
|
|||||||
</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>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|||||||
@ -27,7 +27,7 @@ export function Hero({ countriesCount, datasetsCount, filesCount }) {
|
|||||||
<Button href="#datasets" className="mt-10">
|
<Button href="#datasets" className="mt-10">
|
||||||
Search datasets
|
Search datasets
|
||||||
</Button>
|
</Button>
|
||||||
<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">
|
<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">
|
||||||
{[
|
{[
|
||||||
// Added the plus sign because some datasets do not
|
// Added the plus sign because some datasets do not
|
||||||
// contain defined countries
|
// contain defined countries
|
||||||
@ -36,18 +36,10 @@ export function Hero({ countriesCount, datasetsCount, filesCount }) {
|
|||||||
['Files', filesCount],
|
['Files', filesCount],
|
||||||
].map(([name, value]) => (
|
].map(([name, value]) => (
|
||||||
<div key={name}>
|
<div key={name}>
|
||||||
<div className='flex gap-x-2 items-center sm:hidden' 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">
|
<dd className="mt-0.5 text-2xl font-semibold tracking-tight text-emerald-900">
|
||||||
{value}
|
{value}
|
||||||
</dd>
|
</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>
|
</div>
|
||||||
))}
|
))}
|
||||||
</dl>
|
</dl>
|
||||||
|
|||||||
@ -1,25 +0,0 @@
|
|||||||
import Image from 'next/image';
|
|
||||||
import Link from 'next/link';
|
|
||||||
export default function Footer() {
|
|
||||||
return (
|
|
||||||
<footer className="bg-slate-50 border-t border-slate-100 py-10">
|
|
||||||
<div className="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8 flex flex-col items-center justify-between md:flex-row">
|
|
||||||
<div className="flex gap-x-2 items-center justify-center mx-auto">
|
|
||||||
<p className="text-base text-slate-500">Maintained by</p>
|
|
||||||
<a href="https://www.datopian.com/" target="_blank">
|
|
||||||
<Image
|
|
||||||
alt="Datopian logo"
|
|
||||||
className="mb-1"
|
|
||||||
src="/datopian-logotype.png"
|
|
||||||
width={120}
|
|
||||||
height={30}
|
|
||||||
/>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
<div className="flex gap-x-2 items-center mx-auto h-20">
|
|
||||||
<p className="mt-8 text-base text-slate-500 md:mt-0">Built with <a href="https://portaljs.com" target="_blank" className='text-xl font-medium'>🌀 PortalJS</a></p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</footer>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@ -1,12 +1,10 @@
|
|||||||
import { Header } from '../Header';
|
import { Header } from '../Header';
|
||||||
import Footer from './Footer';
|
|
||||||
|
|
||||||
export default function Layout({ children }) {
|
export default function Layout({ children }) {
|
||||||
return (
|
return (
|
||||||
<div className="bg-white min-h-screen">
|
<div className="bg-white min-h-screen pb-32">
|
||||||
<Header />
|
<Header />
|
||||||
{children}
|
{children}
|
||||||
<Footer />
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,23 +0,0 @@
|
|||||||
---
|
|
||||||
lead: true
|
|
||||||
section: about
|
|
||||||
title: Contact
|
|
||||||
authors:
|
|
||||||
- Anders Pedersen
|
|
||||||
redirect_from:
|
|
||||||
- /contact/
|
|
||||||
---
|
|
||||||
|
|
||||||
Connect with the OpenSpending community.
|
|
||||||
|
|
||||||
The best place for OpenSpending-related discussions is our [forum](https://discuss.okfn.org/c/openspending/), but you can interact with OpenSpending on your favorite social network by following the links below:
|
|
||||||
|
|
||||||
* Open Knowledge Discussion Forum
|
|
||||||
* [English](https://discuss.okfn.org/c/openspending/none)
|
|
||||||
* [Portuguese](https://discuss.okfn.org/c/openspending/gastos-abertos)
|
|
||||||
* <abbr title="Gitter">Gitter</abbr> chat: [OpenSpending Gitter chatroom](https://gitter.im/openspending)
|
|
||||||
* GitHub:
|
|
||||||
* [OpenSpending](https://github.com/openspending) (OpenSpending-related code)
|
|
||||||
|
|
||||||
* Twitter: [@openspending](https://twitter.com/openspending)
|
|
||||||
* Facebook: [OpenSpending](https://www.facebook.com/openspending?_rdr=p)
|
|
||||||
@ -1,172 +0,0 @@
|
|||||||
---
|
|
||||||
section: about
|
|
||||||
lead: true
|
|
||||||
title: Contributors
|
|
||||||
authors:
|
|
||||||
- Anders Pedersen
|
|
||||||
---
|
|
||||||
|
|
||||||
There are many contributors to OpenSpending. There are thousands of registered OpenSpending users contributing data and analysis.
|
|
||||||
|
|
||||||
It is impossible to adequately acknowledge the many individuals and organizations who have contributed.
|
|
||||||
|
|
||||||
This page then is necessarily partial and is focused (though not limited to) those who have made special efforts to contribute through their participation in specific teams, in donating data or in other significant ways.
|
|
||||||
|
|
||||||
If you'd like to be added as a contributor to this page please [get in touch]({{ site.baseurl }}/about/contact/).
|
|
||||||
|
|
||||||
## Teams
|
|
||||||
|
|
||||||
### News and Website Team
|
|
||||||
|
|
||||||
#### News Editors - Descriptions
|
|
||||||
|
|
||||||
These guys run the blog and manage our social media presence. We are
|
|
||||||
still recruiting News Editor volunteers so if you'd like to join the
|
|
||||||
team <a
|
|
||||||
href="http://community.openspending.org/contribute/web/#Sign_up">apply
|
|
||||||
here</a>.
|
|
||||||
|
|
||||||
<strong>Burite Joseph</strong>, <a href="https://twitter.com/BuriteJoseph">@BuriteJoseph</a>
|
|
||||||
|
|
||||||
Independent media practitioner and entrepreneur with over five years
|
|
||||||
of journalism and research experience, Burite runs ZHENOBIA, a media
|
|
||||||
integration and multimedia content aggregation company. She also
|
|
||||||
consults for <a href="http://www.smsmedia.ug">SMS Media Uganda</a>,
|
|
||||||
Ultimate Media Uganda, <a href="http://www.busiweek.com">East African
|
|
||||||
Business Week</a> and <a href="http://www.dailymonitor.co.ug">Daily
|
|
||||||
Monitor</a>.
|
|
||||||
|
|
||||||
<blockquote>
|
|
||||||
Working with data is my new passion. I am a quick learner and teamwork is my steroid.
|
|
||||||
</blockquote>
|
|
||||||
|
|
||||||
<strong>Anna Flagg</strong>, <a href="http://www.annaflagg.com">www.annaflagg.com</a>
|
|
||||||
|
|
||||||
Data journalist at the Center for Responsive Politics, Anna has a background in computer science, data visualization, design and data-storytelling.
|
|
||||||
|
|
||||||
<blockquote>
|
|
||||||
I like working on projects that create awareness of issues important to the public. I'm excited to work with and learn from the Open Spending community.
|
|
||||||
|
|
||||||
</blockquote>
|
|
||||||
<strong>Laura S. García</strong>,<a href="https://twitter.com/Laura_S_Garcia">@laura_s_garcia</a>
|
|
||||||
|
|
||||||
An experienced journalist, Laura has worked for more than ten years as a multi-media journalist in Spain. She has also taught Geography and History to high-school students. Laura speaks Spanish, Galician, English and a little Swedish.
|
|
||||||
|
|
||||||
<blockquote>
|
|
||||||
I’m looking to improve my knowledge of open data, as I’ve always thought this to be the best way to offer a good journalism and a good education as well.
|
|
||||||
|
|
||||||
</blockquote>
|
|
||||||
<strong>Karen Brzezinska</strong>, <a href="https://twitter.com/westofwarsaw">@westofwarsaw</a>
|
|
||||||
|
|
||||||
Also a professional journalist, Karen (Kati) worked for international news services specialising in equity, commodity and currency markets. Her background is in PoliSci (East European studies), and, while originally from midwestern US, her life experience lists Italy, Hungary (1989-1992) and The Netherlands (since 1992) as home-countries. Kati is fluent in English (US) and Dutch.
|
|
||||||
|
|
||||||
<blockquote>
|
|
||||||
I'm interested in learning how open data can be used to enhance governance and education.
|
|
||||||
|
|
||||||
</blockquote>
|
|
||||||
<strong>Dominic Kornu</strong>, <a href="https://twitter.com/Qaphui">@qaphui</a>
|
|
||||||
|
|
||||||
An IT and Maths tutor from Ghana, with an interest in web and social media technologies, Dominic blogs at <a href="http://dominicmary.blogspot.com">Qaphui’s Cafe</a> and volunteers in his free time.
|
|
||||||
|
|
||||||
<blockquote>
|
|
||||||
I am interested in learning how open data can be used to enhance governance and education.
|
|
||||||
|
|
||||||
</blockquote>
|
|
||||||
<strong>Mehmet Koksal</strong>, <a href="https://twitter.com/mehmetkoksal">@mehmetkoksal</a>
|
|
||||||
|
|
||||||
Freelance journalist based in Brussels (Belgium) and conference interpreter, Mehmet also works as a fixer for the international press, including the French weekly <a href="http://www.courrierinternational.com/">Courrier int.</a>. In his free time he volunteers for <a href="http://www.ajp.be/">AJP</a> and acts as a campaign manager for the <a href="http://europe.ifj.org/en/pages/turkey-campaign-set-journalists-free">EFJ</a>.
|
|
||||||
|
|
||||||
<strong>Teodora Beleaga</strong>, <a href="https://twitter.com/t30d0ra">@t30d0ra</a>
|
|
||||||
|
|
||||||
A digital analyst and freelance data journalist based in London, <a href="http://teodorabeleaga.com">Teodora </a>is an alumna of City University’s Interactive Journalism MA and has completed work experience with <a href="http://www.theguardian.com/profile/teodora-beleaga">The Guardian</a>.
|
|
||||||
|
|
||||||
<blockquote>
|
|
||||||
I joined the Open Spending project to share my data analysis skills and expand my understanding of fiscal transparency and government spending.
|
|
||||||
|
|
||||||
</blockquote>
|
|
||||||
<strong>Miriam Ruhenstroth</strong>
|
|
||||||
|
|
||||||
A Science and technology freelance journalist based in Berlin (Germany), Miriam has a background in biological sciences. In 2011 she attended a summer school for data journalism (organized by Initiative Wissenschaftsjournalismus).
|
|
||||||
|
|
||||||
<blockquote>
|
|
||||||
I found the field of data storytelling thrilling and joined OpenSpending, to learn more about it and participate for good.
|
|
||||||
|
|
||||||
</blockquote>
|
|
||||||
|
|
||||||
### Data Team
|
|
||||||
|
|
||||||
|
|
||||||
#### Data Wranglers - Descriptions
|
|
||||||
|
|
||||||
The Data Wranglers work to add, clean and visualise data in OpenSpending. They help community members who need assistance. Some data wranglers focus on cleaning and analysing data whereas others work to visualise data using the OpenSpending API. We are still recruiting Data Wrangler volunteers so if you'd like to join the team <a href="http://community.openspending.org/contribute/data/#Official_sign_up">apply here</a>.
|
|
||||||
|
|
||||||
<strong>Concha Catalan</strong>, <a href="https://twitter.com/conchacatalan">@conchacatalan</a>
|
|
||||||
|
|
||||||
An English teacher and freelance journalist based in Barcelona (Spain), Concha is currently working on a project to open the autonomous government of Catalonia (opengov.cat). She also blogs at <a href="http://barcelonalittleshell.blogspot.com.es">http://barcelonalittleshell.blogspot.com.es</a>.
|
|
||||||
|
|
||||||
<blockquote>
|
|
||||||
I would like to add the data set of the autonomous government of Catalonia budget to OpenSpending. I am coming to terms with lots of new concepts.
|
|
||||||
|
|
||||||
</blockquote>
|
|
||||||
<strong>Prakash Neupane</strong>, <a href="https://twitter.com/nprkshn">@nprkshn</a>
|
|
||||||
|
|
||||||
OKFN Ambassador in Nepal and FOSS Enthusiastic, Prakash is working in social development empowering individuals and communities by using technology. He is an Open Data Researcher and Nepali Wikimedian, responsible for Wikimedia Education Program in Nepal. Find out more about him <a href="http://www.prakashneupane.com.np/about-me">here</a>.
|
|
||||||
|
|
||||||
<strong>Pierre Chrzanowski</strong>, @piezanowski
|
|
||||||
|
|
||||||
A member of the French OKFN working in the field of Open Government Data, Pierre says he is really interested to work on Tax Heaven, Public Procurement and Aid Data.
|
|
||||||
|
|
||||||
<blockquote>
|
|
||||||
I want to learn more about tools to analyse the data sets and how best to do storytelling.
|
|
||||||
|
|
||||||
</blockquote>
|
|
||||||
<strong>Samuel S. Lee</strong>, <a href="https://twitter.com/OpenNotion">@OpenNotion</a>
|
|
||||||
|
|
||||||
Currently based in Washington DC, Samuel is a member of the <a href="https://finances.worldbank.org">World Bank Group Open Finances</a> team. He loves data, innovation, transparency, photography and college football.
|
|
||||||
|
|
||||||
<blockquote>
|
|
||||||
I am passionate about “open” and its potential to transform civic engagement, international development, and the world. I am particularly interested in realizing the potential of open financial information.
|
|
||||||
|
|
||||||
</blockquote>
|
|
||||||
<strong>Adriana Homolova</strong>
|
|
||||||
|
|
||||||
A data journalism student with a passion for open culture, Adriana is a member of the <a href="http://soit.sk">Society for Open Information Technologies</a>.
|
|
||||||
|
|
||||||
<strong>Sipos Zoltán</strong>
|
|
||||||
|
|
||||||
A Hungarian journalist working for an Internet news portal in Romania, Sipos specializes in investigative reporting. His background includes philosophy, sociology and public policies. Sipos has experience working with data, filing FOI requests, and tackling spreadsheets.
|
|
||||||
|
|
||||||
<blockquote>
|
|
||||||
I am trying to learn as much as I can about data journalism through online groups, MOOCs and books purchased from Amazon. My ultimate goal is to set up a small investigative / data journalism start-up in Romania.
|
|
||||||
</blockquote>
|
|
||||||
|
|
||||||
<strong>Gabe Sawhney</strong>
|
|
||||||
|
|
||||||
A member of <a href="http://betterbudget.ca">Better Budget
|
|
||||||
Toronto</a> Gabe joined the Team to bring transparency to his
|
|
||||||
city’s <a
|
|
||||||
href="http://spacing.ca/toronto/2012/12/10/lorinc-building-a-better-budget-at-city-hall/">budget</a>.
|
|
||||||
|
|
||||||
<blockquote>
|
|
||||||
I want to mobilize action (citizens, elected officials and policymakers) for better process, better clarity, better formats, and more transparency around city budgets.
|
|
||||||
</blockquote>
|
|
||||||
|
|
||||||
<strong>Elaine Ayo</strong>, <a href="https://twitter.com/eieayo">@eieayo</a>
|
|
||||||
|
|
||||||
Statistician student based in Washington, DC Elaine has spent the last
|
|
||||||
three years in Seoul, South Korea as a copy editor for an English news
|
|
||||||
wire. Prior to that Elaine reported for her hometown paper, the San
|
|
||||||
Antonio Express-News, in Texas.
|
|
||||||
|
|
||||||
<strong>Hans Loos</strong>
|
|
||||||
|
|
||||||
An IT and telecom freelance journalist based in Belgium, Hans studied
|
|
||||||
sociology and has a passion for statistics.
|
|
||||||
|
|
||||||
<blockquote>
|
|
||||||
I have started to learn to program and study R but without big results up till now.
|
|
||||||
</blockquote>
|
|
||||||
|
|
||||||
## Data Donors
|
|
||||||
|
|
||||||
In progress ...
|
|
||||||
@ -1,329 +0,0 @@
|
|||||||
---
|
|
||||||
section: about
|
|
||||||
lead: true
|
|
||||||
title: Project portfolio
|
|
||||||
authors:
|
|
||||||
- Neil Ashton
|
|
||||||
---
|
|
||||||
Here are some of the projects, past and present, that we have been involved with.
|
|
||||||
|
|
||||||
* <a href="#current-development">Current OpenSpending projects</a>
|
|
||||||
* <a href="#past-development">Past projects</a>
|
|
||||||
* <a href="#gov-tools">Tools for governments</a>
|
|
||||||
* <a href="#gov-use-cases">Government use cases</a>
|
|
||||||
* <a href="#publications">Publications and reports</a>
|
|
||||||
* <a href="#standards">Technical standards</a>
|
|
||||||
* <a href="#stories">Stories and data journalism</a>
|
|
||||||
* <a href="#your-project">Collaborate! Your project here...</a>
|
|
||||||
|
|
||||||
<a name="current-development"></a>
|
|
||||||
|
|
||||||
## Current projects
|
|
||||||
|
|
||||||
We're working on [OpenSpending Next](/next/), the next version of OpenSpending. Learn how to [get involved](/get-involved/)!
|
|
||||||
|
|
||||||
<a name="past-development"></a>
|
|
||||||
|
|
||||||
## Already unleashed
|
|
||||||
|
|
||||||
#### Spending Stories
|
|
||||||
|
|
||||||
In 2011, the Open Knowledge Foundation was awarded a Knight News Challenge Grant to work on the <a href="http://blog.okfn.org/2011/01/18/spending-stories/">Spending Stories</a> Project. Large numbers are often meaningless to the general public, and despite a wealth of information around government spending, the topic of government finance is often overlooked by journalists. The Spending Stories project aims to facilitate reporting by speeding up fact-checking around spending data as well as connecting news stories about public spending to relevant datasets and visualisations to put these stories into context.
|
|
||||||
|
|
||||||
We're into our second year of the project now. <a href="http://www.pbs.org/idealab/2012/12/follow-the-money-a-spending-stories-guide-for-journalists345.html">See what we are up to by following our updates on the PBS Idea Lab blog.</a>
|
|
||||||
|
|
||||||
#### budzeti.ba: Bosnian Budget Bubbles
|
|
||||||
|
|
||||||
<img class="pull-right" style="margin-left: 1em;" title="Balkan Budgets" src="http://farm9.staticflickr.com/8063/8219557569_cc12ebbdea_m.jpg" alt="" />
|
|
||||||
|
|
||||||
In October 2013 OpenSpending launched the "Where Does My Money Go"-site <a href="http://budzeti.ba/">budzeti.ba</a> in Bosnia and Herzegovina. Thanks to a grant from the National Endowment for Democracy, the OpenSpending team collaborated with the Centre for Public Interest Advocacy in Bosnia to produce interactive graphics of national and subnational budgets in Bosnia.
|
|
||||||
|
|
||||||
As part of the project OpenSpending:
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li>Created visualisations of national, entity-, cantonal- and district-level budgets for Bosnia.</li>
|
|
||||||
<li>Conducted onsite trainings and capacity building workshops with organisations from other Balkan countries, on getting, wrangling and presenting financial data (with OpenSpending and other tools).</li>
|
|
||||||
<li>Developed a tax calculator for Bosnia (similar to the <a href="http://wheredoesmymoneygo.org/dailybread.html">Daily Bread</a>).</li>
|
|
||||||
<li>Tested the <a href="http://openspending.org/resources/handbook/ch001_introduction.html">Spending Data Handbook</a> and added an <a href="http://community.openspending.org/help/guide/">OpenSpending guide</a> with a more technical guidance, for those organisations wishing to do more ambitious data work.</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<a href="http://blog.openspending.org/2012/09/26/balkan-budget-bubbles/">Read more about the project.</a> Read the full announcement from <a href="http://community.openspending.org/2013/10/budzeti-ba-follow-the-money-bosnia-herzegovina/">the launch</a>.
|
|
||||||
|
|
||||||
#### OpenSpending Slovakia
|
|
||||||
|
|
||||||
In early 2013, we launched <a href="http://slovakia.openspending.org">Slovakia Openspending</a>, prepared in collaboration with transparency and anti-corruption watchdog <a href="http://www.transparency.sk/">Transparency International Slovakia</a>. The site contains budget and expenditure information gathered from some 20 cities across Slovakia allowing users to examine current municipality budgets and compare them to expenditures going back to 2009. Based on the openspending.org source code, we have added several improvements such as:
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li>Year-on-year comparison for spending categories.</li>
|
|
||||||
<li>Improved listing and more contextual presentation of the data.</li>
|
|
||||||
<li>Embedable graphic drilldowns with accompanying tables.</li>
|
|
||||||
</ul>
|
|
||||||
Transparency Slovakia hopes to promote the site as an example of how budgets could be made more accessible and comprehensible to the public once the site is localized and tested further. While not in its current plans, additional spending data and a feature to allow users to compare cities would improve opportunities for doing crowdsourced benchmarking.
|
|
||||||
|
|
||||||
#### Where Does My Money Go?
|
|
||||||
|
|
||||||
<img class="pull-left" style="margin-right: 3em;" title="WDMMG original" src="http://farm8.staticflickr.com/7088/7315252358_7dae93b263.jpg" alt="" width="250" />
|
|
||||||
|
|
||||||
<a href="http://wheredoesmymoneygo.org/">Where Does My Money Go?</a> (WDMMG) is the project from which OpenSpending was born. Funded originally by 4IP, it allows UK citizens to examine where their taxes are being spent through an interactive 'bubble tree' visualisation. They can even find out how much they contribute on a daily basis through their taxes to various sectors of society through the <a href="http://wheredoesmymoneygo.org/dailybread.html">Daily Bread</a> app.
|
|
||||||
|
|
||||||
You can now build a site like WDMMG for your own country using the OpenSpending API and the WDMMG Toolkit:
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li><a href="http://wheredoesmymoneygo.org/">Visit the Where Does My Money Go? project</a></li>
|
|
||||||
<li><a href="https://twitter.com/#!/wdmmg">Follow Where Does My Money Go? on Twitter</a></li>
|
|
||||||
<li><a href="http://blog.openspending.org/2012/02/16/thekit/">Read more about how to create your own Where Does My Money Go?site</a></li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
#### Cameroon Budget Inquirer
|
|
||||||
|
|
||||||
<img class="pull-left" style="margin-right: 2em;" title="Cameroon Budget Inquirer" src="http://farm9.staticflickr.com/8340/8287000485_4daf7d73da_n.jpg" alt="" />
|
|
||||||
|
|
||||||
We collaborated with the World Bank to produce a citizen-friendly representation of <a href="http://cameroon.openspending.org/">Cameroon's budget</a>.
|
|
||||||
|
|
||||||
The project incorporates the open-source 'bubble visualisations' first seen in Where Does My Money Go, as well as many new elements, such as a map based navigation and heatmaps. The project includes:
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li>Visualisation of the National Investment Budget, the Northwest region's budget of Cameroon (including absolute and per-capita estimates, budgeted as well as actual figures) as well as a similar visualisation of the Tignere local council budget.</li>
|
|
||||||
<li>A sub-national budget transparency index - similar to the work of the International Budget Partnership, but at sub-national levels. This highlights the availability of key budget documents and ranks regions on their availability.</li>
|
|
||||||
<li>Explore the data: filter the data by categories such as amount, location, and activity.</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
#### OffenerHaushalt
|
|
||||||
<img class="pull-right" style="margin-left: 1em;" title="Offener Haushalt" src="http://farm8.staticflickr.com/7077/7315281352_2c00d928d8.jpg" alt="" width="250" />
|
|
||||||
|
|
||||||
<a href="http://bund.offenerhaushalt.de/">OffenerHaushalt</a> allows users to explore and drill down through the various layers of Germany's federal budget, comparing data from as far back as 2006. Through the new TreeMap visualisation, the user can easily see and explore the different departments and programmes and see how much is spent, proportions and statistics on changes between years.
|
|
||||||
|
|
||||||
The success of OffenerHaushalt and the demand to roll it out on a local level was one of the prime motivations for the creation of OpenSpending. To date, the OffenerHaushalt team have received around 90 requests for a similar site in their area.
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li><a href="http://bund.offenerhaushalt.de/">Visit the OffenerHaushalt Project</a></li>
|
|
||||||
<li><a href="https://twitter.com/#!/offenerhaushalt">Follow OffenerHaushalt on Twitter</a></li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
#### Uganda Aid Visualisation
|
|
||||||
|
|
||||||
Aid flows often do not pass through a recipient government’s conventional budget mechanisms. When this happens, recipient governments themselves may not have the complete overview of where aid money goes and how donor priorities align with their own. This information is vital for governments and aid donors to be able to make the best use of scarce resources.
|
|
||||||
|
|
||||||
<img class="pull-left" style="margin-right: 1em;" title="Uganda Aid" src="http://farm9.staticflickr.com/8159/7315314386_7940819de6.jpg" alt="" width="250" />
|
|
||||||
|
|
||||||
Normally this overview is not available – leading to waste, overlap and inefficiency. The lack of comparable information means aid donors and recipient country governments can’t work together to coordinate their efforts or understand how donor priorities align with recipient priorities; it decreases developing country governments' ownership and undermines the potential for good governance and planning. Donors and governments need to know what others are doing - and crucially, what others are planning on doing - if they are to make sure that these resources are used most effectively. Otherwise, some sectors and areas will not receive enough funding, while others may have too many donors involved.
|
|
||||||
|
|
||||||
The Uganda Aid visualisation project was a joint project between the OKFN and Publish What You Fund to combine two key types of fiscal data, revenues from aid together with spending information, and present them together in an informative way for the first time through an interactive visualisation.
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li><a href="http://www.publishwhatyoufund.org/uganda/uganda-with-data.htm">Visit the Publish What You Fund Uganda Visualisation Project</a></li>
|
|
||||||
<li><a href="http://www.publishwhatyoufund.org">Visit Publish What You Fund's website</a></li>
|
|
||||||
<li><a href="http://openspending.org/ugandabudget">Uganda Budget and Aid to Uganda, 2003-2006 dataset in OpenSpending</a></li>
|
|
||||||
<li>Coverage of the Uganda Visualisation: <a href="http://www.guardian.co.uk/global-development/poverty-matters/2011/nov/25/uganda-aid-confusion-analyse-spending?newsfeed=true">Guardian Poverty Matters Blog</a></li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
#### IATI
|
|
||||||
|
|
||||||
The International Aid Transparency Initiative is a common format for publishing aid information. 29 signatories representing 75% of global Official Development Finance have committed to reporting timely information about their aid activities in this standard format. Already, 13 signatories representing 45% of ODF have published.
|
|
||||||
|
|
||||||
<img class="pull-right" style="margin-left: 1em;" title="IATI" src="http://farm9.staticflickr.com/8007/7315331330_4dafe5ea48.jpg" alt="" width="250" />
|
|
||||||
|
|
||||||
IATI publishers release the data as open data feeds in a common XML format through their own websites. They then register their data with the IATI Registry - which runs on the Open Knowledge Foundation's CKAN software - making it easy for users to find this data.
|
|
||||||
|
|
||||||
However, the nature of IATI as a distributed collection of raw data feeds also presents a challenge to non-technical users. The Open Knowledge Foundation worked with Publish What You Fund to transform the data into a format suitable for import into OpenSpending, where the data can be much more easily visualised and analysed.
|
|
||||||
|
|
||||||
<a href="http://openspending.org/iati?_time=2011">View the IATI data on OpenSpending</a>
|
|
||||||
|
|
||||||
<a name="gov-tools"></a>
|
|
||||||
|
|
||||||
## Tools for governments
|
|
||||||
|
|
||||||
#### Data.Gov.Uk Spend Browser
|
|
||||||
|
|
||||||
<img class="pull-left" style="margin-right: 2em;" title="Reporting Tool" src="http://farm6.staticflickr.com/5523/9045231550_505140b175_n.jpg" alt="http://farm6.staticflickr.com/5523/9045231550_505140b175_n.jpg" />
|
|
||||||
|
|
||||||
The OpenSpending team worked with Data.Gov.Uk to build the <a href="http://data.gov.uk/data/openspending-browse">transaction explorer</a> which forms part of the Data.Gov.Uk website.
|
|
||||||
|
|
||||||
The transaction explorer allows any user to directly search the OpenSpending database for companies, departments or projects of interest and investigate how much money was spent on them.
|
|
||||||
|
|
||||||
#### UK Government Spend Reporting Dashboard
|
|
||||||
|
|
||||||
<img class="pull-left" style="margin-right: 2em;" title="Reporting Tool" src="http://farm9.staticflickr.com/8443/7980196066_d4aa29eb0d_z.jpg" alt="" />
|
|
||||||
|
|
||||||
The OpenSpending team worked with Data.Gov.Uk to produce an automatic reporting tool to demonstrate which government departments were complying with their transparency obligations.
|
|
||||||
|
|
||||||
The <a href="http://data.gov.uk/data/openspending-report/index">tool</a> lists departments registered as data publishers on data.gov.uk and details how precisely they have followed the <a href="https://www.gov.uk/government/publications/guidance-for-publishing-spend-over-25000">HM Treasury reporting guidelines</a>. It will also make the whole of the reported data available for search and analysis both on <a href="http://data.gov.uk/openspending">data.gov.uk</a> and on the OpenSpending site.
|
|
||||||
|
|
||||||
<a name="gov-use-cases"></a>
|
|
||||||
|
|
||||||
## Government use cases
|
|
||||||
|
|
||||||
#### City of Bologna
|
|
||||||
|
|
||||||
<img class="pull-left" style="margin-right: 2em;" title="Open Dati Bologna Tool" src="http://dati.comune.bologna.it/file/field/image/open_spending_pic_bologna.png" alt="http://dati.comune.bologna.it/file/field/image/open_spending_pic_bologna.png" />
|
|
||||||
|
|
||||||
The open data team at the City of Bologna uses OpenSpending to visualise several years of <a href="http://openspending.org/bp_2012_entrate/views/table-of-aggregates-bilancio-di-previsione-2012-entrate">the city budget</a>.
|
|
||||||
|
|
||||||
#### City of Berlin
|
|
||||||
<img class="pull-left" style="margin-right: 2em;" title="The budget for Berlin city" src="http://stefanwehrmeyer.com/img/blog/2013/02/budget-berlin.png" alt="http://stefanwehrmeyer.com/img/blog/2013/02/budget-berlin.png" />
|
|
||||||
|
|
||||||
The City of Berlin asked Open Knowledge Foundation Germany to visualise the budget for the city using OpenSpending. The result is featured on the <a href="https://imperia9.berlinonline.de/sen/finanzen/haushalt/haushaltsplan/artikel.5697.php">site for the city finances</a>.
|
|
||||||
|
|
||||||
<a name="publications"></a>
|
|
||||||
|
|
||||||
## Publications and Reports
|
|
||||||
|
|
||||||
#### Technology for Transparent & Accountable Public Finance
|
|
||||||
<img class="pull-left" style="margin-right: 2em;" title="TTAPF" src="http://farm9.staticflickr.com/8031/8002530046_fe4354f76a_m.jpg" alt="" />
|
|
||||||
|
|
||||||
The report, <a href="../../resources/gift/">“Technology for Transparent and Accountable Public Finance”</a>, was commissioned by the Global Initiative for Fiscal Transparency (GIFT) in February 2012 in order to assist GIFT in assessing the potential of technology to aid transparency and accountability in relation to governments’ fiscal activities.
|
|
||||||
|
|
||||||
Read the <a href="../../resources/gift/chapter9-intro/#governments">recommendations</a>.
|
|
||||||
|
|
||||||
<a href="http://content.openspending.org/resources/gift/pdf/ttapf_report_20120530.pdf">Download as PDF</a>
|
|
||||||
|
|
||||||
#### Mapping the Open Spending Data Community
|
|
||||||
<img class="pull-right" style="margin-left: 2em;" title="Spend Report" src="http://farm8.staticflickr.com/7414/8881834696_4176e6d2ea_m.jpg" alt="" />
|
|
||||||
|
|
||||||
In early 2012, we set out on a mission. Our aim was to establish how CSO's currently work with spending data, how they would like to use it, and what they would like to achieve - including:
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li>what existing tools are being used</li>
|
|
||||||
<li>what current technical needs are unmet</li>
|
|
||||||
<li>what would be required to meet these needs and how feasible is it to tackle them</li>
|
|
||||||
</ul>
|
|
||||||
This <a href="../../resources/mappingcommunity/">report</a> is the output of that research. Here, we bring together key case studies from organisations who have done pioneering work in using technology to put government data to best use.
|
|
||||||
|
|
||||||
In this report we:
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li>outline how the data could be improved in order to make it more usable</li>
|
|
||||||
<li>examine some key case studies of how organisations are using technology to do groundbreaking research, citizen engagement, visualisation and tracking of accountability.</li>
|
|
||||||
<li>talk about the training needs for CSO's to help them better use the data available, and to demand better data.</li>
|
|
||||||
</ul>
|
|
||||||
Read the <a href="../../resources/mappingcommunity/conclusions/">conclusions</a>.
|
|
||||||
|
|
||||||
<a href="../../resources/mappingcommunity/introduction/videos/">Athens to Berlin research trip: Watch the video interviews</a>
|
|
||||||
|
|
||||||
#### The Spending Data Handbook
|
|
||||||
<img class="pull-left" style="margin-right: 2em;" title="Spending Handbook" src="http://farm8.staticflickr.com/7449/8754377372_77aed9107e_m.jpg" alt="" />
|
|
||||||
|
|
||||||
The <a href="../../resources/handbook/">Spending Data Handbook</a> is addressed to people and organisations who want to use and understand government budgets and spending data in their work.
|
|
||||||
|
|
||||||
The book covers:
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li>Collaborating with other organizations to pool resources and strengthen your advocacy effort</li>
|
|
||||||
<li>If you're just starting out, what data to look for and what to ask for (nay, demand!) from your government</li>
|
|
||||||
<li>The 'Data Pipeline': Tricks and tips for finding, wrangling and systematically processing your data</li>
|
|
||||||
<li>Getting ambitious, running a technology project</li>
|
|
||||||
<li>Presenting your findings to engage the public, media and government</li>
|
|
||||||
<li>Lists and appendices of technical and non-technical resources</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<a name="standards"></a>
|
|
||||||
|
|
||||||
## Standards
|
|
||||||
|
|
||||||
#### [Draft] Standard for Transaction-level Spending Data
|
|
||||||
The release of transaction-level data (i.e. information about individual disbursements or contract spending) is a relatively new idea, compared to the release of higher-level accounting information or budget overviews. The availability of such data allows for fine-grained analysis and oversight of activities and will, in the future, enable anyone inside or outside of government to reconstruct key reports from raw data. In order to perform these types of analysis, it is often necessary to combine spending information from several sources - either for completeness or comparison.
|
|
||||||
|
|
||||||
Too often, standardization in this context appears to be supply-driven: every publisher wants to express the full range of data they hold and are willing to release. Necessarily, such an approach leads to a standard that is the superset of all the systems that feed into it.
|
|
||||||
|
|
||||||
Such designs tend to be of little use to the intended consumers, as they raise the barriers to understanding the information considerably. Our approach therefore is to generate demand-side use cases first, ensuring that everything that is done will generate value for data users.
|
|
||||||
|
|
||||||
Read our <a href="../../resources/standard/">proposed standard</a>.
|
|
||||||
|
|
||||||
<a name="stories"></a>
|
|
||||||
|
|
||||||
## Stories and Data Journalism
|
|
||||||
|
|
||||||
#### The Guardian (UK)
|
|
||||||
|
|
||||||
<h4>The Real Price of the London Olympics</h4>
|
|
||||||
<a title="olympic-guardian by anderspedersenOKF, on Flickr" href="http://www.flickr.com/photos/94746900@N06/8915659698/"><img src="http://farm3.staticflickr.com/2806/8915659698_60f3b70eed_o.png" alt="olympic-guardian" /></a>
|
|
||||||
|
|
||||||
The Guardian used OpenSpending's bubbletree visualisations to answer the questions: Where is the Olympics money coming from - and where's it being spent? How much is coming from sponsorship - and how much does the Olympic stadium cost?
|
|
||||||
|
|
||||||
<a href="http://www.guardian.co.uk/sport/datablog/interactive/2012/jul/26/london-2012-price-olympic-games-visualised">See the interactive visualisation on the Guardian Datablog</a>.
|
|
||||||
|
|
||||||
<h4>The Daily Bread</h4>
|
|
||||||
<a href="http://www.guardian.co.uk/uk/datablog/interactive/2013/mar/20/budget-2013-how-taxes-spent-interactive">The Daily Bread</a> from Where Does My Money Go? Has made regular appearances on the Guardian Datablog around budget time in the UK.
|
|
||||||
|
|
||||||
#### Le Monde (France)
|
|
||||||
We experienced an extremely high traffic spike when a visualisation based on French data was featured in Le Monde in October 2012.
|
|
||||||
The article <a href="http://www.lemonde.fr/politique/article/2012/10/16/plf-des-avions-au-bouclier-fiscal-la-java-des-amendements_1776093_823448.html?xtmc=depenses&xtcr=52">PLF : des avions au bouclier fiscal, la java des amendements</a>, (PLF=Projet de loi de finances, the draft finance law) deals with suggested amendments to the draft finance law and which parties were demanding what amendments.
|
|
||||||
|
|
||||||
The OpenSpending visualisation used in the article is intended to give a high-level representation of some of the main areas of government expenditure in France.
|
|
||||||
|
|
||||||
#### Politiken (Denmark)
|
|
||||||
<a title="politiken" href="http://farm6.staticflickr.com/5339/9044797934_366b1d8914_m.jpg"><img class="pull-right" style="margin-left: 2em;" src="http://farm6.staticflickr.com/5339/9044797934_366b1d8914_m.jpg" alt="politiken" /></a>
|
|
||||||
|
|
||||||
Municipalities are central for the functioning of the welfare state Denmark. They take care of a range of important tasks like social- and health care, primary education, social benefits, traffic and much more. Even in a year with local elections, however, they do not attract much public attention. The open data web agency Buhl-Rasmussen developed a site of all 98 Danish municipalities for one of the biggest Danish news sites, Politiken.
|
|
||||||
|
|
||||||
#### Sumy News, Ukraine
|
|
||||||
<a title="politiken" href="http://sumynews.com/data-journalism2/budget-economy/item/4726-byudzhet-m-sumy-na-2013-rik-openspending.html<br />
|
|
||||||
"><img class="pull-left" style="margin-right: 1em;" src="http://farm6.staticflickr.com/5459/9045133060_9dbb04b97c_m.jpg" alt="" /></a>
|
|
||||||
|
|
||||||
On December 26, 2012, Sumy City Council approved the city budget for 2013, but there were big concerns about how it would be executed.
|
|
||||||
|
|
||||||
The expected revenues for the coming year did not appear to match the planned output, as Sumy would have to have generated 15.7% more than the expected revenues in 2012....
|
|
||||||
|
|
||||||
<a href="http://sumynews.com/data-journalism2/budget-economy/item/4726-byudzhet-m-sumy-na-2013-rik-openspending.html">Read the article</a>.
|
|
||||||
|
|
||||||
#### Privacy International
|
|
||||||
|
|
||||||
In early 2012, Privacy International approached the Spending Stories team to ask for a search widget to be able to search across all of the government spending datasets held in OpenSpending. They had a list of companies which exhibited at the famous surveillance technology conferences in the US, the so-called Wiretappers' Ball, as well as a list of attendees of the conference, and they wanted to check which attendees also became customers of these companies.
|
|
||||||
|
|
||||||
<img class="pull-right" style="margin-left: 1em;" title="Caelainn Barr" src="http://farm8.staticflickr.com/7213/7315271184_921d9ed606.jpg" alt="" width="250" />
|
|
||||||
|
|
||||||
Some attendees posed no surprises – the FBI, the US Drug Enforcement Administration, the UK Serious Organized Crime Agency and Interpol to name a few – but there were a few that are downright baffling, like the US Department of Commerce, the US Fish & Wildlife Service and the Clark County School District Police Department.
|
|
||||||
|
|
||||||
As more datasets are loaded into OpenSpending, this universal search will get increasingly more powerful, and we look forward to hearing what other people use the search for.
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li><a href="http://opendatalabs.org/spendbrowser">Try out the search for yourself in the spendbrowser</a></li>
|
|
||||||
<li><a href="http://blog.openspending.org/2012/02/24/how-spending-stories-fact-checks-big-brother-the-wiretappers-ball/">Read more about the story</a></li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
#### Italian Regional Accounts Data
|
|
||||||
<img class="pull-left" style="margin-right: 1em;" title="Caelainn Barr" src="http://farm6.staticflickr.com/5224/5639223572_5451048271.jpg" alt="" width="250" />
|
|
||||||
|
|
||||||
During the International Journalism Festival in Perugia in 2011, the OpenSpending team loaded and visualised the Italian regional accounts for 2008. The project received wide coverage in the Italian and International Press and was one of the earliest success stories for OpenSpending after Where Does My Money Go? went international.
|
|
||||||
|
|
||||||
<a href="http://openspending.org/it-regional-accounts">Visit the Italian Regional Accounts</a> on OpenSpending.org.
|
|
||||||
|
|
||||||
Coverage of the Italian Regional Accounts Data:
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li><a href="http://www3.lastampa.it/economia/sezioni/articolo/lstp/398705/">La Stampa</a></li>
|
|
||||||
<li><a href="http://www.guardian.co.uk/news/datablog/interactive/2011/apr/19/italy-public-spending-visualisation">The Guardian</a></li>
|
|
||||||
<li><a href="http://daily.wired.it/news/economia/2011/04/19/open-spending.html">Daily Wired</a></li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
## Training
|
|
||||||
|
|
||||||
<img class="pull-right" style="margin-left: 3em;" title="Caelainn Barr" src="http://farm7.staticflickr.com/6166/6151919267_897ccfbd1c.jpg" alt="" width="250" />
|
|
||||||
|
|
||||||
We regularly conduct training sessions for journalists and NGOs on how to locate, extract, work with and visualise spending and other types of data. If you are interested in exploring these possibilities, please [get in touch](/about/contact/).
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li><a href="http://blog.okfn.org/2011/08/09/data-driven-journalism-workshop-on-eu-spending-tools-techniques-utrecht-8th-9th-september/">Workshop on EU Spending, Utrecht</a></li>
|
|
||||||
<li><a href="http://blog.okfn.org/2011/09/27/eurohack-one-day-data-journalism-competition-and-workshop-on-eu-spending/">EuroHack: One-day data journalism competition and workshop on EU spending</a></li>
|
|
||||||
<li><a href="http://blog.openspending.org/2012/11/26/day-1-openspending-cso-workshop-sarajevo/">Budget and Spending Visualisation Workshop, Sarajevo</a></li>
|
|
||||||
</ul>
|
|
||||||
You can find more of our training materials on the <a href="http://schoolofdata.org/handbook/courses/">School of Data website</a>.
|
|
||||||
|
|
||||||
## Community
|
|
||||||
|
|
||||||
<img class="pull-right" style="margin-left: 1em;" title="Kaitlin Lee presents Sunlight's Analysis OGDCamp" src="http://farm7.staticflickr.com/6166/6270108254_5875c8a7ed.jpg" alt="" width="250" />
|
|
||||||
|
|
||||||
The OpenSpending community includes engaged citizens, dedicated journalists and members of civil society organisations working on developing best practices around opening up and using government financial data with experts from fields ranging from aid experts, participatory budgeting fields, governmental institutions and civic developer initiatives.
|
|
||||||
|
|
||||||
We showcase and display some of the most interesting projects from all over the world on [the OpenSpending blog](/blog/).
|
|
||||||
|
|
||||||
The working group is open to everyone with an interest in improving Government Financial Transparency around the world. If you're interested in joining, please join the <a href="https://discuss.okfn.org/c/openspending">forums</a>.
|
|
||||||
|
|
||||||
<a name="your-project"></a>
|
|
||||||
|
|
||||||
## Contribute
|
|
||||||
|
|
||||||
#### Your project here
|
|
||||||
Have some data? Have a Spending Story? Get in touch - we'd love to hear from you and are open to suggestions!
|
|
||||||
|
|
||||||
|
|
||||||
@ -1,43 +0,0 @@
|
|||||||
---
|
|
||||||
section: about
|
|
||||||
lead: true
|
|
||||||
title: Frequently Asked Questions
|
|
||||||
authors:
|
|
||||||
- Neil Ashton
|
|
||||||
---
|
|
||||||
#### What is OpenSpending?
|
|
||||||
|
|
||||||
OpenSpending is about Mapping the Money.
|
|
||||||
|
|
||||||
The aim is to help track every (public) government and corporate financial transaction across the world and present it in useful and engaging forms for everyone from a schoolchild to a data geek.
|
|
||||||
|
|
||||||
What [OpenStreetMap](http://www.openstreetmap.org/) does for geography, OpenSpending does for money. OpenStreetMap has mapped the world in unprecedented levels of detail, harnessing the power of thousands of volunteers who each contribute data for their little corner of the world. However, as far as we know, there is no 'global atlas' of spending, no integrated, searchable database which would be a valuable resource for policy-makers and civil society alike. We want anyone to be able to go to their local council or national government, request the data, upload, understand and visualize it and contribute to this 'spending commons', which anyone can benefit from.
|
|
||||||
|
|
||||||
#### What is the relationship to Where Does My Money Go?
|
|
||||||
|
|
||||||
Simply put, OpenSpending is the international version of [Where Does My Money Go?](http://wheredoesmymoneygo.org/) (WDMMG). WDMMG used interactive 'bubble trees' to show the UK Taxpayer which spending sectors their tax money is put towards as well as having an interactive tax calculator to let users see for their level of income, how much they contribute to various spending areas through their taxes.
|
|
||||||
|
|
||||||
##### Platform vs. project
|
|
||||||
|
|
||||||
After the success of [the original project](http://jonathangray.org/2007/04/02/where-does-my-money-go-project-proposal/), it became clear that there was need for an international platform to allow people to build such sites at scale. Where Does My Money Go? was remodelled to become an instance of OpenSpending: the data is stored in the central OpenSpending database, and a custom frontend was developed using the OpenSpending API. Anyone can create one just like it, with their own branding at their own URL.
|
|
||||||
|
|
||||||
#### Can anyone contribute?
|
|
||||||
|
|
||||||
Yes! Whether you are interested in international, national or local data, you can contribute, work with and visualize it. See [How can I get involved?](../../help/development/volunteer) for the various ways you can get involved.
|
|
||||||
|
|
||||||
#### How can I get involved?
|
|
||||||
|
|
||||||
The team has worked hard to make it possible to load and visualize your own data, translate the software and even build your own custom front-end sites like [Where Does My Money Go?](http://wheredoesmymoneygo.org/)
|
|
||||||
|
|
||||||
Whether you are technical or non-technical, whether your aims are advocacy, journalism, better policy-making or just making pretty bubbles to help people understand your country's budget, there are plenty of ways to get involved. And don't be shy - if you spot a way to get involved that we haven't thought of, please don't hesitate to let us know.
|
|
||||||
|
|
||||||
See the [get involved](../../help/development/volunteer) page for more information.
|
|
||||||
|
|
||||||
#### What kind of language support do you offer?
|
|
||||||
|
|
||||||
We currently provide language versions of the OpenSpending platform in Greek, Indonesian and Italian. We expect to enable French as well as other languages in the near future.
|
|
||||||
You can help translate OpenSpending into another language at our [Transifex page](https://www.transifex.com/projects/p/openspending/).
|
|
||||||
|
|
||||||
#### How are you funded?
|
|
||||||
|
|
||||||
OpenSpending is a community-run project, but it would not be able to exist without the generous support of many organizations. See [this page](../funders/) for more information.
|
|
||||||
File diff suppressed because it is too large
Load Diff
@ -1,23 +0,0 @@
|
|||||||
---
|
|
||||||
title: The Fiscal Data Package
|
|
||||||
redirect_from:
|
|
||||||
- "/about/governance/"
|
|
||||||
---
|
|
||||||
|
|
||||||
The Fiscal Data Package is a lightweight and user-oriented format for publishing and consuming fiscal data. Fiscal data packages are made of simple and universal components. They can be produced from ordinary spreadsheet software and used in any environment.
|
|
||||||
|
|
||||||
The motivation behind the fiscal data package was to create a specification which is open by nature - based on other open standards, supported by open tools and software, modular, extensible and promoted transparently by a large community.
|
|
||||||
|
|
||||||
It is designed to be simple to use - providing a small but flexible set of features, based on real-world requirements and not theoretical ones. All the while, the built-in extensibility allows this spec to adapt to many different use cases and domains. It is also possible to gradually use more and more part of this specification - thus making it easier to implement this spec with existing data while slowly improving the data quality.
|
|
||||||
|
|
||||||
A main concern of this specification is the ability to work with data as it is currently exists, without forcing publishers to modify the contents or structure of their current data files in order to "adapt" them to the specification.
|
|
||||||
|
|
||||||
#### The Open Fiscal Data Package serves two main purposes:
|
|
||||||
Standardizing the structure and the content of fiscal data so that tools and services can be built over it for visualization, analysis or comparison;
|
|
||||||
Driving data quality by providing a solid framework of publication.
|
|
||||||
|
|
||||||
So the Open Fiscal Data Package specifies the form for fiscal data and offers a standardized framework for the content.
|
|
||||||
|
|
||||||
- Read the [Fiscal Data Package specification](https://frictionlessdata.io/specs/fiscal-data-package/) on the Frictionless Data website
|
|
||||||
- Meet the [OpenSpending tools](/about/tools)
|
|
||||||
- Read about
|
|
||||||
@ -1,36 +0,0 @@
|
|||||||
---
|
|
||||||
section: about
|
|
||||||
lead: true
|
|
||||||
title: Our funders
|
|
||||||
authors:
|
|
||||||
- Neil Ashton
|
|
||||||
---
|
|
||||||
OpenSpending is a community-driven project, but we would not be able to run it without the generous support of these organizations:
|
|
||||||
|
|
||||||
#### 4IP
|
|
||||||
|
|
||||||
<img src="http://blog.openspending.org/files/2013/09/4ip-300x79.jpg" alt="4ip" width="300" height="79" class="alignright size-medium wp-image-1056" />
|
|
||||||
|
|
||||||
It was thanks to Channel 4's Information Program that [Where Does My Money Go?](http://wheredoesmymoneygo.org/) was born. 'Where Does My Money Go?' was the original version of OpenSpending for the United Kingdom and has inspired many international versions of the site.
|
|
||||||
|
|
||||||
#### Open Society Foundations
|
|
||||||
|
|
||||||
<img src="http://blog.openspending.org/files/2013/09/osf-300x70.jpg" alt="Basic CMYK" width="300" height="70" class="alignright size-medium wp-image-1057" />
|
|
||||||
|
|
||||||
The Open Society Foundations support community building work around Open Spending Data. With this project we aim to help more groups and individuals around the world to use and work with spending data more effectively to do the things they care about – whether this is investigative journalism, evidence based policy-making, political campaigning, budgeting or creating new useful applications and services.
|
|
||||||
|
|
||||||
In particular, we would like to document and spread best practices in the legal and technical aspects of reusing public information, and enabling re-use and better collaboration around this material.
|
|
||||||
|
|
||||||
Read [the announce post]( http://blog.openspending.org/2012/01/12/civil-society-and-spending-data-who-is-mapping-the-money/) for more information.
|
|
||||||
|
|
||||||
#### Knight Foundation
|
|
||||||
|
|
||||||
<img src="http://blog.openspending.org/files/2013/09/kf-300x71.png" alt="kf" width="300" height="71" class="alignright size-medium wp-image-1058" />
|
|
||||||
|
|
||||||
The Knight Foundation support the development of the [Spending Stories](http://blog.okfn.org/2011/06/22/spending-stories-is-a-winner-of-the-knight-news-challenge/) project. Spending Stories is a tool designed to speed up fact checking around spending data, helping journalists to connect raw data with their stories and build context around data with visualisations and auxilliary information.
|
|
||||||
|
|
||||||
#### Omidyar Network
|
|
||||||
|
|
||||||
<img src="http://blog.openspending.org/files/2013/09/on-300x100.jpg" alt="on" width="300" height="100" class="alignright size-medium wp-image-1059" />
|
|
||||||
|
|
||||||
The Omidyar Network funded the research behind the report 'Technology for Transparent and Accountable Public Finance', which was presented at the Global Initiative for Fiscal Transparency meeting in Brasilia in April 2012.
|
|
||||||
@ -1,19 +0,0 @@
|
|||||||
---
|
|
||||||
title: About OpenSpending
|
|
||||||
redirect_from:
|
|
||||||
- "/about/governance/"
|
|
||||||
---
|
|
||||||
### What is OpenSpending?
|
|
||||||
OpenSpending is a free, open and global platform to search, visualise and analyse fiscal data in the public sphere. With OpenSpending, Open Knowledge Foundation created the opportunity for governments, civil society organizations and communities to publish and visualize their revenue, budgets, spending and procurements data in an open source platform.
|
|
||||||
|
|
||||||
The OpenSpending platform consists of a core platform with a large, centralised database that allows for deep analysis across a range of datasets. It is designed, developed and maintained by Open Knowledge Foundation. At the same time, OpenSpending offers tools that enable to establish an ecosystem around fiscal data, which is tailored to the specific aspects and local contexts the data is embedded in.
|
|
||||||
|
|
||||||
As an open source and a community-driven project, also reflects the valuable contributions of an active, passionate and committed community.
|
|
||||||
|
|
||||||
### Got it, what now?
|
|
||||||
|
|
||||||
- Meet the [OpenSpending tools](/about/tools)
|
|
||||||
- Learn about the [Fiscal Data Package](/about/fiscaldatapackage)
|
|
||||||
- Read other resources about Fiscal Transparency on the [GIFT website](http://www.fiscaltransparency.net/resources/)
|
|
||||||
- Read the [OpenSpending documentation](https://docs.openspending.org/en/latest/)
|
|
||||||
- Learn more about [this website](/about/meta)
|
|
||||||
@ -1,13 +0,0 @@
|
|||||||
---
|
|
||||||
title: Recent Changes
|
|
||||||
githubactivity: true
|
|
||||||
section: meta
|
|
||||||
---
|
|
||||||
|
|
||||||
A list of the most recent changes or issues raised on the site as
|
|
||||||
documented on the site's
|
|
||||||
[GitHub repository](https://github.com/openspending/community.openspending.org/).
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div id="github-activity" style="width: 100%"></div>
|
|
||||||
@ -1,48 +0,0 @@
|
|||||||
---
|
|
||||||
title: Adding a resource to the library
|
|
||||||
authors:
|
|
||||||
- Mor Rubinstein
|
|
||||||
lang: en
|
|
||||||
section: meta
|
|
||||||
---
|
|
||||||
|
|
||||||
<p>Our resource library is a curated collection open data reosurces from across the community. Everyone can add a resource to the library. This is how to do so.</p>
|
|
||||||
|
|
||||||
<h2>1. Add a folder</h2>
|
|
||||||
|
|
||||||
<p>Log in to github and head to the following <a href=https://github.com https://github.com/{{ site.github_username }}/tree/gh-pages/resources> link: </a></p>
|
|
||||||
|
|
||||||
Every resource has a slug number. To add your resource, you need to give it a number. Look at the list and give you resource the number that follows the current last number in the list (e.g - if the number is 056, your resource should be named 057).
|
|
||||||
Click on the + sign in the directory line and add the number and a “/”. For example: 060/.
|
|
||||||
|
|
||||||
<h2>2. Add an index file</h2>
|
|
||||||
|
|
||||||
<p>Click on the + sign again. Add a file named index.md to your new folder.</p>
|
|
||||||
|
|
||||||
<h2>3. Add the resource</h2>
|
|
||||||
|
|
||||||
<p>In the text editor, add the front matter fields in this pattern:</p>
|
|
||||||
<pre>
|
|
||||||
---
|
|
||||||
section: resources
|
|
||||||
lang: //Two first letters of the language, according to language code in this table.//
|
|
||||||
Author: //The name(s) of the person(s) who wrote the text//
|
|
||||||
Country: //One or more country by full name separated with a comma: “,”. If there is no specific country, write ‘global’//
|
|
||||||
Description: //1-5 lines that summarizes the text. //
|
|
||||||
Keywords: //Important descriptors of the text, separated with a comma, “,”.//
|
|
||||||
Link: //The link to the resource online//
|
|
||||||
MediaType: // List one out of these four types: Presentation, Article, / Publication, Video//
|
|
||||||
Notes: //Any notes or comments.//'
|
|
||||||
Publishing_date: //The year the resource was published, e.g. 2015.//
|
|
||||||
Publishing_entity: //The organisation(s) which publish the resource//
|
|
||||||
Region: North America,Latin America,Asia,Europe,Africa,Mena,Global
|
|
||||||
Title: //The name of the resource//
|
|
||||||
Topic: //Choose one out of these nine : The Basics,Advocacy,Privacy,civic engagement,Right for information,Data training,PolicyStandards.
|
|
||||||
---
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
<h2>4. Make a pull request</h2>
|
|
||||||
|
|
||||||
<p>Click on “Create a new branch for this commit and start a pull request.” This will allow us to review your changes.</p>
|
|
||||||
|
|
||||||
Thank you! All done!
|
|
||||||
@ -1,47 +0,0 @@
|
|||||||
---
|
|
||||||
lang: en
|
|
||||||
title: Adding a term to the glossary
|
|
||||||
authors:
|
|
||||||
- Mor Rubinstein
|
|
||||||
section: meta
|
|
||||||
---
|
|
||||||
<p>Each glossary (meaning, each translated instance of the glossary), has three components:
|
|
||||||
<ul>
|
|
||||||
<li> A layout template for the glossary homepage: 'glossary.html'</li>
|
|
||||||
<li> A layout template for the glossary in each language: 'glossary/{lang}/index.md'</li>
|
|
||||||
<li> A directory of the glossary terms. Each term in the directory is listed as the url slug (In English, all lower case letters, and hyphens instead of white spaces).</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<p></p>Currently, the English glossary has been updated and organized. Other languages please follow these <a href=http://new.opendatahandbook.org/contribute/translate-glossary/>instructions</a>
|
|
||||||
To add a new term, all you need is to have a Github account.</p>
|
|
||||||
|
|
||||||
<h3>1: Create a folder for the term</h3>
|
|
||||||
|
|
||||||
<p>Log - in to Github and go to this <a href="https://github.com/{{ site.github_repo }}tree/gh-pages/glossary/en/terms">link</a></p>
|
|
||||||
|
|
||||||
<p>You will see a the branch name (“gh-pages”) and a directory. You will also see the breadcrumb <code>{{ site.github_repo }} / glossary / en / terms / + </code>. Click on the "+" to create a new folder.<p/>
|
|
||||||
|
|
||||||
<p> Write the name of the term that you want to add in a new slug (In English, all lower case letters, and hyphens instead of white spaces) and add a “/” at the end of the terms name. This will create a new folder name. </p>
|
|
||||||
|
|
||||||
<h3>2: Create a file for your term</h3>
|
|
||||||
|
|
||||||
<p> Now you will see the breadcrumb - <code>{{ site.github_repo }} / glossary / en / terms / your-new-term / + </code> Click on the “+” sign again. Now write in the path “index.md”. This will save the whole file as a markdown file. </p>
|
|
||||||
|
|
||||||
<h3>3: Write the term definition </h3>
|
|
||||||
<p> In the text editor below, add the front matter (Jekyll way to mark the page) - </p>
|
|
||||||
<pre>
|
|
||||||
---
|
|
||||||
section: terms
|
|
||||||
lang: en
|
|
||||||
title: // the term name //
|
|
||||||
---
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
Write the term definition after the front matter as usual.
|
|
||||||
|
|
||||||
|
|
||||||
<h3>4: Make a pull request</h3>
|
|
||||||
|
|
||||||
<p> Click on “Create a new branch for this commit and start a pull request.” This will allow us to review your changes. <p/>
|
|
||||||
|
|
||||||
<p>Thank you! All done! If the handbook editors are happy with your term, it will be added to the glossary. </p>
|
|
||||||
@ -1,126 +0,0 @@
|
|||||||
---
|
|
||||||
lang: en
|
|
||||||
title: Adding a page
|
|
||||||
authors:
|
|
||||||
- Sam Smith
|
|
||||||
section: meta
|
|
||||||
---
|
|
||||||
|
|
||||||
<p class="lead">Most of what you need to know to add a new page is covered under ‘<a href="{{ "/meta/contribute/editing/" | prepend: site.baseurl }}">Editing a page</a>’, so make sure you have first read through that section.</p>
|
|
||||||
|
|
||||||
<p>Adding a page follows a similar process to editing. Instead of locating your page, your first step is to locate your new page’s parent directory.</p>
|
|
||||||
|
|
||||||
<h2>1: Create the page</h2>
|
|
||||||
|
|
||||||
<p>First locate the parent directory, or folder, in which your file will live. If you are adding a page to the "Get Involved" section, for example, you should be in the '<strong>get-involved</strong>' directory, where you’ll see a list of all the pages related to contributions.</p>
|
|
||||||
|
|
||||||
<p>Above the list of pages is a breadcrumb trail <code>{{ site.github_repo }} / get-involved / </code>, to the right of which is a plus symbol <code><strong>+</strong></code>. Click the plus symbol to create your new page.</p>
|
|
||||||
|
|
||||||
<h2>2: Name your file</h2>
|
|
||||||
|
|
||||||
<p>You should now have a new file editor page open. The first editable section you are presented with is the ‘<em>Name your file</em>’ field. As we touched upon when looking at <a href="{{ "/meta/contribute/editing/" | prepend: site.baseurl }}">editing files</a>, the file name corresponds to the URL of the page on the site. There are a few of rules to follow here:</p>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li>The file name should reflect the title of the new page</li>
|
|
||||||
<li>Must be unique</li>
|
|
||||||
<li>Should be all lowercase</li>
|
|
||||||
<li>Words should be separated by hyphens (-)</li>
|
|
||||||
<li>File name should end with the extension '<em>.md</em>' (the .md extension indicates a markdown file)</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<p>As an example, if you were creating a page titled '<em>My Cool Page</em>', you would use a file name of:</p>
|
|
||||||
|
|
||||||
<pre>
|
|
||||||
<code>my-cool-page.md</code>
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
<p>Assuming you are creating this in the '<em>get-involved</em>' directory, this would result in a URL of <em>{{ site.url }}/get-involved/my-cool-page</em></p>
|
|
||||||
|
|
||||||
<div class="note">
|
|
||||||
<h6>Note</h6>
|
|
||||||
<p>The actual words used in your file name are not crucial. It’s fine to use a more succinct version of your page title, for example.</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<h2>3: Formatting your content</h2>
|
|
||||||
|
|
||||||
<p>This step is the same as when editing a page. You need to start your file with the Front Matter, then add your content, formatting it using Markdown. Here is a template to get you started:</p>
|
|
||||||
|
|
||||||
<pre>
|
|
||||||
<code>---
|
|
||||||
title: My Cool Page
|
|
||||||
authors:
|
|
||||||
- Fred Bloggs
|
|
||||||
---
|
|
||||||
|
|
||||||
##A large introductory paragraph.
|
|
||||||
|
|
||||||
Regular paragraphs, separated by empty lines.
|
|
||||||
|
|
||||||
###A heading
|
|
||||||
|
|
||||||
Another paragraph.
|
|
||||||
|
|
||||||
* Maybe
|
|
||||||
* a
|
|
||||||
* list</code>
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
<p>When you’re done, click ‘<em>Propose new file</em>’.</p>
|
|
||||||
|
|
||||||
<h2>4: Make a pull request</h2>
|
|
||||||
|
|
||||||
<p>Once you have created your page(s) and updated the contents document, you're ready to make your pull request. Click the pull request icon to the right of the screen <code class="icon-git-pull-request"><span>[git pull-request icon]</span></code>, then click ‘<em>New pull request</em>’.</p>
|
|
||||||
|
|
||||||
<p>At the top of the resulting comparison screen, you’ll see a row of select boxes. You want to make sure these are configured like so:</p>
|
|
||||||
|
|
||||||
</article>
|
|
||||||
|
|
||||||
<div class="github panel">
|
|
||||||
<div class="range-editor">
|
|
||||||
<span class="icon-git-compare range-editor-icon"></span>
|
|
||||||
<div class="range">
|
|
||||||
|
|
||||||
<div class="range-cross-repo-pair">
|
|
||||||
<div class="select-menu js-menu-container js-select-menu fork-suggester">
|
|
||||||
<span class="minibutton select-menu-button js-menu-target" role="button" aria-label="Choose a Base Repository" aria-haspopup="true">
|
|
||||||
<i>base fork:</i>
|
|
||||||
<span class="js-select-button css-truncate css-truncate-target" title="base: ckan/ckan">{{ site.github_username }}/{{ site.github_repo }}</span>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="select-menu js-menu-container js-select-menu commitish-suggester">
|
|
||||||
<span class="minibutton select-menu-button js-menu-target branch" role="button" aria-label="Choose a base branch" aria-haspopup="true">
|
|
||||||
<i>base:</i>
|
|
||||||
<span class="js-select-button css-truncate css-truncate-target" title="base: master">gh-pages</span>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<span class="dots">...</span>
|
|
||||||
|
|
||||||
<div class="range-cross-repo-pair">
|
|
||||||
<div class="select-menu js-menu-container js-select-menu fork-suggester">
|
|
||||||
<span class="minibutton select-menu-button js-menu-target" role="button" aria-label="Choose a Head Repository" aria-haspopup="true">
|
|
||||||
<i>head fork:</i>
|
|
||||||
<span class="js-select-button css-truncate css-truncate-target" title="head: mintcanary/ckan"><em>username</em>/{{ site.github_repo }}</span>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="select-menu js-menu-container js-select-menu commitish-suggester">
|
|
||||||
<span class="minibutton select-menu-button js-menu-target branch" role="button" aria-label="Choose a head branch" aria-haspopup="true">
|
|
||||||
<i>compare:</i>
|
|
||||||
<span class="js-select-button css-truncate css-truncate-target" title="compare: master"><em>branch</em></span>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<article class="post-content">
|
|
||||||
<p><em><strong>username</strong> being your github username, <strong>branch</strong> being the branch you have been working on.</em></p>
|
|
||||||
|
|
||||||
<p>You should now be able to see listed below, all the changes that you wish to contribute. If everything looks as it should, click ‘<em>Create pull request</em>’.</p>
|
|
||||||
|
|
||||||
<p>Give your pull request a title and description, then click ‘<em>Create pul request</em>’. You have now contributed your pages to the OpenSpending Community site :)</p>
|
|
||||||
@ -1,103 +0,0 @@
|
|||||||
---
|
|
||||||
lang: en
|
|
||||||
title: Editing a page
|
|
||||||
authors:
|
|
||||||
- Sam Smith
|
|
||||||
section: meta
|
|
||||||
---
|
|
||||||
|
|
||||||
<p class="lead">If you haven’t done so already, the first thing you need to do is head over to <a href="https://github.com/" rel="external">Github</a> and create your free account.</p>
|
|
||||||
|
|
||||||
<p>There are three steps to editing a page. First you need to locate the page you wish to edit. There are a couple of ways to do this. <strong>Method A</strong> is probably the simplest, and most likely way you’ll do it. <strong>Method B</strong> will serve as a primer for the next section: <em>Adding a page</em>.</p>
|
|
||||||
|
|
||||||
<h2>1: Locate the page</h2>
|
|
||||||
|
|
||||||
<h4>Method A: Browse the website</h4>
|
|
||||||
|
|
||||||
<p>While reading any section of the Handbook you’ll see an '<em>Edit this page</em>' link in the bottom left of the page. Following this link will take you directly to an editable version of that page. Easy huh?</p>
|
|
||||||
|
|
||||||
<div class="note">
|
|
||||||
<h6>Note</h6>
|
|
||||||
<p>When the editable page opens it will (most likely) contain a message saying <em>“You're editing a file in a project you don't have write access to”</em>. If this is your first edit to The Open Data Handbook it will say <em>“We've created a fork of this project for you to commit your proposed changes to”</em>. This is normal and part of the workflow.</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<h4>Method B: Browse the Github repository</h4>
|
|
||||||
|
|
||||||
<p>The entire file structure of this site can be browsed on Github. For example, the root of the site is <a href="https://github.com/{{ site.github_username }}/{{ site.github_repo }}" rel="external">here</a>, and the English language handbook section is <a href="https://github.com/{{ site.github_username }}/{{ site.github_repo }}/tree/gh-pages/en" rel="external">here</a>. It’s helpful to understand that the page URLs correspond to the file structure you see here. So, if you wanted to edit the Handbook introduction page, given that it’s URL is <code>{{ site.url }}/<strong>en</strong>/<strong>introduction</strong>/</code> we know this file can be found in the <code><strong>en</strong></code> directory with the filename <code><strong>introduction</strong>.md</code> <em>Note: the extension (.md) is stripped from the URL.</em> Following these links you should see a preview of the page you wish to edit. From here click the edit icon <code class="icon-pencil"><span>[pencil icon]</span></code> to start editing.</p>
|
|
||||||
|
|
||||||
<div class="note">
|
|
||||||
<h6>Pro Tip!</h6>
|
|
||||||
<p>Press <code>t</code> on any tree or blob page to launch the file finder.</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<h2>2: Make your changes</h2>
|
|
||||||
|
|
||||||
With the editable content in front of you, you’re probably either thinking “great, let’s get editing”, or “hang on, this looks a bit weird”. In case it’s the latter, let’s have a closer look.
|
|
||||||
|
|
||||||
The first thing to recognise is the ‘Front Matter’, which will look like this:
|
|
||||||
|
|
||||||
<pre>
|
|
||||||
<code>---
|
|
||||||
title: Introduction
|
|
||||||
---</code>
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
<p>The front matter must be the first thing in the file, must adhere to the above syntax, and must be set between triple-dashed lines. Numerous variables can be set here, but you’ll usually just need <code>title</code>. The title set here will be used as the main heading for the page, as well as in the browser tab.</p>
|
|
||||||
|
|
||||||
<p>The other important thing to recognise is the Markdown syntax. For example, where you see a line commencing with two hash marks:</p>
|
|
||||||
|
|
||||||
<pre>
|
|
||||||
<code>##Do you know exactly how much of your tax money is spent on street lights?</code>
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
<p>This is the Markdown way of creating a level two heading. On the site it will be outputted like so:</p>
|
|
||||||
|
|
||||||
<h2>Do you know exactly how much of your tax money is spent on street lights?</h2>
|
|
||||||
|
|
||||||
<p>Another common formatting requirement is bullet points, or lists. These are achieved in Markdown by using asterisks, like so:</p>
|
|
||||||
|
|
||||||
<pre>
|
|
||||||
<code>* civil servants
|
|
||||||
* journalists
|
|
||||||
* politicians</code>
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
<p>giving you:</p>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li>civil servants</li>
|
|
||||||
<li>journalists</li>
|
|
||||||
<li>politicians</li>
|
|
||||||
</ul>
|
|
||||||
<br>
|
|
||||||
<p>Links are created like so:</p>
|
|
||||||
|
|
||||||
<pre>
|
|
||||||
<code>Give your data a home at the [Datahub](http://datahub.io/).</code>
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
<p>result:</p>
|
|
||||||
|
|
||||||
<p>Give your data a home at the <a href="http://datahub.io/">Datahub</a>.</p>
|
|
||||||
|
|
||||||
<div class="note">
|
|
||||||
<h6>Pro Tip!</h6>
|
|
||||||
<p>To get a link to a specific heading on this site, hover over it then click the section icon <code class="icon-section"><span>[section icon]</span></code>. This will put the URL into your address bar.</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<p>More Markdown examples can be found <a href="{{ "/meta/contribute/markdown-examples/" | prepend: site.baseurl }}">here</a>, and a more detailed overview <a href="http://daringfireball.net/projects/markdown/syntax" rel="external">here</a>.</p>
|
|
||||||
|
|
||||||
<p>If you are unsure of your markup while editing, you can switch to the preview tab <code class="icon-eye"><span>[eye icon]</span> Preview changes</code> to see how it will be rendered.</p>
|
|
||||||
|
|
||||||
<div class="note">
|
|
||||||
<h6>Note</h6>
|
|
||||||
<p>The Github previews will look stylistically different from the live site. A different font will be used for example.</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<p>Once you are happy with your changes, add a summary of what you've changed in the field below the editable text. Then click ‘<em>Propose file change</em>’.</p>
|
|
||||||
|
|
||||||
<h2>3: Make a pull request</h2>
|
|
||||||
|
|
||||||
<p>You will now be presented with a ‘pull request’ form. So far, the changes you have made are to your own copy, or fork of the handbook. A pull request simply sends a request to the authors/maintainers of the live handbook, asking them to include your changes - and put them live! Add any comments you have for the handbook team, then press ‘<em>Create pull request</em>’.</p>
|
|
||||||
|
|
||||||
<p>Your work here is done :) If you need to make related changes though, any new commits pushed to your branch will automatically be added to the pull request.</p>
|
|
||||||
@ -1,76 +0,0 @@
|
|||||||
---
|
|
||||||
title: Contributing to this site
|
|
||||||
authors:
|
|
||||||
- Sam Smith
|
|
||||||
lang: en
|
|
||||||
section: meta
|
|
||||||
---
|
|
||||||
|
|
||||||
Thank you for your interest in in helping to build the OpenSpending
|
|
||||||
community site. We warmly welcome comments, corrections and additions,
|
|
||||||
as well as suggestions for additional sections and areas to
|
|
||||||
examine. For general discussion about
|
|
||||||
[OpenSpending](https://openspending.org/), please visit
|
|
||||||
[our forums](https://discuss.okfn.org/c/openspending). To jump in with
|
|
||||||
improvements and additions, read on.
|
|
||||||
|
|
||||||
## How this site works
|
|
||||||
|
|
||||||
In order to contribute, you need a little insight of how things work
|
|
||||||
under the hood. We’re not going to go into too much detail here, but
|
|
||||||
these are the three components you need some understanding of:
|
|
||||||
|
|
||||||
- GitHub
|
|
||||||
- Jekyll
|
|
||||||
- Markdown
|
|
||||||
|
|
||||||
### GitHub
|
|
||||||
|
|
||||||
#### What is it?
|
|
||||||
|
|
||||||
GitHub is a web-based repository hosting service, which amongst other
|
|
||||||
things offers revision control and source code management via a
|
|
||||||
web-based graphical interface.
|
|
||||||
|
|
||||||
#### Why should I care?
|
|
||||||
|
|
||||||
Any changes you wish to make, whether they be edits to an existing
|
|
||||||
page, or creating a new one, will most likely be done via the GitHub
|
|
||||||
website (it is also possible to download and edit the files on your
|
|
||||||
local machine, instructions for this method will be added in the
|
|
||||||
future). All the files for this site can be browsed and edited the
|
|
||||||
GitHub website. You will need to [sign up](https://github.com/) for a
|
|
||||||
(free) GitHub account. For full instructions, see
|
|
||||||
[Editing a page](./editing/).
|
|
||||||
|
|
||||||
### Jekyll
|
|
||||||
|
|
||||||
#### What is it?
|
|
||||||
|
|
||||||
Jekyll is a static site generator, which allows us to host websites
|
|
||||||
based on our GitHub repositories. Jekyll takes the content, renders
|
|
||||||
Markdown, and produces a complete, static website ready to be viewed
|
|
||||||
on the web.
|
|
||||||
|
|
||||||
#### Why should I care?
|
|
||||||
|
|
||||||
All you really need to know about Jekyll is the method it uses to
|
|
||||||
include metadata (ie. page title). Each page needs to start with a
|
|
||||||
section it calls Front Matter, containing the page title. An example
|
|
||||||
is provided in the [Adding a page](./adding/) section.
|
|
||||||
|
|
||||||
### Markdown
|
|
||||||
|
|
||||||
#### What is it?
|
|
||||||
|
|
||||||
Markdown is a markup language with plain text formatting, designed so
|
|
||||||
that it can be converted to HTML. Markdown can be used to create rich
|
|
||||||
text using a plain text editor.
|
|
||||||
|
|
||||||
#### Why should I care?
|
|
||||||
|
|
||||||
Markdown is your key to formatting the text your provide for this
|
|
||||||
site. By learning a few intuitive rules you’ll be able to ensure your
|
|
||||||
text is formatted with headings, list, quotes etc, without writing any
|
|
||||||
HTML. For examples, head to the
|
|
||||||
[Markdown]({{site.baseurl}}/meta/contribute/markdown-examples/) section.
|
|
||||||
@ -1,213 +0,0 @@
|
|||||||
---
|
|
||||||
lang: en
|
|
||||||
title: Markdown Examples
|
|
||||||
section: meta
|
|
||||||
---
|
|
||||||
|
|
||||||
* TOC
|
|
||||||
{:toc}
|
|
||||||
|
|
||||||
* TOC
|
|
||||||
{:toc}
|
|
||||||
|
|
||||||
This is a paragraph.
|
|
||||||
|
|
||||||
This is a paragraph.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Header 1
|
|
||||||
========
|
|
||||||
|
|
||||||
Header 2
|
|
||||||
--------
|
|
||||||
|
|
||||||
Header 1
|
|
||||||
========
|
|
||||||
|
|
||||||
Header 2
|
|
||||||
--------
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Header 1
|
|
||||||
|
|
||||||
## Header 2
|
|
||||||
|
|
||||||
### Header 3
|
|
||||||
|
|
||||||
#### Header 4
|
|
||||||
|
|
||||||
##### Header 5
|
|
||||||
|
|
||||||
###### Header 6
|
|
||||||
|
|
||||||
# Header 1
|
|
||||||
|
|
||||||
## Header 2
|
|
||||||
|
|
||||||
### Header 3
|
|
||||||
|
|
||||||
#### Header 4
|
|
||||||
|
|
||||||
##### Header 5
|
|
||||||
|
|
||||||
###### Header 6
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
> Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aliquam hendrerit mi posuere lectus. Vestibulum enim wisi, viverra nec, fringilla in, laoreet vitae, risus.
|
|
||||||
|
|
||||||
> Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aliquam hendrerit mi posuere lectus. Vestibulum enim wisi, viverra nec, fringilla in, laoreet vitae, risus.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
> ## This is a header.
|
|
||||||
> 1. This is the first list item.
|
|
||||||
> 2. This is the second list item.
|
|
||||||
>
|
|
||||||
> Here's some example code:
|
|
||||||
>
|
|
||||||
> Markdown.generate();
|
|
||||||
|
|
||||||
> ## This is a header.
|
|
||||||
> 1. This is the first list item.
|
|
||||||
> 2. This is the second list item.
|
|
||||||
>
|
|
||||||
> Here's some example code:
|
|
||||||
>
|
|
||||||
> Markdown.generate();
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
* Red
|
|
||||||
* Green
|
|
||||||
* Blue
|
|
||||||
|
|
||||||
~~~
|
|
||||||
* Red
|
|
||||||
* Green
|
|
||||||
* Blue
|
|
||||||
~~~
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
1. Buy flour and salt
|
|
||||||
1. Mix together with water
|
|
||||||
1. Bake
|
|
||||||
|
|
||||||
~~~
|
|
||||||
1. Buy flour and salt
|
|
||||||
1. Mix together with water
|
|
||||||
1. Bake
|
|
||||||
~~~
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Paragraph:
|
|
||||||
|
|
||||||
Code
|
|
||||||
|
|
||||||
<!-- -->
|
|
||||||
|
|
||||||
Paragraph:
|
|
||||||
|
|
||||||
Code
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
* * *
|
|
||||||
|
|
||||||
***
|
|
||||||
|
|
||||||
*****
|
|
||||||
|
|
||||||
- - -
|
|
||||||
|
|
||||||
---------------------------------------
|
|
||||||
|
|
||||||
* * *
|
|
||||||
|
|
||||||
***
|
|
||||||
|
|
||||||
*****
|
|
||||||
|
|
||||||
- - -
|
|
||||||
|
|
||||||
---------------------------------------
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
This is [an example](http://datahub.io/) link.
|
|
||||||
|
|
||||||
[This link](/about/) is internal.
|
|
||||||
|
|
||||||
This is [an example] [ok] reference-style link.
|
|
||||||
|
|
||||||
[ok]: https://okfn.org/
|
|
||||||
|
|
||||||
This is [an example](http://datahub.io/) link.
|
|
||||||
|
|
||||||
[This link](/about/) is internal.
|
|
||||||
|
|
||||||
This is [an example] [ok] reference-style link.
|
|
||||||
|
|
||||||
[ok]: https://okfn.org/
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
*single asterisks*
|
|
||||||
|
|
||||||
_single underscores_
|
|
||||||
|
|
||||||
**double asterisks**
|
|
||||||
|
|
||||||
__double underscores__
|
|
||||||
|
|
||||||
*single asterisks*
|
|
||||||
|
|
||||||
_single underscores_
|
|
||||||
|
|
||||||
**double asterisks**
|
|
||||||
|
|
||||||
__double underscores__
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
This paragraph has some `code` in it.
|
|
||||||
|
|
||||||
This paragraph has some `code` in it.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
|
|
||||||
| Tables | Are | Cool |
|
|
||||||
| ------------- |:-------------:| -----:|
|
|
||||||
| col 3 is | right-aligned | $1600 |
|
|
||||||
| col 2 is | centered | $12 |
|
|
||||||
| zebra stripes | are neat | $1 |
|
|
||||||
|
|
||||||
| Tables | Are | Cool |
|
|
||||||
| ------------- |:-------------:| -----:|
|
|
||||||
| col 3 is | right-aligned | $1600 |
|
|
||||||
| col 2 is | centered | $12 |
|
|
||||||
| zebra stripes | are neat | $1 |
|
|
||||||
|
|
||||||
I bet you'd like more information about this sentence [^1].
|
|
||||||
|
|
||||||
[^1]: Well lucky for you, I've included more information in a footnote.
|
|
||||||
|
|
||||||
~~~
|
|
||||||
I bet you'd like more information about this sentence [^1].
|
|
||||||
[^1]: Well lucky for you, I've included more information in a footnote.
|
|
||||||
~~~
|
|
||||||
@ -1,65 +0,0 @@
|
|||||||
---
|
|
||||||
lang: en
|
|
||||||
title: Translating the glossary
|
|
||||||
authors:
|
|
||||||
- Mor Rubinstein
|
|
||||||
section: meta
|
|
||||||
---
|
|
||||||
|
|
||||||
<h2> What's new in the glossary</h2>
|
|
||||||
<p>In the old version of the handbook, the glossary was one page with all of the term in it. In the new version, we gave each glossary a webpage for better referencing and linking.<\p>
|
|
||||||
Glossaries that were translated in the old version of the handbook have been transfered to the new site. Please checkCheck if your language has an old version of the glossary -
|
|
||||||
. You can find them <a href=https://github.com https://github.com/{{ site.github_username }}/tree/gh-pages/glossary> here </a>
|
|
||||||
|
|
||||||
<h3><b>If you do have an old version translated, follow these steps:</b></h3>
|
|
||||||
<p> The old glossary format does not allow linking from the new version of the guide, and you will need to transfer the term to the new format.</p>
|
|
||||||
|
|
||||||
<h3> 1. Create a new folder for the term</h3>
|
|
||||||
|
|
||||||
<p>Under your language folder, Follow the breadcrumb trail <code>{{ site.github_repo }} / glossary / es /</code>, to the right of which is a plus symbol <code><strong>+</strong></code>. create a folder for each term by pressing on the '+' sign and type the term name in English. The folder names should be in lower-case letters with dashes ‘-’ instead of white spaces. Add a ‘/’ in the end of the name to create a new folder.</p>
|
|
||||||
|
|
||||||
<h3> 2. Translate the term</h3>
|
|
||||||
<p> open a new index.md file by clicking on the '+'. </p>
|
|
||||||
|
|
||||||
In the text editor below add the front matter:
|
|
||||||
<pre>
|
|
||||||
---
|
|
||||||
section: terms
|
|
||||||
lang: en
|
|
||||||
title: Bulk
|
|
||||||
---
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
<p> Change the 'lang' field to your language code. Change the title to the term title in YOUR language.</p>
|
|
||||||
<p>Below the front matter copy the term from the old glossary.</p>
|
|
||||||
|
|
||||||
<h3> 3. Make a pull request.</h3>
|
|
||||||
|
|
||||||
<p>All done! Keep doing this until all terms got their own folder and page.</p>
|
|
||||||
|
|
||||||
<h2><b>If you have never translated the glossary before, follow the these steps:</b></h2>
|
|
||||||
|
|
||||||
<h3> Copy the English Glossary</h3>
|
|
||||||
|
|
||||||
<p> Copy the English terms directory into your target language directory in the glossary folder. This step can not be done through the Github website and you will have to fork the handbook for you machine. Information about forking and cloning can be find <a href=https://help.github.com/articles/fork-a-repo/>here</a> . Notice, some languages have already been moved and translated. Check the folder to make sure you are not overwriting someone’s work.</p>
|
|
||||||
|
|
||||||
<h3>Edit the term</h3>
|
|
||||||
|
|
||||||
<p>Choose a term and open the index.md file.</p>
|
|
||||||
<p>The front matter looks as follows:</p>
|
|
||||||
|
|
||||||
<pre>
|
|
||||||
---
|
|
||||||
section: terms
|
|
||||||
lang: en
|
|
||||||
title: Bulk
|
|
||||||
---
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
<p>Change the lang field to your language code.</p>
|
|
||||||
<p>Change the title to the term title in YOUR language.</p>
|
|
||||||
<p>In the text editor, below the front matter, enter your translation to the term.</p>
|
|
||||||
|
|
||||||
<h3>3. Submit changes through a pull request.</h3>
|
|
||||||
|
|
||||||
<p> All done! Thank you for your help! </p>
|
|
||||||
@ -1,41 +0,0 @@
|
|||||||
---
|
|
||||||
lang: en
|
|
||||||
title: Translating the guide
|
|
||||||
authors:
|
|
||||||
- Mor Rubinstein
|
|
||||||
section: meta
|
|
||||||
---
|
|
||||||
|
|
||||||
Translating the guide is easy, no need to any other software, all you need is a github account!
|
|
||||||
Some languages already have translated version of the guide. If you don't have a version in your language, here is how to do it.
|
|
||||||
|
|
||||||
<h3> 1. Create a new language folder </h3>
|
|
||||||
|
|
||||||
In github, under the breadcrumb - <code>{{ site.github_repo }} / guide/</code> there will be a '+' sign. Click on it and enter your <a http://en.wikipedia.org/wiki/List_of_ISO_639-1_codes >your two letter languages code</a>. Add a dash ('/') after the two letter to create a folder.
|
|
||||||
|
|
||||||
<h3> 2. Create a page folder</h3>
|
|
||||||
|
|
||||||
Now you will see you languages code and a '+' sign on the breadcrumb. Add a the page name that you want to translate in __English__ and add a dash at the end.
|
|
||||||
|
|
||||||
<h3> 3. translate the content</h3>
|
|
||||||
|
|
||||||
You will now see a new '+' sign. Add the file name 'index.md'.
|
|
||||||
In the text editor add the following front matter:
|
|
||||||
<pre>
|
|
||||||
---
|
|
||||||
section: guide
|
|
||||||
lang: Your language two letter code
|
|
||||||
title: The title in your language
|
|
||||||
---
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
Translate as usual.
|
|
||||||
|
|
||||||
<h3> 4. Create a pull request</h3>
|
|
||||||
If all good, we will add it to the site.
|
|
||||||
|
|
||||||
Repeat for other parts of the guide if needed.
|
|
||||||
|
|
||||||
That's it, you are all done!
|
|
||||||
|
|
||||||
Thank you for helping us to make the guide accessiable to others!
|
|
||||||
@ -1,35 +0,0 @@
|
|||||||
---
|
|
||||||
title: About This Site
|
|
||||||
---
|
|
||||||
|
|
||||||
If you are a member of the OpenSpending community---whether you
|
|
||||||
are a data publisher, work on building or testing code, or develop
|
|
||||||
stories and visualizations using OpenSpending data---this site belongs
|
|
||||||
to you.
|
|
||||||
|
|
||||||
This site is a place to showcase the OpenSpending community's work and
|
|
||||||
to share its resources. It includes:
|
|
||||||
|
|
||||||
* information about community [events][3b]
|
|
||||||
* a collection of [resources][2] on spending data
|
|
||||||
* guidance on [how to get involved][3] with the community
|
|
||||||
|
|
||||||
[This site](https://github.com/openspending/community.openspending.org/)
|
|
||||||
is hosted on [GitHub Pages](https://pages.github.com/) and built using
|
|
||||||
[Jekyll](http://jekyllrb.com/), a static site generator. Interested
|
|
||||||
readers are encouraged to contribute changes, fixes, corrections by
|
|
||||||
[raising an issue](https://github.com/openspending/community.openspending.org/issues/new?title=Bug&body=I%27m%20having%20an%20issue%20with...)
|
|
||||||
on the site's
|
|
||||||
[issue tracker](https://github.com/openspending/community.openspending.org/issues).
|
|
||||||
For more detail on how to contribute, see the Contribution Guide
|
|
||||||
below.
|
|
||||||
|
|
||||||
- [Contribution Guide](./contribute/): Detailed information on how to contribute changes to the site
|
|
||||||
- [Recent Changes](./changes/): A list of recent changes to the site
|
|
||||||
- [Media](./media/): Downloadable OpenSpending images and other media
|
|
||||||
|
|
||||||
[1]: {{ site.baseurl }}/blog/
|
|
||||||
[2]: {{ site.baseurl }}/resources/
|
|
||||||
[3]: {{ site.baseurl }}/get-involved/
|
|
||||||
[3b]: {{ site.baseurl }}/events/
|
|
||||||
[4]: {{ site.baseurl }}/help/
|
|
||||||
@ -1,22 +0,0 @@
|
|||||||
---
|
|
||||||
title: Media
|
|
||||||
section: meta
|
|
||||||
---
|
|
||||||
|
|
||||||
## OpenSpending Square Logo
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
## OpenSpending Text Logo
|
|
||||||
|
|
||||||
### Normal
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
### Small
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
### Large
|
|
||||||
|
|
||||||

|
|
||||||
@ -1,102 +0,0 @@
|
|||||||
---
|
|
||||||
section: about
|
|
||||||
lead: true
|
|
||||||
title: 'OpenSpending: first steps'
|
|
||||||
authors:
|
|
||||||
- Neil Ashton
|
|
||||||
redirect_from:
|
|
||||||
- "/openspending-first-steps"
|
|
||||||
---
|
|
||||||
<section class="slide shout">
|
|
||||||
<div>
|
|
||||||
<h2>Welcome to OpenSpending</h2>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
<div id="content">
|
|
||||||
<section class="slide osimage">
|
|
||||||
<div class="well">
|
|
||||||
<div class="row-fluid">
|
|
||||||
<div class="span4">
|
|
||||||
<a title="00-visualize by okfn, on Flickr" href="http://openspending.org/datasets/new"><img src="//farm4.staticflickr.com/3669/9575045401_5a752545b0_n.jpg" class="img-rounded" alt="00-visualize"/></a>
|
|
||||||
</div>
|
|
||||||
<div class="span8">
|
|
||||||
<h2>Upload and visualize data</h2>
|
|
||||||
<a href="http://openspending.org/datasets/new">Upload</a> any kind of financial data to OpenSpending and explore it with our built-in interactive visualizations. Users publish <a href="http://openspending.org/budgetmarocain">budgets</a>, <a href="http://openspending.org/marches-publics-senegal/views/liste-des-attributaires">procurements</a>, <a href="http://openspending.org/ukgov-25k-spending">spending data</a> and even <a href="http://openspending.org/senadofederal/entries">public employee salaries</a>.
|
|
||||||
|
|
||||||
Use our <a href="http://www.pbs.org/idealab/2013/03/how-to-embed-open-spending-visualizations-in-your-own-website078">widgets</a> to embed your visualization on your own website.
|
|
||||||
|
|
||||||
<a href="http://openspending.org/datasets/new" class="btn btn-success btn-large" title="Create a dataset">Upload a dataset</a>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
<section class="slide osimage">
|
|
||||||
<div class="well">
|
|
||||||
<div class="row-fluid">
|
|
||||||
<div class="span4">
|
|
||||||
<a title="01-explore by okfn, on Flickr" href="http://openspending.org/search"><img src="//farm4.staticflickr.com/3670/9575044337_71d0e520ae_n.jpg" class="img-rounded" alt="01-explore"/></a>
|
|
||||||
</div>
|
|
||||||
<div class="span8">
|
|
||||||
<h2>Explore the database</h2>
|
|
||||||
OpenSpending holds nearly 16 mio. transactions from more than 300 datasets across more than 70 countries.
|
|
||||||
|
|
||||||
Browse the <a href="http://openspending.org/datasets">list of datasets</a> and learn about public finances from around the world, or browse <a href="http://apps.openspending.org/maps/">our map of cities</a> on OpenSpending.
|
|
||||||
|
|
||||||
<a href="http://openspending.org/search" class="btn btn-success btn-large" title="Search the datasets">Search transactions</a> <small>or <a href="http://openspending.org/datasets/" title="List of datasets">look at the datasets</a></small>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
<section class="slide osimage">
|
|
||||||
<div class="well">
|
|
||||||
<div class="row-fluid">
|
|
||||||
<div class="span4">
|
|
||||||
<a title="02-extend by okfn, on Flickr" href="http://blog.openspending.org/help/api/"><img src="//farm6.staticflickr.com/5549/9577836924_378752d5f3_n.jpg" class="img-rounded" alt="02-extend"/></a>
|
|
||||||
</div>
|
|
||||||
<div class="span8">
|
|
||||||
<h2>Create your own dataviz with our API</h2>
|
|
||||||
Create your own visualizations with the <a href="http://blog.openspending.org/help/api/aggregate/">OpenSpending API</a> using libraries like <a href="http://blog.openspending.org/2013/08/20/okfb-inesc/">D3.js</a>, jit and Raphael.
|
|
||||||
|
|
||||||
You can even create a satellite site while still using OpenSpending as a backend.
|
|
||||||
|
|
||||||
<a href="http://blog.openspending.org/help/api/" class="btn btn-success btn-large" title="API documentation">Look at the API</a>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
<section class="slide osimage">
|
|
||||||
<div class="well">
|
|
||||||
<div class="row-fluid">
|
|
||||||
<div class="span4">
|
|
||||||
<a title="03-community by okfn, on Flickr" href="http://blog.openspending.org/get-involved/community/"><img src="//farm6.staticflickr.com/5475/9575044189_f4de292c78_n.jpg" class="img-rounded" alt="03-community"/></a>
|
|
||||||
</div>
|
|
||||||
<div class="span8">
|
|
||||||
<h2>Join the community!</h2>
|
|
||||||
OpenSpending is <a href="https://github.com/openspending">open source software</a> built and run by a community of volunteers.
|
|
||||||
|
|
||||||
<a href="http://lists.okfn.org/mailman/listinfo/openspending">Join our mailing list</a> and share what you are creating with OpenSpending!
|
|
||||||
|
|
||||||
<a href="http://blog.openspending.org/get-involved/community/" class="btn btn-success" title="Community introduction">Join the spending community</a> <small>or</small> <a href="http://openspending.org/help/hacking.html" class="btn btn-success" title="Howto hack">Become a developer</a>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
</div>
|
|
||||||
<style>
|
|
||||||
.osimage img {
|
|
||||||
width: 100%;
|
|
||||||
margin: auto auto auto auto;
|
|
||||||
}
|
|
||||||
.row-fluid .span4 {
|
|
||||||
display:inline-block;
|
|
||||||
width: 31.914893614%;
|
|
||||||
}
|
|
||||||
.row-fluid .span8 {
|
|
||||||
display:inline-block;
|
|
||||||
width: 65.95744680199999%;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@ -1,13 +0,0 @@
|
|||||||
---
|
|
||||||
section: about
|
|
||||||
lead: true
|
|
||||||
title: "Introduction to OpenSpending: Mapping the Money"
|
|
||||||
presentation: true
|
|
||||||
authors:
|
|
||||||
- Anders Pedersen
|
|
||||||
redirect_from: /about/community-site/slide-deck-introduction/
|
|
||||||
---
|
|
||||||
|
|
||||||
<center>
|
|
||||||
<iframe src="https://docs.google.com/presentation/d/1IPtNzO5nu16SrSgtgxQ8L2jmeK0ILtsIMi8rj6KxUUk/embed?start=false&loop=false&delayms=3000" frameborder="0" width="640" height="480" allowfullscreen="true" mozallowfullscreen="true" webkitallowfullscreen="true"></iframe>
|
|
||||||
</center>
|
|
||||||
@ -1,12 +0,0 @@
|
|||||||
---
|
|
||||||
title: Presentations
|
|
||||||
section: about
|
|
||||||
---
|
|
||||||
|
|
||||||
<div class="author">Written by
|
|
||||||
<ul>
|
|
||||||
<p><a href="/about/presentation-introduction/">Introduction to OpenSpending: Mapping the Money</a></p>
|
|
||||||
<li>Anders Pedersen</li>
|
|
||||||
|
|
||||||
</ul>
|
|
||||||
</div
|
|
||||||
@ -1,126 +0,0 @@
|
|||||||
---
|
|
||||||
section: about
|
|
||||||
lead: true
|
|
||||||
title: Steering Group
|
|
||||||
redirect_from:
|
|
||||||
- "/about/governance/members-of-the-steering-group/index.html"
|
|
||||||
- "/about/governance/members-of-the-steering-group/"
|
|
||||||
---
|
|
||||||
|
|
||||||
The steering group oversees the project and represents its major stakeholders. This group takes responsibility for maintaining the integrity of the project, setting project policies, representing the project in relation to third parties etc.
|
|
||||||
|
|
||||||
The steering group's specific responsibilities include:
|
|
||||||
|
|
||||||
* **Finances**: overseeing and managing (where relevant) any project finances and resources.
|
|
||||||
* **Branding**. Overseeing Twitter account, website, etc.
|
|
||||||
* **Recognition** of satellite sites as part of the OpenSpending community and use of the OpenSpending name.
|
|
||||||
* **Partnerships** and collaborations with other communities and projects.
|
|
||||||
* **Setting policy** for data licensing and other matters, as necessary.
|
|
||||||
* **Advocacy guidelines**, as appropriate.
|
|
||||||
* **Legal matters**: for example, removal of datasets
|
|
||||||
|
|
||||||
## Meetings
|
|
||||||
|
|
||||||
The Steering Group meets approximately once a quarter via an online conference call.
|
|
||||||
|
|
||||||
The [living minutes of the OpenSpending Steering Group are online](https://docs.google.com/a/okfn.org/document/d/1jCB-RquGYeW9mm466ViucMRjggbCxa0pGZDH5JThcRc/edit).
|
|
||||||
|
|
||||||
## Appointment of the Steering Group
|
|
||||||
|
|
||||||
Anyone who has contributed to the OpenSpending project (whether in code, data, or content) may put themselves forward for membership in the steering group. The existing steering group members will consider the application and decide whether or not to accept. In the future, once the concept of OpenSpending membership is better established, this decision may be made by a vote among OpenSpending members.
|
|
||||||
|
|
||||||
Membership in the steering group is for a term of two years. Multiple consecutive terms are permitted. If members resign during their two-year term, nominations for a replacement will be solicited from the community.
|
|
||||||
|
|
||||||
## Members
|
|
||||||
|
|
||||||
### Anna Alberts, Open Knowledge Germany, Chair
|
|
||||||
|
|
||||||
Based in Berlin, Anna Alberts works as a Project Manager for the EU
|
|
||||||
research project OpenBudgets.eu at Open Knowledge Foundation Germany.
|
|
||||||
|
|
||||||
Anna studied International Development and International Relations,
|
|
||||||
and worked as a policy officer for the Strategy Unit at the Ministry
|
|
||||||
of Foreign Affairs in the Netherlands, focusing on geopolitics and
|
|
||||||
(open) data.
|
|
||||||
|
|
||||||
### Justin Arenstein, International Center for Journalists
|
|
||||||
{: .person-name}
|
|
||||||
|
|
||||||

|
|
||||||
{: .person-photo}
|
|
||||||
|
|
||||||
Justin Arenstein is a Knight International Journalism Fellow who is
|
|
||||||
helping the African Media Initiative (AMI) to establish a digital
|
|
||||||
innovation program that supports experimentation in newsrooms across
|
|
||||||
Africa. AMI, the continent's largest association of media owners and
|
|
||||||
executives, is working with more than 600 of the most influential
|
|
||||||
media companies in both northern and sub-Saharan Africa.
|
|
||||||
|
|
||||||
### Júlia Keserű, Sunlight Foundation
|
|
||||||
{: .person-name}
|
|
||||||
|
|
||||||
Júlia Keserű is the International Policy Manager at the Sunlight
|
|
||||||
Foundation and oversees its international work. Coming from the
|
|
||||||
Hungarian transparency community, Júlia has been an advocate for open
|
|
||||||
government and an expert on open data issues with a special focus on
|
|
||||||
political finance and corruption. She has spoken internationally on
|
|
||||||
technology and transparency and regularly writes about the challenges
|
|
||||||
and the potential of the global open government movement. Júlia holds
|
|
||||||
a Masters degree from International Studies and studied political
|
|
||||||
sciences, international law, sociology and philosophy at Corvinus
|
|
||||||
University Budapest, Free University Berlin and the College for Social
|
|
||||||
Theories in Budapest.
|
|
||||||
|
|
||||||
### Elena Mondo, International Budget Partnership
|
|
||||||
{: .person-name}
|
|
||||||
|
|
||||||

|
|
||||||
{: .person-photo}
|
|
||||||
|
|
||||||
Elena joined the International Budget Partnership (IBP) in 2007. She
|
|
||||||
manages the Open Budget Survey, the only independent, comparative, and
|
|
||||||
regular measure of budget transparency and accountability around the
|
|
||||||
world. Prior to joining the IBP, she worked as a consultant for the
|
|
||||||
Organization for Economic Cooperation and Development (OECD),
|
|
||||||
coordinating research on budget practices and procedures in the OECD
|
|
||||||
and Latin American countries. Mondo holds a BA in international
|
|
||||||
economics and management from Bocconi University, and an MPA in public
|
|
||||||
and economic policy from the London School of Economics.
|
|
||||||
|
|
||||||
### Oluseun Onigbinde, BudgIT
|
|
||||||
{: .person-name}
|
|
||||||
|
|
||||||

|
|
||||||
{: .person-photo}
|
|
||||||
|
|
||||||
Oluseun Onigbinde is the Co-Founder of BudgIT, a Nigerian public data
|
|
||||||
visualisation startup. He is an Ashoka Fellow and Open Knowledge
|
|
||||||
Ambassador for Nigeria.
|
|
||||||
|
|
||||||
### Anders Pedersen, Natural Resource Governance Institute
|
|
||||||
{: .person-name}
|
|
||||||
|
|
||||||
Anders Pedersen is Open Data Program Officer at the Natural Resource Governance
|
|
||||||
Institute. He holds an MA degree in Political Science from University of
|
|
||||||
Copenhagen, and has worked in development and financial data journalism.
|
|
||||||
|
|
||||||
### Federico Ramírez, Fundar
|
|
||||||
{: .person-name}
|
|
||||||
|
|
||||||
[bio coming here]
|
|
||||||
|
|
||||||
### Adam Stiles, Open Budget Oakland
|
|
||||||
{: .person-name}
|
|
||||||
|
|
||||||
Adam is co-creator of <a
|
|
||||||
href="http://openbudgetoakland.org/">openbudgetoakland.org</a> and a
|
|
||||||
member of the City of Oakland's budget advisory committee. He's also a
|
|
||||||
news editor, builder, and outdoor preschool founder.
|
|
||||||
|
|
||||||
### Mark Brough, Publish What You Fund
|
|
||||||
{: .person-name}
|
|
||||||
|
|
||||||
### Cecile Le Guen, Open Knowledge
|
|
||||||
{: .person-name}
|
|
||||||
|
|
||||||
Cecile Le Guen is Project Manager at Open Knowledge, involved in different fiscal open data projects.
|
|
||||||
@ -1,22 +0,0 @@
|
|||||||
---
|
|
||||||
title: OpenSpending tools
|
|
||||||
redirect_from:
|
|
||||||
- "/about/governance/"
|
|
||||||
---
|
|
||||||
|
|
||||||
### [OpenSpending Viewer](https://openspending.org/s/)
|
|
||||||
|
|
||||||
The OpenSpending Viewer is a Javascript app that provides views over data uploaded to OpenSpending. It offers 8 different visualisations and a pivot table for analyzing the data
|
|
||||||
|
|
||||||
### [OpenSpending Packager](https://openspending.org/packager/)
|
|
||||||
Via OpenSpending Packager fiscal data can be uploaded from alternate sources (csv, Excel, Google Sheets and Fiscal Data Package). Data and metadata can be uploaded in 4 simple steps.
|
|
||||||
|
|
||||||
### [OpenSpending Admin](https://openspending.org/admin/)
|
|
||||||
OpenSpending Admin offers the possibility to administer a user account and the associated data packages that have been loaded to the platform. You can access it from the main Packager or Viewer once you create an account.
|
|
||||||
|
|
||||||
### OpenSpending DataMine
|
|
||||||
The OpenSpending DataMine is an experimental feature for investigative analysis of data with direct access to read any part of the database. This feature can be used (and it is encouraged!), but currently it is not subject to further customisation.
|
|
||||||
|
|
||||||
## What kind of data can I upload to OpenSpending?
|
|
||||||
|
|
||||||
OpenSpending is designed to work with any dataset in CSV format containing government budget, spending information or any other fiscal data. To upload this data, we use data pipelines and the Fiscal Data Package. We recommend learning a bit more about it, even if you're not part of the technical team uploading the data.
|
|
||||||
@ -1,17 +0,0 @@
|
|||||||
---
|
|
||||||
authors:
|
|
||||||
- friedrich
|
|
||||||
redirect_from: /2011/03/where-does-my-money-go-goes-international-welcome-to-openspending/
|
|
||||||
title: "'Where Does My Money Go?' Goes international. Welcome to OpenSpending."
|
|
||||||
---
|
|
||||||
|
|
||||||
**This post is by [Friedrich Lindenberg](http://okfn.org/members/pudo), one of the developers working on OpenSpending.**
|
|
||||||
|
|
||||||
Our primary goal has to be to grow WDMMG as an open platform, similar to Open Street Map: while on OSM you sketch out your local streets, WDMMG should become the place to upload and analyze your local or state governments spending. Therefore, our priority has to be providing the right tools to allow people to contribute to this effort themselves: either by loading data, annotating spending or visualizing it in custom ways.
|
|
||||||
|
|
||||||
<img alt="" src="http://farm8.staticflickr.com/7151/6481368965_29d1650856_z.jpg" title="OpenSpending goes global. Open budgets and spending data. " class="alignnone" width="640" height="410" />
|
|
||||||
|
|
||||||
As such transparency is needed not only in the UK but all over the world, we want to re-label the data part of the site (what is now data.wdmmg.org) to the more international OpenSpending. This would both serve as an accessible means to handling financial data and as a backend to more specific sites, such as the UK's WhereDoesMyMoneyGo visualizations and Germany's OffenerHaushalt.
|
|
||||||
|
|
||||||
I'd like to invite all of you to follow up on the remainder of our discussion, which is archived at
|
|
||||||
<http://wiki.openspending.org/Status_2011-02-10> and to contribute your own thoughts.
|
|
||||||
@ -1,21 +0,0 @@
|
|||||||
---
|
|
||||||
authors:
|
|
||||||
- lucy
|
|
||||||
redirect_from: /2011/03/uploading-data-to-openspending/
|
|
||||||
title: Uploading Data to OpenSpending
|
|
||||||
---
|
|
||||||
The amount of datasets that are available on [OpenSpending.org](http://www.openspending.org) are growing fast and we want more! Currently the process looks like this:
|
|
||||||
|
|
||||||
1. You give us data.
|
|
||||||
2. We look at it, try to understand it, possibly ask you some more questions.
|
|
||||||
3. We write a custom loader script to load the data.
|
|
||||||
|
|
||||||
To make this process easier for us and faster for everybody, we offer an alternative process that requires a bit more work from you. But if you know how to transform your data to our CSV format, you will have your spending data online on OpenSpending more quickly and we can spend more time developing features! Here is how it works:
|
|
||||||
|
|
||||||
1. You create a CSV file that is formatted according to our [CSV schema](http://wiki.openspending.org/CSV_Schema). [Here is a really simple example of a CSV file][csv_example].
|
|
||||||
2. You use [our new web based uploader](http://www.openspending.org/sources/add) that automatically checks your CSV file for errors and stores it along with some meta data.
|
|
||||||
3. Contact us and we will do the final step and load the data into OpenSpending.org.
|
|
||||||
|
|
||||||
[csv_example]: https://spreadsheets1.google.com/ccc?hl=en&key=t8rduOMdinCo0smZjQvQUow&hl=en#gid=0
|
|
||||||
|
|
||||||
The schema and this alternative process are by no means set in stone: any feedback is appreciated! Most important: if you have spending data, but can't provide it in our CSV format, don't worry and just contact us. We always prefer some data over no data!
|
|
||||||
@ -1,69 +0,0 @@
|
|||||||
---
|
|
||||||
authors:
|
|
||||||
- lucy
|
|
||||||
redirect_from: /2011/10/thoughts-from-the-global-investigative-journalism-conference/
|
|
||||||
title: Thoughts from the Global Investigative Journalism Conference
|
|
||||||
tags:
|
|
||||||
- Data Journalism
|
|
||||||
- Spending Stories
|
|
||||||
---
|
|
||||||
**This post is by [Lucy Chambers](http://okfn.org/members/lucychambers), community coordinator at the Open Knowledge Foundation, and [Friedrich Lindenberg](http://okfn.org/members/pudo), Developer on OpenSpending. They recently attended the Global Investigative Journalism Conference 2011 in Kyiv, Ukraine, and in this post, bring home their thoughts on journalist-programmer collaboration...**
|
|
||||||
|
|
||||||
# The conference
|
|
||||||
|
|
||||||
The Global Investigative Journalism Conference must be one of the most intense yet rewarding experiences either of us have attended since joining the OKF. With topics ranging from human trafficking to offshore companies, the meeting highlighted the importance of long-term, investigative reporting in great clarity.
|
|
||||||
|
|
||||||
With around 500 participants from all over the globe with plenty of experience in evidence gathering, we used this opportunity to ask many of them how platforms like OpenSpending can contribute, not only to the way in which data is presented, but also to how it is gathered and analyzed in the course of an investigation.
|
|
||||||
|
|
||||||
# Spending Stories - the brainstorm
|
|
||||||
|
|
||||||
As many of you will be aware, earlier this year we won a Knight News Challenge award to help journalists contextualise and build narratives around spending data. Research for the project, [Spending Stories](http://blog.okfn.org/2011/06/22/spending-stories-is-a-winner-of-the-knight-news-challenge/), was one of the main reasons for our trip to Ukraine...
|
|
||||||
|
|
||||||
During the data clinic session as well as over drinks in the bar of "Hotel President" we asked the investigators what they would like to see in a spend analysis platform targeted at data journalists. Cutting to the chase, they immediately raised the key questions:
|
|
||||||
|
|
||||||
### How will it support my work?
|
|
||||||
|
|
||||||
|
|
||||||
It was clear that the platform should support the existing journalistic workflow through publishing embargos, private datasets and note making. At the same time, the need for statistical and analytical heuristics to dissect the data, find outliers and visualize distributions was highlighted as a means to enable truly data-driven investigations of datasets. The goal in this is to distinguish anomalies from errors and patterns of corruption from policies.
|
|
||||||
|
|
||||||
### What's in it for my readers?
|
|
||||||
|
|
||||||
|
|
||||||
With the data loaded and analyzed, the next question is what value can be added to published articles. Just like DocumentCloud enabled the easy embedding of source documents and excerpts, OpenSpending should allow journalists to visualize distributions of funds, embed search widgets and data links, as well as information about how the data was acquired and cleaned.
|
|
||||||
|
|
||||||
### What do I need to learn to do it?
|
|
||||||
|
|
||||||
|
|
||||||
Many of those we spoke to were concerned about the complexity required to contribute data. The recurring question was: should I even try myself or hire help? It's clear that for the platform to be accessible to journalists, a large variety of data cleansing tutorials, examples and tools need to be at their disposal.
|
|
||||||
|
|
||||||
We've listed the full brainstorm on the [OpenSpending wiki](http://wiki.openspending.org/Spending_Stories_Ideas#GIJC_Brainstorm)
|
|
||||||
|
|
||||||
You can also see the mind map with concrete points below:
|
|
||||||
|
|
||||||
<a href="http://www.flickr.com/photos/okfn/6254141727/sizes/l/in/photostream/"><img alt="" src="http://farm7.static.flickr.com/6151/6254141727_fe12468a67_b.jpg" title="Spending Stories brainstorm OpenSpending" class="alignnone" width="1024" height="507" /></a>
|
|
||||||
|
|
||||||
## Hacks & Scrapers - How technical need data journalists be?
|
|
||||||
|
|
||||||
In a second session, "Data Camp" we went through the question of how to generate structured data from unstructured sources such as web pages and PDF documents. We tried to emphasize the value of easily machine-readable data over less structured information by pointing to some examples on ScraperWiki.
|
|
||||||
|
|
||||||
As we went through basic steps needed to scrape a web page, the questions began turning towards the purpose of the exercise:
|
|
||||||
> "So why do we need to learn how to scrape? Can't we just hire someone to do this for us?"
|
|
||||||
|
|
||||||
Our answer went something like...
|
|
||||||
|
|
||||||
> "Well, yes - you can actually, <strong>but</strong>..."
|
|
||||||
|
|
||||||
...it may be a good idea to have some understanding of which data can be easily retrieved and what difficulties and errors you might encounter in the extraction process. This includes:
|
|
||||||
|
|
||||||
1. Understanding the possibilities and limitations of various data structures on the web to understand how to approach programmers and what to ask for (and importantly, what it is reasonable to pay).
|
|
||||||
2. Understanding how to quality-check data extracted from the internet and where errors could be introduced.
|
|
||||||
3. Appreciating that programmers are expensive and that having a basic understanding of some of the principles behind screen scraping yourself could save your organisation quite a lot of money for simpler tasks
|
|
||||||
|
|
||||||
The notes from the scraping session are available on this [pad](http://pudo.okfnpad.org/scrapetutu)
|
|
||||||
|
|
||||||
### So how do I hire a hacker?
|
|
||||||
|
|
||||||
The final thing that became blatantly apparent in sessions such as "Journalist or Programmer? Do Reporters Need to become Coders?" was that there is a huge void that needs to be bridged between the hacker and journalist world. If I had a pound for every time someone at the conference asked me how they could find a hacker, would be mighty happy. We pointed people in the direction of Hacks and Hackers meetings but there is clearly a need for a more extensive 'address' book of reliable contacts is obvious.
|
|
||||||
|
|
||||||
I will attempt to pull together some of the thoughts we had about how to find (and trust!) your hacker in a separate post to address some of these needs. If you have further advice or anecdotes on this subject, please don't hesitate to get in contact via the [OpenSpending mailing list](http://lists.okfn.org/mailman/listinfo/wdmmg-discuss).
|
|
||||||
|
|
||||||
@ -1,28 +0,0 @@
|
|||||||
---
|
|
||||||
authors:
|
|
||||||
- lucy
|
|
||||||
redirect_from: /2011/11/new-translation-documentation-for-openspending/
|
|
||||||
title: New Translation Documentation for OpenSpending
|
|
||||||
---
|
|
||||||
There's been a lot of demand for us to document the translation procedure for OpenSpending, so this is now up and live on the [wiki](http://wiki.openspending.org/Translations)
|
|
||||||
|
|
||||||
For reference, I've also briefly included the steps here:
|
|
||||||
|
|
||||||
## In order to translate OpenSpending, please follow the following steps:
|
|
||||||
|
|
||||||
* Create an account on [Transifex](https://www.transifex.net/home/)
|
|
||||||
* Email info [at] openspending.org with your Transifex Username and ask to be added to the group for your language of translation.
|
|
||||||
* Proceed to the following [link](https://www.transifex.net/projects/p/openspending/resource/openspendinguipot/)
|
|
||||||
* Click 'Add a translation' and follow the instructions on-screen.
|
|
||||||
|
|
||||||
|
|
||||||
## When you have finished your translation...
|
|
||||||
|
|
||||||
* Drop us an email to info [at] openspending.org and we will include it into our next release.
|
|
||||||
|
|
||||||
|
|
||||||
## Things to be aware of
|
|
||||||
|
|
||||||
* With each new release of the code, you may need to update your translation, to make sure all the new commands are accounted for...***We are currently building up to a big code release and will inform the list when the strings are stable. If you are eager to get going, you may start translating, most of your translation should be preserved, but there will be a little additional work to do before the release.***
|
|
||||||
|
|
||||||
**Happy translating, drop me an email if you have any questions via the [mailing list](http://lists.okfn.org/mailman/listinfo/openspending).**
|
|
||||||
@ -1,23 +0,0 @@
|
|||||||
---
|
|
||||||
authors:
|
|
||||||
- friedrich
|
|
||||||
redirect_from: /2011/11/openspending-v0-11-released/
|
|
||||||
title: OpenSpending v0.11 Released
|
|
||||||
tags:
|
|
||||||
- Releases
|
|
||||||
---
|
|
||||||
We are happy to announce the release of the latest version of OpenSpending. Most of our work has been to improve how we store and or organise spending data. Users will notice that the web frontend has been refreshed and is now much better integrated.
|
|
||||||
|
|
||||||
<img alt="" src="http://farm7.static.flickr.com/6055/6350321577_a96d5e8fc1_z.jpg" title="OpenSpending site redesign" class="alignnone" width="640" height="403" />
|
|
||||||
|
|
||||||
## New features include
|
|
||||||
|
|
||||||
* New backend using a conventional relational database allowing clean separation of datasets, and better scalability. The database backend is also much more familiar to developers than the previous backend
|
|
||||||
* [OpenSpending Developer Documentation](http://openspending.readthedocs.org/en/latest/index.html)
|
|
||||||
* Lots of documentation for API users and visualization hackers
|
|
||||||
* [OpenSpending Data Wrangler Documentation](http://openspending.org/help/api.html)
|
|
||||||
* New theme based on twitter's bootstrap framework
|
|
||||||
* Begun support for i18n/translation of the frontend
|
|
||||||
* Better validation of input data and model.
|
|
||||||
|
|
||||||
Feedback on the new site and features are welcome. Please drop us a line via the [mailing list](http://lists.okfn.org/mailman/listinfo/openspending).
|
|
||||||
@ -1,27 +0,0 @@
|
|||||||
---
|
|
||||||
authors:
|
|
||||||
- lucy
|
|
||||||
redirect_from: /2011/11/openspending-visualisations-featured-in-the-guardian/
|
|
||||||
title: OpenSpending visualisations featured in the Guardian
|
|
||||||
---
|
|
||||||
**This post is by [Lucy Chambers](http://okfn.org/members/lucychambers), Community Coordinator on OpenSpending.**
|
|
||||||
|
|
||||||
On Friday, the Guardian Poverty Matters blog published [a piece on the Uganda visualisation](http://www.guardian.co.uk/global-development/poverty-matters/2011/nov/25/uganda-aid-confusion-analyse-spending?newsfeed=true) that the OpenSpending team had been working on with [Publish What You Fund](http://www.publishwhatyoufund.org/).
|
|
||||||
|
|
||||||
<img alt="" src="http://farm8.staticflickr.com/7024/6417743801_4a67740798_z.jpg" title="Uganda Aid visualisation Guardian Publish What You Fund" class="alignnone" width="640" height="335" />
|
|
||||||
|
|
||||||
## From the article
|
|
||||||
|
|
||||||
> "The [Publish What You Fund campaign group](http://www.publishwhatyoufund.org/) and the [Open Knowledge Foundation](http://okfn.org) have now produced a [visualisation of Uganda's aid and budget data for 2003-2006](http://www.publishwhatyoufund.org/uganda/uganda-with-data.htm#/^/2004/~/aid-and-domestic-spending-in-uganda-br----ugx-), billed as the first time both sets of data have been displayed together in a way that is easy to explore. A quick look shows just how big a piece of the puzzle aid spending is – more than 50% of overall resources available in Uganda for 2005-2006. The vast majority of this $1.1bn in aid was spent directly by donors on various projects, with only a third given to the government to spend along with its domestic resources. Interestingly, aid money made up only a small proportion of resources for education, while accounting for the majority of resources for health, agriculture, water and the environment."
|
|
||||||
|
|
||||||
## Busan Aid effectiveness meeting
|
|
||||||
|
|
||||||
The release of the visualisation comes ahead of the [Busan aid effectiveness meeting](http://www.aideffectiveness.org/busanhlf4/) and highlights some of the key benefits of opening up spending data, both to the donor organisations and the governments of the recipient countries themselves:
|
|
||||||
|
|
||||||
> "Four years ago, researchers at the [London-based Overseas Development Institute](http://www.odi.org.uk/) took up the enormous task of trying to figure out how dozens of donors were spending aid in Uganda, and how that compared with where the government was allocating its own resources. The results were striking: it turned out the Ugandan government was only aware of half the aid being spent in the country, despite routinely requesting this information from donors."
|
|
||||||
|
|
||||||
It is hoped that visualisations such as these will make it easier to digest complex datasets of this type, where a government receives support from multiple sources. It is also hoped that discussions around the topic will result in the more timely and regular release of data to help highlight practices that will lead to aid money being most effectively spent.
|
|
||||||
|
|
||||||
**Read the full Article in [the Guardian Poverty Matters blog](http://www.guardian.co.uk/global-development/poverty-matters/2011/nov/25/uganda-aid-confusion-analyse-spending?newsfeed=true).**
|
|
||||||
|
|
||||||
**Have data similar to this you would like to create a similar visualisation for? Drop us an email via the [OpenSpending mailing list](http://lists.okfn.org/mailman/listinfo/openspending).**
|
|
||||||
@ -1,62 +0,0 @@
|
|||||||
---
|
|
||||||
authors:
|
|
||||||
- martin
|
|
||||||
redirect_from: /2011/12/how-spending-stories-spots-errors-in-public-spending/
|
|
||||||
title: How Spending Stories Spots Errors in Public Spending
|
|
||||||
tags:
|
|
||||||
- Data Journalism
|
|
||||||
- Spending Stories
|
|
||||||
---
|
|
||||||
*This article was originally published on [MediaShift Idea Lab](http://www.pbs.org/idealab/2011/12/how-spending-stories-spots-errors-in-public-spending328.html) and was co-written by Martin Keegan, project lead for Spending Stories and Lucy Chambers, Community Coordinator for OpenSpending.*
|
|
||||||
|
|
||||||
How public funds should be spent is often controversial. Information about how that money has already been spent should not be ambiguous at all. People arguing about the future will care about the present, and if data about past or present public spending is available, many will certainly look at it. When they do, occasionally they will find errors, or believe themselves to have found errors.
|
|
||||||
|
|
||||||
[OpenSpending](http://openspending.org/), which aims to track every (public) government and corporate financial transaction across the world, encourages users to:
|
|
||||||
|
|
||||||
* augment the existing spending database with additional sources of data
|
|
||||||
* use that data -- e.g., to write evidence-based articles and formulate informed decisions about how their society is financed.
|
|
||||||
|
|
||||||
[Spending Stories is our effort](http://www.pbs.org/idealab/2011/09/spending-stories-to-help-journalists-analyze-spending-data258.html) to make OpenSpending a natural way to do data journalism about public spending.
|
|
||||||
|
|
||||||
<img alt="openspending.jpg" src="http://www.pbs.org/idealab/openspending.jpg" width="500" height="170" class="mt-image-center" style="text-align: center; display: block; margin: 0 auto 20px;" />
|
|
||||||
|
|
||||||
## The Problem
|
|
||||||
|
|
||||||
**FACT 1:** Errors occur in data, no matter how official the source.
|
|
||||||
|
|
||||||
**FACT 2:** Data wrangling (manipulating or restructuring datasets to correct inaccuracies, remix with other datasets to augment the data, or perform calculations on the data), *generally* improves data quality, for example, through reconciling entities and flagging amounts that are obviously incorrect.
|
|
||||||
|
|
||||||
**FACT 3:** Data wrangling can also *introduce* errors if not tackled correctly.
|
|
||||||
|
|
||||||
Crucial to ensuring the use of this data in articles or ensuring re-use by concerned citizens is the ability to show that the data is valid. In addition, maintaining a good relationship with public bodies who are confident that they are not being misrepresented in the data is vital to ensuring the data continues to be released in the first place. In practice, this means that the provenance of the data has to be clear including:
|
|
||||||
|
|
||||||
* where the data originally came from (preferably a URL)
|
|
||||||
* whether anyone (e.g., government, community data wrangler, or OpenSpending) has worked on the data since it was published, and what steps they took to change the data (i.e., these steps should be reproducible to produce the same result)
|
|
||||||
|
|
||||||
The OpenSpending team has gone to lengths to retain enough information to say who was responsible for both of the above.
|
|
||||||
|
|
||||||
OpenSpending is a system, somewhat like a wiki, which allows you to track back through the data wrangling process and work out what changes were made to the data, when and by whom.
|
|
||||||
|
|
||||||
## Error reporting in practice
|
|
||||||
|
|
||||||
OpenSpending recently received a pointed inquiry from the U.K. Treasury disputing the claims we were making about the payment of British public money to a private company. Believing that an error had been introduced, we attempted to retrace our steps and find out where this had occurred, and who was responsible.
|
|
||||||
|
|
||||||
As we discovered, the payment *had* actually taken place, but the the OpenSpending descriptions used to label the transaction were not sufficiently detailed to accurately reflect the item in question.
|
|
||||||
|
|
||||||
With Spending Stories, we were able to retrace our steps because we had preserved a copy of the software tools we used for collecting the data (the data is published by about 50 public bodies, and must be downloaded, stitched together, and firmly molded into shape). These tools had been also made available to the public, so the Treasury and other concerned citizens could have checked our work themselves; the availability of this kind of check keeps all participants in the fiscal debate honest.
|
|
||||||
|
|
||||||
What had gone wrong was a problem of terminology: The transactions existed, but ambiguous language had been used to describe them, glossing over the distinction between the government department reporting what money had been spent and the government agency which actually spent the money. The bodies in question were the Department of Health and a regional health care trust; this distinction is certainly one which a concerned citizen would expect to be made clearly -- so we should make sure our system makes it easy to know which question is being asked.
|
|
||||||
|
|
||||||
## Checkpoints in OpenSpending
|
|
||||||
|
|
||||||
In the short term, we are mitigating the problem of data errors as follows:
|
|
||||||
|
|
||||||
* **Data provenance** - is the source identifiable and the process reproducible? OpenSpending encourages people to add modified datasets to a "package" in the Data Hub. This allows other users to see the original document alongside any modified documents and track the chain of changes made to see clearly which points errors could have been introduced.
|
|
||||||
* **Crowdsourcing feedback** on spending data.
|
|
||||||
* **Permitting re-use of the structured data** we present, so that it can inform decisions in other fact-checking systems.
|
|
||||||
|
|
||||||
Ultimately, we will build our part of the ecosystem to provide feedback to the political process, by improving democratic discourse about the public finances.
|
|
||||||
|
|
||||||
*Lucy Chambers is a community coordinator at the Open Knowledge Foundation. She works on the OKF's OpenSpending project and coordinates the data-driven-journalism activities of the foundation, including running training sessions and helping to streamline the production of a collaboratively written handbook for data journalists.*
|
|
||||||
|
|
||||||
*Martin Keegan is a software engineer and linguist, currently leading the Open Knowledge Foundation's OpenSpending project. He is also on the Open Knowledge Foundation's board, and has worked for SRI, Citrix, University of Cambridge and co-founded and worked for various civil society organizations.*
|
|
||||||
@ -1,89 +0,0 @@
|
|||||||
---
|
|
||||||
authors:
|
|
||||||
- mark
|
|
||||||
redirect_from: /2011/12/data-seized-sanitised-and-sanity-checked-open-data-day-2011/
|
|
||||||
title: Data = Seized, Sanitised and Sanity-checked. Open Data Day 2011
|
|
||||||
tags:
|
|
||||||
- CKAN
|
|
||||||
- events
|
|
||||||
- IATI
|
|
||||||
- Open Data Day
|
|
||||||
- Publish What You Fund
|
|
||||||
---
|
|
||||||
**This post is by Mark Brough, Research Officer at [Publish What You Fund](http://www.publishwhatyoufund.org/), [Lucy Chambers](http://okfn.org/members/lucychambers), Community Coordinator for OpenSpending, and [Irina Bolychevsky](http://okfn.org/members/shevski), Product Owner for CKAN. It is cross-posted on the [OpenSpending Blog](http://blog.openspending.org/2011/12/10/data-seized-sanitised-and-sanity-checked-open-data-day-2011) and the [Open Knowledge Foundation Blog](http://blog.okfn.org/2011/12/12/data-seized-sanitised-and-sanity-checked-open-data-day-2011) and Mark Brough's contribution is also featured on [aidinfolabs.org](http://www.aidinfolabs.org/archives/786).**
|
|
||||||
|
|
||||||
**Saturday, December 3rd was Open Data Day, and London took the challenge to throw a hackday to help data be opened, cleaned and shown off to the world...**
|
|
||||||
|
|
||||||
Fuelled only by enthusiasm, caffeine and 5 packets of ready-made popcorn, the CKAN, OpenSpending and IATI teams, along with some new faces, joined forces to liberate as much data as they could...
|
|
||||||
|
|
||||||
<img alt="" src="http://farm8.staticflickr.com/7157/6471082237_b687e15771_z.jpg" title="Mark Brough hard at Work on IATI wrangling" class="alignnone" width="640" height="480" />
|
|
||||||
|
|
||||||
## OpenSpending + IATI + CKAN
|
|
||||||
|
|
||||||
As part of the IATI Open Data Day challenges, Mark Brough did some work to get the existing IATI Data into OpenSpending. David Read, from the CKAN team, and a new face to the data wrangling crew, Johannes, scraped data on aid donations from France and Austria that were locked-up in web apps in order to help fill in the gaps in the global aid data jigsaw puzzle. You can see the results on OpenSpending.
|
|
||||||
|
|
||||||
* France: <http://thedatahub.org/dataset/france-afd> and on OpenSpending: <http://openspending.org/afd>
|
|
||||||
* Austria: <http://thedatahub.org/dataset/ada>, on OpenSpending: <http://openspending.org/ada>
|
|
||||||
|
|
||||||
The French (AFD) and Austrian (ADA) aid data appears to be incomplete: the AFD's [2010 Annual Report]<http://www.afd.fr/jahia/webdav/site/afd/shared/PUBLICATIONS/Colonne-droite/Rapport-annuel-AFD-VF.pdf> suggests that South Africa is the biggest recipient country, receiving €403 million, but in the data, Morocco is the biggest recipient and there are no transactions in South Africa.
|
|
||||||
|
|
||||||
The Austrian Development Agency data was carefully cleaned by Johannes, with region and country codes being added for all entries to create a tidier dataset. However, the original data contained, for example, four different spellings of Bosnia and Herzegovina, suggesting that countries are being manually entered rather than selected from an existing list. [For 2010]<http://openspending.org/ada/?_time=2010&_view=country>, the second biggest recipient of the Austrian Development Agency's aid (after aid not going to a specific country) appears to be Austria.
|
|
||||||
|
|
||||||
Nevertheless, despite the issues surrounding data quality, it was a useful exercise to show both the value of open data - that if you release your data, you can do pretty cool things with it - and the costs of keeping it locked away, namely that the data then has to be scraped from sites in quite a labour-intensive way.
|
|
||||||
|
|
||||||
These, along with many other datasets discovered on the day via tweets and emails have been added to the [Open Data Day Group](http://thedatahub.org/group/open-data-day) on [theDataHub.org](http://thedatahub.org).
|
|
||||||
|
|
||||||
On the same day, we worked to get the data released as part of the International Aid Transparency Initiative into OpenSpending. You can see the results of the IATI wrangling process on [OpenSpending.org/iati](http://www.openspending.org/iati). This following section is written by Mark.
|
|
||||||
|
|
||||||
### 1. Getting the data
|
|
||||||
|
|
||||||
Downloading the existing IATI data has already become quite a big task; with 19 publishers so far, the data currently amounts to over 750MB with 1169 packages. Fortunately this is made easier by the IATI Registry, which provides an API to access all existing datasets, and a simple script (links at end) can retrieve all of the data.
|
|
||||||
|
|
||||||
### 2. Extracting the data
|
|
||||||
Extracting the data from the XML files is more complicated. Although IATI data uses a standard schema, there are a few cases where publishers have either used the markup incorrectly, or else interpreted the definitions slightly differently. This can be simple problems such as stating that an organisation is “implementing” rather than “Implementing”, or placing the date within the text of the <activity-date> tag and not the “iso-date” attribute of that tag, or more significant problems such as placing implementing organisations in the “accountable” organisation field.
|
|
||||||
|
|
||||||
However, these problems are still fairly limited and follow fairly regular patterns, so they are not too hard to overcome. There are more significant problems when some donors have for example used three-letter (ISO-3) country codes, rather than two-letter (ISO-2) country codes. (This is considered below in “next steps”.)
|
|
||||||
|
|
||||||
### 3. Wrangling the data
|
|
||||||
OpenSpending is designed to show spending data, and has a powerful aggregation system to show large collections of transactions in a meaningful way. However, IATI data is organised by activities, with transactions nested within activities (projects), and – reflecting the business models of funders – activities sit within other activities (e.g., projects within programs), although they are not nested in the actual XML. Furthermore, one of the significant advantages of IATI compared to other aid data formats is that it permits multiple sectoral classifications, allowing you to assign a proportion of the value of an activity to each sector. So, you might have an activity that is 50% related to health and 50% to education.
|
|
||||||
|
|
||||||
To prepare the data for OpenSpending, each transaction inherits the properties of its activity (and, if that activity has a parent, that parent activity’s title and description). Then, the transaction is broken out into mini transactions, with the proportion of the activity assigned to each sector used to assign a proportion of the value of the transaction to each sector. So, from transactions, you get mini “sector-transactions”.
|
|
||||||
|
|
||||||
This takes about 40 minutes to compile, and then one final step remains: to convert the currencies to a single currency. Currently, USD, EUR and GBP amounts are used in the IATI data. All data is converted to USD using the average for 2010 from the OECD’s Financial Indicators (MEI) dataset. (This is also considered below in “next steps”.)
|
|
||||||
|
|
||||||
|
|
||||||
### 4. Loading the data
|
|
||||||
OpenSpending’s new web-based loading interface makes it relatively easy to load data in, although you currently also have to write a model and views (links at end).
|
|
||||||
|
|
||||||
|
|
||||||
### Results
|
|
||||||
The results can be viewed in the OpenSpending IATI dataset. You can explore the data by recipient country, sectors, funding organisation, and drill down through the data to see the data for an individual country.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### Problems with the data
|
|
||||||
So far I’ve noticed the following problems:
|
|
||||||
|
|
||||||
* “Unknown” recipient location is incorrectly marked as “South Sudan”
|
|
||||||
* Recipient countries are listed twice, as Spain has used ISO3 rather than ISO2 country codes.
|
|
||||||
* Sweden is listed as “Ministry of Foreign Affairs” (this is how they have listed themselves as the Funding Organisation in the data)
|
|
||||||
* Sweden’s implementing organisations have been lost as they placed them in the accountable organisation field.
|
|
||||||
|
|
||||||
Please let me know if you see anything else problematic, if you have and criticisms of feedback of the way the data has been presented, or if you think there are other ways you’d like to be able to explore the data, based on the available dimensions.
|
|
||||||
|
|
||||||
### Next steps
|
|
||||||
As mentioned above, there are some problems with the data which should properly be dealt with at the level of the donor agency. But there are others that will probably have to be dealt with by users of the data:
|
|
||||||
|
|
||||||
* Mapping between different sector vocabularies, so that you can see all “Health” projects, and not only the health projects according to a single vocabulary
|
|
||||||
* Mapping between countries and regions, so that every project in a country has a related region
|
|
||||||
* Correctly converting currencies using the “value-date” column to get a more precise (at least month-specific) conversion.
|
|
||||||
|
|
||||||
**What else have you noticed with the data? Is there anything else that should be changed? Anything interesting?**
|
|
||||||
|
|
||||||
You can contact Mark about this data via the [OpenSpending mailing list](http://lists.okfn.org/mailman/listinfo/openspending)
|
|
||||||
|
|
||||||
### Useful Links
|
|
||||||
* [IATI on OpenSpending](http://www.openspending.org/iati)
|
|
||||||
* [Data wrangling scripts and tools](https://github.com/okfn/iatitools)
|
|
||||||
* [Mapping spreadsheets](https://github.com/okfn/iatitools/tree/master/mapping)
|
|
||||||
* [Etherpad from Open Data Day - attendees and projects they worked on](http://ckan.okfnpad.org/opendataday)
|
|
||||||
@ -1,54 +0,0 @@
|
|||||||
---
|
|
||||||
authors:
|
|
||||||
- lucy
|
|
||||||
redirect_from: /2012/01/civil-society-and-spending-data-who-is-mapping-the-money/
|
|
||||||
title: "Civil Society and Spending Data: Who is mapping the money?"
|
|
||||||
tags:
|
|
||||||
- Contribute
|
|
||||||
- OSF
|
|
||||||
---
|
|
||||||
**This post is by [Lucy Chambers](http://okfn.org/members/lucychambers), Community Coordinator on the OpenSpending project at the Open Knowledge Foundation. The post is cross-posted on the [Open Knowledge Foundation blog](http://blog.okfn.org/2012/01/12/civil-society-and-spending-data-who-is-mapping-the-money/).**
|
|
||||||
|
|
||||||
We're excited to announce that, thanks to the generous support of the Open Society Foundations, OKFN's activities around financial transparency will expand to include a second pillar: next to the OpenSpending platform, we have just started a 6 month project to map the technology needs of Civil Society Organisations in relation to public spending and budget information.
|
|
||||||
|
|
||||||
## We're going to be working on...
|
|
||||||
|
|
||||||
* **Identifying CSOs around the world who are interested in working with spending data** - building on the existing network of contacts from the OpenSpending.org project.
|
|
||||||
|
|
||||||
* **Connecting these CSOs with each other**, with open data communities and with other key stakeholders to exchange knowledge, experiences and best practices in relation to spending data
|
|
||||||
|
|
||||||
* **Establishing how CSOs currently work with spending data**, how they would like to use it, and what they would like to achieve - including:
|
|
||||||
1. what existing tools are being used
|
|
||||||
2. what current technical needs are unmet
|
|
||||||
3. what would be required to meet these needs and how feasible is it to tackle them
|
|
||||||
|
|
||||||
* **Creating a registry of spending datasets**, from official and unofficial sources in theDataHub.org
|
|
||||||
* **A Spending Data Manual** - A wiki-like, community driven manual on acquiring, working with, publishing and archiving spending data, based on input and exchanges with CSOs we talk to.This will augment and reference existing publications from numerous organisations as well as channelling the results of our research into two areas:
|
|
||||||
* **A section to help CSO’s clarify their demands towards governments:** e.g. guidance on open licensing and structured data formats, applicable for spending data.
|
|
||||||
* **A section focused on best practice for CSOs when using and reusing spending data:** for example collaborative processes such as data-sharing.
|
|
||||||
|
|
||||||
* **Running Spending Analysis Sessions with CSOs**, both in person and virtually. We’re interested in learning from about what data people are trying to acquire / having difficulty in doing so, how they plan to use the data to further their mission and learning what barriers, legal, technical and otherwise could be removed to make their jobs easier.
|
|
||||||
|
|
||||||
|
|
||||||
* **Getting Spending Data from numerous countries loaded into OpenSpending.org** - with the support of CSOs, OKFN developers, and volunteers from the open data community. We we're interested in are using the OpenSpending.org tools, and collect input from them on how these could be improved to meet their needs.
|
|
||||||
|
|
||||||
<img alt="" src="http://farm7.staticflickr.com/6166/6270108254_5875c8a7ed_z.jpg" title="Kaitlin Lee talking at Open Government Data Camp" class="alignnone" width="640" height="426" />
|
|
||||||
|
|
||||||
## Vision: Improved Spending Data Literacy, Sharing and Re-use amongst CSOs around the world
|
|
||||||
|
|
||||||
We are very keen to help more groups and individuals around the world to use and work with spending data more effectively to do the things they care about - whether this is investigative journalism, evidence based policy-making, political campaigning, budgeting or creating new useful applications and services.
|
|
||||||
|
|
||||||
In particular, we would like to document and spread best practices in the legal and technical aspects of reusing public information, and enabling re-use and better collaboration around this material.
|
|
||||||
|
|
||||||
### Ultimately we would like to:
|
|
||||||
* **Build stronger, broader communities** of groups and individuals who work together to acquire, use, and openly share spending data
|
|
||||||
* **Increase ‘literacy’ around spending data** - enabling more CSOs to understand and work with large and complex spending datasets to help them to pursue their objectives
|
|
||||||
* **Encourage more CSOs to publish datasets which they acquire**, use or create in machine readable formats, under open licenses, to avoid duplication of effort and enable CSOs to build on each others’ work, to harness external expertise more effectively and to facilitate stronger collaboration between different organisations who are interested in spending information
|
|
||||||
|
|
||||||
## How can I get involved?
|
|
||||||
|
|
||||||
* **Join the Working Group on Spending Data**. The working group will bring together data experts and CSOs who will help to weave a community of best practice around spending data, collect and provide feedback on material for the manual and help to develop the network of those collaborating around and sharing spending data. More details about the working group can be found on this [wiki page](http://wiki.openspending.org/Working_Group).
|
|
||||||
|
|
||||||
* **Write for the [Spending Data Blog](http://blog.openspending.org)** - we're interested in posts by and about CSOs who work with spending data, observations on the current status quo on releasing data in your area. Anything from short comment pieces to full proposals for what could be done, legal, technical or otherwise, to improve the situation in the sphere where you work. Contact details as above.
|
|
||||||
|
|
||||||
**If you would like to get started, or know of organisations we should extend the invitation to: drop us an email via the [mailing list](http://lists.okfn.org/mailman/listinfo/openspending) or contact me directly via info [at] openspending.org. **
|
|
||||||
@ -1,22 +0,0 @@
|
|||||||
---
|
|
||||||
authors:
|
|
||||||
- lucy
|
|
||||||
redirect_from: /2012/01/open-bookkeeping-what-role-can-accountants-play-in-open-spending-budget-projects/
|
|
||||||
title: "Open Bookkeeping: What role can accountants play in Open Spending & Budget Projects?"
|
|
||||||
---
|
|
||||||
The next OpenSpending online community meeting will take place on *Thursday, 19th Jan - 6pm GMT*.
|
|
||||||
|
|
||||||
## The topic
|
|
||||||
|
|
||||||
Accountants spend their entire working lives mapping the money:
|
|
||||||
|
|
||||||
* How can their expertise be put to good use in Open Spending Data projects?
|
|
||||||
* What interesting initiatives are going on around the world which could benefit from the input of accountants?
|
|
||||||
|
|
||||||
<a href="http://blog.openspending.org/files/2012/01/money.png"><img src="http://blog.openspending.org/files/2012/01/money-300x212.png" alt="Via OpenClipArt" title="money" width="300" height="212" class="aligncenter size-medium wp-image-96" /></a>
|
|
||||||
|
|
||||||
All are welcome! If you'd like to contribute to the discussion by joining the call, please just add your name and Skype ID to [the pad](http://wdmmg.okfnpad.org/community-2012-01-12)
|
|
||||||
|
|
||||||
Please feel free to share with colleagues friends and other communities.
|
|
||||||
|
|
||||||
N.B. Over the next weeks, we'll be trying to theme the discussions and proactively invite people along to join them. If you have a suggestion for a topic you think the group should discuss, please drop us a line via the [OpenSpending mailing list](http://lists.okfn.org/mailman/listinfo/openspending).
|
|
||||||
@ -1,60 +0,0 @@
|
|||||||
---
|
|
||||||
authors:
|
|
||||||
- fabiano
|
|
||||||
redirect_from: /2012/01/transparency-and-technology-in-brazil-linking-politicians-to-bad-entrepreneurs/
|
|
||||||
title: "Transparency and technology in Brazil: linking politicians to bad entrepreneurs"
|
|
||||||
tags:
|
|
||||||
- Data Journalism
|
|
||||||
- Spending Stories
|
|
||||||
---
|
|
||||||
**This story by Fabiano Angélico, who formerly worked at Transparencia Brasil, is about how technology and the help of coders can be used to highlight links between politicians and corrupt entrepreneurs. It is followed by a brief "Behind the News" interview which shows some of the time costs of datawrangling and problems faced when getting the story out.**
|
|
||||||
|
|
||||||
How can transparency and technology point out connections between politicians and bad entrepreneurs? Well, first of all you will need some information about the politicians and about the entrepreneurs.
|
|
||||||
|
|
||||||
In Brazil, in spite of the historical lack of transparency in governments (Brazil's freedom of information law was sanctioned just late last year), the Electoral Court has been proactively providing information on political candidates since 2002. One piece of info is the financial donation to the candidates, containing info about who is donating to whom and how much. Although this database is released only after the elections -- the info would surely be more powerful if it were released DURING the political campaigns --, one must admit this is a rich source of information.
|
|
||||||
|
|
||||||
<a href="http://www.flickr.com/photos/elaws/3883627250/sizes/z/in/photostream/"><img alt="" src="http://farm3.staticflickr.com/2542/3883627250_067b94c247_z.jpg" title="Roger Schultz via Flickr (CC-BY)" class="alignnone" width="640" height="425" /></a>
|
|
||||||
|
|
||||||
January, 2010. Elections for President and for the Parliament, as well as for State Governors and State Parliaments, would happen in only 9 months time, in October. However, many people were already discussing them.
|
|
||||||
|
|
||||||
At that time, 2010 had just begun, I was at work, thinking of how to find rich and useful information on the candidates. Then I was reminded of the so-called ["Dirty List"](http://www.mte.gov.br/sgcnoticia.asp?IdConteudoNoticia=6680&PalavraChave=lista%20suja) -- this is a list regularly published by the Ministry of Labour which indicates the companies and farmers who are caught by government officials using workers in very lousy conditions, similar to slavery.
|
|
||||||
|
|
||||||
The list published in the Ministry's website is in not-so-friendly PDF format, but it has a plus: there is not only the name of the companies or the entrepreneur/farmer, but also their registry numbers within the government. I remembered that in the Electoral Court one can also find the numbers. That was important because having the registry numbers would avoid ambiguities.
|
|
||||||
|
|
||||||
I had both lists: the donators to the previous elections (2008, 2006, 2004 and 2002) and the "Dirty" companies. But I had a problem; I did not know how to matchup the datasets. My tech knowledge allowed me to transform the PDFs into CSV, but I could no go further without help.
|
|
||||||
|
|
||||||
I then sent the datasets, in CSV format, to [Transparencia Hacker](http://thacker.com.br/), a Google Groups list which now gathers over 800 people interested in the connections between transparency and politics/public administration.
|
|
||||||
|
|
||||||
Within 2 days, the guys made the datasets talk, and we found that 16 politicians had been elected with the help of "Dirty" money in the 4 previous elections. Other 13 politicians had received donations from the "Dirty List" but had not succeeded in winning the elections.
|
|
||||||
|
|
||||||
[A local newspaper told the story](http://www.agenciasebrae.com.br/noticia.kmf?canal=36&cod=9376495&indice=0).
|
|
||||||
|
|
||||||
In October 2012, there are local elections in Brazil. Hope we can shed even more light in the candidates.
|
|
||||||
|
|
||||||
# Behind the news:
|
|
||||||
|
|
||||||
## Roughly how long did it take you to extract the data from the PDFs? Do you know how long the guys from Transparencia Hacker spent working on the data?
|
|
||||||
|
|
||||||
This was kind of easy. It took me just some minutes. The "Dirty List" is a 20-page PDF. I always use a website to convert it into xls or csv (I like [Cometdocs](http://www.cometdocs.com/) for this work).
|
|
||||||
|
|
||||||
[Here](http://portal.mte.gov.br/data/files/8A7C812D3374524E0133835496AF7D72/CADASTRO%20DE%20EMPREGADORES%2008%20de%20novembro%202011.pdf) is the Dirty List, in PDF (last updated on the 8th of November, 2011; the list we used is in CSV but it it very outdated because it was due to January 2010)
|
|
||||||
Here are the Electoral Court pages for the list of donators: [2002](http://www.tse.jus.br/internet/eleicoes/2002/prest_blank.htm), [2004](http://www.tse.jus.br/internet/eleicoes/2004/prest_blank.htm), [2006](http://www.tse.jus.br/eleicoes/eleicoes-anteriores/eleicoes-2006/prestacao-de-contas-eleicoes-2006), [2008](http://www.tse.jus.br/eleicoes/contas-eleitorais/candidatos-e-comites/prestacao-de-contas-eleitorais-2008) and [2010](http://spce2010.tse.jus.br/spceweb.consulta.prestacaoconta2010/pesquisaCandidato.jsp).
|
|
||||||
|
|
||||||
What I asked the Transparencia Hacker community was to check whether the CNPJs (companies register number within the governments) in the CSV would match any item in the Electoral Court webpage. The guys worked on the data for 2 days.
|
|
||||||
|
|
||||||
## Is sufficient data available to visualise the total amount lobbyists donated to political campaigns, and would it be useful to / no? If you were to visualise the info - what would the priorities be to show? Would any tools be useful to explore the data?
|
|
||||||
|
|
||||||
Yes, there is enough data. And YES, it would be very useful to visualize those links. I would prioritise the presidential and governor candidates as well as some Congressmen who hold top-positions in both Houses of Congress. Also, the donations to political parties (not to individual politicians) would be a plus.
|
|
||||||
|
|
||||||
A search form would be very useful. The search could have filters for position (Presidential candidate, governor candidate, political party etc), geography (Brazil, states) and donators (with no filters, just a blank for writing)
|
|
||||||
|
|
||||||
## In your ideal world, in time for the impending elections - what would be done differently from last time? Any additional data you would like to see released?
|
|
||||||
|
|
||||||
I'd have to think more carefully to respond that, but concerning additional data: the number which identifies the market (the field) in which the companies work.
|
|
||||||
|
|
||||||
*Interested in writing a "Behind the News" piece for the OpenSpending blog? Get in touch via our [twitter account](https://twitter.com/#!/openspending) or email **info [at] openspending.org**.*
|
|
||||||
|
|
||||||
Some useful links (mainly in Portuguese):
|
|
||||||
|
|
||||||
* [Brasil adopts access to information law](http://www.article19.org/resources.php/resource/2862/en/brazil-adopts-access-to-information-law)
|
|
||||||
* [View the Dirty List in Full](http://www.mte.gov.br/sgcnoticia.asp?IdConteudoNoticia=6680&PalavraChave=lista%20suja)
|
|
||||||
@ -1,16 +0,0 @@
|
|||||||
---
|
|
||||||
authors:
|
|
||||||
- friedrich
|
|
||||||
redirect_from: /2012/01/updates-from-the-openspending-dev-team/
|
|
||||||
title: Updates from the OpenSpending Dev Team
|
|
||||||
tags:
|
|
||||||
- Releases
|
|
||||||
- Spending Stories
|
|
||||||
- Updates
|
|
||||||
---
|
|
||||||
# What are we focusing on this week?
|
|
||||||
|
|
||||||
* Working on implementing [Collections](http://wdmmg.okfnpad.org/collections) <- draft notes, beware.
|
|
||||||
* Prototyping the Compar-o-tron [Mockup 1](http://www.flickr.com/photos/okfn/4623584907/), [Mockup 2](http://www.flickr.com/photos/okfn/4624190848/).
|
|
||||||
* Continuing work on Embeddable widgets for Spending Stories.
|
|
||||||
|
|
||||||
@ -1,34 +0,0 @@
|
|||||||
---
|
|
||||||
authors:
|
|
||||||
- friedrich
|
|
||||||
redirect_from: /2012/01/hakuna-my-data-nbo-data-bootcamp/
|
|
||||||
title: "Hakuna My Data: NBO Data Bootcamp"
|
|
||||||
tags:
|
|
||||||
- Data Journalism
|
|
||||||
- events
|
|
||||||
- Kenya
|
|
||||||
- NBO
|
|
||||||
- x
|
|
||||||
---
|
|
||||||
**This post is by [Friedrich Lindenberg](http://okfn.org/members/pudo), developer on OpenSpending.**
|
|
||||||
|
|
||||||
>"My Name is XXXX, I am a member of the Kenyan parliament for the constituency of XXXX in the 2007-2012 election cycle. During my time in parliament, I have positioned myself against taxes for MPs.
|
|
||||||
|
|
||||||
>Of the Development Funds allocated to my constituency, I have spent 12mn KSH in 2010 and 8mn KSH in 2009. Since 2007, I've funded 201 projects, of which 72 (9mn KSH) related to Education, 56 (7.2mn KSH) related to Health and 20 (4.2mn KSH) to Infrastructure.
|
|
||||||
|
|
||||||
>The largest projects I have funded include... "
|
|
||||||
|
|
||||||
Auto-generated, spending data-driven campaign speeches like this are just one of the many ideas of the Data Bootcamp that took place in Nairobi last week. Invited by the African Media Initiative and the World Bank Insititute, about 70 participants - both journalists and developers - met on Strathmore University's campus to learn and practise both the skills and tools required for data-driven reporting.
|
|
||||||
|
|
||||||
The four-day programme combined tools training with practical work in small groups. Elena Egawhary (BBC NewsNight) gave a workshop on data analysis in Excel, Sreeram Balakrishnan (Google Fusion Tables) introduced both Refine and Fusion Tables. Team members from both the Kenya data portal and the World Bank finance site presented their respective offerings, while Gregor and myself from the OpenSpending team gave intros to web scraping and advanced
|
|
||||||
map visualisation.
|
|
||||||
|
|
||||||
<img alt="" src="http://farm8.staticflickr.com/7009/6789058651_9a25483ba0_z.jpg" title="Hakuna My Data" class="alignnone" width="640" height="478" />
|
|
||||||
|
|
||||||
During group work, journalists and developers teamed up to try their newly learned skills in different domains ranging from sports (football player profiles) to education (missing toilets in schools, "The Shit Ordeal") and the financial transparency story-telling mentioned above.
|
|
||||||
|
|
||||||
The workshop also served as a community-building event for Kenya's young and impressive Open Data initiative. Future events, aimed at civil society organisations and polictical actors will help to further promote the re-use of government information released through the initiative.
|
|
||||||
|
|
||||||
All this is happening in a place where transparency is an essential tool to be developed: Not only is the access to information now guaranteed by the 2010 Kenyan constitution, there are also major political issues that deserve close attention from local and international watchdogs. These include not only the ongoing incursion of Kenyan troops into Somalia in an effort to fight Al-Shebab terrorist groups, but also the upcoming nationwide elections in December 2012. The elections will instate a new bicameral system of government, with many previously unknown candidates standing for office. In the previous 2007 vote, bad polling station data had quite literally led to widespread unrest and thousands of deaths across the nation.
|
|
||||||
|
|
||||||
In all, it was a fantastic to get in touch with the Kenyan participants of the workshop and to see how the organizers of the event - a brilliant team including Craig Hammer, Justin Arenstein and Jay Bhalla - are working to foster an open data community in this bustling developing nation.Given the great ideas generated during the team sessions, I'm sure this work will soon bear its first fruits.
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user