Compare commits

..

1 Commits

Author SHA1 Message Date
Luccas Mateus de Medeiros Gomes
e9620992e8 [examples/538][m] - little fixes and renaming 2023-05-11 13:16:04 -03:00
861 changed files with 16005 additions and 130210 deletions

View File

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

View File

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

View File

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

2
.gitignore vendored
View File

@@ -4,7 +4,6 @@
dist
tmp
/out-tsc
**/*.tgz
# dependencies
node_modules
@@ -17,7 +16,6 @@ node_modules
*.launch
.settings/
*.sublime-workspace
.obsidian
# IDE - VSCode
.vscode/*

View File

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

View File

@@ -10,24 +10,12 @@ This is also a Next.JS project so you can use the following steps to run the web
## Getting started
To get started first clone this repo in your local machine like so:
```bash
npx create-next-app turing --example https://github.com/datopian/portaljs/tree/main/examples/turing
cd turing
```
Then install the npm dependencies:
To get started first install the npm dependencies:
```bash
npm install
```
Next, run this command, its related to [markdowndb](https://github.com/datopian/markdowndb):
```bash
npm run mddb
```
Next, run the development server:
```bash

View File

@@ -140,7 +140,7 @@ function MobileNavigation(props) {
</div>
<nav className="mt-6">
<ul className="-my-2 divide-y divide-zinc-100 text-base text-zinc-800 dark:divide-zinc-100/5 dark:text-zinc-300">
<MobileNavItem href="https://github.com/datopian/portaljs/tree/main/examples/turing">
<MobileNavItem href="https://github.com/leondz/hatespeechdata">
View on Github <GithubIcon />
</MobileNavItem>
</ul>
@@ -179,7 +179,7 @@ function DesktopNavigation(props) {
return (
<nav {...props}>
<ul className="flex rounded-full bg-white/90 px-3 text-sm font-medium text-zinc-800 shadow-lg shadow-zinc-800/5 ring-1 ring-zinc-900/5 backdrop-blur dark:bg-zinc-800/90 dark:text-zinc-200 dark:ring-white/10">
<NavItem href="https://github.com/datopian/portaljs/tree/main/examples/turing">
<NavItem href="https://github.com/leondz/hatespeechdata">
View on Github <GithubIcon />
</NavItem>
</ul>

View File

@@ -36,7 +36,7 @@ In the following page type `content/datasets/<name-of-the-file>.md`. if you want
### Fill in content
Copy the contents of `templates/dataset.md` or `templates/keywords.md` respectively to the camp below, filling out the fields with the correct data format. Everything below the second `---` will automatically get rendered into the page, so you may add any standard markdown fields e.g tables, headings, lists...
Copy the contents of `templates/dataset.md` or `templates/keywords.md` respectively to the camp below, filling out the fields with the correct data format
![](https://i.imgur.com/x6JIjhz.png)

Binary file not shown.

View File

@@ -6,6 +6,7 @@ import { Card } from '../components/Card'
import Head from 'next/head'
import parse from '../lib/markdown'
import { Mermaid } from '@flowershow/core';
import { Header } from '../components/Header';
export const getStaticProps = async ({ params }) => {
const urlPath = params.slug ? params.slug.join('/') : ''
@@ -81,13 +82,15 @@ export default function DRDPage({ mdxSource }) {
)
return (
<>
<Header />
<Head>
<title>{meta.title}</title>
</Head>
<Container className="mt-9 relative">
<Container className="mt-16 lg:mt-32 relative">
<Header />
<article>
<header className="flex flex-col">
<h1 className="text-4xl font-bold tracking-tight text-zinc-800 dark:text-zinc-100 sm:text-5xl">
<h1 className="mt-6 text-4xl font-bold tracking-tight text-zinc-800 dark:text-zinc-100 sm:text-5xl">
{meta.title}
</h1>
<Card as="article">

View File

Before

Width:  |  Height:  |  Size: 566 B

After

Width:  |  Height:  |  Size: 566 B

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,55 +0,0 @@
import {
CKAN,
DatasetSearchForm,
ListOfDatasets,
PackageSearchOptions,
Organization,
Group,
} from '@portaljs/ckan';
import getConfig from 'next/config';
import { useState } from 'react';
const backend_url = getConfig().publicRuntimeConfig.DMS;
export async function getServerSideProps() {
const ckan = new CKAN(backend_url);
const groups = await ckan.getGroupsWithDetails();
const orgs = await ckan.getOrgsWithDetails();
return {
props: {
groups,
orgs,
},
};
}
export default function Home({
orgs,
groups,
}: {
orgs: Organization[];
groups: Group[];
}) {
const ckan = new CKAN(backend_url);
const [options, setOptions] = useState<PackageSearchOptions>({
offset: 0,
limit: 5,
tags: [],
groups: [],
orgs: [],
});
return (
<main className="flex min-h-screen flex-col items-center p-24 bg-zinc-900">
<DatasetSearchForm
options={options}
setOptions={setOptions}
groups={groups}
orgs={orgs}
/>
<div className="bg-white p-8 my-4 rounded-lg">
<ListOfDatasets options={options} setOptions={setOptions} ckan={ckan} />{' '}
</div>
</main>
);
}

View File

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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

View File

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

Before

Width:  |  Height:  |  Size: 1.3 KiB

View File

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

Before

Width:  |  Height:  |  Size: 629 B

View File

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

View File

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

View File

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

View File

@@ -1,10 +1,4 @@
This is a replica of the awesome data.fivethirtyeight.com using PortalJS.
You might be asking why we did that, there are three main reasons:
- The website has a great UI, with multiple datasets being displayed elegantly and with simplicity.
- PortalJS allows us to add more functionality to it e.g dataset previews and search functionality.
- The project follows our same principles of open sourcing and free data, with every dataset being publicly available on Github.
This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app).
## Getting Started

View File

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

View File

@@ -1,4 +1,33 @@
[
{
"url": "https://github.com/fivethirtyeight/data/tree/master/polls",
"name": "polls",
"displayName": "<span class=\"lastword\">polls</span>",
"articles": [
{
"date": "2023-05-11T14:35:40.000Z",
"title": "Latest Polls",
"url": "https://projects.fivethirtyeight.com/polls/"
}
],
"files": [
"https://projects.fivethirtyeight.com/polls-page/data/president_primary_polls.csv",
"https://projects.fivethirtyeight.com/polls-page/data/president_primary_polls_historical.csv",
"https://projects.fivethirtyeight.com/polls-page/data/president_polls.csv",
"https://projects.fivethirtyeight.com/polls-page/data/president_polls_historical.csv",
"https://projects.fivethirtyeight.com/polls-page/data/senate_polls.csv",
"https://projects.fivethirtyeight.com/polls-page/data/senate_polls_historical.csv",
"https://projects.fivethirtyeight.com/polls-page/data/house_polls.csv",
"https://projects.fivethirtyeight.com/polls-page/data/house_polls_historical.csv",
"https://projects.fivethirtyeight.com/polls-page/data/governor_polls.csv",
"https://projects.fivethirtyeight.com/polls-page/data/governor_polls_historical.csv",
"https://projects.fivethirtyeight.com/polls-page/data/president_approval_polls.csv",
"https://projects.fivethirtyeight.com/polls-page/data/generic_ballot_polls.csv",
"https://projects.fivethirtyeight.com/polls-page/data/generic_ballot_polls_historical.csv",
"https://projects.fivethirtyeight.com/2020-primary-data/pres_primary_avgs_2020.csv",
"https://projects.fivethirtyeight.com/2020-general-data/presidential_poll_averages_2020.csv"
]
},
{
"url": "https://github.com/fivethirtyeight/data/tree/master/congress-generic-ballot",
"name": "congress-generic-ballot",
@@ -166,35 +195,6 @@
}
]
},
{
"url": "https://github.com/fivethirtyeight/data/tree/master/polls",
"name": "polls",
"displayName": "<span class=\"lastword\">polls</span>",
"articles": [
{
"date": "2023-05-11T14:35:40.000Z",
"title": "Latest Polls",
"url": "https://projects.fivethirtyeight.com/polls/"
}
],
"files": [
"https://projects.fivethirtyeight.com/polls-page/data/president_primary_polls.csv",
"https://projects.fivethirtyeight.com/polls-page/data/president_primary_polls_historical.csv",
"https://projects.fivethirtyeight.com/polls-page/data/president_polls.csv",
"https://projects.fivethirtyeight.com/polls-page/data/president_polls_historical.csv",
"https://projects.fivethirtyeight.com/polls-page/data/senate_polls.csv",
"https://projects.fivethirtyeight.com/polls-page/data/senate_polls_historical.csv",
"https://projects.fivethirtyeight.com/polls-page/data/house_polls.csv",
"https://projects.fivethirtyeight.com/polls-page/data/house_polls_historical.csv",
"https://projects.fivethirtyeight.com/polls-page/data/governor_polls.csv",
"https://projects.fivethirtyeight.com/polls-page/data/governor_polls_historical.csv",
"https://projects.fivethirtyeight.com/polls-page/data/president_approval_polls.csv",
"https://projects.fivethirtyeight.com/polls-page/data/generic_ballot_polls.csv",
"https://projects.fivethirtyeight.com/polls-page/data/generic_ballot_polls_historical.csv",
"https://projects.fivethirtyeight.com/2020-primary-data/pres_primary_avgs_2020.csv",
"https://projects.fivethirtyeight.com/2020-general-data/presidential_poll_averages_2020.csv"
]
},
{
"url": "https://github.com/fivethirtyeight/data/tree/master/nfl-elo",
"name": "nfl-elo",
@@ -211,6 +211,18 @@
"https://projects.fivethirtyeight.com/nfl-api/nfl_elo_latest.csv"
]
},
{
"url": "https://github.com/fivethirtyeight/checking-our-work-data",
"name": "checking-our-work-data",
"displayName": "checking-our-work-<span class=\"lastword\">data</span>",
"articles": [
{
"date": "2023-02-02T16:30:00.000Z",
"title": "How Good Are FiveThirtyEight Forecasts?",
"url": "https://projects.fivethirtyeight.com/checking-our-work/"
}
]
},
{
"url": "https://github.com/fivethirtyeight/data/tree/master/world-cup-2022",
"name": "world-cup-2022",
@@ -227,6 +239,18 @@
"https://projects.fivethirtyeight.com/soccer-api/international/2022/wc_forecasts.csv"
]
},
{
"url": "https://github.com/fivethirtyeight/covid-19-polls",
"name": "covid-19-polls",
"displayName": "covid-19-<span class=\"lastword\">polls</span>",
"articles": [
{
"date": "2022-11-29T20:20:08.000Z",
"title": "How Americans View Bidens Response To The Coronavirus Crisis",
"url": "https://projects.fivethirtyeight.com/coronavirus-polls/"
}
]
},
{
"url": "https://github.com/fivethirtyeight/data/tree/master/election-deniers",
"name": "election-deniers",
@@ -347,6 +371,18 @@
}
]
},
{
"url": "https://github.com/fivethirtyeight/nfl-elo-game",
"name": "nfl-elo-game",
"displayName": "nfl-elo-<span class=\"lastword\">game</span>",
"articles": [
{
"date": "2022-02-14T03:03:26.000Z",
"title": "Can You Beat FiveThirtyEights NFL Forecasts?",
"url": "https://projects.fivethirtyeight.com/2021-nfl-forecasting-game/"
}
]
},
{
"url": "https://github.com/fivethirtyeight/data/tree/master/redlining",
"name": "redlining",
@@ -371,6 +407,42 @@
}
]
},
{
"url": "https://github.com/fivethirtyeight/negro-leagues-player-ratings",
"name": "negro-leagues-player-ratings",
"displayName": "negro-leagues-player-<span class=\"lastword\">ratings</span>",
"articles": [
{
"date": "2021-02-25T11:00:00.000Z",
"title": "The Negro League Stars That MLB Kept Out — And Is Finally Recognizing",
"url": "https://projects.fivethirtyeight.com/negro-leagues-mlb/"
}
]
},
{
"url": "https://github.com/fivethirtyeight/police-settlements",
"name": "police-settlements",
"displayName": "police-<span class=\"lastword\">settlements</span>",
"articles": [
{
"date": "2021-02-22T11:00:49.000Z",
"title": "Cities Spend Millions On Police Misconduct Every Year. Heres Why Its So Difficult to Hold Departments Accountable.",
"url": "https://fivethirtyeight.com/features/police-misconduct-costs-cities-millions-every-year-but-thats-where-the-accountability-ends/"
}
]
},
{
"url": "https://github.com/fivethirtyeight/superbowl-ads",
"name": "superbowl-ads",
"displayName": "superbowl-<span class=\"lastword\">ads</span>",
"articles": [
{
"date": "2021-02-04T16:11:00.000Z",
"title": "According To Super Bowl Ads, Americans Love America, Animals And Sex",
"url": "https://projects.fivethirtyeight.com/super-bowl-ads/"
}
]
},
{
"url": "https://github.com/fivethirtyeight/data/tree/master/trump-approval-ratings",
"name": "trump-approval-ratings",
@@ -403,6 +475,18 @@
"https://projects.fivethirtyeight.com/congress-tracker-data/csv/vote_predictions.csv"
]
},
{
"url": "https://github.com/fivethirtyeight/election-results",
"name": "election-results",
"displayName": "election-<span class=\"lastword\">results</span>",
"articles": [
{
"date": "2020-11-03T05:33:43.000Z",
"title": "2020 Election Forecast",
"url": "https://projects.fivethirtyeight.com/2020-election-forecast/"
}
]
},
{
"url": "https://github.com/fivethirtyeight/data/tree/master/election-forecasts-2020",
"name": "election-forecasts-2020",
@@ -473,6 +557,18 @@
}
]
},
{
"url": "https://github.com/fivethirtyeight/WNBA-stats",
"name": "WNBA-stats",
"displayName": "WNBA-<span class=\"lastword\">stats</span>",
"articles": [
{
"date": "2020-05-27T19:06:43.000Z",
"title": "Its Time To Give Basketballs Other GOAT Her Due",
"url": "https://fivethirtyeight.com/features/its-time-to-give-basketballs-other-goat-her-due/"
}
]
},
{
"url": "https://github.com/fivethirtyeight/data/tree/master/covid-geography",
"name": "covid-geography",
@@ -512,6 +608,18 @@
"https://projects.fivethirtyeight.com/endorsements-2020-data/endorsements-2020.csv"
]
},
{
"url": "https://github.com/fivethirtyeight/nba-player-advanced-metrics",
"name": "nba-player-advanced-metrics",
"displayName": "nba-player-advanced-<span class=\"lastword\">metrics</span>",
"articles": [
{
"date": "2020-03-09T15:27:37.000Z",
"title": "Luka Dončić And The Mavs Are Pushing The Limits Of Offensive Efficiency",
"url": "https://fivethirtyeight.com/features/luka-doncic-and-the-mavs-are-pushing-the-limits-of-offensive-efficiency/"
}
]
},
{
"url": "https://github.com/fivethirtyeight/data/tree/master/impeachment-polls",
"name": "impeachment-polls",
@@ -603,6 +711,18 @@
}
]
},
{
"url": "https://github.com/fivethirtyeight/candidate-emails",
"name": "candidate-emails",
"displayName": "candidate-<span class=\"lastword\">emails</span>",
"articles": [
{
"date": "2019-07-11T15:33:15.000Z",
"title": "What Our Inbox Tells Us About How Democrats Are Tackling Trump",
"url": "https://fivethirtyeight.com/features/which-democrats-are-campaigning-on-trump/"
}
]
},
{
"url": "https://github.com/fivethirtyeight/data/tree/master/nba-draymond",
"name": "nba-draymond",
@@ -643,6 +763,18 @@
}
]
},
{
"url": "https://github.com/fivethirtyeight/twitter-overlap",
"name": "twitter-overlap",
"displayName": "twitter-<span class=\"lastword\">overlap</span>",
"articles": [
{
"date": "2019-06-12T15:24:07.000Z",
"title": "Which 2020 Candidates Have The Most In Common … On Twitter?",
"url": "https://fivethirtyeight.com/features/which-2020-candidates-have-the-most-in-common-on-twitter/"
}
]
},
{
"url": "https://github.com/fivethirtyeight/data/tree/master/trump-lawsuits",
"name": "trump-lawsuits",
@@ -825,6 +957,18 @@
"https://projects.fivethirtyeight.com/congress-model-2018/governor_state_forecast.csv"
]
},
{
"url": "https://github.com/fivethirtyeight/actblue-analysis",
"name": "actblue-analysis",
"displayName": "actblue-<span class=\"lastword\">analysis</span>",
"articles": [
{
"date": "2018-10-25T17:31:42.000Z",
"title": "How ActBlue Is Trying To Turn Small Donations Into A Blue Wave",
"url": "https://fivethirtyeight.com/features/how-actblue-is-trying-to-turn-small-donations-into-a-blue-wave"
}
]
},
{
"url": "https://github.com/fivethirtyeight/data/tree/master/primary-candidates-2018",
"name": "primary-candidates-2018",
@@ -1035,6 +1179,18 @@
}
]
},
{
"url": "https://github.com/fivethirtyeight/redistricting-atlas-data",
"name": "redistricting-atlas-data",
"displayName": "redistricting-atlas-<span class=\"lastword\">data</span>",
"articles": [
{
"date": "2018-01-25T11:00:00.000Z",
"title": "The Atlas Of Redistricting",
"url": "https://projects.fivethirtyeight.com/redistricting-maps/"
}
]
},
{
"url": "https://github.com/fivethirtyeight/data/tree/master/next-bechdel",
"name": "next-bechdel",
@@ -1169,6 +1325,18 @@
}
]
},
{
"url": "https://github.com/fivethirtyeight/data/tree/master/undefeated-boxers",
"name": "undefeated-boxers",
"displayName": "undefeated-<span class=\"lastword\">boxers</span>",
"articles": [
{
"date": "2017-08-18T18:47:32.000Z",
"title": "Mayweather Is Defined By The Zero Next To His Name",
"url": "https://fivethirtyeight.com/features/mayweather-is-defined-by-the-zero-next-to-his-name/"
}
]
},
{
"url": "https://github.com/fivethirtyeight/data/tree/master/chess-transfers",
"name": "chess-transfers",
@@ -1452,6 +1620,37 @@
}
]
},
{
"url": "https://github.com/fivethirtyeight/uber-tlc-foil-response",
"name": "uber-tlc-foil-response",
"displayName": "uber-tlc-foil-<span class=\"lastword\">response</span>",
"articles": [
{
"date": "2015-12-09T16:19:40.000Z",
"title": "Is Uber Making NYC Rush-Hour Traffic Worse?",
"rowspan": 4,
"url": "https://fivethirtyeight.com/features/is-uber-making-nyc-rush-hour-traffic-worse/"
},
{
"date": "2015-10-13T20:44:12.000Z",
"title": "Uber Is Taking Millions Of Manhattan Rides Away From Taxis",
"rowspan": 0,
"url": "https://fivethirtyeight.com/features/uber-is-taking-millions-of-manhattan-rides-away-from-taxis/"
},
{
"date": "2015-08-28T10:30:36.000Z",
"title": "Public Transit Should Be Ubers New Best Friend",
"rowspan": 0,
"url": "https://fivethirtyeight.com/features/public-transit-should-be-ubers-new-best-friend/"
},
{
"date": "2015-08-10T18:06:17.000Z",
"title": "Uber Is Serving New Yorks Outer Boroughs More Than Taxis Are",
"rowspan": 0,
"url": "https://fivethirtyeight.com/features/uber-is-serving-new-yorks-outer-boroughs-more-than-taxis-are/"
}
]
},
{
"url": "https://github.com/fivethirtyeight/data/tree/master/tarantino",
"name": "tarantino",
@@ -1970,6 +2169,18 @@
}
]
},
{
"url": "https://github.com/fivethirtyeight/data/tree/master/comma-survey-data",
"name": "comma-survey-data",
"displayName": "comma-survey-<span class=\"lastword\">data</span>",
"articles": [
{
"date": "2014-06-17T16:28:55.000Z",
"title": "Elitist, Superfluous, Or Popular? We Polled Americans on the Oxford Comma",
"url": "http://fivethirtyeight.com/features/elitist-superfluous-or-popular-we-polled-americans-on-the-oxford-comma/"
}
]
},
{
"url": "https://github.com/fivethirtyeight/data/tree/master/world-cup-predictions",
"name": "world-cup-predictions",
@@ -2127,18 +2338,6 @@
}
]
},
{
"url": "https://github.com/fivethirtyeight/data/tree/master/undefeated-boxers",
"name": "undefeated-boxers",
"displayName": "undefeated-<span class=\"lastword\">boxers</span>",
"articles": [
{
"date": "2017-08-18T18:47:32.000Z",
"title": "Mayweather Is Defined By The Zero Next To His Name",
"url": "https://fivethirtyeight.com/features/mayweather-is-defined-by-the-zero-next-to-his-name/"
}
]
},
{
"url": "https://github.com/fivethirtyeight/data/tree/master/march-madness-predictions",
"name": "march-madness-predictions",

File diff suppressed because it is too large Load Diff

View File

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

View File

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

View File

@@ -9,19 +9,40 @@ export default function Document() {
type="image/x-icon"
href="https://projects.fivethirtyeight.com/shared/favicon.ico"
/>
<meta
property="og:image"
content="https://portaljs-fivethirtyeight.vercel.app/share_image.png"
/>
<meta
property="twitter:image"
content="https://portaljs-fivethirtyeight.vercel.app/share_image.png"
/>
</Head>
<body>
<header className="max-w-5xl mx-auto mt-8 w-full">
<div className="border-b-2 pb-2.5 mx-2 border-zinc-800">
<h1>
<span className="sr-only">FiveThirtyEight</span>
<a
className="flex gap-x-2 items-center"
href="http://fivethirtyeight.com"
>
<img
width="197"
height="25"
alt="FiveThirtyEight"
src="data:image/svg+xml;base64,PHN2ZyBpZD0iTGF5ZXJfMSIgZGF0YS1uYW1lPSJMYXllciAxIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0MjEgNTMuNzYiPjxkZWZzPjxzdHlsZT4uY2xzLTF7ZmlsbDojMDEwMTAxO308L3N0eWxlPjwvZGVmcz48dGl0bGU+QXJ0Ym9hcmQgOTU8L3RpdGxlPjxwYXRoIGNsYXNzPSJjbHMtMSIgZD0iTTAgMGgyNXY4SDl2MTBoMTV2OEg5djE3SDBWMHpNMzEgMzZoNVYxOGgtNXYtOGgxM3YyNmg0djdIMzF6bTUtMzZoOHY4aC04ek0xNzkgMzZoNVYxOGgtNXYtOGgxM3YyNmg0djdoLTE3em01LTM2aDh2OGgtOHpNMzE2IDM2aDVWMThoLTV2LThoMTN2MjZoNHY3aC0xN3ptNS0zNmg4djhoLTh6TTU0IDI3VjEwaDh2MTVsNCA5Ljk4aDFMNzEgMjVWMTBoOHYxN2wtNyAxNkg2MWwtNy0xNnpNMTExIDQzSDk3LjQyQzg5LjIzIDQzIDg1IDM5LjE5IDg1IDMxLjE3VjIyYzAtNy41NyA0LjMtMTMgMTMtMTMgOS4zMyAwIDEzIDUuMDcgMTMgMTR2N0g5NHYxLjc0YzAgMi42MiAxIDQuMjYgMy40MiA0LjI2SDExMXpNOTQgMjNoOHYtMS41NWMwLTIuNjItMS4wNi01LjQ1LTQuMTMtNS40NS0yLjc5IDAtMy44NyAyLjItMy44NyA1LjQ1ek0xMjUgOGgtMTBWMGgyOXY4aC0xMHYzNWgtOVY4ek0yMDIgNDNWMTBoOHY0YzEuMTQtMi40NSAzLjc1LTQgNy4yMi00SDIyMHY4aC02Yy0yLjg0IDAtNCAuOTQtNCAzLjlWNDN6TTI0NSA0M2gtNC44NEMyMzMuMDUgNDMgMjMwIDM5LjMxIDIzMCAzMS44NVYxOGgtNnYtOGg2VjNoOHY3aDd2OGgtN2wtLjA3IDEzLjkzYzAgMi4yMi45MyA0LjA3IDMuNjYgNC4wN0gyNDV6TTQyMSA0M2gtNC44NEM0MDkuMDUgNDMgNDA2IDM5LjMxIDQwNiAzMS44NVYxOGgtNnYtOGg2VjNoOHY3aDd2OGgtN2wtLjA3IDEzLjkzYzAgMi4yMi45MyA0LjA3IDMuNjYgNC4wN0g0MjF6TTI1NC4yNiA1My43Nmw0LjYxLTkuNUwyNTEgMjdWMTBoOHYxNWw0IDEwaDFsNC0xMFYxMGg4djE3bC0xMi4zIDI2Ljc2aC05LjQ0ek0yODQgMGgyNXY4aC0xNnY5aDE1djhoLTE1djEwaDE2djhoLTI1VjB6TTMzNyA0OHYtMmgxNi4xYzIgMCAyLjktLjE4IDIuOS0xLjI3di0uMzRjMC0xLjA4LS45MS0xLjM5LTIuOS0xLjM5SDM0MHYtNWw1LTVjLTUuMjktMS40OC04LTUuNDMtOC0xMXYtMWMwLTcuNTYgNC40NC0xMiAxNC0xMmEyMS45MyAyMS45MyAwIDAgMSA1Ljk1IDFMMzYxIDRsNSAzLTQgNmMxLjM3IDEuOTMgMyA0LjkzIDMgOHYxYzAgNy0zLjMgMTAuNjYtMTIgMTFsLTMgNGg2YzUuOTIgMCA5IDIuNjIgOSA3LjY4di4xMWMwIDUuMDYtMi43MSA4LjIxLTguNjIgOC4yMWgtMTNjLTQuMjkgMC02LjM4LTEuODQtNi4zOC01em0xOS0yNXYtM2MwLTMuMy0xLjMzLTQtNS00cy01IC43LTUgNHYzYzAgMy4zIDEuMzkgNCA1IDRzNS0uNyA1LTR6TTM4MCA0M2gtOFYwaDh2MTRjMS4xNC0yLjY3IDMuNC00IDctNCA2LjI2IDAgOSAzLjA4IDkgMTAuNzZWNDNoLThWMjJjMC0zLjEzLTEuMDctNS00LTVzLTQgMS44Ny00IDV6TTE1NyA0M2gtOFYwaDh2MTRjMS4xNC0yLjY3IDMuOTEtNCA3LjQ5LTQgNi4yNiAwIDguNTEgMy4xMyA4LjUxIDEwLjgxVjQzaC04VjIxYzAtMy4xMy0xLjA3LTQuNDQtNC00LjQ0cy00IDIuMjYtNCA1LjM5eiIvPjwvc3ZnPg=="
/>{' '}
by PortalJS
</a>
</h1>
</div>
<div className="mx-2 py-1.5 text-[14px] text-[#3c3c3c]">
<ul className='flex gap-x-4'>
<li>
<a className='hover:opacity-75 transition' href="https://portaljs.org">PortalJS</a>
</li>
<li>
<a className='hover:opacity-75 transition' href="https://github.com/datopian/portaljs/tree/main/examples/fivethirtyeight">View on Github</a>
</li>
</ul>
</div>
</header>
<Main />
<NextScript />
</body>
<NextScript />
</Html>
);
}

View File

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

View File

@@ -3,8 +3,6 @@ import { Inter } from 'next/font/google';
import { format } from 'timeago.js';
import { promises as fs } from 'fs';
import path from 'path';
import { NextSeo } from 'next-seo';
import Layout from '@/components/Layout';
const inter = Inter({ subsets: ['latin'] });
@@ -33,7 +31,11 @@ export function MobileItem({ dataset }: { dataset: Dataset }) {
return (
<div className="flex gap-x-2 pb-2 py-4 items-center justify-between border-b border-zinc-600">
<div className="flex flex-col">
<span className="font-mono font-light">{dataset.name}</span>
<span className="font-mono font-light">
<a className="underline" href={dataset.url} target="_blank">
{dataset.name}
</a>
</span>
{dataset.articles.map((article) => (
<div key={article.title} className="py-1 flex flex-col">
<span className="font-bold hover:underline">{article.title}</span>
@@ -48,16 +50,25 @@ export function MobileItem({ dataset }: { dataset: Dataset }) {
<div className="flex flex-col justify-start">
<a
className="ml-2 border border-zinc-900 font-light px-4 py-1 text-sm transition hover:bg-zinc-900 hover:text-white"
href={dataset.url}
>
info
</a>
<a
className="ml-2 border border-[#3c3c3c] px-[25px] py-2.5 text-sm transition bg-[#3c3c3c] text-white hover:bg-zinc-900"
href={`/datasets/${dataset.name}`}
>
explore
</a>
{/*
<button>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="currentColor"
className="w-12 h-12 text-blue-400 hover:text-blue-300 transition mt-1"
>
<path
fillRule="evenodd"
d="M12 2.25c-5.385 0-9.75 4.365-9.75 9.75s4.365 9.75 9.75 9.75 9.75-4.365 9.75-9.75S17.385 2.25 12 2.25zm-.53 14.03a.75.75 0 001.06 0l3-3a.75.75 0 10-1.06-1.06l-1.72 1.72V8.25a.75.75 0 00-1.5 0v5.69l-1.72-1.72a.75.75 0 00-1.06 1.06l3 3z"
clipRule="evenodd"
/>
</svg>
</button> */}
</div>
</div>
);
@@ -73,8 +84,10 @@ export function DesktopItem({ dataset }: { dataset: Dataset }) {
index === dataset.articles.length - 1 ? 'border-b' : ''
} border-zinc-400`}
>
<td className="py-8 font-light font-mono text-[13px] text-zinc-700">
{index === 0 ? dataset.name : ''}
<td className="py-8 font-light font-mono text-[14px] text-zinc-700">
<a className="underline" href={dataset.url} target="_blank">
{index === 0 ? dataset.name : ''}
</a>
</td>
<td>
<a
@@ -89,26 +102,33 @@ export function DesktopItem({ dataset }: { dataset: Dataset }) {
? new Date(article.date).toLocaleString('en-US', options)
: format(article.date)}
</td>
<td>
{index === 0 && (
<a
className="ml-2 border border-[#3c3c3c] px-[25px] py-2.5 text-sm transition bg-[#3c3c3c] text-white hover:bg-zinc-900"
href={`/datasets/${dataset.name}`}
>
explore
</a>
)}
</td>
<td className="py-8">
{index === 0 && (
<a
className="ml-2 border border-zinc-900 font-light px-[25px] py-2.5 text-sm transition hover:bg-zinc-900 hover:text-white"
href={dataset.url}
href={`/datasets/${dataset.name}`}
>
info
explore
</a>
)}
</td>
{/*
<td>
<button>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="currentColor"
className="w-12 h-12 text-blue-400 hover:text-blue-300 transition mt-1"
>
<path
fillRule="evenodd"
d="M12 2.25c-5.385 0-9.75 4.365-9.75 9.75s4.365 9.75 9.75 9.75 9.75-4.365 9.75-9.75S17.385 2.25 12 2.25zm-.53 14.03a.75.75 0 001.06 0l3-3a.75.75 0 10-1.06-1.06l-1.72 1.72V8.25a.75.75 0 00-1.5 0v5.69l-1.72-1.72a.75.75 0 00-1.06 1.06l3 3z"
clipRule="evenodd"
/>
</svg>
</button>
</td>*/}
</tr>
))}
</>
@@ -127,8 +147,6 @@ export async function getStaticProps() {
export default function Home({ datasets }: { datasets: Dataset[] }) {
return (
<>
<NextSeo title="FiveThirtyEight tribute by PortalJS" />
<Layout>
<main
className={`flex min-h-screen flex-col items-center max-w-5xl mx-auto pt-20 px-2.5 ${inter.className}`}
>
@@ -192,7 +210,6 @@ export default function Home({ datasets }: { datasets: Dataset[] }) {
.
</p>
</main>
</Layout>
</>
);
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 81 KiB

View File

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

View File

@@ -1,5 +1,8 @@
{
"extends": ["next", "next/core-web-vitals"],
"extends": [
"next",
"next/core-web-vitals"
],
"ignorePatterns": ["!**/*", ".next/**/*"],
"overrides": [
{

View File

@@ -1,7 +0,0 @@
node_modules
**/.next/**
**/_next/**
**/dist/**
**/__tmp__/**
lerna.json
.github

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