Compare commits
9 Commits
@portaljs/
...
examples-d
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3cf945a194 | ||
|
|
fe225715e9 | ||
|
|
a801baf34d | ||
|
|
f8ef07646f | ||
|
|
0225eb49ba | ||
|
|
b68c52ce36 | ||
|
|
c80cae27a4 | ||
|
|
b14500b213 | ||
|
|
062e817f3a |
@@ -16,8 +16,6 @@ We welcome contributions from anyone who is interested in improving OpenSpending
|
|||||||
|
|
||||||
The main platform for communication and collaboration for OpenSpending is Github, if you want to interact with us you can o so by submitting an issue.
|
The main platform for communication and collaboration for OpenSpending is Github, if you want to interact with us you can o so by submitting an issue.
|
||||||
|
|
||||||
**Repo for issues:** [https://github.com/os-data/registry/issues](https://github.com/os-data/registry/issues)
|
|
||||||
|
|
||||||
If you want to submit a dataset for evaluation and inclusion in OpenSpending, you will need to create an issue on Github using this template:
|
If you want to submit a dataset for evaluation and inclusion in OpenSpending, you will need to create an issue on Github using this template:
|
||||||
|
|
||||||
```markdown
|
```markdown
|
||||||
|
|||||||
@@ -1,284 +0,0 @@
|
|||||||
---
|
|
||||||
title: An Exploration of Moers' 2016 Budget Anomaly
|
|
||||||
date: 06/13/2023
|
|
||||||
---
|
|
||||||
|
|
||||||
_Note: The currency in this post has been converted to USD using an average exchange rate of 1 EUR = 1.20 USD.
|
|
||||||
Additionally, the text values for account groups have been loosely translated to English. You can find the
|
|
||||||
original dataset here: [Moers budget dataset](https://www.openspending.org/@os-data/moers-all)_
|
|
||||||
|
|
||||||
In the fiscal landscape of Moers, Germany, 2016 stands out as an anomaly. An examination of the budget allocations
|
|
||||||
for this particular year shows a significant surge in spending across various areas. After this anomalous
|
|
||||||
spike, spending patterns then seemed to resume their previous trajectory of a slow, steady climb in the
|
|
||||||
following years. While it's tempting to dismiss this as an irregularity, it's worth exploring the potential
|
|
||||||
underlying causes of this fiscal fluctuation.
|
|
||||||
|
|
||||||
<VegaLite
|
|
||||||
spec={{
|
|
||||||
$schema: 'https://vega.github.io/schema/vega-lite/v5.json',
|
|
||||||
title: 'Spending by Account Group',
|
|
||||||
description: 'Spending by Account Group',
|
|
||||||
data: {
|
|
||||||
url: 'https://storage.openspending.org/moers-all/moers-sums.csv',
|
|
||||||
},
|
|
||||||
transform: [
|
|
||||||
{
|
|
||||||
calculate: "format(datum.amount / 1e6 * 1.20, '$,.1f') + 'M'",
|
|
||||||
as: 'formattedAmountMillion',
|
|
||||||
},
|
|
||||||
{ calculate: 'datum.amount / 1e9 * 1.20', as: 'amountBillion' },
|
|
||||||
],
|
|
||||||
mark: 'bar',
|
|
||||||
height: 400,
|
|
||||||
width: 350,
|
|
||||||
encoding: {
|
|
||||||
x: {
|
|
||||||
field: 'date',
|
|
||||||
type: 'temporal',
|
|
||||||
timeUnit: 'utcyear',
|
|
||||||
title: 'Year',
|
|
||||||
},
|
|
||||||
y: {
|
|
||||||
field: 'amount',
|
|
||||||
type: 'quantitative',
|
|
||||||
title: 'Spending (USD in millions)',
|
|
||||||
axis: {
|
|
||||||
format: '~s',
|
|
||||||
labelExpr: "format(datum.value / 1e6 * 1.20, '$,.0f') + 'M'",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
color: {
|
|
||||||
field: 'account group',
|
|
||||||
type: 'nominal',
|
|
||||||
title: 'Account Group',
|
|
||||||
scale: {
|
|
||||||
domain: [
|
|
||||||
'Activated Own Work',
|
|
||||||
'Balance Expenses',
|
|
||||||
'Care Expenses',
|
|
||||||
'Donations And General Levies',
|
|
||||||
'Expenses For Material And Services',
|
|
||||||
'Extraordinary Expenses',
|
|
||||||
'Extraordinary Income',
|
|
||||||
'Other Ordinary Expenses',
|
|
||||||
'Other Ordinary Income',
|
|
||||||
'Other Transfer Income',
|
|
||||||
'Personnel Expenses',
|
|
||||||
'Private Law Performance Fees',
|
|
||||||
'Public-Service Performance Fees',
|
|
||||||
'Taxes And Similar Charges',
|
|
||||||
'Transfer Expenses',
|
|
||||||
],
|
|
||||||
range: [
|
|
||||||
'#EF5350',
|
|
||||||
'#F06292',
|
|
||||||
'#BA68C8',
|
|
||||||
'#9575CD',
|
|
||||||
'#7986CB',
|
|
||||||
'#64B5F6',
|
|
||||||
'#4FC3F7',
|
|
||||||
'#4DD0E1',
|
|
||||||
'#4DB6AC',
|
|
||||||
'#81C784',
|
|
||||||
'#AED581',
|
|
||||||
'#DCE775',
|
|
||||||
'#FFF176',
|
|
||||||
'#FFD54F',
|
|
||||||
'#FFB74D',
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
tooltip: [
|
|
||||||
{ field: 'account group', type: 'nominal', title: 'Account Group' },
|
|
||||||
{
|
|
||||||
field: 'formattedAmountMillion',
|
|
||||||
type: 'ordinal',
|
|
||||||
title: 'Spending (USD)',
|
|
||||||
},
|
|
||||||
{ field: 'date', type: 'temporal', title: 'Year', format: '%Y' }
|
|
||||||
],
|
|
||||||
},
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
|
|
||||||
## Why?
|
|
||||||
|
|
||||||
One possible explanation could be the global refugee crisis that was unfolding around this time, particularly
|
|
||||||
in Germany. While we can't assert this connection definitively due to the lack of specific data, it's an angle
|
|
||||||
worth examining to better understand the budget anomaly of 2016.
|
|
||||||
|
|
||||||
For instance, the "Donations and General Levies" account group saw a distinct increase in 2016. This could be
|
|
||||||
reflective of Moers' attempts to provide immediate support to incoming refugees, although we can only speculate
|
|
||||||
at this point.
|
|
||||||
|
|
||||||
<VegaLite
|
|
||||||
spec={{
|
|
||||||
$schema: 'https://vega.github.io/schema/vega-lite/v5.json',
|
|
||||||
title: 'Donations and General Levies',
|
|
||||||
description: 'Donations and General Levies',
|
|
||||||
data: {
|
|
||||||
url: 'https://storage.openspending.org/moers-all/moers-sums.csv',
|
|
||||||
},
|
|
||||||
transform: [
|
|
||||||
{ filter: "datum['account group']==='Donations And General Levies'" },
|
|
||||||
{
|
|
||||||
calculate: "format(datum.amount / 1e6 * 1.20, '$,.1f') + 'M'",
|
|
||||||
as: 'formattedAmountMillion',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
mark: {
|
|
||||||
type: 'area',
|
|
||||||
line: true,
|
|
||||||
point: true,
|
|
||||||
},
|
|
||||||
width: 400,
|
|
||||||
height: 400,
|
|
||||||
encoding: {
|
|
||||||
x: {
|
|
||||||
field: 'date',
|
|
||||||
type: 'temporal',
|
|
||||||
timeUnit: 'utcyear',
|
|
||||||
title: 'Year',
|
|
||||||
},
|
|
||||||
y: {
|
|
||||||
field: 'amount',
|
|
||||||
type: 'quantitative',
|
|
||||||
title: 'Spending (USD in millions)',
|
|
||||||
axis: {
|
|
||||||
format: '~s',
|
|
||||||
labelExpr: "format(datum.value / 1e6 * 1.20, '$,.0f') + 'M'",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
color: {
|
|
||||||
title: 'Account Group',
|
|
||||||
field: 'account group',
|
|
||||||
scale: {
|
|
||||||
domain: ['Donations And General Levies'],
|
|
||||||
range: ['#9575CD'],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
tooltip: [
|
|
||||||
{ field: 'account group', type: 'nominal', title: 'Area' },
|
|
||||||
{
|
|
||||||
field: 'formattedAmountMillion',
|
|
||||||
type: 'ordinal',
|
|
||||||
title: 'Spending (USD in millions)',
|
|
||||||
},
|
|
||||||
{ field: 'date', type: 'temporal', title: 'Year', format: '%Y' }
|
|
||||||
],
|
|
||||||
},
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
|
|
||||||
Similarly, "Expenses for Material and Services" also experienced an upswing. This could suggest
|
|
||||||
that the town was working to establish necessary infrastructure and resources for the newcomers. It's plausible
|
|
||||||
that procurement of essential supplies and services to aid the refugees was a factor contributing to this budget
|
|
||||||
increase.
|
|
||||||
|
|
||||||
The rise in "Personnel Expenses" may suggest an expansion of the town's workforce during this period. Additional
|
|
||||||
staffing in areas like interpretation, social work, healthcare, and administration would be necessary to handle
|
|
||||||
the influx of refugees.
|
|
||||||
|
|
||||||
The two account groups that experienced the most substantial raw monetary increases were "Taxes and Similar Charges"
|
|
||||||
and "Transfer Expenses". Both these categories more than doubled in size during the year, a significant surge
|
|
||||||
especially considering their already high baseline spending. This could be for a variety of reasons.
|
|
||||||
|
|
||||||
For "Taxes and Similar Charges", the hike could indicate the town adjusting local taxation to meet the additional
|
|
||||||
expenditures, or it could reflect an increase in income from other sources falling under this group. The influx
|
|
||||||
of refugees and the resulting uptick in economic activity may have also led to a rise in the collection of certain
|
|
||||||
local taxes or fees.
|
|
||||||
|
|
||||||
Concurrently, the "Transfer Expenses" spike could be an indication of heightened social welfare payments, costs
|
|
||||||
associated with refugee integration, and funds transferred to other entities managing the crisis. These financial
|
|
||||||
escalations are a testament to the extensive and multifaceted financial impact the refugee crisis had on the town's
|
|
||||||
budget.
|
|
||||||
|
|
||||||
<VegaLite
|
|
||||||
spec={{
|
|
||||||
$schema: 'https://vega.github.io/schema/vega-lite/v5.json',
|
|
||||||
title: 'Largest Spending by Account Group',
|
|
||||||
description: 'Largest Spending by Account Group',
|
|
||||||
data: {
|
|
||||||
url: 'https://storage.openspending.org/moers-all/moers-sums.csv',
|
|
||||||
},
|
|
||||||
transform: [
|
|
||||||
{
|
|
||||||
filter: {
|
|
||||||
field: 'account group',
|
|
||||||
oneOf: [
|
|
||||||
'Donations And General Levies',
|
|
||||||
'Expenses For Material And Services',
|
|
||||||
'Personnel Expenses',
|
|
||||||
'Taxes And Similar Charges',
|
|
||||||
'Transfer Expenses'
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
calculate: "format(datum.amount / 1e6 * 1.20, '$,.1f') + 'M'",
|
|
||||||
as: 'formattedAmountMillion',
|
|
||||||
}
|
|
||||||
],
|
|
||||||
mark: {
|
|
||||||
type: 'line',
|
|
||||||
point: true,
|
|
||||||
},
|
|
||||||
width: 400,
|
|
||||||
height: 400,
|
|
||||||
encoding: {
|
|
||||||
x: {
|
|
||||||
field: 'date',
|
|
||||||
type: 'temporal',
|
|
||||||
timeUnit: 'utcyear',
|
|
||||||
title: 'Year'
|
|
||||||
},
|
|
||||||
y: {
|
|
||||||
field: 'amount',
|
|
||||||
type: 'quantitative',
|
|
||||||
title: 'Spending (USD in millions)',
|
|
||||||
axis: {
|
|
||||||
format: '~s',
|
|
||||||
labelExpr: "format(datum.value / 1e6 * 1.20, '$,.0f') + 'M'",
|
|
||||||
}
|
|
||||||
},
|
|
||||||
color: {
|
|
||||||
field: 'account group',
|
|
||||||
type: 'nominal',
|
|
||||||
title: 'Account Group',
|
|
||||||
scale: {
|
|
||||||
domain: [
|
|
||||||
'Donations And General Levies',
|
|
||||||
'Expenses For Material And Services',
|
|
||||||
'Personnel Expenses',
|
|
||||||
'Taxes And Similar Charges',
|
|
||||||
'Transfer Expenses'
|
|
||||||
],
|
|
||||||
range: [
|
|
||||||
'#9575CD',
|
|
||||||
'#7986CB',
|
|
||||||
'#AED581',
|
|
||||||
'#FFD54F',
|
|
||||||
'#FFB74D'
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
tooltip: [
|
|
||||||
{ field: 'account group', type: 'nominal', title: 'Area' },
|
|
||||||
{
|
|
||||||
field: 'formattedAmountMillion',
|
|
||||||
type: 'ordinal',
|
|
||||||
title: 'Spending (USD in millions)',
|
|
||||||
},
|
|
||||||
{ field: 'date', type: 'temporal', title: 'Year', format: '%Y' }
|
|
||||||
],
|
|
||||||
},
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
|
|
||||||
By 2017, these budget items returned to their pre-2016 levels, which may suggest that the town had successfully
|
|
||||||
adapted to the new circumstances, perhaps by implementing more cost-effective strategies.
|
|
||||||
|
|
||||||
While this exploration offers a compelling perspective, it's important to note that these are theories derived
|
|
||||||
from the available budget data and the concurrent global events of the time. It underscores how global crises,
|
|
||||||
like the refugee crisis, may potentially impact not just national budgets, but also the fiscal management of
|
|
||||||
smaller towns like Moers.
|
|
||||||
@@ -1,105 +0,0 @@
|
|||||||
---
|
|
||||||
title: Where does Berlin spends its ERDF benefits?
|
|
||||||
date: 2023-06-12
|
|
||||||
authors: ['João Demenech']
|
|
||||||
---
|
|
||||||
|
|
||||||
In this data-driven story, let's analyze how the city of Berlin has benefited from ERDF from 2008 to 2015.
|
|
||||||
|
|
||||||
## What is ERDF?
|
|
||||||
|
|
||||||
If you're not familiar with ERDF, it's the European Regional Development Fund. According to its [official website](https://ec.europa.eu/regional_policy/funding/erdf_en):
|
|
||||||
|
|
||||||
> The European Regional Development Fund (ERDF) aims to strengthen economic, social and territorial cohesion in the European Union by correcting imbalances between its regions. In 2021-2027 it will enable investments in a smarter, greener, more connected and more social Europe that is closer to its citizens.
|
|
||||||
|
|
||||||
## A look into the data
|
|
||||||
|
|
||||||
The dataset that will be used is this one: https://www.openspending.org/@os-data/de3-berlin-2007-2013-erdf (if you're looking for ERDF data for other cities/regions, take a look at the data catalog).
|
|
||||||
|
|
||||||
Here's a sample of this data:
|
|
||||||
|
|
||||||
<FlatUiTable url="https://storage.openspending.org/de3-berlin-2007-2013-erdf/concat.csv" />
|
|
||||||
|
|
||||||
Note that we will only use the rows where the "amount_kind" column is set to "total_amount".
|
|
||||||
|
|
||||||
## How has the total amount changed over the years?
|
|
||||||
|
|
||||||
The line chart below shows the sum of the total amount of EUR that was approved for each year:
|
|
||||||
|
|
||||||
<LineChart data="https://storage.openspending.org/de3-berlin-2007-2013-erdf/berlin-erdf-2007-2013-total-amount-apporved-per-year.csv" xAxis="approval_year" yAxis="total_amount" />
|
|
||||||
|
|
||||||
As you can see, the total increased significantly from 2007 to 2010, later fluctuating between €7 million and €9 million per year.
|
|
||||||
|
|
||||||
## Who were the top beneficiaries for each year?
|
|
||||||
|
|
||||||
Now, let's try to understand who were the top beneficiaries each year. To do that, let's filter the data to show only the two top beneficiaries for each year:
|
|
||||||
|
|
||||||
<FlatUiTable url="https://storage.openspending.org/de3-berlin-2007-2013-erdf/berlin-erdf-2007-2013-total-amount-approved-per-year-per-beneficiary--top-2.csv" />
|
|
||||||
|
|
||||||
Since there are many years in this range, let's split this analysis into two ranges: one for 2008-2010 and the other for 2011-2015.
|
|
||||||
|
|
||||||
<VegaLite spec={{
|
|
||||||
"data": { "url": "https://storage.openspending.org/de3-berlin-2007-2013-erdf/berlin-erdf-2007-2013-total-amount-approved-per-year-per-beneficiary--top-2.csv"},
|
|
||||||
"transform": [
|
|
||||||
{"filter": "datum.approval_year <= 2010"},
|
|
||||||
],
|
|
||||||
"title": "Total Amount (EUR) x Approval Year (2007-2010)",
|
|
||||||
"width": "container",
|
|
||||||
"mark": {"type": "bar", "tooltip": true },
|
|
||||||
"encoding": {
|
|
||||||
"y": {
|
|
||||||
"aggregate": "sum",
|
|
||||||
"field": "total_amount",
|
|
||||||
"title": "Total Amount (EUR)",
|
|
||||||
"stack": null
|
|
||||||
},
|
|
||||||
"x": {"field": "approval_year", "title": "Approval Year"},
|
|
||||||
"color": {
|
|
||||||
"type": "nominal",
|
|
||||||
"field": "beneficiary_name",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}} />
|
|
||||||
|
|
||||||
<VegaLite spec={{
|
|
||||||
"title": "Total Amount (EUR) x Approval Year (2011-2013)",
|
|
||||||
"data": { "url": "https://storage.openspending.org/de3-berlin-2007-2013-erdf/berlin-erdf-2007-2013-total-amount-approved-per-year-per-beneficiary--top-2.csv"},
|
|
||||||
"transform": [
|
|
||||||
{"filter": "datum.approval_year > 2010"},
|
|
||||||
],
|
|
||||||
"width": "container",
|
|
||||||
"mark": {"type": "bar", "tooltip": true },
|
|
||||||
"encoding": {
|
|
||||||
"y": {
|
|
||||||
"aggregate": "sum",
|
|
||||||
"field": "total_amount",
|
|
||||||
"title": "Total Amount (EUR)",
|
|
||||||
"stack": null
|
|
||||||
},
|
|
||||||
"x": {"field": "approval_year", "title": "Approval Year"},
|
|
||||||
"color": {
|
|
||||||
"type": "nominal",
|
|
||||||
"field": "beneficiary_name",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}} />
|
|
||||||
|
|
||||||
It's easy to spot some repeating colors. Now, let's see to which sector the top beneficiaries belong to:
|
|
||||||
|
|
||||||
<Table csv="
|
|
||||||
Beneficiary,Sector
|
|
||||||
D & B,Education
|
|
||||||
Stiftung Sozialpädagogisches Institut Berlin (SPI),Education/Social work
|
|
||||||
IB e.V.,Social work
|
|
||||||
gsub-Projektegesellschaft mbH,Consulting
|
|
||||||
BBW Berufsvorbereitungs-u.Ausbildungsgesellschaft,Education
|
|
||||||
Arbeit und Bildung e.V.,Consulting
|
|
||||||
Gesellschaft für soziale Unternehmensberatung GSUB,Consulting
|
|
||||||
SPI Consult GmbH,Consulting
|
|
||||||
Beuth Hochschule für Technik Berlin,Education
|
|
||||||
TU Berlin, Fakultät II,Education
|
|
||||||
Hochschule für Technik und Wirtschaft Berlin,Education
|
|
||||||
WeTeK gGmbH,Education
|
|
||||||
" />
|
|
||||||
|
|
||||||
Based on the sectors of the top beneficiaries, it's clear that education and professional training have been a major focus of ERDF investment in Berlin during that period of time.
|
|
||||||
@@ -5,6 +5,7 @@
|
|||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"changeset": "changeset",
|
"changeset": "changeset",
|
||||||
|
"prerelease": "nx run-many --targets=lint,test,build --projects=tag:test",
|
||||||
"release": "changeset publish"
|
"release": "changeset publish"
|
||||||
},
|
},
|
||||||
"private": true,
|
"private": true,
|
||||||
|
|||||||
@@ -1,11 +1,5 @@
|
|||||||
# @portaljs/components
|
# @portaljs/components
|
||||||
|
|
||||||
## 0.1.12
|
|
||||||
|
|
||||||
### Patch Changes
|
|
||||||
|
|
||||||
- [#960](https://github.com/datopian/portaljs/pull/960) [`add2f6d0`](https://github.com/datopian/portaljs/commit/add2f6d0f372434eb996d59d6faf5cd06530c932) Thanks [@demenech](https://github.com/demenech)! - Fix width of the <LineChart /> component
|
|
||||||
|
|
||||||
## 0.1.11
|
## 0.1.11
|
||||||
|
|
||||||
### Patch Changes
|
### Patch Changes
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@portaljs/components",
|
"name": "@portaljs/components",
|
||||||
"version": "0.1.12",
|
"version": "0.1.11",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"description": "https://portaljs.org",
|
"description": "https://portaljs.org",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ export function LineChart({
|
|||||||
const spec = {
|
const spec = {
|
||||||
$schema: 'https://vega.github.io/schema/vega-lite/v5.json',
|
$schema: 'https://vega.github.io/schema/vega-lite/v5.json',
|
||||||
title,
|
title,
|
||||||
width: 'container',
|
width: 600,
|
||||||
height: 300,
|
height: 300,
|
||||||
mark: {
|
mark: {
|
||||||
type: 'line',
|
type: 'line',
|
||||||
|
|||||||
@@ -1,11 +1,5 @@
|
|||||||
# @portaljs/core
|
# @portaljs/core
|
||||||
|
|
||||||
## 1.0.6
|
|
||||||
|
|
||||||
### Patch Changes
|
|
||||||
|
|
||||||
- [#958](https://github.com/datopian/portaljs/pull/958) [`c4bf5bd0`](https://github.com/datopian/portaljs/commit/c4bf5bd05401982125750e61a27ed31f9bb14a4d) Thanks [@olayway](https://github.com/olayway)! - Add basic Hero component.
|
|
||||||
|
|
||||||
## 1.0.5
|
## 1.0.5
|
||||||
|
|
||||||
### Patch Changes
|
### Patch Changes
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@portaljs/core",
|
"name": "@portaljs/core",
|
||||||
"version": "1.0.6",
|
"version": "1.0.5",
|
||||||
"description": "Core Portal.JS components, configs and utils.",
|
"description": "Core Portal.JS components, configs and utils.",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
|
|||||||
@@ -1,90 +0,0 @@
|
|||||||
interface Button {
|
|
||||||
title: string;
|
|
||||||
href: string;
|
|
||||||
type: 'filled' | 'text'
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface HeroProps {
|
|
||||||
title: string;
|
|
||||||
subtitle?: string;
|
|
||||||
announcement?: {
|
|
||||||
title: string;
|
|
||||||
href?: string;
|
|
||||||
};
|
|
||||||
buttons?: Array<Button>
|
|
||||||
}
|
|
||||||
|
|
||||||
const buttonStyle = {
|
|
||||||
'filled': "rounded-md bg-secondary px-3.5 py-2.5 text-sm font-semibold text-white shadow-sm hover:bg-secondary/90 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600",
|
|
||||||
'text': "text-sm font-semibold leading-6"
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
export const Hero: React.FC<HeroProps> = ({ title, subtitle, announcement, buttons }) => {
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="text-primary dark:text-primary-dark">
|
|
||||||
<div className="relative isolate px-6 pt-14 lg:px-8">
|
|
||||||
{/* <div
|
|
||||||
className="absolute inset-x-0 -top-40 -z-10 transform-gpu overflow-hidden blur-3xl sm:-top-80"
|
|
||||||
aria-hidden="true"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
className="relative left-[calc(50%-11rem)] aspect-[1155/678] w-[36.125rem] -translate-x-1/2 rotate-[30deg] bg-gradient-to-tr from-[#38bdf8] to-[#89a8fc] opacity-30 sm:left-[calc(50%-30rem)] sm:w-[72.1875rem]"
|
|
||||||
style={{
|
|
||||||
clipPath:
|
|
||||||
'polygon(74.1% 44.1%, 100% 61.6%, 97.5% 26.9%, 85.5% 0.1%, 80.7% 2%, 72.5% 32.5%, 60.2% 62.4%, 52.4% 68.1%, 47.5% 58.3%, 45.2% 34.5%, 27.5% 76.7%, 0.1% 64.9%, 17.9% 100%, 27.6% 76.8%, 76.1% 97.7%, 74.1% 44.1%)',
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div> */}
|
|
||||||
<div className="mx-auto max-w-2xl py-16 sm:py-32 lg:py-40">
|
|
||||||
{announcement && (
|
|
||||||
<div className="hidden sm:mb-8 sm:flex sm:justify-center">
|
|
||||||
<div className="relative rounded-full px-3 py-1 text-sm leading-6 ring-1 ring-primary/20 hover:ring-primary/30 dark:ring-primary-dark/30 dark:hover:ring-primary-dark/40">
|
|
||||||
{announcement.title}{' '}
|
|
||||||
<a href="#" className="font-semibold text-secondary">
|
|
||||||
<span className="absolute inset-0" aria-hidden="true" />
|
|
||||||
Read more <span aria-hidden="true">→</span>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
<div className="text-center">
|
|
||||||
<h1 className="text-4xl font-bold tracking-tight sm:text-6xl">
|
|
||||||
{title}
|
|
||||||
</h1>
|
|
||||||
{subtitle && (
|
|
||||||
<p className="mt-6 text-lg leading-8 text-primary/90 dark:text-primary-dark/80">
|
|
||||||
{subtitle}
|
|
||||||
</p>
|
|
||||||
)}
|
|
||||||
{buttons && buttons.length && (
|
|
||||||
<div className="mt-10 flex items-center justify-center gap-x-6">
|
|
||||||
{buttons.map((b) => (
|
|
||||||
<a
|
|
||||||
href={b.href}
|
|
||||||
className={buttonStyle[b.type]}
|
|
||||||
>
|
|
||||||
{b.title}
|
|
||||||
</a>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{/* <div
|
|
||||||
className="absolute inset-x-0 top-[calc(100%-13rem)] -z-10 transform-gpu overflow-hidden blur-3xl sm:top-[calc(100%-30rem)]"
|
|
||||||
aria-hidden="true"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
className="relative left-[calc(50%+3rem)] aspect-[1155/678] w-[36.125rem] -translate-x-1/2 bg-gradient-to-tr from-[#89a8fc] to-[#38bdf8] opacity-30 sm:left-[calc(50%+36rem)] sm:w-[72.1875rem]"
|
|
||||||
style={{
|
|
||||||
clipPath:
|
|
||||||
'polygon(74.1% 44.1%, 100% 61.6%, 97.5% 26.9%, 85.5% 0.1%, 80.7% 2%, 72.5% 32.5%, 60.2% 62.4%, 52.4% 68.1%, 47.5% 58.3%, 45.2% 34.5%, 27.5% 76.7%, 0.1% 64.9%, 17.9% 100%, 27.6% 76.8%, 76.1% 97.7%, 74.1% 44.1%)',
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div> */}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
export { Hero } from "./Hero"
|
|
||||||
@@ -18,5 +18,5 @@ export { BlogLayout } from "./BlogLayout";
|
|||||||
export { Mermaid } from "./Mermaid";
|
export { Mermaid } from "./Mermaid";
|
||||||
export { SiteToc, NavItem, NavGroup } from "./SiteToc";
|
export { SiteToc, NavItem, NavGroup } from "./SiteToc";
|
||||||
export { Comments, CommentsConfig } from "./Comments";
|
export { Comments, CommentsConfig } from "./Comments";
|
||||||
|
|
||||||
export { AuthorConfig } from "./types";
|
export { AuthorConfig } from "./types";
|
||||||
export { Hero } from "./Hero";
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { defaultConfig } from "@portaljs/core";
|
import { defaultConfig } from "@flowershow/core";
|
||||||
import userConfig from "../content/config";
|
import userConfig from "../content/config";
|
||||||
|
|
||||||
export const siteConfig: any = {
|
export const siteConfig: any = {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
---
|
---
|
||||||
title: "Setup Guide: How to create a full-featured custom data portal frontend for CKAN with PortalJS"
|
title: "PortalJS example 1: Create a full-featured custom data portal frontend for CKAN with PortalJS"
|
||||||
authors: ['Luccas Mateus']
|
authors: ['Luccas Mateus']
|
||||||
date: 2021-04-20
|
date: 2021-04-20
|
||||||
---
|
---
|
||||||
|
|||||||
@@ -142,7 +142,7 @@ process.exit(0);
|
|||||||
|
|
||||||
Since we're using ES6 modules, we also need to add `"type": "module"` to our `package.json` file.
|
Since we're using ES6 modules, we also need to add `"type": "module"` to our `package.json` file.
|
||||||
|
|
||||||
Before we run the above script, we need to make sure that the `dbPath` variable is pointing to our `markdown.db` file. If you want to store the database outside of your project folder, you can update the `dbPath` variable to point to the correct location. If you want to have it inside your project folder, you can copy it there, or simply re-run the `npx mddb <path-to-markdown-folder>` command from within your project folder.
|
Before we run the above script, we need to make sure that the `dbPath` variable is pointing to our `markdown.db` file. If you want to store the database outside of your project folder, you can update the `dbPath` variable to point to the correct location. If you want to have it inside your project folder, you can copy it there, or simply re-run the `npx mddb` {'<'}path-to-markdown-folder{'>'}` command from within your project folder.
|
||||||
|
|
||||||
Now, let's run the script:
|
Now, let's run the script:
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
---
|
---
|
||||||
title: "Setup Guide: Create a data catalog with PortalJS and CKAN to share your data stories"
|
title: "Example: Data catalog with data on CKAN"
|
||||||
authors: ['Luccas Mateus']
|
authors: ['Luccas Mateus']
|
||||||
date: 2023-04-20
|
date: 2023-04-20
|
||||||
filetype: blog
|
filetype: blog
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
---
|
---
|
||||||
title: "Setup Guide: Create a data catalog to display and share your GitHub datasets with PortalJS"
|
title: "Example: Data catalog with data on GitHub"
|
||||||
authors: ['Luccas Mateus']
|
authors: ['Luccas Mateus']
|
||||||
date: 2023-04-20
|
date: 2023-04-20
|
||||||
filetype: blog
|
filetype: blog
|
||||||
|
|||||||
@@ -2,10 +2,10 @@
|
|||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
|
|
||||||
The following example uses components imported from the [`@portaljs/core` package](https://www.npmjs.com/package/@portaljs/core). If you want to follow along install it too:
|
The following example uses components imported from the [`@flowershow/core` package](https://github.com/datopian/flowershow). If you want to follow along install it too:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
npm i @portaljs/core
|
npm i @flowershow/core
|
||||||
```
|
```
|
||||||
|
|
||||||
## Create home page for your blogs
|
## Create home page for your blogs
|
||||||
@@ -13,7 +13,7 @@ npm i @portaljs/core
|
|||||||
Add the following code to the Next.js page that is going to be your blog home page, e.g. to `/pages/blog/index.tsx`:
|
Add the following code to the Next.js page that is going to be your blog home page, e.g. to `/pages/blog/index.tsx`:
|
||||||
|
|
||||||
```tsx
|
```tsx
|
||||||
import { BlogsList, SimpleLayout } from "@portaljs/core";
|
import { BlogsList, SimpleLayout } from "@flowershow/core";
|
||||||
|
|
||||||
// pass a list of blogs, home page title and home page description, e.g. from `getStaticProps`
|
// pass a list of blogs, home page title and home page description, e.g. from `getStaticProps`
|
||||||
export default function BlogIndex({ blogs, title, description }) {
|
export default function BlogIndex({ blogs, title, description }) {
|
||||||
@@ -47,7 +47,7 @@ interface Blog {
|
|||||||
Add the following code to your blog pages, e.g. to `/pages/blog/[...slug].tsx`:
|
Add the following code to your blog pages, e.g. to `/pages/blog/[...slug].tsx`:
|
||||||
|
|
||||||
```tsx
|
```tsx
|
||||||
import { BlogLayout } from "@portaljs/core";
|
import { BlogLayout } from "@flowershow/core";
|
||||||
|
|
||||||
export default BlogPost({ content, title, date, authors }) {
|
export default BlogPost({ content, title, date, authors }) {
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -75,10 +75,10 @@ NEXT_PUBLIC_DISQUS_SHORTNAME=
|
|||||||
|
|
||||||
## Add comments to your page layout
|
## Add comments to your page layout
|
||||||
|
|
||||||
You can use `@portaljs/core` to import the comments section component. Install it with:
|
You can use `@flowershow/core` to import the comments section component. Install it with:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
npm i @portaljs/core
|
npm i @flowershow/core
|
||||||
```
|
```
|
||||||
|
|
||||||
Then, add the following to your custom layout (or directly to your pages):
|
Then, add the following to your custom layout (or directly to your pages):
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import {
|
import {
|
||||||
SimpleLayout,
|
SimpleLayout,
|
||||||
UnstyledLayout,
|
UnstyledLayout,
|
||||||
} from "@portaljs/core";
|
} from "@flowershow/core";
|
||||||
import { BlogLayout } from "./blog";
|
import { BlogLayout } from "./blog";
|
||||||
import DefaultLayout from "./default";
|
import DefaultLayout from "./default";
|
||||||
import { DocsLayout } from "./docs";
|
import { DocsLayout } from "./docs";
|
||||||
|
|||||||
@@ -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";
|
||||||
// import config from "./markdowndb.config.js";
|
// import config from "./markdowndb.config.js";
|
||||||
|
|
||||||
// TODO get this path from markdowndb.config.js or something
|
// TODO get this path from markdowndb.config.js or something
|
||||||
|
|||||||
1510
site/package-lock.json
generated
1510
site/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -10,18 +10,18 @@
|
|||||||
"mddb": "mddb content"
|
"mddb": "mddb content"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@flowershow/core": "^0.4.11",
|
||||||
|
"@flowershow/markdowndb": "^0.1.1",
|
||||||
|
"@flowershow/remark-callouts": "^1.0.0",
|
||||||
|
"@flowershow/remark-embed": "^1.0.0",
|
||||||
|
"@flowershow/remark-wiki-link": "^1.0.1",
|
||||||
"@headlessui/react": "^1.3.0",
|
"@headlessui/react": "^1.3.0",
|
||||||
"@heroicons/react": "^1.0.3",
|
"@heroicons/react": "^1.0.3",
|
||||||
"@mdx-js/loader": "^2.3.0",
|
"@mdx-js/loader": "^2.3.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",
|
|
||||||
"axios": "^1.3.6",
|
"axios": "^1.3.6",
|
||||||
"clsx": "^1.2.1",
|
"clsx": "^1.2.1",
|
||||||
"gray-matter": "^4.0.3",
|
"gray-matter": "^4.0.3",
|
||||||
"hastscript": "^7.2.0",
|
"hastscript": "^7.2.0",
|
||||||
"mddb": "^0.1.9",
|
|
||||||
"next": "^13.2.1",
|
"next": "^13.2.1",
|
||||||
"next-mdx-remote": "^4.4.1",
|
"next-mdx-remote": "^4.4.1",
|
||||||
"next-seo": "^5.15.0",
|
"next-seo": "^5.15.0",
|
||||||
@@ -45,17 +45,17 @@
|
|||||||
"remark-slug": "^6.1.0",
|
"remark-slug": "^6.1.0",
|
||||||
"remark-smartypants": "^2.0.0",
|
"remark-smartypants": "^2.0.0",
|
||||||
"remark-toc": "^7.2.0",
|
"remark-toc": "^7.2.0",
|
||||||
"strip-markdown": "^5.0.0",
|
|
||||||
"vega": "^5.20.2",
|
"vega": "^5.20.2",
|
||||||
"vega-lite": "^5.1.0"
|
"vega-lite": "^5.1.0",
|
||||||
|
"strip-markdown": "^5.0.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@tailwindcss/typography": "^0.5.9",
|
"@tailwindcss/typography": "^0.5.9",
|
||||||
"autoprefixer": "^10.4.14",
|
"autoprefixer": "^10.4.14",
|
||||||
"postcss": "^8.4.22",
|
"postcss": "^8.4.22",
|
||||||
"prettier": "^2.8.7",
|
"prettier": "^2.8.7",
|
||||||
"remark": "^14.0.2",
|
|
||||||
"tailwindcss": "^3.3.1",
|
"tailwindcss": "^3.3.1",
|
||||||
"typescript": "^5.0.4"
|
"typescript": "^5.0.4",
|
||||||
|
"remark": "^14.0.2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import clientPromise from '@/lib/mddb';
|
|||||||
import Layout from 'components/Layout';
|
import Layout from 'components/Layout';
|
||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
import { useRouter } from 'next/router.js';
|
import { useRouter } from 'next/router.js';
|
||||||
import { NavGroup, NavItem, collectHeadings } from '@portaljs/core';
|
import { NavGroup, NavItem, collectHeadings } from '@flowershow/core';
|
||||||
import { GetStaticProps, GetStaticPropsResult } from 'next';
|
import { GetStaticProps, GetStaticPropsResult } from 'next';
|
||||||
import { CustomAppProps } from './_app.jsx';
|
import { CustomAppProps } from './_app.jsx';
|
||||||
import computeFields from '@/lib/computeFields';
|
import computeFields from '@/lib/computeFields';
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import Script from "next/script";
|
|||||||
|
|
||||||
import { DefaultSeo } from "next-seo";
|
import { DefaultSeo } from "next-seo";
|
||||||
|
|
||||||
import { NavGroup, NavItem, pageview, ThemeProvider } from "@portaljs/core";
|
import { NavGroup, NavItem, pageview, ThemeProvider } from "@flowershow/core";
|
||||||
import { siteConfig } from "../config/siteConfig";
|
import { siteConfig } from "../config/siteConfig";
|
||||||
import { useEffect } from "react";
|
import { useEffect } from "react";
|
||||||
import { useRouter } from "next/dist/client/router";
|
import { useRouter } from "next/dist/client/router";
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import Layout from '@/components/Layout';
|
import Layout from '@/components/Layout';
|
||||||
import computeFields from '@/lib/computeFields';
|
import computeFields from '@/lib/computeFields';
|
||||||
import clientPromise from '@/lib/mddb';
|
import clientPromise from '@/lib/mddb';
|
||||||
import { BlogsList, SimpleLayout } from '@portaljs/core';
|
import { BlogsList, SimpleLayout } from '@flowershow/core';
|
||||||
import * as fs from 'fs';
|
import * as fs from 'fs';
|
||||||
|
|
||||||
export default function Blog({ blogs }) {
|
export default function Blog({ blogs }) {
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import Showcases from '@/components/Showcases';
|
|||||||
import Layout from '../components/Layout';
|
import Layout from '../components/Layout';
|
||||||
import { useRouter } from 'next/router';
|
import { useRouter } from 'next/router';
|
||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
import { collectHeadings } from '@portaljs/core';
|
import { collectHeadings } from '@flowershow/core';
|
||||||
|
|
||||||
export default function Home({ sidebarTree }) {
|
export default function Home({ sidebarTree }) {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
@import "@portaljs/remark-callouts/styles.css";
|
@import "@flowershow/remark-callouts/styles.css";
|
||||||
@import './prism.css';
|
@import './prism.css';
|
||||||
|
|
||||||
html,
|
html,
|
||||||
|
|||||||
@@ -13,8 +13,8 @@ module.exports = {
|
|||||||
"./components/**/*.jsx",
|
"./components/**/*.jsx",
|
||||||
"./components/**/*.tsx",
|
"./components/**/*.tsx",
|
||||||
"./lib/markdown.mjs",
|
"./lib/markdown.mjs",
|
||||||
"./node_modules/@portaljs/core/dist/*.js",
|
"./node_modules/@flowershow/core/dist/*.js",
|
||||||
"./node_modules/@portaljs/core/*.js",
|
"./node_modules/@flowershow/core/*.js",
|
||||||
],
|
],
|
||||||
darkMode: "class", // or 'media' or 'class'
|
darkMode: "class", // or 'media' or 'class'
|
||||||
theme: {
|
theme: {
|
||||||
|
|||||||
@@ -2,12 +2,12 @@
|
|||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"baseUrl": ".",
|
"baseUrl": ".",
|
||||||
"paths": {
|
"paths": {
|
||||||
"@portaljs/core": ["node_modules/@portaljs/core/dist/src"],
|
"@flowershow/core": ["node_modules/@flowershow/core/dist/src"],
|
||||||
"@portaljs/remark-callouts": [
|
"@flowershow/remark-callouts": [
|
||||||
"node_modules/@portaljs/remark-callouts/dist/src"
|
"node_modules/@flowershow/remark-callouts/dist/src"
|
||||||
],
|
],
|
||||||
"@portaljs/remark-embed": [
|
"@flowershow/remark-embed": [
|
||||||
"node_modules/@portaljs/remark-embed/dist/src"
|
"node_modules/@flowershow/remark-embed/dist/src"
|
||||||
],
|
],
|
||||||
"@/*": ["./*"]
|
"@/*": ["./*"]
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user