Compare commits
50 Commits
@portaljs/
...
feature/up
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d80d1f5012 | ||
|
|
8487175f01 | ||
|
|
ad5a176e85 | ||
|
|
eeb480e8cf | ||
|
|
30fcb256b2 | ||
|
|
a4f8c0ed76 | ||
|
|
829f3b1f13 | ||
|
|
836b143a31 | ||
|
|
be38086794 | ||
|
|
63d9e3b754 | ||
|
|
f86f0541eb | ||
|
|
64bc212384 | ||
|
|
1e7daf353d | ||
|
|
cc69dabf80 | ||
|
|
a5d87712e0 | ||
|
|
86834fd1a6 | ||
|
|
8a661b1617 | ||
|
|
1baebc3f3c | ||
|
|
bbac4954f5 | ||
|
|
be6b184884 | ||
|
|
64103d6488 | ||
|
|
8e3496782c | ||
|
|
e034503399 | ||
|
|
93ae498ec2 | ||
|
|
97e43fdcba | ||
|
|
32f29024f8 | ||
|
|
134f72948c | ||
|
|
c1f2c526a8 | ||
|
|
8feb87739d | ||
|
|
3a07267e44 | ||
|
|
3f19ca16ed | ||
|
|
5deabac5fe | ||
|
|
96901150c6 | ||
|
|
9ff25ed7c4 | ||
|
|
8f884fceab | ||
|
|
7094eded50 | ||
|
|
30e7c6379f | ||
|
|
feada58932 | ||
|
|
31406d48e3 | ||
|
|
d6bf344ca3 | ||
|
|
d1a5138c6e | ||
|
|
a6047a9341 | ||
|
|
a4e60540ae | ||
|
|
e4c456c237 | ||
|
|
ce9ebbf41e | ||
|
|
a8fb176bcc | ||
|
|
2ac82367c5 | ||
|
|
85de6f7878 | ||
|
|
1a8e7ac06e | ||
|
|
4355efe0c4 |
@@ -4,7 +4,7 @@ title: Developer docs for contributors
|
||||
|
||||
## Our repository
|
||||
|
||||
https://github.com/datopian/portaljs
|
||||
https://github.com/datopian/datahub
|
||||
|
||||
Structure:
|
||||
|
||||
@@ -17,7 +17,7 @@ Structure:
|
||||
|
||||
## How to contribute
|
||||
|
||||
You can start by checking our [issues board](https://github.com/datopian/portaljs/issues).
|
||||
You can start by checking our [issues board](https://github.com/datopian/datahub/issues).
|
||||
|
||||
If you'd like to work on one of the issues you can:
|
||||
|
||||
@@ -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.
|
||||
|
||||
> [!note]
|
||||
> Join our [Discord channel](https://discord.gg/rTxfCutu) do discuss existing issues and to ask for help.
|
||||
> Join our [Discord channel](https://discord.gg/KZSf3FG4EZ) do discuss existing issues and to ask for help.
|
||||
|
||||
## Nx
|
||||
|
||||
|
||||
@@ -41,7 +41,7 @@ https://datahub.io/docs
|
||||
|
||||
DataHub 🌀 is a platform for rapidly creating rich data portal and publishing systems using a modern frontend approach. Datahub can be used to publish a single dataset or build a full-scale data catalog/portal.
|
||||
|
||||
DataHub is built in JavaScript and React on top of the popular [Next.js](https://nextjs.com/) framework. DataHub 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.
|
||||
DataHub is built in JavaScript and React on top of the popular [Next.js](https://nextjs.org) framework. DataHub 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
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
**🚩 UPDATE April 2023: This example is now deprecated - though still works!. Please use the [new CKAN examples](https://github.com/datopian/portaljs/tree/main/examples)**
|
||||
|
||||
This example shows how you can build a full data portal using a CKAN Backend with a Next.JS Frontend powered by Apollo, a full fledged guide is available as a [blog post](https://portaljs.org/blog/example-ckan-2021)
|
||||
This example shows how you can build a full data portal using a CKAN Backend with a Next.JS Frontend powered by Apollo, a full fledged guide is available as a [blog post](https://portaljs.com/blog/example-ckan-2021)
|
||||
|
||||
## Developers
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
This is a repo intended to serve as an example of a data catalog that get its data from a CKAN Instance.
|
||||
|
||||
```
|
||||
npx create-next-app <app-name> --example https://github.com/datopian/portaljs/tree/main/examples/ckan-example
|
||||
npx create-next-app <app-name> --example https://github.com/datopian/datahub/tree/main/examples/ckan-ssg
|
||||
cd <app-name>
|
||||
```
|
||||
|
||||
@@ -19,7 +19,7 @@ npm run dev
|
||||
|
||||
Congratulations, you now have something similar to this running on `http://localhost:4200`
|
||||

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

|
||||
|
||||
## Deployment
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
This example creates a portal/showcase for a single dataset. The dataset should be a [Frictionless dataset (data package)][fd] i.e. there should be a `datapackage.json`.
|
||||
|
||||
[fd]: https://frictionlessdata.io/data-packages/
|
||||
[fd]: https://specs.frictionlessdata.io/data-package/
|
||||
|
||||
## How to use
|
||||
|
||||
|
||||
@@ -59,7 +59,7 @@ export default function Layout({ children }: { children: React.ReactNode }) {
|
||||
<div className="md:flex items-center gap-x-3 text-[#3c3c3c] -mb-1 hidden">
|
||||
<a
|
||||
className="hover:opacity-75 transition"
|
||||
href="https://portaljs.org"
|
||||
href="https://portaljs.com"
|
||||
>
|
||||
Built with 🌀PortalJS
|
||||
</a>
|
||||
@@ -77,7 +77,7 @@ export default function Layout({ children }: { children: React.ReactNode }) {
|
||||
<li>
|
||||
<a
|
||||
className="hover:opacity-75 transition"
|
||||
href="https://portaljs.org"
|
||||
href="https://portaljs.com"
|
||||
>
|
||||
PortalJS
|
||||
</a>
|
||||
|
||||
@@ -6,7 +6,7 @@ A `datasets.json` file is used to specify which datasets are going to be part of
|
||||
|
||||
The application contains an index page, which lists all the datasets specified in the `datasets.json` file, and users can see more information about each dataset, such as the list of data files in it and the README, by clicking the "info" button on the list.
|
||||
|
||||
You can read more about it on the [Data catalog with data on GitHub](https://portaljs.org/docs/examples/github-backed-catalog) blog post.
|
||||
You can read more about it on the [Data catalog with data on GitHub](https://portaljs.com/docs/examples/github-backed-catalog) blog post.
|
||||
|
||||
## Demo
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@ export function Datasets({ projects }) {
|
||||
<Link
|
||||
target="_blank"
|
||||
className="underline"
|
||||
href="https://portaljs.org/"
|
||||
href="https://portaljs.com/"
|
||||
>
|
||||
🌀 PortalJS
|
||||
</Link>
|
||||
|
||||
@@ -1 +1 @@
|
||||
PortalJS Learn Example - https://portaljs.org/docs
|
||||
PortalJS Learn Example - https://portaljs.com/docs
|
||||
@@ -6,7 +6,7 @@ A `datasets.json` file is used to specify which datasets are going to be part of
|
||||
|
||||
The application contains an index page, which lists all the datasets specified in the `datasets.json` file, and users can see more information about each dataset, such as the list of data files in it and the README, by clicking the "info" button on the list.
|
||||
|
||||
You can read more about it on the [Data catalog with data on GitHub](https://portaljs.org/docs/examples/github-backed-catalog) blog post.
|
||||
You can read more about it on the [Data catalog with data on GitHub](https://portaljs.com/docs/examples/github-backed-catalog) blog post.
|
||||
|
||||
## Demo
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ export default function Footer() {
|
||||
</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.org" target="_blank" className='text-xl font-medium'>🌀 PortalJS</a></p>
|
||||
<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>
|
||||
|
||||
@@ -127,4 +127,4 @@ Based on the bar chart above we can conclude that the following 3 countries have
|
||||
2. Poland - EUR ~68b.
|
||||
3. Italy - EUR ~35b.
|
||||
|
||||
_This data story was created by using Datopian's PortalJS framework. You can learn more about the framework by visiting https://portaljs.org/_
|
||||
_This data story was created by using Datopian's PortalJS framework. You can learn more about the framework by visiting https://portaljs.com/_
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
This demo data portal is designed for https://hatespeechdata.com. It catalogs datasets annotated for hate speech, online abuse, and offensive language which are useful for training a natural language processing system to detect this online abuse.
|
||||
|
||||
The site is built on top of [PortalJS](https://portaljs.org/). It catalogs datasets and lists of offensive keywords. It also includes static pages. All of these are stored as markdown files inside the `content` folder.
|
||||
The site is built on top of [PortalJS](https://portaljs.com/). It catalogs datasets and lists of offensive keywords. It also includes static pages. All of these are stored as markdown files inside the `content` folder.
|
||||
|
||||
- .md files inside `content/datasets/` will appear on the dataset list section of the homepage and be searchable as well as having a individual page in `datasets/<file name>`
|
||||
- .md files inside `content/keywords/` will appear on the list of offensive keywords section of the homepage as well as having a individual page in `keywords/<file name>`
|
||||
|
||||
@@ -21,7 +21,7 @@ export function Footer() {
|
||||
<Container.Inner>
|
||||
<div className="flex flex-col items-center justify-between gap-6 sm:flex-row">
|
||||
<p className="text-sm font-medium text-zinc-800 dark:text-zinc-200">
|
||||
Built with <a href='https://portaljs.org'>PortalJS 🌀</a>
|
||||
Built with <a href='https://portaljs.com'>PortalJS 🌀</a>
|
||||
</p>
|
||||
<p className="text-sm text-zinc-400 dark:text-zinc-500">
|
||||
© {new Date().getFullYear()} Leon Derczynski. All rights
|
||||
|
||||
4
package-lock.json
generated
4
package-lock.json
generated
@@ -49897,7 +49897,7 @@
|
||||
},
|
||||
"packages/components": {
|
||||
"name": "@portaljs/components",
|
||||
"version": "0.6.0",
|
||||
"version": "1.2.0",
|
||||
"dependencies": {
|
||||
"@githubocto/flat-ui": "^0.14.1",
|
||||
"@heroicons/react": "^2.0.17",
|
||||
@@ -50383,7 +50383,7 @@
|
||||
},
|
||||
"packages/remark-wiki-link": {
|
||||
"name": "@portaljs/remark-wiki-link",
|
||||
"version": "1.1.3",
|
||||
"version": "1.2.0",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"mdast-util-to-markdown": "^1.5.0",
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"name": "@portaljs/ckan",
|
||||
"version": "0.1.0",
|
||||
"type": "module",
|
||||
"description": "https://portaljs.org",
|
||||
"description": "https://portaljs.com",
|
||||
"keywords": [
|
||||
"data portal",
|
||||
"data catalog",
|
||||
|
||||
@@ -1,9 +1,16 @@
|
||||
import 'tailwindcss/tailwind.css'
|
||||
import '../src/index.css'
|
||||
|
||||
|
||||
import type { Preview } from '@storybook/react';
|
||||
|
||||
window.process = {
|
||||
...window.process,
|
||||
env:{
|
||||
...window.process?.env,
|
||||
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
const preview: Preview = {
|
||||
parameters: {
|
||||
actions: { argTypesRegex: '^on[A-Z].*' },
|
||||
|
||||
@@ -1,5 +1,35 @@
|
||||
# @portaljs/components
|
||||
|
||||
## 1.2.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [`eeb480e8`](https://github.com/datopian/datahub/commit/eeb480e8cff2d11072ace55ad683a65f54f5d07a) Thanks [@olayway](https://github.com/olayway)! - Adjust `xAxisTimeUnit` property in LineChart to allow for passing `yearmonth`.
|
||||
|
||||
## 1.2.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [`836b143a`](https://github.com/datopian/datahub/commit/836b143a3178b893b1aae3fb511d795dd3a63545) Thanks [@olayway](https://github.com/olayway)! - Fix: make tileLayerName in Map optional.
|
||||
|
||||
## 1.2.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- [#1338](https://github.com/datopian/datahub/pull/1338) [`63d9e3b7`](https://github.com/datopian/datahub/commit/63d9e3b7543c38154e6989ef1cc1d694ae9fc4f8) Thanks [@olayway](https://github.com/olayway)! - Support for plotting multiple series in LineChart component.
|
||||
|
||||
## 1.1.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- [#1122](https://github.com/datopian/datahub/pull/1122) [`8e349678`](https://github.com/datopian/datahub/commit/8e3496782c022b0653e07f217c6b315ba84e0e61) Thanks [@willy1989cv](https://github.com/willy1989cv)! - Map: allow users to choose a base layer setting
|
||||
|
||||
## 1.0.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#1170](https://github.com/datopian/datahub/pull/1170) [`9ff25ed7`](https://github.com/datopian/datahub/commit/9ff25ed7c47c8c02cc078c64f76ae35d6754c508) Thanks [@lucasmbispo](https://github.com/lucasmbispo)! - iFrame component: change height
|
||||
|
||||
## 1.0.0
|
||||
|
||||
### Major Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# PortalJS React Components
|
||||
|
||||
**Storybook:** https://storybook.portaljs.org
|
||||
**Docs**: https://portaljs.org/docs
|
||||
**Docs**: https://portaljs.com/opensource
|
||||
|
||||
## Usage
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
{
|
||||
"name": "@portaljs/components",
|
||||
"version": "1.0.0",
|
||||
"version": "1.2.2",
|
||||
"type": "module",
|
||||
"description": "https://portaljs.org",
|
||||
"description": "https://portaljs.com",
|
||||
"keywords": [
|
||||
"data portal",
|
||||
"data catalog",
|
||||
|
||||
@@ -11,7 +11,7 @@ export function Iframe({ data, style }: IframeProps) {
|
||||
return (
|
||||
<iframe
|
||||
src={url}
|
||||
style={style ?? { width: `100%`, height: `100%` }}
|
||||
style={style ?? { width: `100%`, height: `600px` }}
|
||||
></iframe>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ import loadData from '../lib/loadData';
|
||||
import { Data } from '../types/properties';
|
||||
|
||||
type AxisType = 'quantitative' | 'temporal';
|
||||
type TimeUnit = 'year' | undefined; // or ...
|
||||
type TimeUnit = 'year' | 'yearmonth' | undefined; // or ...
|
||||
|
||||
export type LineChartProps = {
|
||||
data: Omit<Data, 'csv'>;
|
||||
@@ -13,9 +13,10 @@ export type LineChartProps = {
|
||||
xAxis: string;
|
||||
xAxisType?: AxisType;
|
||||
xAxisTimeUnit?: TimeUnit;
|
||||
yAxis: string;
|
||||
yAxis: string | string[];
|
||||
yAxisType?: AxisType;
|
||||
fullWidth?: boolean;
|
||||
symbol?: string;
|
||||
};
|
||||
|
||||
export function LineChart({
|
||||
@@ -26,6 +27,7 @@ export function LineChart({
|
||||
xAxisTimeUnit = 'year', // TODO: defaults to undefined would probably work better... keeping it as it's for compatibility purposes
|
||||
yAxis,
|
||||
yAxisType = 'quantitative',
|
||||
symbol,
|
||||
}: LineChartProps) {
|
||||
const url = data.url;
|
||||
const values = data.values;
|
||||
@@ -33,6 +35,7 @@ export function LineChart({
|
||||
|
||||
// By default, assumes data is an Array...
|
||||
const [specData, setSpecData] = useState<any>({ name: 'table' });
|
||||
const isMultiYAxis = Array.isArray(yAxis);
|
||||
|
||||
const spec = {
|
||||
$schema: 'https://vega.github.io/schema/vega-lite/v5.json',
|
||||
@@ -46,6 +49,11 @@ export function LineChart({
|
||||
tooltip: true,
|
||||
},
|
||||
data: specData,
|
||||
...(isMultiYAxis
|
||||
? {
|
||||
transform: [{ fold: yAxis, as: ['key', 'value'] }],
|
||||
}
|
||||
: {}),
|
||||
selection: {
|
||||
grid: {
|
||||
type: 'interval',
|
||||
@@ -59,9 +67,25 @@ export function LineChart({
|
||||
type: xAxisType,
|
||||
},
|
||||
y: {
|
||||
field: yAxis,
|
||||
field: isMultiYAxis ? 'value' : yAxis,
|
||||
type: yAxisType,
|
||||
},
|
||||
...(symbol
|
||||
? {
|
||||
color: {
|
||||
field: symbol,
|
||||
type: 'nominal',
|
||||
},
|
||||
}
|
||||
: {}),
|
||||
...(isMultiYAxis
|
||||
? {
|
||||
color: {
|
||||
field: 'key',
|
||||
type: 'nominal',
|
||||
},
|
||||
}
|
||||
: {}),
|
||||
},
|
||||
} as any;
|
||||
|
||||
|
||||
@@ -12,8 +12,32 @@ import {
|
||||
|
||||
import 'leaflet/dist/leaflet.css';
|
||||
import * as L from 'leaflet';
|
||||
import providers from '../lib/tileLayerPresets';
|
||||
|
||||
type VariantKeys<T> = T extends { variants: infer V }
|
||||
? {
|
||||
[K in keyof V]: K extends string
|
||||
? `${K}` | `${K}.${VariantKeys<V[K]>}`
|
||||
: never;
|
||||
}[keyof V]
|
||||
: never;
|
||||
|
||||
type ProviderVariantKeys<T> = {
|
||||
[K in keyof T]: K extends string
|
||||
? `${K}` | `${K}.${VariantKeys<T[K]>}`
|
||||
: never;
|
||||
}[keyof T];
|
||||
|
||||
type TileLayerPreset = ProviderVariantKeys<typeof providers> | 'custom';
|
||||
|
||||
interface TileLayerSettings extends L.TileLayerOptions {
|
||||
url?: string;
|
||||
variant?: string | any;
|
||||
}
|
||||
|
||||
export type MapProps = {
|
||||
tileLayerName?: TileLayerPreset;
|
||||
tileLayerOptions?: TileLayerSettings | undefined;
|
||||
layers: {
|
||||
data: GeospatialData;
|
||||
name: string;
|
||||
@@ -36,7 +60,19 @@ export type MapProps = {
|
||||
};
|
||||
};
|
||||
|
||||
const tileLayerDefaultName = process?.env
|
||||
.NEXT_PUBLIC_MAP_TILE_LAYER_NAME as TileLayerPreset;
|
||||
|
||||
const tileLayerDefaultOptions = Object.keys(process?.env)
|
||||
.filter((key) => key.startsWith('NEXT_PUBLIC_MAP_TILE_LAYER_OPTION_'))
|
||||
.reduce((obj, key) => {
|
||||
obj[key.split('NEXT_PUBLIC_MAP_TILE_LAYER_OPTION_')[1]] = process.env[key];
|
||||
return obj;
|
||||
}, {}) as TileLayerSettings;
|
||||
|
||||
export function Map({
|
||||
tileLayerName = tileLayerDefaultName || 'OpenStreetMap',
|
||||
tileLayerOptions,
|
||||
layers = [
|
||||
{
|
||||
data: null,
|
||||
@@ -54,6 +90,95 @@ export function Map({
|
||||
const [isLoading, setIsLoading] = useState<boolean>(false);
|
||||
const [layersData, setLayersData] = useState<any>([]);
|
||||
|
||||
/*
|
||||
tileLayerDefaultOptions
|
||||
extract all environment variables thats starts with NEXT_PUBLIC_MAP_TILE_LAYER_OPTION_.
|
||||
the variables names are the same as the TileLayer object properties:
|
||||
- NEXT_PUBLIC_MAP_TILE_LAYER_OPTION_url:
|
||||
- NEXT_PUBLIC_MAP_TILE_LAYER_OPTION_attribution
|
||||
- NEXT_PUBLIC_MAP_TILE_LAYER_OPTION_accessToken
|
||||
- NEXT_PUBLIC_MAP_TILE_LAYER_OPTION_id
|
||||
- NEXT_PUBLIC_MAP_TILE_LAYER_OPTION_ext
|
||||
- NEXT_PUBLIC_MAP_TILE_LAYER_OPTION_bounds
|
||||
- NEXT_PUBLIC_MAP_TILE_LAYER_OPTION_maxZoom
|
||||
- NEXT_PUBLIC_MAP_TILE_LAYER_OPTION_minZoom
|
||||
see TileLayerOptions inteface
|
||||
*/
|
||||
|
||||
//tileLayerData prioritizes properties passed through component over those passed through .env variables
|
||||
tileLayerOptions = Object.assign(tileLayerDefaultOptions, tileLayerOptions);
|
||||
|
||||
let provider = {
|
||||
url: tileLayerOptions.url,
|
||||
options: tileLayerOptions,
|
||||
};
|
||||
|
||||
if (tileLayerName != 'custom') {
|
||||
var parts = tileLayerName.split('.');
|
||||
var providerName = parts[0];
|
||||
var variantName: string = parts[1];
|
||||
|
||||
//make sure to declare a variant if url depends on a variant: assume first
|
||||
if (providers[providerName].url?.includes('{variant}') && !variantName)
|
||||
variantName = Object.keys(providers[providerName].variants)[0];
|
||||
|
||||
if (!providers[providerName]) {
|
||||
throw 'No such provider (' + providerName + ')';
|
||||
}
|
||||
|
||||
provider = {
|
||||
url: providers[providerName].url,
|
||||
options: providers[providerName].options,
|
||||
};
|
||||
|
||||
// overwrite values in provider from variant.
|
||||
if (variantName && 'variants' in providers[providerName]) {
|
||||
if (!(variantName in providers[providerName].variants)) {
|
||||
throw 'No such variant of ' + providerName + ' (' + variantName + ')';
|
||||
}
|
||||
var variant = providers[providerName].variants[variantName];
|
||||
var variantOptions;
|
||||
if (typeof variant === 'string') {
|
||||
variantOptions = {
|
||||
variant: variant,
|
||||
};
|
||||
} else {
|
||||
variantOptions = variant.options;
|
||||
}
|
||||
provider = {
|
||||
url: variant.url || provider.url,
|
||||
options: L.Util.extend({}, provider.options, variantOptions),
|
||||
};
|
||||
}
|
||||
|
||||
var attributionReplacer = function (attr) {
|
||||
if (attr.indexOf('{attribution.') === -1) {
|
||||
return attr;
|
||||
}
|
||||
return attr.replace(
|
||||
/\{attribution.(\w*)\}/g,
|
||||
function (match: any, attributionName: string) {
|
||||
match;
|
||||
return attributionReplacer(
|
||||
providers[attributionName].options.attribution
|
||||
);
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
provider.options.attribution = attributionReplacer(
|
||||
provider.options.attribution
|
||||
);
|
||||
}
|
||||
|
||||
var tileLayerData = L.Util.extend(
|
||||
{
|
||||
url: provider.url,
|
||||
},
|
||||
provider.options,
|
||||
tileLayerOptions
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
const loadDataPromises = layers.map(async (layer) => {
|
||||
const url = layer.data.url;
|
||||
@@ -100,6 +225,7 @@ export function Map({
|
||||
</div>
|
||||
) : (
|
||||
<MapContainer
|
||||
key={layersData}
|
||||
center={[center.latitude, center.longitude]}
|
||||
zoom={zoom}
|
||||
scrollWheelZoom={false}
|
||||
@@ -144,10 +270,8 @@ export function Map({
|
||||
map.target.fitBounds(layerToZoomBounds);
|
||||
}}
|
||||
>
|
||||
<TileLayer
|
||||
attribution='© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
|
||||
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
|
||||
/>
|
||||
{tileLayerData.url && <TileLayer {...tileLayerData} />}
|
||||
|
||||
<LayersControl position="bottomright">
|
||||
{layers.map((layer) => {
|
||||
const data = layersData.find(
|
||||
|
||||
1211
packages/components/src/lib/tileLayerPresets.tsx
Normal file
1211
packages/components/src/lib/tileLayerPresets.tsx
Normal file
File diff suppressed because it is too large
Load Diff
@@ -28,6 +28,6 @@ export const Normal: Story = {
|
||||
data: {
|
||||
url: 'https://app.powerbi.com/view?r=eyJrIjoiYzBmN2Q2MzYtYzE3MS00ODkxLWE5OWMtZTQ2MjBlMDljMDk4IiwidCI6Ijk1M2IwZjgzLTFjZTYtNDVjMy04MmM5LTFkODQ3ZTM3MjMzOSIsImMiOjh9',
|
||||
},
|
||||
style: { width: `100%`, height: `100%` },
|
||||
style: { width: `100%`, height: `600px` },
|
||||
},
|
||||
};
|
||||
|
||||
@@ -4,6 +4,6 @@ import { Meta } from '@storybook/blocks';
|
||||
|
||||
# Welcome to the PortalJS components guide
|
||||
|
||||
**Official Website:** [portaljs.org](https://portaljs.org)
|
||||
**Docs:** [portaljs.org/docs](https://portaljs.org/docs)
|
||||
**Official Website:** [portaljs.com](https://portaljs.com)
|
||||
**Docs:** [portaljs.com/opensource](https://portaljs.com/opensource)
|
||||
**GitHub:** [github.com/datopian/portaljs](https://github.com/datopian/portaljs)
|
||||
@@ -30,11 +30,15 @@ Must be an object with one of the following properties: `url` or `values` \n\n \
|
||||
},
|
||||
yAxis: {
|
||||
description:
|
||||
'Name of the column header or object property that represents the Y-axis on the data.',
|
||||
'Name of the column headers or object properties that represent the Y-axis on the data.',
|
||||
},
|
||||
yAxisType: {
|
||||
description: 'Type of the Y-axis',
|
||||
},
|
||||
symbol: {
|
||||
description:
|
||||
'Name of the column header or object property that represents a series for multiple series.',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@@ -60,6 +64,51 @@ export const FromDataPoints: Story = {
|
||||
},
|
||||
};
|
||||
|
||||
export const MultiSeries: Story = {
|
||||
name: 'Line chart with multiple series (specifying symbol)',
|
||||
args: {
|
||||
data: {
|
||||
values: [
|
||||
{ year: '1850', value: -0.41765878, z: 'A' },
|
||||
{ year: '1851', value: -0.2333498, z: 'A' },
|
||||
{ year: '1852', value: -0.22939907, z: 'A' },
|
||||
{ year: '1853', value: -0.27035445, z: 'A' },
|
||||
{ year: '1854', value: -0.29163003, z: 'A' },
|
||||
{ year: '1850', value: -0.42993882, z: 'B' },
|
||||
{ year: '1851', value: -0.30365549, z: 'B' },
|
||||
{ year: '1852', value: -0.27905189, z: 'B' },
|
||||
{ year: '1853', value: -0.22939704, z: 'B' },
|
||||
{ year: '1854', value: -0.25688013, z: 'B' },
|
||||
{ year: '1850', value: -0.4757164, z: 'C' },
|
||||
{ year: '1851', value: -0.41971018, z: 'C' },
|
||||
{ year: '1852', value: -0.40724799, z: 'C' },
|
||||
{ year: '1853', value: -0.45049156, z: 'C' },
|
||||
{ year: '1854', value: -0.41896583, z: 'C' },
|
||||
],
|
||||
},
|
||||
xAxis: 'year',
|
||||
yAxis: 'value',
|
||||
symbol: 'z',
|
||||
},
|
||||
};
|
||||
|
||||
export const MultiColumns: Story = {
|
||||
name: 'Line chart with multiple series (with multiple columns)',
|
||||
args: {
|
||||
data: {
|
||||
values: [
|
||||
{ year: '1850', A: -0.41765878, B: -0.42993882, C: -0.4757164 },
|
||||
{ year: '1851', A: -0.2333498, B: -0.30365549, C: -0.41971018 },
|
||||
{ year: '1852', A: -0.22939907, B: -0.27905189, C: -0.40724799 },
|
||||
{ year: '1853', A: -0.27035445, B: -0.22939704, C: -0.45049156 },
|
||||
{ year: '1854', A: -0.29163003, B: -0.25688013, C: -0.41896583 },
|
||||
],
|
||||
},
|
||||
xAxis: 'year',
|
||||
yAxis: ['A', 'B', 'C'],
|
||||
},
|
||||
};
|
||||
|
||||
export const FromURL: Story = {
|
||||
name: 'Line chart from URL',
|
||||
args: {
|
||||
|
||||
@@ -43,6 +43,10 @@ type Story = StoryObj<MapProps>;
|
||||
export const GeoJSONPolygons: Story = {
|
||||
name: 'GeoJSON polygons map',
|
||||
args: {
|
||||
tileLayerName:'MapBox',
|
||||
tileLayerOptions:{
|
||||
accessToken : 'pk.eyJ1Ijoid2lsbHktcGFsbWFyZWpvIiwiYSI6ImNqNzk5NmRpNDFzb2cyeG9sc2luMHNjajUifQ.lkoVRFSI8hOLH4uJeOzwXw',
|
||||
},
|
||||
layers: [
|
||||
{
|
||||
data: {
|
||||
|
||||
@@ -53,7 +53,7 @@ export const Nav: React.FC<Props> = ({
|
||||
<nav className="flex justify-between">
|
||||
{/* Mobile navigation */}
|
||||
<div className="mr-2 sm:mr-4 flex lg:hidden">
|
||||
<NavMobile links={links}>{children}</NavMobile>
|
||||
<NavMobile {...{title, links, social, search, defaultTheme, themeToggleIcon}}>{children}</NavMobile>
|
||||
</div>
|
||||
{/* Non-mobile navigation */}
|
||||
<div className="flex flex-none items-center">
|
||||
|
||||
@@ -4,20 +4,16 @@ import { useRouter } from "next/router.js";
|
||||
import { useEffect, useState } from "react";
|
||||
import { SearchContext, SearchField } from "../Search";
|
||||
import { MenuIcon, CloseIcon } from "../Icons";
|
||||
import { NavLink, SearchProviderConfig } from "../types";
|
||||
import type { NavConfig, ThemeConfig } from "./Nav";
|
||||
|
||||
interface Props extends React.PropsWithChildren {
|
||||
author?: string;
|
||||
links?: Array<NavLink>;
|
||||
search?: SearchProviderConfig;
|
||||
}
|
||||
interface Props extends NavConfig, ThemeConfig, React.PropsWithChildren {}
|
||||
|
||||
// TODO why mobile navigation only accepts author and regular nav accepts different things like title, logo, version
|
||||
// TODO: Search doesn't appear
|
||||
export const NavMobile: React.FC<Props> = ({
|
||||
children,
|
||||
title,
|
||||
links,
|
||||
search,
|
||||
author,
|
||||
}) => {
|
||||
const router = useRouter();
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
@@ -77,8 +73,8 @@ export const NavMobile: React.FC<Props> = ({
|
||||
legacyBehavior
|
||||
>
|
||||
{/* <Logomark className="h-9 w-9" /> */}
|
||||
<div className="font-extrabold text-primary dark:text-primary-dark text-2xl ml-6">
|
||||
{author}
|
||||
<div className="font-extrabold text-primary dark:text-primary-dark text-lg ml-6">
|
||||
{title}
|
||||
</div>
|
||||
</Link>
|
||||
</div>
|
||||
@@ -106,9 +102,7 @@ export const NavMobile: React.FC<Props> = ({
|
||||
))}
|
||||
</ul>
|
||||
)}
|
||||
{/* <div className="pt-6 border border-t-2">
|
||||
{children}
|
||||
</div> */}
|
||||
<div className="pt-6">{children}</div>
|
||||
</Dialog.Panel>
|
||||
</Dialog>
|
||||
</>
|
||||
|
||||
@@ -38,6 +38,5 @@ const defaultPathToPermalinkFunc = (
|
||||
.replace(markdownFolder, "") // make the permalink relative to the markdown folder
|
||||
.replace(/\.(mdx|md)/, "")
|
||||
.replace(/\\/g, "/") // replace windows backslash with forward slash
|
||||
.replace(/\/index$/, ""); // remove index from the end of the permalink
|
||||
return permalink.length > 0 ? permalink : "/"; // for home page
|
||||
};
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
import * as path from "path";
|
||||
// import * as url from "url";
|
||||
import { getPermalinks } from "../src/utils";
|
||||
|
||||
// const __dirname = url.fileURLToPath(new URL(".", import.meta.url));
|
||||
// const markdownFolder = path.join(__dirname, "/fixtures/content");
|
||||
const markdownFolder = path.join(
|
||||
".",
|
||||
"test/fixtures/content"
|
||||
@@ -12,12 +9,12 @@ const markdownFolder = path.join(
|
||||
describe("getPermalinks", () => {
|
||||
test("should return an array of permalinks", () => {
|
||||
const expectedPermalinks = [
|
||||
"/", // /index.md
|
||||
"/README",
|
||||
"/abc",
|
||||
"/blog/first-post",
|
||||
"/blog/Second Post",
|
||||
"/blog/third-post",
|
||||
"/blog", // /blog/index.md
|
||||
"/blog/README",
|
||||
"/blog/tutorials/first-tutorial",
|
||||
"/assets/Pasted Image 123.png",
|
||||
];
|
||||
@@ -28,35 +25,4 @@ describe("getPermalinks", () => {
|
||||
expect(expectedPermalinks).toContain(permalink);
|
||||
});
|
||||
});
|
||||
|
||||
test("should return an array of permalinks with custom path -> permalink converter function", () => {
|
||||
const expectedPermalinks = [
|
||||
"/", // /index.md
|
||||
"/abc",
|
||||
"/blog/first-post",
|
||||
"/blog/second-post",
|
||||
"/blog/third-post",
|
||||
"/blog", // /blog/index.md
|
||||
"/blog/tutorials/first-tutorial",
|
||||
"/assets/pasted-image-123.png",
|
||||
];
|
||||
|
||||
const func = (filePath: string, markdownFolder: string) => {
|
||||
const permalink = filePath
|
||||
.replace(markdownFolder, "") // make the permalink relative to the markdown folder
|
||||
.replace(/\.(mdx|md)/, "")
|
||||
.replace(/\\/g, "/") // replace windows backslash with forward slash
|
||||
.replace(/\/index$/, "") // remove index from the end of the permalink
|
||||
.replace(/ /g, "-") // replace spaces with hyphens
|
||||
.toLowerCase(); // convert to lowercase
|
||||
|
||||
return permalink.length > 0 ? permalink : "/"; // for home page
|
||||
};
|
||||
|
||||
const permalinks = getPermalinks(markdownFolder, [/\.DS_Store/], func);
|
||||
expect(permalinks).toHaveLength(expectedPermalinks.length);
|
||||
permalinks.forEach((permalink) => {
|
||||
expect(expectedPermalinks).toContain(permalink);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -286,56 +286,6 @@ describe("micromark-extension-wiki-link", () => {
|
||||
});
|
||||
});
|
||||
|
||||
test("parses wiki links to index files", () => {
|
||||
const serialized = micromark("[[/some/folder/index]]", "ascii", {
|
||||
extensions: [syntax()],
|
||||
htmlExtensions: [html() as any], // TODO type fix
|
||||
});
|
||||
expect(serialized).toBe(
|
||||
'<p><a href="/some/folder" class="internal new">/some/folder/index</a></p>'
|
||||
);
|
||||
});
|
||||
|
||||
describe("other", () => {
|
||||
test("parses a wiki link to some index page in a folder with no matching permalink", () => {
|
||||
const serialized = micromark("[[/some/folder/index]]", "ascii", {
|
||||
extensions: [syntax()],
|
||||
htmlExtensions: [html() as any], // TODO type fix
|
||||
});
|
||||
expect(serialized).toBe(
|
||||
'<p><a href="/some/folder" class="internal new">/some/folder/index</a></p>'
|
||||
);
|
||||
});
|
||||
|
||||
test("parses a wiki link to some index page in a folder with a matching permalink", () => {
|
||||
const serialized = micromark("[[/some/folder/index]]", "ascii", {
|
||||
extensions: [syntax()],
|
||||
htmlExtensions: [html({ permalinks: ["/some/folder"] }) as any], // TODO type fix
|
||||
});
|
||||
expect(serialized).toBe(
|
||||
'<p><a href="/some/folder" class="internal">/some/folder/index</a></p>'
|
||||
);
|
||||
});
|
||||
|
||||
test("parses a wiki link to home index page with no matching permalink", () => {
|
||||
const serialized = micromark("[[/index]]", "ascii", {
|
||||
extensions: [syntax()],
|
||||
htmlExtensions: [html() as any], // TODO type fix
|
||||
});
|
||||
expect(serialized).toBe(
|
||||
'<p><a href="/" class="internal new">/index</a></p>'
|
||||
);
|
||||
});
|
||||
|
||||
test("parses a wiki link to home index page with a matching permalink", () => {
|
||||
const serialized = micromark("[[/index]]", "ascii", {
|
||||
extensions: [syntax()],
|
||||
htmlExtensions: [html({ permalinks: ["/"] }) as any], // TODO type fix
|
||||
});
|
||||
expect(serialized).toBe('<p><a href="/" class="internal">/index</a></p>');
|
||||
});
|
||||
});
|
||||
|
||||
describe("transclusions", () => {
|
||||
test("parsers a transclusion as a regular wiki link", () => {
|
||||
const serialized = micromark("![[Some Page]]", "ascii", {
|
||||
|
||||
@@ -485,109 +485,6 @@ describe("remark-wiki-link", () => {
|
||||
});
|
||||
});
|
||||
|
||||
test("parses wiki links to index files", () => {
|
||||
const processor = unified().use(markdown).use(wikiLinkPlugin);
|
||||
|
||||
let ast = processor.parse("[[/some/folder/index]]");
|
||||
ast = processor.runSync(ast);
|
||||
|
||||
expect(select("wikiLink", ast)).not.toEqual(null);
|
||||
|
||||
visit(ast, "wikiLink", (node: Node) => {
|
||||
expect(node.data?.exists).toEqual(false);
|
||||
expect(node.data?.permalink).toEqual("/some/folder");
|
||||
expect(node.data?.alias).toEqual(null);
|
||||
expect(node.data?.hName).toEqual("a");
|
||||
expect((node.data?.hProperties as any).className).toEqual("internal new");
|
||||
expect((node.data?.hProperties as any).href).toEqual("/some/folder");
|
||||
expect((node.data?.hChildren as any)[0].value).toEqual(
|
||||
"/some/folder/index"
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("other", () => {
|
||||
test("parses a wiki link to some index page in a folder with no matching permalink", () => {
|
||||
const processor = unified().use(markdown).use(wikiLinkPlugin);
|
||||
|
||||
let ast = processor.parse("[[/some/folder/index]]");
|
||||
ast = processor.runSync(ast);
|
||||
|
||||
visit(ast, "wikiLink", (node: Node) => {
|
||||
expect(node.data?.exists).toEqual(false);
|
||||
expect(node.data?.permalink).toEqual("/some/folder");
|
||||
expect(node.data?.alias).toEqual(null);
|
||||
expect(node.data?.hName).toEqual("a");
|
||||
expect((node.data?.hProperties as any).className).toEqual(
|
||||
"internal new"
|
||||
);
|
||||
expect((node.data?.hProperties as any).href).toEqual("/some/folder");
|
||||
expect((node.data?.hChildren as any)[0].value).toEqual(
|
||||
"/some/folder/index"
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
test("parses a wiki link to some index page in a folder with a matching permalink", () => {
|
||||
const processor = unified()
|
||||
.use(markdown)
|
||||
.use(wikiLinkPlugin, { permalinks: ["/some/folder"] });
|
||||
|
||||
let ast = processor.parse("[[/some/folder/index]]");
|
||||
ast = processor.runSync(ast);
|
||||
|
||||
visit(ast, "wikiLink", (node: Node) => {
|
||||
expect(node.data?.exists).toEqual(true);
|
||||
expect(node.data?.permalink).toEqual("/some/folder");
|
||||
expect(node.data?.alias).toEqual(null);
|
||||
expect(node.data?.hName).toEqual("a");
|
||||
expect((node.data?.hProperties as any).className).toEqual("internal");
|
||||
expect((node.data?.hProperties as any).href).toEqual("/some/folder");
|
||||
expect((node.data?.hChildren as any)[0].value).toEqual(
|
||||
"/some/folder/index"
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
test("parses a wiki link to home index page with no matching permalink", () => {
|
||||
const processor = unified().use(markdown).use(wikiLinkPlugin);
|
||||
|
||||
let ast = processor.parse("[[/index]]");
|
||||
ast = processor.runSync(ast);
|
||||
|
||||
visit(ast, "wikiLink", (node: Node) => {
|
||||
expect(node.data?.exists).toEqual(false);
|
||||
expect(node.data?.permalink).toEqual("/");
|
||||
expect(node.data?.alias).toEqual(null);
|
||||
expect(node.data?.hName).toEqual("a");
|
||||
expect((node.data?.hProperties as any).className).toEqual(
|
||||
"internal new"
|
||||
);
|
||||
expect((node.data?.hProperties as any).href).toEqual("/");
|
||||
expect((node.data?.hChildren as any)[0].value).toEqual("/index");
|
||||
});
|
||||
});
|
||||
|
||||
test("parses a wiki link to home index page with a matching permalink", () => {
|
||||
const processor = unified()
|
||||
.use(markdown)
|
||||
.use(wikiLinkPlugin, { permalinks: ["/"] });
|
||||
|
||||
let ast = processor.parse("[[/index]]");
|
||||
ast = processor.runSync(ast);
|
||||
|
||||
visit(ast, "wikiLink", (node: Node) => {
|
||||
expect(node.data?.exists).toEqual(true);
|
||||
expect(node.data?.permalink).toEqual("/");
|
||||
expect(node.data?.alias).toEqual(null);
|
||||
expect(node.data?.hName).toEqual("a");
|
||||
expect((node.data?.hProperties as any).className).toEqual("internal");
|
||||
expect((node.data?.hProperties as any).href).toEqual("/");
|
||||
expect((node.data?.hChildren as any)[0].value).toEqual("/index");
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("transclusions", () => {
|
||||
test("replaces a transclusion with a regular wiki link", () => {
|
||||
const processor = unified().use(markdown).use(wikiLinkPlugin);
|
||||
|
||||
@@ -12,7 +12,7 @@ export default function JSONLD({
|
||||
return <></>;
|
||||
}
|
||||
|
||||
const baseUrl = process.env.NEXT_PUBLIC_SITE_URL || 'https://portaljs.org';
|
||||
const baseUrl = process.env.NEXT_PUBLIC_SITE_URL || 'https://portaljs.com';
|
||||
const pageUrl = `${baseUrl}/${meta.urlPath}`;
|
||||
|
||||
const imageMatches = source.match(
|
||||
|
||||
@@ -81,7 +81,6 @@ export default function Layout({
|
||||
}
|
||||
return section.children.findIndex(isActive) > -1;
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
{title && <NextSeo title={title} description={description} />}
|
||||
|
||||
@@ -22,11 +22,41 @@ const items = [
|
||||
sourceUrl: 'https://github.com/FCSCOpendata/frontend',
|
||||
},
|
||||
{
|
||||
title: 'Datahub Open Data',
|
||||
href: 'https://opendata.datahub.io/',
|
||||
image: '/images/showcases/datahub.webp',
|
||||
description: 'Demo Data Portal by DataHub',
|
||||
title: 'Frictionless Data',
|
||||
href: 'https://datahub.io/core/co2-ppm',
|
||||
repository: 'https://github.com/datopian/datahub/tree/main/examples/dataset-frictionless',
|
||||
image: '/images/showcases/frictionless-capture.png',
|
||||
description: 'Progressive open-source framework for building data infrastructure - data management, data integration, data flows, etc. It includes various data standards and provides software to work with data.',
|
||||
},
|
||||
{
|
||||
title: "OpenSpending",
|
||||
image: "/images/showcases/openspending.png",
|
||||
href: "https://www.openspending.org",
|
||||
repository: 'https://github.com/datopian/datahub/tree/main/examples/openspending',
|
||||
description: "OpenSpending is a free, open and global platform to search, visualise and analyse fiscal data in the public sphere."
|
||||
},
|
||||
{
|
||||
title: "FiveThirtyEight",
|
||||
image: "/images/showcases/fivethirtyeight.png",
|
||||
href: "https://fivethirtyeight.portaljs.org/",
|
||||
repository: 'https://github.com/datopian/datahub/tree/main/examples/fivethirtyeight',
|
||||
description: "This is a replica of data.fivethirtyeight.com using PortalJS."
|
||||
},
|
||||
{
|
||||
title: "Github Datasets",
|
||||
image: "/images/showcases/github-datasets.png",
|
||||
href: "https://example.portaljs.org/",
|
||||
repository: 'https://github.com/datopian/datahub/tree/main/examples/github-backed-catalog',
|
||||
description: "A simple data catalog that get its data from a list of GitHub repos that serve as datasets."
|
||||
},
|
||||
{
|
||||
title: "Hatespeech Data",
|
||||
image: "/images/showcases/turing.png",
|
||||
href: "https://hatespeechdata.com/",
|
||||
repository: 'https://github.com/datopian/datahub/tree/main/examples/turing',
|
||||
description: "Datasets annotated for hate speech, online abuse, and offensive language which are useful for training a natural language processing system to detect this online abuse."
|
||||
},
|
||||
|
||||
];
|
||||
|
||||
export default function Showcases() {
|
||||
|
||||
@@ -1,10 +1,6 @@
|
||||
export default function ShowcasesItem({ item }) {
|
||||
return (
|
||||
<a
|
||||
className="rounded overflow-hidden group relative border-1 shadow-lg"
|
||||
target="_blank"
|
||||
href={item.href}
|
||||
>
|
||||
<div className="rounded overflow-hidden group relative border-1 shadow-lg">
|
||||
<div
|
||||
className="bg-cover bg-no-repeat bg-top aspect-video w-full group-hover:blur-sm group-hover:scale-105 transition-all duration-200"
|
||||
style={{ backgroundImage: `url(${item.image})` }}
|
||||
@@ -16,9 +12,48 @@ export default function ShowcasesItem({ item }) {
|
||||
<div className="text-center text-primary-dark">
|
||||
<span className="text-xl font-semibold">{item.title}</span>
|
||||
<p className="text-base font-medium">{item.description}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex justify-center mt-2 gap-2 ">
|
||||
{item.href && (
|
||||
<a
|
||||
target="_blank"
|
||||
className=" text-white w-8 h-8 p-1 bg-primary rounded-full hover:scale-110 transition cursor-pointer z-50"
|
||||
rel="noreferrer"
|
||||
href={item.href}
|
||||
>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 420 420"
|
||||
stroke="white"
|
||||
fill="none"
|
||||
>
|
||||
<path stroke-width="26" d="M209,15a195,195 0 1,0 2,0z" />
|
||||
<path
|
||||
stroke-width="18"
|
||||
d="m210,15v390m195-195H15M59,90a260,260 0 0,0 302,0 m0,240 a260,260 0 0,0-302,0M195,20a250,250 0 0,0 0,382 m30,0 a250,250 0 0,0 0-382"
|
||||
/>
|
||||
</svg>
|
||||
</a>
|
||||
)}
|
||||
{item.repository && (
|
||||
<a
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
className="w-8 h-8 bg-black rounded-full p-1 hover:scale-110 transition cursor-pointer z-50"
|
||||
href={item.repository}
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
viewBox="0 0 16 16"
|
||||
fill="currentColor"
|
||||
>
|
||||
<path d="M8 0C3.58 0 0 3.58 0 8C0 11.54 2.29 14.53 5.47 15.59C5.87 15.66 6.02 15.42 6.02 15.21C6.02 15.02 6.01 14.39 6.01 13.72C4 14.09 3.48 13.23 3.32 12.78C3.23 12.55 2.84 11.84 2.5 11.65C2.22 11.5 1.82 11.13 2.49 11.12C3.12 11.11 3.57 11.7 3.72 11.94C4.44 13.15 5.59 12.81 6.05 12.6C6.12 12.08 6.33 11.73 6.56 11.53C4.78 11.33 2.92 10.64 2.92 7.58C2.92 6.71 3.23 5.99 3.74 5.43C3.66 5.23 3.38 4.41 3.82 3.31C3.82 3.31 4.49 3.1 6.02 4.13C6.66 3.95 7.34 3.86 8.02 3.86C8.7 3.86 9.38 3.95 10.02 4.13C11.55 3.09 12.22 3.31 12.22 3.31C12.66 4.41 12.38 5.23 12.3 5.43C12.81 5.99 13.12 6.7 13.12 7.58C13.12 10.65 11.25 11.33 9.47 11.53C9.76 11.78 10.01 12.26 10.01 13.01C10.01 14.08 10 14.94 10 15.21C10 15.42 10.15 15.67 10.55 15.59C13.71 14.53 16 11.53 16 8C16 3.58 12.42 0 8 0Z" />
|
||||
</svg>
|
||||
</a>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -7,17 +7,17 @@ filetype: 'blog'
|
||||
|
||||
This post walks you though adding maps and geospatial visualizations to PortalJS.
|
||||
|
||||
Are you interested in building rich and interactive data portals? Do you find value in the power and flexibility of JavaScript, Nextjs, and React? If so, [PortalJS](https://portaljs.org/) is for you. It's a state-of-the-art framework leveraging these technologies to help you build rich data portals.
|
||||
Are you interested in building rich and interactive data portals? Do you find value in the power and flexibility of JavaScript, Nextjs, and React? If so, [PortalJS](https://portaljs.com/) is for you. It's a state-of-the-art framework leveraging these technologies to help you build rich data portals.
|
||||
|
||||
Effective data visualization lies in the use of various data components. Within [PortalJS](https://portaljs.org/), we take data visualization a step further. It's not just about displaying data - it's about telling a story through combining a variety of data components.
|
||||
Effective data visualization lies in the use of various data components. Within [PortalJS](https://portaljs.com/), we take data visualization a step further. It's not just about displaying data - it's about telling a story through combining a variety of data components.
|
||||
|
||||
In this post we will share our latest enhancement to PortalJS: maps, a powerful tool for visualizing geospatial data. In this post, we will to take you on a tour of our experiments and progress in enhancing map functionalities on PortalJS. The journey is still in its early stages, with new facets being unveiled and refined as we perfect our API.
|
||||
|
||||
## Exploring Map Formats
|
||||
|
||||
Maps play a crucial role in geospatial data visualization. Several formats exist for storing and sharing this type of data, with GeoJSON, KML, and shapefiles being among the most popular. As a prominent figure in the field of open-source data portal platforms, [PortalJS](https://portaljs.org/) strives to support as many map formats as possible.
|
||||
Maps play a crucial role in geospatial data visualization. Several formats exist for storing and sharing this type of data, with GeoJSON, KML, and shapefiles being among the most popular. As a prominent figure in the field of open-source data portal platforms, [PortalJS](https://portaljs.com/) strives to support as many map formats as possible.
|
||||
|
||||
Taking inspiration from the ckanext-geoview extension, we currently support KML and GeoJSON formats in [PortalJS](https://portaljs.org/). This remarkable extension is a plugin for CKAN, the world’s leading open source data management system, that enables users to visualize geospatial data in diverse formats on an interactive map. Apart from KML and GeoJSON formats support, our roadmap entails extending compatibility to encompass all other formats supported by ckanext-geoview. Rest assured, we are committed to empowering users with a wide array of map format options in the future.
|
||||
Taking inspiration from the ckanext-geoview extension, we currently support KML and GeoJSON formats in [PortalJS](https://portaljs.com/). This remarkable extension is a plugin for CKAN, the world’s leading open source data management system, that enables users to visualize geospatial data in diverse formats on an interactive map. Apart from KML and GeoJSON formats support, our roadmap entails extending compatibility to encompass all other formats supported by ckanext-geoview. Rest assured, we are committed to empowering users with a wide array of map format options in the future.
|
||||
|
||||
So, what makes these formats special?
|
||||
|
||||
@@ -27,7 +27,7 @@ So, what makes these formats special?
|
||||
|
||||
## Unveiling the Power of Leaflet and OpenLayers
|
||||
|
||||
To display maps in [PortalJS](https://portaljs.org/), we utilize two powerful JavaScript libraries for creating interactive maps based on different layers: Leaflet and OpenLayers. Each offers distinct advantages (and disadvantages), inspiring us to integrate both and give users the flexibility to choose.
|
||||
To display maps in [PortalJS](https://portaljs.com/), we utilize two powerful JavaScript libraries for creating interactive maps based on different layers: Leaflet and OpenLayers. Each offers distinct advantages (and disadvantages), inspiring us to integrate both and give users the flexibility to choose.
|
||||
|
||||
Leaflet is the leading open-source JavaScript library known for its mobile-friendly, interactive maps. With its compact size (just 42 KB of JS), it provides all the map features most developers need. Leaflet is designed with simplicity, performance and usability in mind. It works efficiently across all major desktop and mobile platforms.
|
||||
|
||||
@@ -59,8 +59,8 @@ Users can also choose a region of focus, which will depend on the data, by setti
|
||||
|
||||
Through our ongoing enhancements to the [PortalJS library](https://storybook.portaljs.org/), we aim to empower users to create engaging and informative data portals featuring diverse map formats and data components.
|
||||
|
||||
Why not give [PortalJS](https://portaljs.org/) a try today and discover the possibilities for your own data portals? To get started, check out our comprehensive documentation here: [PortalJS Documentation](https://portaljs.org/docs).
|
||||
Why not give [PortalJS](https://portaljs.com/) a try today and discover the possibilities for your own data portals? To get started, check out our comprehensive documentation here: [PortalJS Documentation](https://portaljs.com/opensource).
|
||||
|
||||
Have questions or comments about using [PortalJS](https://portaljs.org/) for your data portals? Feel free to share your thoughts on our [Discord channel](https://discord.com/invite/EeyfGrGu4U). We're here to help you make the most of your data.
|
||||
Have questions or comments about using [PortalJS](https://portaljs.com/) for your data portals? Feel free to share your thoughts on our [Discord channel](https://discord.com/invite/EeyfGrGu4U). We're here to help you make the most of your data.
|
||||
|
||||
Stay tuned for more exciting developments as we continue to enhance [PortalJS](https://portaljs.org/)!
|
||||
Stay tuned for more exciting developments as we continue to enhance [PortalJS](https://portaljs.com/)!
|
||||
|
||||
@@ -4,7 +4,7 @@ authors: ['Luccas Mateus']
|
||||
date: 2021-04-20
|
||||
---
|
||||
|
||||
We have created a full data portal demo using PortalJS all backed by a CKAN instance storing data and metadata, you can see below a screenshot of the homepage and of an individual dataset page.
|
||||
We have created a full data portal demo using DataHub PortalJS all backed by a CKAN instance storing data and metadata, you can see below a screenshot of the homepage and of an individual dataset page.
|
||||
|
||||

|
||||

|
||||
@@ -14,7 +14,7 @@ We have created a full data portal demo using PortalJS all backed by a CKAN inst
|
||||
To create a Portal app, run the following command in your terminal:
|
||||
|
||||
```console
|
||||
npx create-next-app -e https://github.com/datopian/portaljs/tree/main/examples/ckan
|
||||
npx create-next-app -e https://github.com/datopian/datahub/tree/main/examples/ckan
|
||||
```
|
||||
|
||||
> NB: Under the hood, this uses the tool called create-next-app, which bootstraps an app for you based on our CKAN example.
|
||||
|
||||
@@ -30,12 +30,12 @@ https://github.com/datopian/markdowndb
|
||||
|
||||
## 📚 The Guide
|
||||
|
||||
https://portaljs.org/guide
|
||||
https://portaljs.com/opensource
|
||||
|
||||
I’ve sketched overviews for two upcoming tutorials:
|
||||
|
||||
1. **Collaborating with others on your website**: Learn how to make your website projects a team effort. [See it here](https://portaljs.org/guide#tutorial-3-collaborating-with-others-on-your-website-project)
|
||||
2. **Customising your website and previewing your changes locally**: Customize and preview your site changes locally, without headaches. [See it here](https://portaljs.org/guide#tutorial-4-customising-your-website-locally-and-previewing-your-changes-locally)
|
||||
1. **Collaborating with others on your website**: Learn how to make your website projects a team effort. [See it here](https://portaljs.com/guide#tutorial-3-collaborating-with-others-on-your-website-project)
|
||||
2. **Customising your website and previewing your changes locally**: Customize and preview your site changes locally, without headaches. [See it here](https://portaljs.com/guide#tutorial-4-customising-your-website-locally-and-previewing-your-changes-locally)
|
||||
|
||||
## 🌐 LifeItself.org
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ In our last article, we explored [the Open Spending revamp](https://www.datopian
|
||||
|
||||
## The Core: PortalJS
|
||||
|
||||
At the core of the revamped OpenSpending website is [PortalJS](https://portaljs.org), a JavaScript library that's a game-changer in building powerful data portals with data visualizations. What makes it so special? Well, it's packed with reusable React components that make our lives - and yours - a whole lot easier. Take, for example, our sleek CSV previews; they're brought to life by PortalJS' [FlatUI Component](https://storybook.portaljs.org/?path=/story/components-flatuitable--from-url). It helps transform raw numbers into visuals that you can easily understand and use. Curious to know more? Check out the [official PortalJS website](https://portaljs.org).
|
||||
At the core of the revamped OpenSpending website is [PortalJS](https://portaljs.com), a JavaScript library that's a game-changer in building powerful data portals with data visualizations. What makes it so special? Well, it's packed with reusable React components that make our lives - and yours - a whole lot easier. Take, for example, our sleek CSV previews; they're brought to life by PortalJS' [FlatUI Component](https://storybook.portaljs.org/?path=/story/components-flatuitable--from-url). It helps transform raw numbers into visuals that you can easily understand and use. Curious to know more? Check out the [official PortalJS website](https://portaljs.com).
|
||||
|
||||

|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
const config = {
|
||||
title: 'PortalJS - The JavaScript framework for data portals.',
|
||||
title: 'DataHub PortalJS - The JavaScript framework for data portals.',
|
||||
description:
|
||||
'PortalJS is a JavaScript framework for rapidly building rich data portal frontends using a modern frontend approach.',
|
||||
'DataHub PortalJS is a JavaScript framework for rapidly building rich data portal frontends using a modern frontend approach.',
|
||||
theme: {
|
||||
default: 'dark',
|
||||
toggleIcon: '/images/theme-button.svg',
|
||||
@@ -11,19 +11,18 @@ const config = {
|
||||
authorUrl: 'https://datopian.com/',
|
||||
navbarTitle: {
|
||||
// logo: "/images/logo.svg",
|
||||
text: '🌀 PortalJS',
|
||||
text: '🌀 DataHub PortalJS',
|
||||
// version: "Alpha",
|
||||
},
|
||||
navLinks: [
|
||||
{ name: 'Docs', href: '/docs' },
|
||||
// { name: "Components", href: "/docs/components" },
|
||||
{ name: 'Blog', href: '/blog' },
|
||||
{ name: 'Showcases', href: '/#showcases' },
|
||||
{ name: 'Howtos', href: '/howtos' },
|
||||
{ name: 'Guide', href: '/guide' },
|
||||
{
|
||||
name: 'Examples',
|
||||
href: '/examples/'
|
||||
name: 'Showcases',
|
||||
href: '/showcases/'
|
||||
},
|
||||
{
|
||||
name: 'Components',
|
||||
@@ -68,8 +67,8 @@ const config = {
|
||||
cardType: 'summary_large_image',
|
||||
},
|
||||
},
|
||||
github: 'https://github.com/datopian/portaljs',
|
||||
discord: 'https://discord.gg/xfFDMPU9dC',
|
||||
github: 'https://github.com/datopian/datahub',
|
||||
discord: 'https://discord.gg/KrRzMKU',
|
||||
tableOfContents: true,
|
||||
analytics: 'G-96GWZHMH57',
|
||||
// editLinkShow: true,
|
||||
|
||||
@@ -26,7 +26,7 @@ Below are some screenshots:
|
||||
- Create a new app with `create-next-app`:
|
||||
|
||||
```
|
||||
npx create-next-app <app-name> --example https://github.com/datopian/portaljs/tree/main/examples/ckan-example
|
||||
npx create-next-app <app-name> --example https://github.com/datopian/datahub/tree/main/examples/ckan-example
|
||||
cd <app-name>
|
||||
```
|
||||
|
||||
@@ -49,7 +49,7 @@ If yo go to any one of those pages by clicking on `More info` you will see somet
|
||||
|
||||
## Deployment
|
||||
|
||||
[](https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2Fdatopian%2Fportaljs%2Ftree%2Fmain%2Fexamples%2Fckan-example&env=DMS&envDescription=URL%20For%20the%20CKAN%20Backend%20Ex%3A%20https%3A%2F%2Fdemo.dev.datopian.com)
|
||||
[](https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2Fdatopian%2Fdatahub%2Ftree%2Fmain%2Fexamples%2Fckan-example&env=DMS&envDescription=URL%20For%20the%20CKAN%20Backend%20Ex%3A%20https%3A%2F%2Fdemo.dev.datopian.com)
|
||||
|
||||
By clicking on this button, you will be redirected to a page which will allow you to clone the content into your own github/gitlab/bitbucket account and automatically deploy everything.
|
||||
|
||||
@@ -70,6 +70,6 @@ npm run start
|
||||
|
||||
## Links
|
||||
|
||||
- [Repo](https://github.com/datopian/portaljs/tree/main/examples/ckan-example)
|
||||
- [Repo](https://github.com/datopian/datahub/tree/main/examples/ckan-example)
|
||||
- [Live Demo](https://ckan-example.portaljs.org)
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ To get a feel of the project, check out the demo at [live deployment](https://ck
|
||||
Navigate to the directory in which you want to create the project folder and run the following command:
|
||||
|
||||
```
|
||||
npx create-next-app <app-name> --example https://github.com/datopian/portaljs/tree/main/examples/ckan
|
||||
npx create-next-app <app-name> --example https://github.com/datopian/datahub/tree/main/examples/ckan
|
||||
cd <app-name>
|
||||
```
|
||||
|
||||
@@ -56,7 +56,7 @@ If you navigate to any of the dataset pages by clicking on the dataset title you
|
||||
|
||||
## Deployment
|
||||
|
||||
[](https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2Fdatopian%2Fportaljs%2Ftree%2Fmain%2Fexamples%2Fckan&env=DMS&envDescription=URL%20For%20the%20CKAN%20Backend%20Ex%3A%20https%3A%2F%2Fdemo.dev.datopian.com)
|
||||
[](https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2Fdatopian%2Fdatahub%2Ftree%2Fmain%2Fexamples%2Fckan&env=DMS&envDescription=URL%20For%20the%20CKAN%20Backend%20Ex%3A%20https%3A%2F%2Fdemo.dev.datopian.com)
|
||||
|
||||
By clicking on this button, you will be redirected to a page which allows you to clone the base project into your own GitHub/GitLab/BitBucket account and automatically deploy it.
|
||||
|
||||
@@ -158,6 +158,6 @@ Thanks to TypeScript, you can get a list of all the API methods in `@portaljs/ck
|
||||
|
||||
## Links
|
||||
|
||||
- [Repo](https://github.com/datopian/portaljs/tree/main/examples/ckan)
|
||||
- [Repo](https://github.com/datopian/datahub/tree/main/examples/ckan)
|
||||
- [Live Demo](http://ckan.portaljs.org/)
|
||||
|
||||
|
||||
@@ -1,48 +0,0 @@
|
||||
---
|
||||
title: "Example: showcase for a single Frictionless dataset"
|
||||
authors: ['Luccas Mateus']
|
||||
date: 2023-04-20
|
||||
filetype: blog
|
||||
---
|
||||
|
||||
**See the repo:** https://github.com/datopian/portaljs/tree/main/examples/dataset-frictionless
|
||||
|
||||
This example creates a portal/showcase for a single dataset. The dataset should be a [Frictionless dataset (data package)][fd] i.e. there should be a `datapackage.json`.
|
||||
|
||||
[fd]: https://frictionlessdata.io/data-packages/
|
||||
|
||||
## How to use
|
||||
|
||||
```bash
|
||||
npx create-next-app -e https://github.com/datopian/portaljs/tree/main/examples/dataset-frictionless
|
||||
# choose a name for your portal when prompted e.g. your-portal or go with default my-app
|
||||
|
||||
# then run it
|
||||
cd your-portal
|
||||
yarn #install packages
|
||||
yarn dev #start app in dev mode
|
||||
```
|
||||
|
||||
You should see the demo portal running with the example dataset provided:
|
||||
|
||||
<img src="/assets/examples/frictionless-dataset-demo.gif" />
|
||||
|
||||
### Use your own dataset
|
||||
|
||||
You can try it out with other [Frictionless datasets](https://datahub.io/search).
|
||||
|
||||
In the directory of your portal do:
|
||||
|
||||
```bash
|
||||
export PORTAL_DATASET_PATH=/path/to/my/dataset
|
||||
```
|
||||
|
||||
Then restart the dev server:
|
||||
|
||||
```
|
||||
yarn dev
|
||||
```
|
||||
|
||||
Check the portal page and it should have updated e.g. like:
|
||||
|
||||

|
||||
@@ -33,7 +33,7 @@ Run the following commands:
|
||||
|
||||
|
||||
```bash
|
||||
npx create-next-app <app-name> --example https://github.com/datopian/portaljs/tree/main/examples/github-backed-catalog
|
||||
npx create-next-app <app-name> --example https://github.com/datopian/datahub/tree/main/examples/github-backed-catalog
|
||||
cd <app-name>
|
||||
```
|
||||
|
||||
@@ -61,7 +61,7 @@ Congratulations, your new app is now running at http://localhost:3000.
|
||||
|
||||
## Deployment
|
||||
|
||||
[](https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2Fdatopian%2Fportaljs%2Ftree%2Fmain%2Fexamples%2Fgithub-backed-catalog)
|
||||
[](https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2Fdatopian%2Fdatahub%2Ftree%2Fmain%2Fexamples%2Fgithub-backed-catalog)
|
||||
|
||||
By clicking on this button, you will be redirected to a page which will allow you to clone the example into your own GitHub/GitLab/BitBucket account and automatically deploy it.
|
||||
|
||||
@@ -119,5 +119,5 @@ npm run start
|
||||
|
||||
## Links
|
||||
|
||||
- [Repo](https://github.com/datopian/portaljs/tree/main/examples/github-backed-catalog)
|
||||
- [Repo](https://github.com/datopian/datahub/tree/main/examples/github-backed-catalog)
|
||||
- [Live Demo](https://example.portaljs.org)
|
||||
|
||||
@@ -3,9 +3,9 @@ title: Getting Started
|
||||
description: 'Getting started guide and tutorial about data portal-building with PortalJS!'
|
||||
---
|
||||
|
||||
Welcome to the PortalJS documentation!
|
||||
Welcome to the DataHub PortalJS documentation!
|
||||
|
||||
If you have questions about anything related to PortalJS, you're always welcome to ask our community on [GitHub Discussions](https://github.com/datopian/portaljs/discussions) or on [our chat channel on Discord](https://discord.gg/EeyfGrGu4U).
|
||||
If you have questions about anything related to PortalJS, you're always welcome to ask our community on [GitHub Discussions](https://github.com/datopian/datahub/discussions) or on [our chat channel on Discord](https://discord.com/invite/KrRzMKU).
|
||||
|
||||
## Setup
|
||||
|
||||
@@ -16,10 +16,10 @@ If you have questions about anything related to PortalJS, you're always welcome
|
||||
|
||||
### Create a PortalJS app
|
||||
|
||||
To create a PortalJS app, open your terminal, cd into the directory you’d like to create the app in, and run the following command:
|
||||
To create a DataHub PortalJS app, open your terminal, cd into the directory you’d like to create the app in, and run the following command:
|
||||
|
||||
```bash
|
||||
npx create-next-app my-data-portal --example https://github.com/datopian/portaljs/tree/main/examples/learn
|
||||
npx create-next-app my-data-portal --example https://github.com/datopian/datahub/tree/main/examples/learn
|
||||
```
|
||||
|
||||
> [!tip]
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
# Examples
|
||||
|
||||
For now, see the examples folder in github:
|
||||
|
||||
https://github.com/datopian/portaljs/tree/main/examples
|
||||
@@ -29,5 +29,5 @@ It would be too complicated (and long) to explain all of the formatting aspects
|
||||
|
||||
## Other useful pages
|
||||
|
||||
[How to quickly add a simple Markdown-based page](https://guide.portaljs.org/guides/add-a-simple-md-page)
|
||||
[How to quickly edit text content on a single Markdown-based page](https://guide.portaljs.org/guides/edit-text-on-a-single-md-page)
|
||||
[How to quickly add a simple Markdown-based page](https://www.portaljs.com/opensource/howtos/markdown)
|
||||
[How to quickly edit text content on a single Markdown-based page](https://www.portaljs.com/opensource/howtos/markdown)
|
||||
|
||||
@@ -11,5 +11,5 @@ description: Learn more about how you can achieve different data portal features
|
||||
- [[howtos/drd|How to create data-rich documents with charts and tables?]]
|
||||
- [[howtos/comments|How to add user comments?]]
|
||||
|
||||
If you have questions about anything related to PortalJS, you're always welcome to ask our community on [GitHub Discussions](https://github.com/datopian/portaljs/discussions) or on [our chat channel on Discord](https://discord.gg/EeyfGrGu4U).
|
||||
If you have questions about anything related to PortalJS, you're always welcome to ask our community on [GitHub Discussions](https://github.com/datopian/datahub/discussions) or on [our chat channel on Discord](https://discord.gg/EeyfGrGu4U).
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/** @type {import('next-sitemap').IConfig} */
|
||||
module.exports = {
|
||||
siteUrl: process.env.SITE_URL || 'https://portaljs.org',
|
||||
siteUrl: process.env.SITE_URL || 'https://portaljs.com',
|
||||
generateRobotsTxt: true,
|
||||
robotsTxtOptions: {
|
||||
policies: [
|
||||
|
||||
@@ -50,7 +50,7 @@ function MyApp({ Component, pageProps }) {
|
||||
<DefaultSeo
|
||||
defaultTitle={siteConfig.title}
|
||||
description={siteConfig.description}
|
||||
titleTemplate="PortalJS - %s"
|
||||
titleTemplate="DataHub PortalJS - %s"
|
||||
{...siteConfig.nextSeo}
|
||||
/>
|
||||
|
||||
|
||||
@@ -26,8 +26,8 @@ export default function Home({ sidebarTree }) {
|
||||
return (
|
||||
<>
|
||||
<LogoJsonLd
|
||||
url="https://portaljs.org"
|
||||
logo="https://portaljs.org/icon.png"
|
||||
url="https://portaljs.com"
|
||||
logo="https://portaljs.com/icon.png"
|
||||
/>
|
||||
<Layout
|
||||
isHomePage={true}
|
||||
@@ -35,7 +35,7 @@ export default function Home({ sidebarTree }) {
|
||||
sidebarTree={sidebarTree}
|
||||
>
|
||||
<Features />
|
||||
<Showcases />
|
||||
|
||||
<Community />
|
||||
</Layout>
|
||||
</>
|
||||
|
||||
8
site/pages/showcases.tsx
Normal file
8
site/pages/showcases.tsx
Normal file
@@ -0,0 +1,8 @@
|
||||
import Layout from "@/components/Layout";
|
||||
import Showcases from "@/components/Showcases";
|
||||
|
||||
export default function ShowcasesList() {
|
||||
return (
|
||||
<Layout><Showcases/></Layout>
|
||||
)
|
||||
}
|
||||
BIN
site/public/images/showcases/fivethirtyeight.png
Normal file
BIN
site/public/images/showcases/fivethirtyeight.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 66 KiB |
BIN
site/public/images/showcases/frictionless-capture.png
Normal file
BIN
site/public/images/showcases/frictionless-capture.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 70 KiB |
BIN
site/public/images/showcases/github-datasets.png
Normal file
BIN
site/public/images/showcases/github-datasets.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 41 KiB |
BIN
site/public/images/showcases/openspending.png
Normal file
BIN
site/public/images/showcases/openspending.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 62 KiB |
BIN
site/public/images/showcases/turing.png
Normal file
BIN
site/public/images/showcases/turing.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 88 KiB |
@@ -1,7 +1,7 @@
|
||||
#!/bin/bash
|
||||
rm -rf portal
|
||||
mkdir -p portal
|
||||
npx create-next-app portal -e https://github.com/datopian/portaljs/tree/main/examples/dataset-frictionless
|
||||
npx create-next-app portal -e https://github.com/datopian/datahub/tree/main/examples/dataset-frictionless
|
||||
mkdir portal/public/dataset
|
||||
|
||||
cp -a ./data portal/public/dataset
|
||||
@@ -12,7 +12,7 @@ PORTAL_DATASET_PATH=$PWD"/portal/public/dataset"
|
||||
export PORTAL_DATASET_PATH
|
||||
|
||||
mkdir -p .github && mkdir -p .github/workflows && touch .github/workflows/main.yml
|
||||
curl https://raw.githubusercontent.com/datopian/portaljs/main/site/public/scripts/gh-page-builder-action.yml > .github/workflows/main.yml
|
||||
curl https://raw.githubusercontent.com/datopian/datahub/main/site/public/scripts/gh-page-builder-action.yml > .github/workflows/main.yml
|
||||
|
||||
cd portal
|
||||
assetPrefix='"/'$PORTAL_REPO_NAME'/"'
|
||||
|
||||
@@ -3,7 +3,7 @@ git checkout -b gh-pages
|
||||
git rm -r --cached .
|
||||
rm -rf portal
|
||||
mkdir -p portal
|
||||
npx create-next-app portal -e https://github.com/datopian/portaljs/tree/main/examples/dataset-frictionless
|
||||
npx create-next-app portal -e https://github.com/datopian/datahub/tree/main/examples/dataset-frictionless
|
||||
mkdir portal/public/dataset
|
||||
|
||||
cp -a ./data portal/public/dataset
|
||||
|
||||
Reference in New Issue
Block a user