Merge branch 'master' of github.com:datopian/portal
This commit is contained in:
commit
9b957abf06
24
.prettierignore
Normal file
24
.prettierignore
Normal file
@ -0,0 +1,24 @@
|
||||
node_modules/
|
||||
|
||||
# testing
|
||||
/coverage
|
||||
|
||||
# next.js
|
||||
.next/
|
||||
/out/
|
||||
|
||||
# yarn
|
||||
yarn-error.log
|
||||
yarn.lock
|
||||
|
||||
# sass
|
||||
.sass-cache
|
||||
|
||||
# misc
|
||||
sandbox/*
|
||||
.env
|
||||
.staging.env
|
||||
.nyc_output/*
|
||||
.DS_Store
|
||||
|
||||
public/
|
||||
26
README.md
26
README.md
@ -2,8 +2,8 @@
|
||||
|
||||
`Portal` 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][]. `portal` is built in Javascript and React on top of the popular [Next.js][] framework.
|
||||
|
||||
[CKAN]: https://ckan.org/
|
||||
[Next.js]: https://nextjs.com/
|
||||
[ckan]: https://ckan.org/
|
||||
[next.js]: https://nextjs.com/
|
||||
|
||||
Live DEMO: https://portal.datopian1.now.sh
|
||||
|
||||
@ -22,13 +22,12 @@ npm init portal-app my-data-portal
|
||||
```
|
||||
|
||||
> NB: Under the hood, this uses the tool called create-next-app, which bootstraps a Next.js app for you. It uses this template through the --example flag.
|
||||
>
|
||||
>
|
||||
> If it doesn’t work, please open an issue.
|
||||
|
||||
|
||||
## Guide
|
||||
|
||||
### Styling :art:
|
||||
### Styling :art:
|
||||
|
||||
We use Tailwind as a CSS framework. Take a look at `/styles/index.css` to see what we're importing from Tailwind bundle. You can also configure Tailwind using `tailwind.config.js` file.
|
||||
|
||||
@ -49,13 +48,13 @@ $ export CMS=http://myblog.wordpress.com
|
||||
|
||||
These are the default routes set up in the "starter" app.
|
||||
|
||||
* Home `/`
|
||||
* Search `/search`
|
||||
* Dataset `/@org/dataset`
|
||||
* Resource `/@org/dataset/r/resource`
|
||||
* Organization `/@org`
|
||||
* Collection (aka group in CKAN) (?) - suggest to merge into org
|
||||
* Static pages, eg, `/about` etc. from CMS or can do it without external CMS, e.g., in Next.js
|
||||
- Home `/`
|
||||
- Search `/search`
|
||||
- Dataset `/@org/dataset`
|
||||
- Resource `/@org/dataset/r/resource`
|
||||
- Organization `/@org`
|
||||
- Collection (aka group in CKAN) (?) - suggest to merge into org
|
||||
- Static pages, eg, `/about` etc. from CMS or can do it without external CMS, e.g., in Next.js
|
||||
|
||||
### New Routes
|
||||
|
||||
@ -77,11 +76,10 @@ Boot the demo portal:
|
||||
$ yarn dev # or npm run dev
|
||||
```
|
||||
|
||||
Open [http://localhost:3000](http://localhost:3000) to see the home page :tada:
|
||||
Open [http://localhost:3000](http://localhost:3000) to see the home page :tada:
|
||||
|
||||
You can start editing the page by modifying `/pages/index.tsx`. The page auto-updates as you edit the file.
|
||||
|
||||
|
||||
### Tests
|
||||
|
||||
We use Jest for running tests:
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
import React from 'react'
|
||||
import { render } from '@testing-library/react'
|
||||
import renderer from 'react-test-renderer'
|
||||
import Total from '../../../components/search/Total'
|
||||
import React from 'react';
|
||||
import { render } from '@testing-library/react';
|
||||
import renderer from 'react-test-renderer';
|
||||
import Total from '../../../components/search/Total';
|
||||
|
||||
test('📸 of Total component', () => {
|
||||
const tree = renderer.create(<Total total={2} />).toJSON()
|
||||
expect(tree).toMatchSnapshot()
|
||||
})
|
||||
test('📸 of Total component', () => {
|
||||
const tree = renderer.create(<Total total={2} />).toJSON();
|
||||
expect(tree).toMatchSnapshot();
|
||||
});
|
||||
|
||||
@ -1,17 +1,15 @@
|
||||
import React from 'react'
|
||||
import { render } from '@testing-library/react'
|
||||
import renderer from 'react-test-renderer'
|
||||
import Index from '../../pages/index'
|
||||
import React from 'react';
|
||||
import { render } from '@testing-library/react';
|
||||
import renderer from 'react-test-renderer';
|
||||
import Index from '../../pages/index';
|
||||
|
||||
test('📸 of Home page', () => {
|
||||
const tree = renderer.create(<Index />).toJSON()
|
||||
expect(tree).toMatchSnapshot()
|
||||
})
|
||||
test('📸 of Home page', () => {
|
||||
const tree = renderer.create(<Index />).toJSON();
|
||||
expect(tree).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('renders text from hero section', () => {
|
||||
const { getByText } = render(<Index />)
|
||||
const linkElement = getByText(
|
||||
/Find, Share and Publish/
|
||||
)
|
||||
expect(linkElement).toBeInTheDocument()
|
||||
})
|
||||
const { getByText } = render(<Index />);
|
||||
const linkElement = getByText(/Find, Share and Publish/);
|
||||
expect(linkElement).toBeInTheDocument();
|
||||
});
|
||||
|
||||
@ -15,22 +15,16 @@ export default function About({ datapackage }) {
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td className="px-4 py-2">{ datapackage.resources.length }</td>
|
||||
<td className="px-4 py-2">{ datapackage.size || 'N\A' }</td>
|
||||
<td className="px-4 py-2">
|
||||
|
||||
</td>
|
||||
<td className="px-4 py-2">{ datapackage.created }</td>
|
||||
<td className="px-4 py-2">{ datapackage.modified }</td>
|
||||
<td className="px-4 py-2">
|
||||
|
||||
</td>
|
||||
<td className="px-4 py-2">
|
||||
|
||||
</td>
|
||||
<td className="px-4 py-2">{datapackage.resources.length}</td>
|
||||
<td className="px-4 py-2">{datapackage.size || 'NA'}</td>
|
||||
<td className="px-4 py-2"></td>
|
||||
<td className="px-4 py-2">{datapackage.created}</td>
|
||||
<td className="px-4 py-2">{datapackage.modified}</td>
|
||||
<td className="px-4 py-2"></td>
|
||||
<td className="px-4 py-2"></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@ -1,17 +1,26 @@
|
||||
import Link from 'next/link'
|
||||
import Link from 'next/link';
|
||||
|
||||
export default function Org({ org }) {
|
||||
return (
|
||||
<>
|
||||
{org
|
||||
? <>
|
||||
<img src={org.image_url || 'https://datahub.io/static/img/datahub-cube-edited.svg'} className="h-5 w-5 mr-2 inline-block" />
|
||||
{org ? (
|
||||
<>
|
||||
<img
|
||||
src={
|
||||
org.image_url ||
|
||||
'https://datahub.io/static/img/datahub-cube-edited.svg'
|
||||
}
|
||||
className="h-5 w-5 mr-2 inline-block"
|
||||
/>
|
||||
<Link href={`/@${org.name}`}>
|
||||
<a className="font-semibold text-primary underline">{ org.title || org.name }</a>
|
||||
<a className="font-semibold text-primary underline">
|
||||
{org.title || org.name}
|
||||
</a>
|
||||
</Link>
|
||||
</>
|
||||
: ''
|
||||
}
|
||||
) : (
|
||||
''
|
||||
)}
|
||||
</>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import Link from 'next/link'
|
||||
import Link from 'next/link';
|
||||
|
||||
export default function Resources({ datapackage }) {
|
||||
return (
|
||||
@ -16,25 +16,24 @@ export default function Resources({ datapackage }) {
|
||||
</thead>
|
||||
<tbody>
|
||||
{datapackage.resources.map((resource, index) => (
|
||||
<tr key={index}>
|
||||
<td className="px-4 py-2">
|
||||
<Link href={`${datapackage.name}/r/${resource.name}`}>
|
||||
<a className="underline">{ resource.title || resource.name }</a>
|
||||
</Link>
|
||||
</td>
|
||||
<td className="px-4 py-2">{ resource.format }</td>
|
||||
<td className="px-4 py-2">{ resource.created }</td>
|
||||
<td className="px-4 py-2">{ resource.last_modified }</td>
|
||||
<td className="px-4 py-2">
|
||||
<Link href={`${datapackage.name}/r/${resource.name}`}>
|
||||
<a className="underline">Preview</a>
|
||||
</Link>
|
||||
</td>
|
||||
</tr>
|
||||
)
|
||||
)}
|
||||
<tr key={index}>
|
||||
<td className="px-4 py-2">
|
||||
<Link href={`${datapackage.name}/r/${resource.name}`}>
|
||||
<a className="underline">{resource.title || resource.name}</a>
|
||||
</Link>
|
||||
</td>
|
||||
<td className="px-4 py-2">{resource.format}</td>
|
||||
<td className="px-4 py-2">{resource.created}</td>
|
||||
<td className="px-4 py-2">{resource.last_modified}</td>
|
||||
<td className="px-4 py-2">
|
||||
<Link href={`${datapackage.name}/r/${resource.name}`}>
|
||||
<a className="underline">Preview</a>
|
||||
</Link>
|
||||
</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
</>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@ -1,13 +1,13 @@
|
||||
import Link from 'next/link'
|
||||
import React, { useState } from 'react'
|
||||
import Link from 'next/link';
|
||||
import React, { useState } from 'react';
|
||||
|
||||
export default function Nav() {
|
||||
const [open, setOpen] = useState(false)
|
||||
const [open, setOpen] = useState(false);
|
||||
|
||||
const handleClick = (event) => {
|
||||
event.preventDefault()
|
||||
setOpen(!open)
|
||||
}
|
||||
event.preventDefault();
|
||||
setOpen(!open);
|
||||
};
|
||||
|
||||
return (
|
||||
<nav className="flex items-center justify-between flex-wrap bg-white p-4 border-b border-gray-200">
|
||||
@ -15,25 +15,40 @@ export default function Nav() {
|
||||
<img src="/images/logo.svg" alt="portal logo" width="40" />
|
||||
</div>
|
||||
<div className="block lg:hidden mx-4">
|
||||
<button onClick={handleClick} className="flex items-center px-3 py-2 border rounded text-gray-700 border-orange-400 hover:text-black hover:border-black">
|
||||
<svg className="fill-current h-3 w-3" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><title>Menu</title><path d="M0 3h20v2H0V3zm0 6h20v2H0V9zm0 6h20v2H0v-2z"/></svg>
|
||||
<button
|
||||
onClick={handleClick}
|
||||
className="flex items-center px-3 py-2 border rounded text-gray-700 border-orange-400 hover:text-black hover:border-black"
|
||||
>
|
||||
<svg
|
||||
className="fill-current h-3 w-3"
|
||||
viewBox="0 0 20 20"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<title>Menu</title>
|
||||
<path d="M0 3h20v2H0V3zm0 6h20v2H0V9zm0 6h20v2H0v-2z" />
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
<div className={`${open ? `block` : `hidden`} lg:block`}>
|
||||
<Link href="/search">
|
||||
<Link href="/search">
|
||||
<a className="block mt-4 lg:inline-block lg:mt-0 text-gray-700 hover:text-black mr-6">
|
||||
Search
|
||||
</a>
|
||||
</Link>
|
||||
<Link href="http://tech.datopian.com/frontend/">
|
||||
<a className="block mt-4 lg:inline-block lg:mt-0 text-gray-700 hover:text-black mr-6" target="_blank">
|
||||
<a
|
||||
className="block mt-4 lg:inline-block lg:mt-0 text-gray-700 hover:text-black mr-6"
|
||||
target="_blank"
|
||||
>
|
||||
Docs
|
||||
</a>
|
||||
</Link>
|
||||
<Link href="https://github.com/datopian/portal">
|
||||
<a className="inline-block text-sm px-4 py-2 leading-none border rounded text-white bg-black border-black hover:border-gray-700 hover:text-gray-700 hover:bg-white mt-4 lg:mt-0">GitHub</a>
|
||||
<a className="inline-block text-sm px-4 py-2 leading-none border rounded text-white bg-black border-black hover:border-gray-700 hover:text-gray-700 hover:bg-white mt-4 lg:mt-0">
|
||||
GitHub
|
||||
</a>
|
||||
</Link>
|
||||
</div>
|
||||
</nav>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import Link from 'next/link'
|
||||
import Link from 'next/link';
|
||||
|
||||
export default function Recent() {
|
||||
return (
|
||||
@ -8,28 +8,46 @@ export default function Recent() {
|
||||
<div className="border px-4 mb-4 mr-3 border-gray-100 w-5/6 shadow-sm">
|
||||
<h1 className="text-2xl font-thin">Our World in Data - COVID 19</h1>
|
||||
<p className="text-gray-500">Dataset</p>
|
||||
<p>data collected and managed by Our World in Data - COVID 19 pulled from GitHub on 06/10/2020 https://ourworldindata.org/coronavirus</p>
|
||||
<p>
|
||||
data collected and managed by Our World in Data - COVID 19 pulled
|
||||
from GitHub on 06/10/2020 https://ourworldindata.org/coronavirus
|
||||
</p>
|
||||
<Link href="/">
|
||||
<a className="pt-3 flex justify-end text-orange-500"> View Dataset </a>
|
||||
<a className="pt-3 flex justify-end text-orange-500">
|
||||
{' '}
|
||||
View Dataset{' '}
|
||||
</a>
|
||||
</Link>
|
||||
</div>
|
||||
<div className="border px-4 mb-4 mr-3 border-gray-100 w-5/6 shadow-sm">
|
||||
<h1 className="text-2xl font-thin">Our World in Data - COVID 19</h1>
|
||||
<p className="text-gray-500">Dataset</p>
|
||||
<p>data collected and managed by Our World in Data - COVID 19 pulled from GitHub on 06/10/2020 https://ourworldindata.org/coronavirus</p>
|
||||
<p>
|
||||
data collected and managed by Our World in Data - COVID 19 pulled
|
||||
from GitHub on 06/10/2020 https://ourworldindata.org/coronavirus
|
||||
</p>
|
||||
<Link href="/">
|
||||
<a className="pt-3 flex justify-end text-orange-500"> View Dataset </a>
|
||||
<a className="pt-3 flex justify-end text-orange-500">
|
||||
{' '}
|
||||
View Dataset{' '}
|
||||
</a>
|
||||
</Link>
|
||||
</div>
|
||||
<div className="border px-4 mb-4 border-gray-100 w-5/6 shadow-sm">
|
||||
<h1 className="text-2xl font-thin">Our World in Data - COVID 19</h1>
|
||||
<p className="text-gray-500 mb-2">Dataset</p>
|
||||
<p>data collected and managed by Our World in Data - COVID 19 pulled from GitHub on 06/10/2020 https://ourworldindata.org/coronavirus</p>
|
||||
<p>
|
||||
data collected and managed by Our World in Data - COVID 19 pulled
|
||||
from GitHub on 06/10/2020 https://ourworldindata.org/coronavirus
|
||||
</p>
|
||||
<Link href="/">
|
||||
<a className="pt-3 flex justify-end text-orange-500"> View Dataset </a>
|
||||
<a className="pt-3 flex justify-end text-orange-500">
|
||||
{' '}
|
||||
View Dataset{' '}
|
||||
</a>
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import Link from 'next/link'
|
||||
import Link from 'next/link';
|
||||
|
||||
export default function About({ resource }) {
|
||||
return (
|
||||
@ -18,21 +18,23 @@ export default function About({ resource }) {
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td className="px-4 py-2">{ resource.name || resource.id }</td>
|
||||
<td className="px-4 py-2">{ resource.title || '' }</td>
|
||||
<td className="px-4 py-2">{ resource.description || '' }</td>
|
||||
<td className="px-4 py-2">{ resource.format }</td>
|
||||
<td className="px-4 py-2">{ resource.size }</td>
|
||||
<td className="px-4 py-2">{ resource.created }</td>
|
||||
<td className="px-4 py-2">{ resource.last_modified || '' }</td>
|
||||
<td className="px-4 py-2">{resource.name || resource.id}</td>
|
||||
<td className="px-4 py-2">{resource.title || ''}</td>
|
||||
<td className="px-4 py-2">{resource.description || ''}</td>
|
||||
<td className="px-4 py-2">{resource.format}</td>
|
||||
<td className="px-4 py-2">{resource.size}</td>
|
||||
<td className="px-4 py-2">{resource.created}</td>
|
||||
<td className="px-4 py-2">{resource.last_modified || ''}</td>
|
||||
<td className="px-4 py-2">
|
||||
<Link href={resource.path}>
|
||||
<a className="bg-white hover:bg-gray-200 border text-black font-semibold py-2 px-4 rounded">{ resource.format }</a>
|
||||
<a className="bg-white hover:bg-gray-200 border text-black font-semibold py-2 px-4 rounded">
|
||||
{resource.format}
|
||||
</a>
|
||||
</Link>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import Link from 'next/link'
|
||||
import Link from 'next/link';
|
||||
|
||||
export default function DataExplorer({ resource }) {
|
||||
return <>{JSON.stringify(resource)}</>
|
||||
return <>{JSON.stringify(resource)}</>;
|
||||
}
|
||||
|
||||
@ -1,35 +1,40 @@
|
||||
import { useState } from 'react'
|
||||
import { useRouter } from 'next/router'
|
||||
import Link from 'next/link'
|
||||
import { useState } from 'react';
|
||||
import { useRouter } from 'next/router';
|
||||
import Link from 'next/link';
|
||||
|
||||
export default function Input({ query }) {
|
||||
const router = useRouter()
|
||||
const [q, setQ] = useState(query.q)
|
||||
const router = useRouter();
|
||||
const [q, setQ] = useState(query.q);
|
||||
|
||||
const handleChange = (event) => {
|
||||
setQ(event.target.value)
|
||||
}
|
||||
setQ(event.target.value);
|
||||
};
|
||||
|
||||
const handleSubmit = (event) => {
|
||||
event.preventDefault()
|
||||
event.preventDefault();
|
||||
router.push({
|
||||
pathname: '/search',
|
||||
query: { q },
|
||||
})
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<form onSubmit={handleSubmit} className="flex items-center">
|
||||
<input
|
||||
type='text'
|
||||
name='q'
|
||||
value={q}
|
||||
onChange={handleChange}
|
||||
placeholder='Search'
|
||||
aria-label='Search'
|
||||
className="bg-white focus:outline-none focus:shadow-outline border border-gray-300 w-1/2 rounded-lg py-2 px-4 block appearance-none leading-normal"
|
||||
/>
|
||||
<button onClick={handleSubmit} className="inline-block text-sm px-4 py-3 mx-3 leading-none border rounded text-white bg-black border-black lg:mt-0">Search</button>
|
||||
type="text"
|
||||
name="q"
|
||||
value={q}
|
||||
onChange={handleChange}
|
||||
placeholder="Search"
|
||||
aria-label="Search"
|
||||
className="bg-white focus:outline-none focus:shadow-outline border border-gray-300 w-1/2 rounded-lg py-2 px-4 block appearance-none leading-normal"
|
||||
/>
|
||||
<button
|
||||
onClick={handleSubmit}
|
||||
className="inline-block text-sm px-4 py-3 mx-3 leading-none border rounded text-white bg-black border-black lg:mt-0"
|
||||
>
|
||||
Search
|
||||
</button>
|
||||
</form>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@ -1,21 +1,31 @@
|
||||
import Link from 'next/link'
|
||||
import Link from 'next/link';
|
||||
|
||||
export default function Item({ datapackage }) {
|
||||
return (
|
||||
<div className="mb-6">
|
||||
<h3 className="text-xl font-semibold">
|
||||
<Link href={`/@${datapackage.organization ? datapackage.organization.name : 'dataset'}/${datapackage.name}`}>
|
||||
<a className="text-primary">{ datapackage.title || datapackage.name }</a>
|
||||
<Link
|
||||
href={`/@${
|
||||
datapackage.organization ? datapackage.organization.name : 'dataset'
|
||||
}/${datapackage.name}`}
|
||||
>
|
||||
<a className="text-primary">
|
||||
{datapackage.title || datapackage.name}
|
||||
</a>
|
||||
</Link>
|
||||
</h3>
|
||||
<Link href={`/@${datapackage.organization ? datapackage.organization.name : 'dataset'}`}>
|
||||
<Link
|
||||
href={`/@${
|
||||
datapackage.organization ? datapackage.organization.name : 'dataset'
|
||||
}`}
|
||||
>
|
||||
<a className="text-gray-500 block mt-1">
|
||||
{ datapackage.organization ? datapackage.organization.title : 'dataset' }
|
||||
{datapackage.organization
|
||||
? datapackage.organization.title
|
||||
: 'dataset'}
|
||||
</a>
|
||||
</Link>
|
||||
<div className="leading-relaxed mt-2">
|
||||
{ datapackage.description }
|
||||
</div>
|
||||
<div className="leading-relaxed mt-2">{datapackage.description}</div>
|
||||
</div>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@ -1,9 +1,11 @@
|
||||
import Item from './Item'
|
||||
import Item from './Item';
|
||||
|
||||
export default function List({ datapackages }) {
|
||||
return (
|
||||
<ul>
|
||||
{datapackages.map((datapackage, index) => <Item datapackage={datapackage} key={index} />)}
|
||||
{datapackages.map((datapackage, index) => (
|
||||
<Item datapackage={datapackage} key={index} />
|
||||
))}
|
||||
</ul>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@ -10,5 +10,5 @@ export default function Sort() {
|
||||
<option value="views_recent:desc">Popular</option>
|
||||
</select>
|
||||
</div>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
export default function Total({ total }) {
|
||||
return (
|
||||
<h1 className="text-3xl font-semibold text-primary my-6 inline-block">
|
||||
{ total } results found
|
||||
{total} results found
|
||||
</h1>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@ -1,15 +1,14 @@
|
||||
'use strict'
|
||||
'use strict';
|
||||
|
||||
const nconf = require('nconf')
|
||||
require('dotenv').config({path: process.env.DOTENV_PATH || '.env'})
|
||||
const nconf = require('nconf');
|
||||
require('dotenv').config({ path: process.env.DOTENV_PATH || '.env' });
|
||||
|
||||
nconf.argv()
|
||||
.env()
|
||||
nconf.argv().env();
|
||||
|
||||
nconf.use('memory')
|
||||
nconf.use('memory');
|
||||
|
||||
const dms = (process.env.DMS || 'http://mock.ckan').replace(/\/?$/, '')
|
||||
const cms = (process.env.CMS || 'http://mock.cms').replace(/\/?$/, '')
|
||||
const dms = (process.env.DMS || 'http://mock.ckan').replace(/\/?$/, '');
|
||||
const cms = (process.env.CMS || 'http://mock.cms').replace(/\/?$/, '');
|
||||
|
||||
// This is the object that you want to override in your own local config
|
||||
nconf.defaults({
|
||||
@ -17,10 +16,10 @@ nconf.defaults({
|
||||
debug: process.env.DEBUG || false,
|
||||
DMS: dms,
|
||||
CMS: cms,
|
||||
})
|
||||
});
|
||||
|
||||
module.exports = {
|
||||
get: nconf.get.bind(nconf),
|
||||
set: nconf.set.bind(nconf),
|
||||
reset: nconf.reset.bind(nconf)
|
||||
}
|
||||
reset: nconf.reset.bind(nconf),
|
||||
};
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
module.exports = {
|
||||
process() {
|
||||
return 'module.exports = {};'
|
||||
return 'module.exports = {};';
|
||||
},
|
||||
getCacheKey() {
|
||||
return 'cssTransform'
|
||||
return 'cssTransform';
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
@ -1,29 +1,29 @@
|
||||
module.exports = {
|
||||
collectCoverageFrom: [
|
||||
"**/*.{js,jsx,ts,tsx}",
|
||||
"!**/*.d.ts",
|
||||
"!**/node_modules/**",
|
||||
"!**/config/**",
|
||||
"!**/coverage/**",
|
||||
"!**/**.config.js**",
|
||||
'**/*.{js,jsx,ts,tsx}',
|
||||
'!**/*.d.ts',
|
||||
'!**/node_modules/**',
|
||||
'!**/config/**',
|
||||
'!**/coverage/**',
|
||||
'!**/**.config.js**',
|
||||
],
|
||||
setupFilesAfterEnv: ["<rootDir>/setupTests.js"],
|
||||
setupFilesAfterEnv: ['<rootDir>/setupTests.js'],
|
||||
testPathIgnorePatterns: [
|
||||
"/node_modules/",
|
||||
"/.next/",
|
||||
"/jest.config.js/",
|
||||
"/tailwind.config.js/",
|
||||
"<rootDir>/postcss.config.js",
|
||||
'/node_modules/',
|
||||
'/.next/',
|
||||
'/jest.config.js/',
|
||||
'/tailwind.config.js/',
|
||||
'<rootDir>/postcss.config.js',
|
||||
],
|
||||
transform: {
|
||||
"^.+\\.(js|jsx|ts|tsx)$": "<rootDir>/node_modules/babel-jest",
|
||||
"^.+\\.css$": "<rootDir>/config/jest/cssTransform.js",
|
||||
'^.+\\.(js|jsx|ts|tsx)$': '<rootDir>/node_modules/babel-jest',
|
||||
'^.+\\.css$': '<rootDir>/config/jest/cssTransform.js',
|
||||
},
|
||||
transformIgnorePatterns: [
|
||||
"/node_modules/",
|
||||
"^.+\\.module\\.(css|sass|scss)$",
|
||||
'/node_modules/',
|
||||
'^.+\\.module\\.(css|sass|scss)$',
|
||||
],
|
||||
moduleNameMapper: {
|
||||
"^.+\\.module\\.(css|sass|scss)$": "identity-obj-proxy",
|
||||
'^.+\\.module\\.(css|sass|scss)$': 'identity-obj-proxy',
|
||||
},
|
||||
};
|
||||
|
||||
204
mocks/index.js
204
mocks/index.js
@ -1,142 +1,146 @@
|
||||
const nock = require('nock')
|
||||
const nock = require('nock');
|
||||
|
||||
const gdp = {
|
||||
"name": "gdp",
|
||||
"title": "Country, Regional and World GDP (Gross Domestic Product)",
|
||||
"notes": "Country, regional and world GDP in current US Dollars ($). Regional means collections of countries e.g. Europe & Central Asia. Data is sourced from the World Bank and turned into a standard normalized CSV.",
|
||||
"resources": [
|
||||
name: 'gdp',
|
||||
title: 'Country, Regional and World GDP (Gross Domestic Product)',
|
||||
notes:
|
||||
'Country, regional and world GDP in current US Dollars ($). Regional means collections of countries e.g. Europe & Central Asia. Data is sourced from the World Bank and turned into a standard normalized CSV.',
|
||||
resources: [
|
||||
{
|
||||
"name": "gdp",
|
||||
"id": "gdp",
|
||||
"title": "GDP data",
|
||||
"format": "csv",
|
||||
"created": "2019-03-07T12:00:36.273495",
|
||||
"last_modified": "2020-05-07T12:00:36.273495",
|
||||
"datastore_active": false,
|
||||
"url": "http://mock.filestore/gdp.csv"
|
||||
}
|
||||
name: 'gdp',
|
||||
id: 'gdp',
|
||||
title: 'GDP data',
|
||||
format: 'csv',
|
||||
created: '2019-03-07T12:00:36.273495',
|
||||
last_modified: '2020-05-07T12:00:36.273495',
|
||||
datastore_active: false,
|
||||
url: 'http://mock.filestore/gdp.csv',
|
||||
},
|
||||
],
|
||||
"organization": {
|
||||
"title": "World Bank",
|
||||
"name": "world-bank",
|
||||
"description": "The World Bank is an international financial institution that provides loans and grants to the governments of poorer countries for the purpose of pursuing capital projects.",
|
||||
"created": "2019-03-07T11:51:13.758844",
|
||||
"image_url": "https://github.com/datahq/frontend/raw/master/public/img/avatars/world-bank.jpg"
|
||||
organization: {
|
||||
title: 'World Bank',
|
||||
name: 'world-bank',
|
||||
description:
|
||||
'The World Bank is an international financial institution that provides loans and grants to the governments of poorer countries for the purpose of pursuing capital projects.',
|
||||
created: '2019-03-07T11:51:13.758844',
|
||||
image_url:
|
||||
'https://github.com/datahq/frontend/raw/master/public/img/avatars/world-bank.jpg',
|
||||
},
|
||||
"metadata_created": "2019-03-07T11:56:19.696257",
|
||||
"metadata_modified": "2019-03-07T12:03:58.817280"
|
||||
}
|
||||
metadata_created: '2019-03-07T11:56:19.696257',
|
||||
metadata_modified: '2019-03-07T12:03:58.817280',
|
||||
};
|
||||
|
||||
const population = {
|
||||
"name": "population",
|
||||
"title": "World population data",
|
||||
"notes": "Population figures for countries, regions (e.g. Asia) and the world. Data comes originally from World Bank and has been converted into standard CSV.",
|
||||
"resources": [
|
||||
name: 'population',
|
||||
title: 'World population data',
|
||||
notes:
|
||||
'Population figures for countries, regions (e.g. Asia) and the world. Data comes originally from World Bank and has been converted into standard CSV.',
|
||||
resources: [
|
||||
{
|
||||
"name": "population",
|
||||
"id": "population",
|
||||
"title": "Population data",
|
||||
"format": "csv",
|
||||
"created": "2019-03-07T12:00:36.273495",
|
||||
"last_modified": "2020-05-07T12:00:36.273495",
|
||||
"datastore_active": true,
|
||||
"url": "http://mock.filestore/population.csv"
|
||||
}
|
||||
name: 'population',
|
||||
id: 'population',
|
||||
title: 'Population data',
|
||||
format: 'csv',
|
||||
created: '2019-03-07T12:00:36.273495',
|
||||
last_modified: '2020-05-07T12:00:36.273495',
|
||||
datastore_active: true,
|
||||
url: 'http://mock.filestore/population.csv',
|
||||
},
|
||||
],
|
||||
"organization": {
|
||||
"title": "World Bank",
|
||||
"name": "world-bank",
|
||||
"description": "The World Bank is an international financial institution that provides loans and grants to the governments of poorer countries for the purpose of pursuing capital projects.",
|
||||
"created": "2019-03-07T11:51:13.758844",
|
||||
"image_url": "https://github.com/datahq/frontend/raw/master/public/img/avatars/world-bank.jpg"
|
||||
}
|
||||
}
|
||||
organization: {
|
||||
title: 'World Bank',
|
||||
name: 'world-bank',
|
||||
description:
|
||||
'The World Bank is an international financial institution that provides loans and grants to the governments of poorer countries for the purpose of pursuing capital projects.',
|
||||
created: '2019-03-07T11:51:13.758844',
|
||||
image_url:
|
||||
'https://github.com/datahq/frontend/raw/master/public/img/avatars/world-bank.jpg',
|
||||
},
|
||||
};
|
||||
|
||||
module.exports.initMocks = function() {
|
||||
module.exports.initMocks = function () {
|
||||
// Uncomment this line if you want to record API calls
|
||||
// nock.recorder.rec()
|
||||
|
||||
|
||||
// "package_search" mocks
|
||||
nock('http://mock.ckan/api/3/action', {'encodedQueryParams':true})
|
||||
nock('http://mock.ckan/api/3/action', { encodedQueryParams: true })
|
||||
.persist()
|
||||
// 1. Call without query.
|
||||
.get('/package_search?facet.field=organization&facet.field=groups&facet.field=tags&facet.field=res_format&facet.field=license_id&facet.limit=5')
|
||||
.get(
|
||||
'/package_search?facet.field=organization&facet.field=groups&facet.field=tags&facet.field=res_format&facet.field=license_id&facet.limit=5'
|
||||
)
|
||||
.reply(200, {
|
||||
"success": true,
|
||||
"result": {
|
||||
"count": 2,
|
||||
"sort": "score desc, metadata_modified desc",
|
||||
"facets": {},
|
||||
"results": [
|
||||
gdp,
|
||||
population
|
||||
],
|
||||
"search_facets": {}
|
||||
}
|
||||
success: true,
|
||||
result: {
|
||||
count: 2,
|
||||
sort: 'score desc, metadata_modified desc',
|
||||
facets: {},
|
||||
results: [gdp, population],
|
||||
search_facets: {},
|
||||
},
|
||||
})
|
||||
// 2. Call with `q=gdp` query.
|
||||
.get('/package_search?q=gdp&facet.field=organization&facet.field=groups&facet.field=tags&facet.field=res_format&facet.field=license_id&facet.limit=5')
|
||||
.get(
|
||||
'/package_search?q=gdp&facet.field=organization&facet.field=groups&facet.field=tags&facet.field=res_format&facet.field=license_id&facet.limit=5'
|
||||
)
|
||||
.reply(200, {
|
||||
"success": true,
|
||||
"result": {
|
||||
"count": 1,
|
||||
"sort": "score desc, metadata_modified desc",
|
||||
"facets": {},
|
||||
"results": [
|
||||
gdp
|
||||
],
|
||||
"search_facets": {}
|
||||
}
|
||||
})
|
||||
success: true,
|
||||
result: {
|
||||
count: 1,
|
||||
sort: 'score desc, metadata_modified desc',
|
||||
facets: {},
|
||||
results: [gdp],
|
||||
search_facets: {},
|
||||
},
|
||||
});
|
||||
|
||||
// "package_show" mocks
|
||||
nock('http://mock.ckan/api/3/action', {'encodedQueryParams':true})
|
||||
nock('http://mock.ckan/api/3/action', { encodedQueryParams: true })
|
||||
.persist()
|
||||
.get('/package_show?id=gdp')
|
||||
.reply(200, {
|
||||
"success": true,
|
||||
"result": gdp
|
||||
success: true,
|
||||
result: gdp,
|
||||
})
|
||||
.get('/package_show?id=population')
|
||||
.reply(200, {
|
||||
"success": true,
|
||||
"result": population
|
||||
})
|
||||
success: true,
|
||||
result: population,
|
||||
});
|
||||
|
||||
// "datastore_search" mocks
|
||||
nock('http://mock.ckan/api/3/action', {'encodedQueryParams':true})
|
||||
nock('http://mock.ckan/api/3/action', { encodedQueryParams: true })
|
||||
.persist()
|
||||
.get('/datastore_search?resource_id=population')
|
||||
.reply(200, {
|
||||
"success": true,
|
||||
"result": {
|
||||
"records": [
|
||||
success: true,
|
||||
result: {
|
||||
records: [
|
||||
{
|
||||
"Country Code": "ARB",
|
||||
"Country Name": "Arab World",
|
||||
"Value": 92197753,
|
||||
"Year": 1960
|
||||
'Country Code': 'ARB',
|
||||
'Country Name': 'Arab World',
|
||||
Value: 92197753,
|
||||
Year: 1960,
|
||||
},
|
||||
{
|
||||
"Country Code": "ARB",
|
||||
"Country Name": "Arab World",
|
||||
"Value": 94724510,
|
||||
"Year": 1961
|
||||
'Country Code': 'ARB',
|
||||
'Country Name': 'Arab World',
|
||||
Value: 94724510,
|
||||
Year: 1961,
|
||||
},
|
||||
{
|
||||
"Country Code": "ARB",
|
||||
"Country Name": "Arab World",
|
||||
"Value": 97334442,
|
||||
"Year": 1962
|
||||
}
|
||||
]
|
||||
}
|
||||
})
|
||||
'Country Code': 'ARB',
|
||||
'Country Name': 'Arab World',
|
||||
Value: 97334442,
|
||||
Year: 1962,
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
|
||||
// Filestore mocks
|
||||
nock('http://mock.filestore', {'encodedQueryParams':true})
|
||||
nock('http://mock.filestore', { encodedQueryParams: true })
|
||||
.persist()
|
||||
.get('/gdp.csv')
|
||||
.reply(200, 'a,b,c\n1,2,3\n4,5,6\n')
|
||||
}
|
||||
.reply(200, 'a,b,c\n1,2,3\n4,5,6\n');
|
||||
};
|
||||
|
||||
15
package.json
15
package.json
@ -8,7 +8,9 @@
|
||||
"start": "next start",
|
||||
"test": "jest",
|
||||
"test:watch": "jest --watch",
|
||||
"test:coverage": "jest --coverage"
|
||||
"test:coverage": "jest --coverage",
|
||||
"format": "prettier --single-quote --write .",
|
||||
"pre-commit": "echo 'formating your changes.....' && prettier --single-quote --write"
|
||||
},
|
||||
"dependencies": {
|
||||
"bytes": "^3.1.0",
|
||||
@ -26,12 +28,23 @@
|
||||
"@types/react": "^16.9.35",
|
||||
"babel-jest": "^26.0.1",
|
||||
"dotenv": "^8.2.0",
|
||||
"husky": ">=4",
|
||||
"jest": "^26.0.1",
|
||||
"lint-staged": ">=10",
|
||||
"nconf": "^0.10.0",
|
||||
"nock": "^12.0.3",
|
||||
"postcss-preset-env": "^6.7.0",
|
||||
"prettier": "2.0.5",
|
||||
"react-test-renderer": "^16.13.1",
|
||||
"tailwindcss": "^1.4.6",
|
||||
"typescript": "^3.9.3"
|
||||
},
|
||||
"husky": {
|
||||
"hooks": {
|
||||
"pre-commit": "lint-staged"
|
||||
}
|
||||
},
|
||||
"lint-staged": {
|
||||
"*.{ts,tsx,js,jsx,css,html,md}": "yarn pre-commit"
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,11 +1,11 @@
|
||||
import { GetServerSideProps } from 'next'
|
||||
import config from '../../../config'
|
||||
import utils from '../../../utils'
|
||||
import Head from 'next/head'
|
||||
import Nav from '../../../components/home/Nav'
|
||||
import About from '../../../components/dataset/About'
|
||||
import Org from '../../../components/dataset/Org'
|
||||
import Resources from '../../../components/dataset/Resources'
|
||||
import { GetServerSideProps } from 'next';
|
||||
import config from '../../../config';
|
||||
import utils from '../../../utils';
|
||||
import Head from 'next/head';
|
||||
import Nav from '../../../components/home/Nav';
|
||||
import About from '../../../components/dataset/About';
|
||||
import Org from '../../../components/dataset/Org';
|
||||
import Resources from '../../../components/dataset/Resources';
|
||||
|
||||
function Dataset({ datapackage }) {
|
||||
return (
|
||||
@ -17,21 +17,23 @@ function Dataset({ datapackage }) {
|
||||
<Nav />
|
||||
<main className="p-6">
|
||||
<h1 className="text-3xl font-semibold text-primary mb-2">
|
||||
{ datapackage.title || datapackage.name }
|
||||
{datapackage.title || datapackage.name}
|
||||
</h1>
|
||||
<Org org={datapackage.organization} />
|
||||
<About datapackage={datapackage} />
|
||||
<Resources datapackage={datapackage} />
|
||||
</main>
|
||||
</>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
export const getServerSideProps: GetServerSideProps = async (context) => {
|
||||
const res = await fetch(`${config.get('DMS')}/api/3/action/package_show?id=${context.query.dataset}`)
|
||||
const ckanResult = (await res.json()).result
|
||||
const datapackage = utils.ckanToDataPackage(ckanResult)
|
||||
return { props: { datapackage } }
|
||||
}
|
||||
const res = await fetch(
|
||||
`${config.get('DMS')}/api/3/action/package_show?id=${context.query.dataset}`
|
||||
);
|
||||
const ckanResult = (await res.json()).result;
|
||||
const datapackage = utils.ckanToDataPackage(ckanResult);
|
||||
return { props: { datapackage } };
|
||||
};
|
||||
|
||||
export default Dataset
|
||||
export default Dataset;
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
import { GetServerSideProps } from 'next'
|
||||
import config from '../../../../../config'
|
||||
import utils from '../../../../../utils'
|
||||
import Head from 'next/head'
|
||||
import Nav from '../../../../../components/home/Nav'
|
||||
import About from '../../../../../components/resource/About'
|
||||
import DataExplorer from '../../../../../components/resource/DataExplorer'
|
||||
import { GetServerSideProps } from 'next';
|
||||
import config from '../../../../../config';
|
||||
import utils from '../../../../../utils';
|
||||
import Head from 'next/head';
|
||||
import Nav from '../../../../../components/home/Nav';
|
||||
import About from '../../../../../components/resource/About';
|
||||
import DataExplorer from '../../../../../components/resource/DataExplorer';
|
||||
|
||||
function Resource({ resource }) {
|
||||
return (
|
||||
@ -16,24 +16,29 @@ function Resource({ resource }) {
|
||||
<Nav />
|
||||
<main className="p-6">
|
||||
<h1 className="text-3xl font-semibold text-primary mb-2">
|
||||
{ resource.title || resource.name }
|
||||
{resource.title || resource.name}
|
||||
</h1>
|
||||
<About resource={resource} />
|
||||
<DataExplorer resource={resource} />
|
||||
</main>
|
||||
</>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
export const getServerSideProps: GetServerSideProps = async (context) => {
|
||||
const res = await fetch(`${config.get('DMS')}/api/3/action/package_show?id=${context.query.dataset}`)
|
||||
const ckanResult = (await res.json()).result
|
||||
const res = await fetch(
|
||||
`${config.get('DMS')}/api/3/action/package_show?id=${context.query.dataset}`
|
||||
);
|
||||
const ckanResult = (await res.json()).result;
|
||||
// Only keep single resource
|
||||
ckanResult.resources = ckanResult.resources.filter(resource => {
|
||||
return resource.name === context.query.resource || resource.id === context.query.resource
|
||||
})
|
||||
const resourceDescriptor = utils.ckanToDataPackage(ckanResult).resources[0]
|
||||
return { props: { resource: resourceDescriptor } }
|
||||
}
|
||||
ckanResult.resources = ckanResult.resources.filter((resource) => {
|
||||
return (
|
||||
resource.name === context.query.resource ||
|
||||
resource.id === context.query.resource
|
||||
);
|
||||
});
|
||||
const resourceDescriptor = utils.ckanToDataPackage(ckanResult).resources[0];
|
||||
return { props: { resource: resourceDescriptor } };
|
||||
};
|
||||
|
||||
export default Resource
|
||||
export default Resource;
|
||||
|
||||
@ -1,13 +1,13 @@
|
||||
/* istanbul ignore file */
|
||||
import '../styles/index.css'
|
||||
import '../styles/index.css';
|
||||
|
||||
// Setup mocks
|
||||
if (process.env.NODE_ENV === 'development') {
|
||||
const mocks = require('../mocks')
|
||||
mocks.initMocks()
|
||||
console.warn('You have activated the mocks.')
|
||||
const mocks = require('../mocks');
|
||||
mocks.initMocks();
|
||||
console.warn('You have activated the mocks.');
|
||||
}
|
||||
|
||||
export default function MyApp({ Component, pageProps }) {
|
||||
return <Component {...pageProps} />
|
||||
return <Component {...pageProps} />;
|
||||
}
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import Head from 'next/head'
|
||||
import Nav from '../components/home/Nav'
|
||||
import Recent from '../components/home/Recent'
|
||||
import Input from '../components/search/Input'
|
||||
import Head from 'next/head';
|
||||
import Nav from '../components/home/Nav';
|
||||
import Recent from '../components/home/Recent';
|
||||
import Input from '../components/search/Input';
|
||||
|
||||
export default function Home() {
|
||||
return (
|
||||
@ -13,9 +13,15 @@ export default function Home() {
|
||||
<Nav />
|
||||
<section className="flex justify-center items-center flex-col mt-8 mx-4 lg:flex-row">
|
||||
<div>
|
||||
<h1 className="text-4xl mb-3 font-thin">Find, Share and Publish <br /> Quality Data with <span className="text-orange-500">Datahub</span>
|
||||
<h1 className="text-4xl mb-3 font-thin">
|
||||
Find, Share and Publish <br /> Quality Data with{' '}
|
||||
<span className="text-orange-500">Datahub</span>
|
||||
</h1>
|
||||
<p className="text-md font-light mb-3 w-4/5">At Datahub, we have over thousands of datasets for free and a Premium Data Service for additional or customised data with guaranteed updates.</p>
|
||||
<p className="text-md font-light mb-3 w-4/5">
|
||||
At Datahub, we have over thousands of datasets for free and a
|
||||
Premium Data Service for additional or customised data with
|
||||
guaranteed updates.
|
||||
</p>
|
||||
<Input query={{}} />
|
||||
</div>
|
||||
<div className="mt-4">
|
||||
@ -24,5 +30,5 @@ export default function Home() {
|
||||
</section>
|
||||
<Recent />
|
||||
</div>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@ -1,42 +1,46 @@
|
||||
import { GetServerSideProps } from 'next'
|
||||
import querystring from 'querystring'
|
||||
import config from '../config'
|
||||
import utils from '../utils'
|
||||
import Head from 'next/head'
|
||||
import Nav from '../components/home/Nav'
|
||||
import Input from '../components/search/Input'
|
||||
import Total from '../components/search/Total'
|
||||
import Sort from '../components/search/Sort'
|
||||
import List from '../components/search/List'
|
||||
import { GetServerSideProps } from 'next';
|
||||
import querystring from 'querystring';
|
||||
import config from '../config';
|
||||
import utils from '../utils';
|
||||
import Head from 'next/head';
|
||||
import Nav from '../components/home/Nav';
|
||||
import Input from '../components/search/Input';
|
||||
import Total from '../components/search/Total';
|
||||
import Sort from '../components/search/Sort';
|
||||
import List from '../components/search/List';
|
||||
|
||||
function Search({ ckanResult, datapackages, query }) {
|
||||
return (
|
||||
<>
|
||||
<Head>
|
||||
<title>Portal | Search</title>
|
||||
<link rel="icon" href="/favicon.ico" />
|
||||
</Head>
|
||||
<Nav />
|
||||
<main className="p-6">
|
||||
<Input query={query} />
|
||||
<Total total={ckanResult.count} />
|
||||
<Sort />
|
||||
<List datapackages={datapackages} />
|
||||
</main>
|
||||
<Head>
|
||||
<title>Portal | Search</title>
|
||||
<link rel="icon" href="/favicon.ico" />
|
||||
</Head>
|
||||
<Nav />
|
||||
<main className="p-6">
|
||||
<Input query={query} />
|
||||
<Total total={ckanResult.count} />
|
||||
<Sort />
|
||||
<List datapackages={datapackages} />
|
||||
</main>
|
||||
</>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
export const getServerSideProps: GetServerSideProps = async (context) => {
|
||||
const query = context.query || {}
|
||||
const query = context.query || {};
|
||||
const ckanQuery = querystring.stringify(
|
||||
utils.convertToCkanSearchQuery(query)
|
||||
)
|
||||
const res = await fetch(`${config.get('DMS')}/api/3/action/package_search?${ckanQuery}`)
|
||||
const ckanResult = (await res.json()).result
|
||||
const datapackages = ckanResult.results.map(item => utils.ckanToDataPackage(item))
|
||||
);
|
||||
const res = await fetch(
|
||||
`${config.get('DMS')}/api/3/action/package_search?${ckanQuery}`
|
||||
);
|
||||
const ckanResult = (await res.json()).result;
|
||||
const datapackages = ckanResult.results.map((item) =>
|
||||
utils.ckanToDataPackage(item)
|
||||
);
|
||||
|
||||
return { props: { ckanResult, datapackages, query } }
|
||||
}
|
||||
return { props: { ckanResult, datapackages, query } };
|
||||
};
|
||||
|
||||
export default Search
|
||||
export default Search;
|
||||
|
||||
@ -1,3 +1,3 @@
|
||||
module.exports = {
|
||||
plugins: ['tailwindcss', 'postcss-preset-env'],
|
||||
}
|
||||
};
|
||||
|
||||
@ -1 +1 @@
|
||||
import '@testing-library/jest-dom/extend-expect'
|
||||
import '@testing-library/jest-dom/extend-expect';
|
||||
|
||||
@ -1,3 +1,3 @@
|
||||
@import "tailwindcss/base";
|
||||
@import "tailwindcss/components";
|
||||
@import "tailwindcss/utilities";
|
||||
@import 'tailwindcss/base';
|
||||
@import 'tailwindcss/components';
|
||||
@import 'tailwindcss/utilities';
|
||||
|
||||
@ -1,10 +1,8 @@
|
||||
module.exports = {
|
||||
purge: [
|
||||
'./**/*.tsx'
|
||||
],
|
||||
purge: ['./**/*.tsx'],
|
||||
theme: {
|
||||
extend: {},
|
||||
},
|
||||
variants: {},
|
||||
plugins: [],
|
||||
}
|
||||
};
|
||||
|
||||
@ -1,11 +1,7 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "es5",
|
||||
"lib": [
|
||||
"dom",
|
||||
"dom.iterable",
|
||||
"esnext"
|
||||
],
|
||||
"lib": ["dom", "dom.iterable", "esnext"],
|
||||
"allowJs": true,
|
||||
"skipLibCheck": true,
|
||||
"strict": false,
|
||||
@ -18,12 +14,13 @@
|
||||
"isolatedModules": true,
|
||||
"jsx": "preserve"
|
||||
},
|
||||
"exclude": [
|
||||
"node_modules"
|
||||
],
|
||||
"exclude": ["node_modules"],
|
||||
"include": [
|
||||
"next-env.d.ts",
|
||||
"**/*.ts",
|
||||
"**/*.tsx", "setupTests.js", "jest.config.js", "config/jest/cssTransform.js"
|
||||
"**/*.tsx",
|
||||
"setupTests.js",
|
||||
"jest.config.js",
|
||||
"config/jest/cssTransform.js"
|
||||
]
|
||||
}
|
||||
|
||||
518
utils/index.js
518
utils/index.js
@ -1,123 +1,123 @@
|
||||
const { URL } = require('url')
|
||||
const bytes = require('bytes')
|
||||
const slugify = require('slugify')
|
||||
const config = require('../config')
|
||||
const { URL } = require('url');
|
||||
const bytes = require('bytes');
|
||||
const slugify = require('slugify');
|
||||
const config = require('../config');
|
||||
|
||||
module.exports.ckanToDataPackage = function (descriptor) {
|
||||
// Make a copy
|
||||
const datapackage = JSON.parse(JSON.stringify(descriptor))
|
||||
const datapackage = JSON.parse(JSON.stringify(descriptor));
|
||||
|
||||
// Lowercase name
|
||||
datapackage.name = datapackage.name.toLowerCase()
|
||||
datapackage.name = datapackage.name.toLowerCase();
|
||||
|
||||
// Rename notes => description
|
||||
if (datapackage.notes) {
|
||||
datapackage.description = datapackage.notes
|
||||
delete datapackage.notes
|
||||
datapackage.description = datapackage.notes;
|
||||
delete datapackage.notes;
|
||||
}
|
||||
|
||||
// Rename ckan_url => homepage
|
||||
if (datapackage.ckan_url) {
|
||||
datapackage.homepage = datapackage.ckan_url
|
||||
delete datapackage.ckan_url
|
||||
datapackage.homepage = datapackage.ckan_url;
|
||||
delete datapackage.ckan_url;
|
||||
}
|
||||
|
||||
// Parse license
|
||||
const license = {}
|
||||
const license = {};
|
||||
if (datapackage.license_id) {
|
||||
license.type = datapackage.license_id
|
||||
delete datapackage.license_id
|
||||
license.type = datapackage.license_id;
|
||||
delete datapackage.license_id;
|
||||
}
|
||||
if (datapackage.license_title) {
|
||||
license.title = datapackage.license_title
|
||||
delete datapackage.license_title
|
||||
license.title = datapackage.license_title;
|
||||
delete datapackage.license_title;
|
||||
}
|
||||
if (datapackage.license_url) {
|
||||
license.url = datapackage.license_url
|
||||
delete datapackage.license_url
|
||||
license.url = datapackage.license_url;
|
||||
delete datapackage.license_url;
|
||||
}
|
||||
if (Object.keys(license).length > 0) {
|
||||
datapackage.license = license
|
||||
datapackage.license = license;
|
||||
}
|
||||
|
||||
// Parse author and sources
|
||||
const source = {}
|
||||
const source = {};
|
||||
if (datapackage.author) {
|
||||
source.name = datapackage.author
|
||||
delete datapackage.author
|
||||
source.name = datapackage.author;
|
||||
delete datapackage.author;
|
||||
}
|
||||
if (datapackage.author_email) {
|
||||
source.email = datapackage.author_email
|
||||
delete datapackage.author_email
|
||||
source.email = datapackage.author_email;
|
||||
delete datapackage.author_email;
|
||||
}
|
||||
if (datapackage.url) {
|
||||
source.web = datapackage.url
|
||||
delete datapackage.url
|
||||
source.web = datapackage.url;
|
||||
delete datapackage.url;
|
||||
}
|
||||
if (Object.keys(source).length > 0) {
|
||||
datapackage.sources = [source]
|
||||
datapackage.sources = [source];
|
||||
}
|
||||
|
||||
// Parse maintainer
|
||||
const author = {}
|
||||
const author = {};
|
||||
if (datapackage.maintainer) {
|
||||
author.name = datapackage.maintainer
|
||||
delete datapackage.maintainer
|
||||
author.name = datapackage.maintainer;
|
||||
delete datapackage.maintainer;
|
||||
}
|
||||
if (datapackage.maintainer_email) {
|
||||
author.email = datapackage.maintainer_email
|
||||
delete datapackage.maintainer_email
|
||||
author.email = datapackage.maintainer_email;
|
||||
delete datapackage.maintainer_email;
|
||||
}
|
||||
if (Object.keys(author).length > 0) {
|
||||
datapackage.author = author
|
||||
datapackage.author = author;
|
||||
}
|
||||
|
||||
// Parse tags
|
||||
if (datapackage.tags) {
|
||||
datapackage.keywords = []
|
||||
datapackage.tags.forEach(tag => {
|
||||
datapackage.keywords.push(tag.name)
|
||||
})
|
||||
delete datapackage.tags
|
||||
datapackage.keywords = [];
|
||||
datapackage.tags.forEach((tag) => {
|
||||
datapackage.keywords.push(tag.name);
|
||||
});
|
||||
delete datapackage.tags;
|
||||
}
|
||||
|
||||
// Parse extras
|
||||
// TODO
|
||||
|
||||
// Resources
|
||||
datapackage.resources = datapackage.resources.map(resource => {
|
||||
datapackage.resources = datapackage.resources.map((resource) => {
|
||||
if (resource.name) {
|
||||
resource.title = resource.title || resource.name
|
||||
resource.name = resource.name.toLowerCase().replace(/ /g, '_')
|
||||
resource.title = resource.title || resource.name;
|
||||
resource.name = resource.name.toLowerCase().replace(/ /g, '_');
|
||||
} else {
|
||||
resource.name = resource.id
|
||||
resource.name = resource.id;
|
||||
}
|
||||
|
||||
if (resource.url) {
|
||||
resource.path = resource.url
|
||||
delete resource.url
|
||||
resource.path = resource.url;
|
||||
delete resource.url;
|
||||
}
|
||||
|
||||
if (!resource.schema) {
|
||||
// If 'fields' property exists use it as schema fields
|
||||
if (resource.fields) {
|
||||
if (typeof(resource.fields) === 'string') {
|
||||
if (typeof resource.fields === 'string') {
|
||||
try {
|
||||
resource.fields = JSON.parse(resource.fields)
|
||||
resource.fields = JSON.parse(resource.fields);
|
||||
} catch (e) {
|
||||
console.log('Could not parse resource.fields')
|
||||
console.log('Could not parse resource.fields');
|
||||
}
|
||||
}
|
||||
resource.schema = {fields: resource.fields}
|
||||
delete resource.fields
|
||||
resource.schema = { fields: resource.fields };
|
||||
delete resource.fields;
|
||||
}
|
||||
}
|
||||
|
||||
return resource
|
||||
})
|
||||
return resource;
|
||||
});
|
||||
|
||||
return datapackage
|
||||
}
|
||||
return datapackage;
|
||||
};
|
||||
|
||||
/*
|
||||
At the moment, we're considering only following examples of CKAN view:
|
||||
@ -141,86 +141,98 @@ module.exports.ckanViewToDataPackageView = (ckanView) => {
|
||||
geojson_view: 'map',
|
||||
pdf_view: 'document',
|
||||
image_view: 'web',
|
||||
webpage_view: 'web'
|
||||
}
|
||||
const dataPackageView = JSON.parse(JSON.stringify(ckanView))
|
||||
dataPackageView.specType = viewTypeToSpecType[ckanView.view_type]
|
||||
|| dataPackageView.specType
|
||||
|| 'unsupported'
|
||||
webpage_view: 'web',
|
||||
};
|
||||
const dataPackageView = JSON.parse(JSON.stringify(ckanView));
|
||||
dataPackageView.specType =
|
||||
viewTypeToSpecType[ckanView.view_type] ||
|
||||
dataPackageView.specType ||
|
||||
'unsupported';
|
||||
|
||||
if (dataPackageView.specType === 'dataExplorer') {
|
||||
dataPackageView.spec = {
|
||||
widgets: [
|
||||
{specType: 'table'},
|
||||
{specType: 'simple'},
|
||||
{specType: 'tabularmap'}
|
||||
]
|
||||
}
|
||||
{ specType: 'table' },
|
||||
{ specType: 'simple' },
|
||||
{ specType: 'tabularmap' },
|
||||
],
|
||||
};
|
||||
} else if (dataPackageView.specType === 'simple') {
|
||||
const graphTypeConvert = {
|
||||
lines: 'line',
|
||||
'lines-and-points': 'lines-and-points',
|
||||
points: 'points',
|
||||
bars: 'horizontal-bar',
|
||||
columns: 'bar'
|
||||
}
|
||||
columns: 'bar',
|
||||
};
|
||||
dataPackageView.spec = {
|
||||
group: ckanView.group,
|
||||
series: Array.isArray(ckanView.series) ? ckanView.series : [ckanView.series],
|
||||
type: graphTypeConvert[ckanView.graph_type] || 'line'
|
||||
}
|
||||
series: Array.isArray(ckanView.series)
|
||||
? ckanView.series
|
||||
: [ckanView.series],
|
||||
type: graphTypeConvert[ckanView.graph_type] || 'line',
|
||||
};
|
||||
} else if (dataPackageView.specType === 'tabularmap') {
|
||||
if (ckanView.map_field_type === 'geojson') {
|
||||
dataPackageView.spec = {
|
||||
geomField: ckanView.geojson_field
|
||||
}
|
||||
geomField: ckanView.geojson_field,
|
||||
};
|
||||
} else {
|
||||
dataPackageView.spec = {
|
||||
lonField: ckanView.longitude_field,
|
||||
latField: ckanView.latitude_field
|
||||
}
|
||||
latField: ckanView.latitude_field,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return dataPackageView
|
||||
}
|
||||
return dataPackageView;
|
||||
};
|
||||
|
||||
/*
|
||||
Takes single field descriptor from datastore data dictionary and coverts into
|
||||
tableschema field descriptor.
|
||||
*/
|
||||
module.exports.dataStoreDataDictionaryToTableSchema = (dataDictionary) => {
|
||||
const internalDataStoreFields = ['_id', '_full_text', '_count']
|
||||
const internalDataStoreFields = ['_id', '_full_text', '_count'];
|
||||
if (internalDataStoreFields.includes(dataDictionary.id)) {
|
||||
return null
|
||||
return null;
|
||||
}
|
||||
const dataDictionaryType2TableSchemaType = {
|
||||
'text': 'string',
|
||||
'int': 'integer',
|
||||
'float': 'number',
|
||||
'date': 'date',
|
||||
'time': 'time',
|
||||
'timestamp': 'datetime',
|
||||
'bool': 'boolean',
|
||||
'json': 'object'
|
||||
}
|
||||
text: 'string',
|
||||
int: 'integer',
|
||||
float: 'number',
|
||||
date: 'date',
|
||||
time: 'time',
|
||||
timestamp: 'datetime',
|
||||
bool: 'boolean',
|
||||
json: 'object',
|
||||
};
|
||||
const field = {
|
||||
name: dataDictionary.id,
|
||||
type: dataDictionaryType2TableSchemaType[dataDictionary.type] || 'any'
|
||||
}
|
||||
type: dataDictionaryType2TableSchemaType[dataDictionary.type] || 'any',
|
||||
};
|
||||
if (dataDictionary.info) {
|
||||
const constraintsAttributes = ['required', 'unique', 'minLength', 'maxLength', 'minimum', 'maximum', 'pattern', 'enum']
|
||||
field.constraints = {}
|
||||
Object.keys(dataDictionary.info).forEach(key => {
|
||||
const constraintsAttributes = [
|
||||
'required',
|
||||
'unique',
|
||||
'minLength',
|
||||
'maxLength',
|
||||
'minimum',
|
||||
'maximum',
|
||||
'pattern',
|
||||
'enum',
|
||||
];
|
||||
field.constraints = {};
|
||||
Object.keys(dataDictionary.info).forEach((key) => {
|
||||
if (constraintsAttributes.includes(key)) {
|
||||
field.constraints[key] = dataDictionary.info[key]
|
||||
field.constraints[key] = dataDictionary.info[key];
|
||||
} else {
|
||||
field[key] = dataDictionary.info[key]
|
||||
field[key] = dataDictionary.info[key];
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
return field
|
||||
}
|
||||
return field;
|
||||
};
|
||||
|
||||
module.exports.convertToStandardCollection = (descriptor) => {
|
||||
const standard = {
|
||||
@ -228,20 +240,19 @@ module.exports.convertToStandardCollection = (descriptor) => {
|
||||
title: '',
|
||||
summary: '',
|
||||
image: '',
|
||||
count: null
|
||||
}
|
||||
count: null,
|
||||
};
|
||||
|
||||
standard.name = descriptor.name
|
||||
standard.title = descriptor.title || descriptor.display_name
|
||||
standard.summary = descriptor.description || ''
|
||||
standard.image = descriptor.image_display_url || descriptor.image_url
|
||||
standard.count = descriptor.package_count || 0
|
||||
standard.extras = descriptor.extras || []
|
||||
standard.groups = descriptor.groups || []
|
||||
|
||||
return standard
|
||||
}
|
||||
standard.name = descriptor.name;
|
||||
standard.title = descriptor.title || descriptor.display_name;
|
||||
standard.summary = descriptor.description || '';
|
||||
standard.image = descriptor.image_display_url || descriptor.image_url;
|
||||
standard.count = descriptor.package_count || 0;
|
||||
standard.extras = descriptor.extras || [];
|
||||
standard.groups = descriptor.groups || [];
|
||||
|
||||
return standard;
|
||||
};
|
||||
|
||||
module.exports.convertToCkanSearchQuery = (query) => {
|
||||
const ckanQuery = {
|
||||
@ -250,79 +261,87 @@ module.exports.convertToCkanSearchQuery = (query) => {
|
||||
rows: '',
|
||||
start: '',
|
||||
sort: '',
|
||||
'facet.field': ['organization', 'groups', 'tags', 'res_format', 'license_id'],
|
||||
'facet.field': [
|
||||
'organization',
|
||||
'groups',
|
||||
'tags',
|
||||
'res_format',
|
||||
'license_id',
|
||||
],
|
||||
'facet.limit': 5,
|
||||
'facet.mincount': 0
|
||||
}
|
||||
'facet.mincount': 0,
|
||||
};
|
||||
// Split by space but ignore spaces within double quotes:
|
||||
if (query.q) {
|
||||
query.q.match(/(?:[^\s"]+|"[^"]*")+/g).forEach(part => {
|
||||
query.q.match(/(?:[^\s"]+|"[^"]*")+/g).forEach((part) => {
|
||||
if (part.includes(':')) {
|
||||
ckanQuery.fq += part + ' '
|
||||
ckanQuery.fq += part + ' ';
|
||||
} else {
|
||||
ckanQuery.q += part + ' '
|
||||
ckanQuery.q += part + ' ';
|
||||
}
|
||||
})
|
||||
ckanQuery.fq = ckanQuery.fq.trim()
|
||||
ckanQuery.q = ckanQuery.q.trim()
|
||||
});
|
||||
ckanQuery.fq = ckanQuery.fq.trim();
|
||||
ckanQuery.q = ckanQuery.q.trim();
|
||||
}
|
||||
|
||||
if (query.fq) {
|
||||
ckanQuery.fq = ckanQuery.fq ? ckanQuery.fq + ' ' + query.fq : query.fq
|
||||
ckanQuery.fq = ckanQuery.fq ? ckanQuery.fq + ' ' + query.fq : query.fq;
|
||||
}
|
||||
|
||||
// standard 'size' => ckan 'rows'
|
||||
ckanQuery.rows = query.size || ''
|
||||
ckanQuery.rows = query.size || '';
|
||||
|
||||
// standard 'from' => ckan 'start'
|
||||
ckanQuery.start = query.from || ''
|
||||
ckanQuery.start = query.from || '';
|
||||
|
||||
// standard 'sort' => ckan 'sort'
|
||||
const sortQueries = []
|
||||
const sortQueries = [];
|
||||
if (query.sort && query.sort.constructor == Object) {
|
||||
for (let [key, value] of Object.entries(query.sort)) {
|
||||
sortQueries.push(`${key} ${value}`)
|
||||
sortQueries.push(`${key} ${value}`);
|
||||
}
|
||||
ckanQuery.sort = sortQueries.join(',')
|
||||
ckanQuery.sort = sortQueries.join(',');
|
||||
} else if (query.sort && query.sort.constructor == String) {
|
||||
ckanQuery.sort = query.sort.replace(':', ' ')
|
||||
ckanQuery.sort = query.sort.replace(':', ' ');
|
||||
} else if (query.sort && query.sort.constructor == Array) {
|
||||
query.sort.forEach(sort => {
|
||||
sortQueries.push(sort.replace(':', ' '))
|
||||
})
|
||||
ckanQuery.sort = sortQueries.join(',')
|
||||
query.sort.forEach((sort) => {
|
||||
sortQueries.push(sort.replace(':', ' '));
|
||||
});
|
||||
ckanQuery.sort = sortQueries.join(',');
|
||||
}
|
||||
|
||||
// Facets
|
||||
ckanQuery['facet.field'] = query['facet.field'] || ckanQuery['facet.field']
|
||||
ckanQuery['facet.limit'] = query['facet.limit'] || ckanQuery['facet.limit']
|
||||
ckanQuery['facet.mincount'] = query['facet.mincount'] || ckanQuery['facet.mincount']
|
||||
ckanQuery['facet.field'] = query['facet.field'] || ckanQuery['facet.field']
|
||||
ckanQuery['facet.field'] = query['facet.field'] || ckanQuery['facet.field'];
|
||||
ckanQuery['facet.limit'] = query['facet.limit'] || ckanQuery['facet.limit'];
|
||||
ckanQuery['facet.mincount'] =
|
||||
query['facet.mincount'] || ckanQuery['facet.mincount'];
|
||||
ckanQuery['facet.field'] = query['facet.field'] || ckanQuery['facet.field'];
|
||||
|
||||
// Remove attributes with empty string, null or undefined values
|
||||
Object.keys(ckanQuery).forEach((key) => (!ckanQuery[key]) && delete ckanQuery[key])
|
||||
|
||||
return ckanQuery
|
||||
}
|
||||
Object.keys(ckanQuery).forEach(
|
||||
(key) => !ckanQuery[key] && delete ckanQuery[key]
|
||||
);
|
||||
|
||||
return ckanQuery;
|
||||
};
|
||||
|
||||
module.exports.pagination = (c, m) => {
|
||||
let current = c,
|
||||
last = m,
|
||||
delta = 2,
|
||||
left = current - delta,
|
||||
right = current + delta + 1,
|
||||
range = [],
|
||||
rangeWithDots = [],
|
||||
l;
|
||||
last = m,
|
||||
delta = 2,
|
||||
left = current - delta,
|
||||
right = current + delta + 1,
|
||||
range = [],
|
||||
rangeWithDots = [],
|
||||
l;
|
||||
|
||||
range.push(1)
|
||||
range.push(1);
|
||||
for (let i = c - delta; i <= c + delta; i++) {
|
||||
if (i >= left && i < right && i < m && i > 1) {
|
||||
range.push(i);
|
||||
}
|
||||
}
|
||||
range.push(m)
|
||||
range.push(m);
|
||||
|
||||
for (let i of range) {
|
||||
if (l) {
|
||||
@ -336,15 +355,13 @@ module.exports.pagination = (c, m) => {
|
||||
l = i;
|
||||
}
|
||||
return rangeWithDots;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
module.exports.processMarkdown = require('markdown-it')({
|
||||
html: true,
|
||||
linkify: true,
|
||||
typographer: true
|
||||
})
|
||||
|
||||
typographer: true,
|
||||
});
|
||||
|
||||
/**
|
||||
* Process data package attributes prior to display to users.
|
||||
@ -353,39 +370,41 @@ module.exports.processMarkdown = require('markdown-it')({
|
||||
* etc.
|
||||
**/
|
||||
module.exports.processDataPackage = function (datapackage) {
|
||||
const newDatapackage = JSON.parse(JSON.stringify(datapackage))
|
||||
const newDatapackage = JSON.parse(JSON.stringify(datapackage));
|
||||
if (newDatapackage.description) {
|
||||
newDatapackage.descriptionHtml = module.exports.processMarkdown
|
||||
.render(newDatapackage.description)
|
||||
newDatapackage.descriptionHtml = module.exports.processMarkdown.render(
|
||||
newDatapackage.description
|
||||
);
|
||||
}
|
||||
|
||||
if (newDatapackage.readme) {
|
||||
newDatapackage.readmeHtml = module.exports.processMarkdown
|
||||
.render(newDatapackage.readme)
|
||||
newDatapackage.readmeHtml = module.exports.processMarkdown.render(
|
||||
newDatapackage.readme
|
||||
);
|
||||
}
|
||||
|
||||
newDatapackage.formats = newDatapackage.formats || []
|
||||
newDatapackage.formats = newDatapackage.formats || [];
|
||||
// Per each resource:
|
||||
newDatapackage.resources.forEach(resource => {
|
||||
newDatapackage.resources.forEach((resource) => {
|
||||
if (resource.description) {
|
||||
resource.descriptionHtml = module.exports.processMarkdown
|
||||
.render(resource.description)
|
||||
resource.descriptionHtml = module.exports.processMarkdown.render(
|
||||
resource.description
|
||||
);
|
||||
}
|
||||
// Normalize format (lowercase)
|
||||
if (resource.format) {
|
||||
resource.format = resource.format.toLowerCase()
|
||||
newDatapackage.formats.push(resource.format)
|
||||
resource.format = resource.format.toLowerCase();
|
||||
newDatapackage.formats.push(resource.format);
|
||||
}
|
||||
|
||||
// Convert bytes into human-readable format:
|
||||
if (resource.size) {
|
||||
resource.sizeFormatted = bytes(resource.size, {decimalPlaces: 0})
|
||||
resource.sizeFormatted = bytes(resource.size, { decimalPlaces: 0 });
|
||||
}
|
||||
})
|
||||
|
||||
return newDatapackage
|
||||
}
|
||||
});
|
||||
|
||||
return newDatapackage;
|
||||
};
|
||||
|
||||
/**
|
||||
* Create 'displayResources' property which has:
|
||||
@ -396,114 +415,127 @@ module.exports.processDataPackage = function (datapackage) {
|
||||
* slug: slugified name of a resource
|
||||
**/
|
||||
module.exports.prepareResourcesForDisplay = function (datapackage) {
|
||||
const newDatapackage = JSON.parse(JSON.stringify(datapackage))
|
||||
newDatapackage.displayResources = []
|
||||
const newDatapackage = JSON.parse(JSON.stringify(datapackage));
|
||||
newDatapackage.displayResources = [];
|
||||
newDatapackage.resources.forEach((resource, index) => {
|
||||
const api = resource.datastore_active
|
||||
? config.get('API_URL') + 'datastore_search?resource_id=' + resource.id + '&sort=_id asc'
|
||||
: null
|
||||
? config.get('API_URL') +
|
||||
'datastore_search?resource_id=' +
|
||||
resource.id +
|
||||
'&sort=_id asc'
|
||||
: null;
|
||||
// Use proxy path if datastore/filestore proxies are given:
|
||||
let proxy, cc_proxy
|
||||
let proxy, cc_proxy;
|
||||
try {
|
||||
const resourceUrl = new URL(resource.path)
|
||||
if (resourceUrl.host === config.get('PROXY_DATASTORE') && resource.format !== 'pdf') {
|
||||
proxy = '/proxy/datastore' + resourceUrl.pathname + resourceUrl.search
|
||||
const resourceUrl = new URL(resource.path);
|
||||
if (
|
||||
resourceUrl.host === config.get('PROXY_DATASTORE') &&
|
||||
resource.format !== 'pdf'
|
||||
) {
|
||||
proxy = '/proxy/datastore' + resourceUrl.pathname + resourceUrl.search;
|
||||
}
|
||||
if (resourceUrl.host === config.get('PROXY_FILESTORE') && resource.format !== 'pdf') {
|
||||
proxy = '/proxy/filestore' + resourceUrl.pathname + resourceUrl.search
|
||||
if (
|
||||
resourceUrl.host === config.get('PROXY_FILESTORE') &&
|
||||
resource.format !== 'pdf'
|
||||
) {
|
||||
proxy = '/proxy/filestore' + resourceUrl.pathname + resourceUrl.search;
|
||||
}
|
||||
// Store a CKAN Classic proxy path
|
||||
// https://github.com/ckan/ckan/blob/master/ckanext/resourceproxy/plugin.py#L59
|
||||
const apiUrlObject = new URL(config.get('API_URL'))
|
||||
cc_proxy = apiUrlObject.origin + `/dataset/${datapackage.id}/resource/${resource.id}/proxy`
|
||||
const apiUrlObject = new URL(config.get('API_URL'));
|
||||
cc_proxy =
|
||||
apiUrlObject.origin +
|
||||
`/dataset/${datapackage.id}/resource/${resource.id}/proxy`;
|
||||
} catch (e) {
|
||||
console.warn(e)
|
||||
console.warn(e);
|
||||
}
|
||||
const displayResource = {
|
||||
resource,
|
||||
api, // URI for getting the resource via API, e.g., Datastore. Useful when you want to fetch only 100 rows or similar.
|
||||
proxy, // alternative for path in case there is CORS issue
|
||||
cc_proxy,
|
||||
slug: slugify(resource.name) + '-' + index // Used for anchor links
|
||||
}
|
||||
newDatapackage.displayResources.push(displayResource)
|
||||
})
|
||||
return newDatapackage
|
||||
}
|
||||
|
||||
slug: slugify(resource.name) + '-' + index, // Used for anchor links
|
||||
};
|
||||
newDatapackage.displayResources.push(displayResource);
|
||||
});
|
||||
return newDatapackage;
|
||||
};
|
||||
|
||||
/**
|
||||
* Prepare 'views' property which is used by 'datapackage-views-js' library to
|
||||
* render visualizations such as tables, graphs and maps.
|
||||
**/
|
||||
module.exports.prepareViews = function (datapackage) {
|
||||
const newDatapackage = JSON.parse(JSON.stringify(datapackage))
|
||||
newDatapackage.views = newDatapackage.views || []
|
||||
newDatapackage.resources.forEach(resource => {
|
||||
const resourceViews = resource.views && resource.views.map(view => {
|
||||
view.resources = [resource.name]
|
||||
return view
|
||||
})
|
||||
const newDatapackage = JSON.parse(JSON.stringify(datapackage));
|
||||
newDatapackage.views = newDatapackage.views || [];
|
||||
newDatapackage.resources.forEach((resource) => {
|
||||
const resourceViews =
|
||||
resource.views &&
|
||||
resource.views.map((view) => {
|
||||
view.resources = [resource.name];
|
||||
return view;
|
||||
});
|
||||
|
||||
newDatapackage.views = newDatapackage.views.concat(resourceViews)
|
||||
})
|
||||
|
||||
return newDatapackage
|
||||
}
|
||||
newDatapackage.views = newDatapackage.views.concat(resourceViews);
|
||||
});
|
||||
|
||||
return newDatapackage;
|
||||
};
|
||||
|
||||
/**
|
||||
* Create 'dataExplorers' property which is used by 'data-explorer' library to
|
||||
* render data explorer widgets.
|
||||
**/
|
||||
module.exports.prepareDataExplorers = function (datapackage) {
|
||||
const newDatapackage = JSON.parse(JSON.stringify(datapackage))
|
||||
const newDatapackage = JSON.parse(JSON.stringify(datapackage));
|
||||
newDatapackage.displayResources.forEach((displayResource, idx) => {
|
||||
newDatapackage.displayResources[idx].dataExplorers = []
|
||||
displayResource.resource.views && displayResource.resource.views.forEach(view => {
|
||||
const widgets = []
|
||||
if (view.specType === 'dataExplorer') {
|
||||
view.spec.widgets.forEach((widget, index) => {
|
||||
const widgetNames = {
|
||||
table: 'Table',
|
||||
simple: 'Chart',
|
||||
tabularmap: 'Map'
|
||||
}
|
||||
widget = {
|
||||
name: widgetNames[widget.specType] || 'Widget-' + index,
|
||||
active: index === 0 ? true : false,
|
||||
newDatapackage.displayResources[idx].dataExplorers = [];
|
||||
displayResource.resource.views &&
|
||||
displayResource.resource.views.forEach((view) => {
|
||||
const widgets = [];
|
||||
if (view.specType === 'dataExplorer') {
|
||||
view.spec.widgets.forEach((widget, index) => {
|
||||
const widgetNames = {
|
||||
table: 'Table',
|
||||
simple: 'Chart',
|
||||
tabularmap: 'Map',
|
||||
};
|
||||
widget = {
|
||||
name: widgetNames[widget.specType] || 'Widget-' + index,
|
||||
active: index === 0 ? true : false,
|
||||
datapackage: {
|
||||
views: [
|
||||
{
|
||||
id: view.id,
|
||||
specType: widget.specType,
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
widgets.push(widget);
|
||||
});
|
||||
} else {
|
||||
const widget = {
|
||||
name: view.title || '',
|
||||
active: true,
|
||||
datapackage: {
|
||||
views: [
|
||||
{
|
||||
id: view.id,
|
||||
specType: widget.specType
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
widgets.push(widget)
|
||||
})
|
||||
} else {
|
||||
const widget = {
|
||||
name: view.title || '',
|
||||
active: true,
|
||||
views: [view],
|
||||
},
|
||||
};
|
||||
widgets.push(widget);
|
||||
}
|
||||
|
||||
displayResource.resource.api =
|
||||
displayResource.resource.api || displayResource.api;
|
||||
const dataExplorer = JSON.stringify({
|
||||
widgets,
|
||||
datapackage: {
|
||||
views: [view]
|
||||
}
|
||||
}
|
||||
widgets.push(widget)
|
||||
}
|
||||
resources: [displayResource.resource],
|
||||
},
|
||||
}).replace(/'/g, ''');
|
||||
newDatapackage.displayResources[idx].dataExplorers.push(dataExplorer);
|
||||
});
|
||||
});
|
||||
|
||||
displayResource.resource.api = displayResource.resource.api || displayResource.api
|
||||
const dataExplorer = JSON.stringify({
|
||||
widgets,
|
||||
datapackage: {
|
||||
resources: [displayResource.resource]
|
||||
}
|
||||
}).replace(/'/g, "'")
|
||||
newDatapackage.displayResources[idx].dataExplorers.push(dataExplorer)
|
||||
})
|
||||
})
|
||||
|
||||
return newDatapackage
|
||||
}
|
||||
return newDatapackage;
|
||||
};
|
||||
|
||||
282
yarn.lock
282
yarn.lock
@ -1417,6 +1417,11 @@
|
||||
resolved "https://registry.yarnpkg.com/@types/normalize-package-data/-/normalize-package-data-2.4.0.tgz#e486d0d97396d79beedd0a6e33f4534ff6b4973e"
|
||||
integrity sha512-f5j5b/Gf71L+dbqxIpQ4Z2WlmI/mPJ0fOkGGmFgtb6sAu97EPczzbS3/tJKxmcYDj55OX6ssqwDAWOHIYDRDGA==
|
||||
|
||||
"@types/parse-json@^4.0.0":
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@types/parse-json/-/parse-json-4.0.0.tgz#2f8bb441434d163b35fb8ffdccd7138927ffb8c0"
|
||||
integrity sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==
|
||||
|
||||
"@types/prettier@^2.0.0":
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.0.1.tgz#b6e98083f13faa1e5231bfa3bdb1b0feff536b6d"
|
||||
@ -1713,7 +1718,12 @@ anser@1.4.9:
|
||||
resolved "https://registry.yarnpkg.com/anser/-/anser-1.4.9.tgz#1f85423a5dcf8da4631a341665ff675b96845760"
|
||||
integrity sha512-AI+BjTeGt2+WFk4eWcqbQ7snZpDBt8SaLlj0RT2h5xfdWaiy51OjYvqwMrNzJLGy8iOAL6nKDITWO+rd4MkYEA==
|
||||
|
||||
ansi-escapes@^4.2.1:
|
||||
ansi-colors@^3.2.1:
|
||||
version "3.2.4"
|
||||
resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-3.2.4.tgz#e3a3da4bfbae6c86a9c285625de124a234026fbf"
|
||||
integrity sha512-hHUXGagefjN2iRrID63xckIvotOXOojhQKWIPUZ4mNUZ9nLZW+7FMNoE1lOkEhNWYsx/7ysGIuJYCiMAA9FnrA==
|
||||
|
||||
ansi-escapes@^4.2.1, ansi-escapes@^4.3.0:
|
||||
version "4.3.1"
|
||||
resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.1.tgz#a5c47cc43181f1f38ffd7076837700d395522a61"
|
||||
integrity sha512-JWF7ocqNrp8u9oqpgV+wH5ftbt+cfvv+PTjOvKLT3AdYly/LmORARfEVT1iyjwN+4MqE5UmVKoAdIBqeoCHgLA==
|
||||
@ -1852,6 +1862,11 @@ assign-symbols@^1.0.0:
|
||||
resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367"
|
||||
integrity sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=
|
||||
|
||||
astral-regex@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-2.0.0.tgz#483143c567aeed4785759c0865786dc77d7d2e31"
|
||||
integrity sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==
|
||||
|
||||
async-each@^1.0.1:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.3.tgz#b727dbf87d7651602f06f4d4ac387f47d91b0cbf"
|
||||
@ -2463,6 +2478,21 @@ clean-stack@^2.0.0:
|
||||
resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b"
|
||||
integrity sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==
|
||||
|
||||
cli-cursor@^3.1.0:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-3.1.0.tgz#264305a7ae490d1d03bf0c9ba7c925d1753af307"
|
||||
integrity sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==
|
||||
dependencies:
|
||||
restore-cursor "^3.1.0"
|
||||
|
||||
cli-truncate@2.1.0, cli-truncate@^2.1.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/cli-truncate/-/cli-truncate-2.1.0.tgz#c39e28bf05edcde5be3b98992a22deed5a2b93c7"
|
||||
integrity sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==
|
||||
dependencies:
|
||||
slice-ansi "^3.0.0"
|
||||
string-width "^4.2.0"
|
||||
|
||||
cliui@^3.0.3:
|
||||
version "3.2.0"
|
||||
resolved "https://registry.yarnpkg.com/cliui/-/cliui-3.2.0.tgz#120601537a916d29940f934da3b48d585a39213d"
|
||||
@ -2574,7 +2604,7 @@ commander@^2.20.0:
|
||||
resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33"
|
||||
integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==
|
||||
|
||||
commander@^5.0.0:
|
||||
commander@^5.0.0, commander@^5.1.0:
|
||||
version "5.1.0"
|
||||
resolved "https://registry.yarnpkg.com/commander/-/commander-5.1.0.tgz#46abbd1652f8e059bddaef99bbdcb2ad9cf179ae"
|
||||
integrity sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==
|
||||
@ -2584,6 +2614,11 @@ commondir@^1.0.1:
|
||||
resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b"
|
||||
integrity sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=
|
||||
|
||||
compare-versions@^3.6.0:
|
||||
version "3.6.0"
|
||||
resolved "https://registry.yarnpkg.com/compare-versions/-/compare-versions-3.6.0.tgz#1a5689913685e5a87637b8d3ffca75514ec41d62"
|
||||
integrity sha512-W6Af2Iw1z4CB7q4uU4hv646dW9GQuBM+YpC0UvUCWSD8w90SJjp+ujJuXaEMtAXBtSqGfMPuFOVn4/+FlaqfBA==
|
||||
|
||||
component-emitter@^1.2.1:
|
||||
version "1.3.0"
|
||||
resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.0.tgz#16e4070fba8ae29b679f2215853ee181ab2eabc0"
|
||||
@ -2678,6 +2713,17 @@ cosmiconfig@^5.0.0:
|
||||
js-yaml "^3.13.1"
|
||||
parse-json "^4.0.0"
|
||||
|
||||
cosmiconfig@^6.0.0:
|
||||
version "6.0.0"
|
||||
resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-6.0.0.tgz#da4fee853c52f6b1e6935f41c1a2fc50bd4a9982"
|
||||
integrity sha512-xb3ZL6+L8b9JLLCx3ZdoZy4+2ECphCMo2PwqgP1tlfVq6M6YReyzBJtvWWtbDSpNr9hn96pkCiZqUcFEc+54Qg==
|
||||
dependencies:
|
||||
"@types/parse-json" "^4.0.0"
|
||||
import-fresh "^3.1.0"
|
||||
parse-json "^5.0.0"
|
||||
path-type "^4.0.0"
|
||||
yaml "^1.7.2"
|
||||
|
||||
create-ecdh@^4.0.0:
|
||||
version "4.0.3"
|
||||
resolved "https://registry.yarnpkg.com/create-ecdh/-/create-ecdh-4.0.3.tgz#c9111b6f33045c4697f144787f9254cdc77c45ff"
|
||||
@ -3041,6 +3087,11 @@ decode-uri-component@^0.2.0:
|
||||
resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545"
|
||||
integrity sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=
|
||||
|
||||
dedent@^0.7.0:
|
||||
version "0.7.0"
|
||||
resolved "https://registry.yarnpkg.com/dedent/-/dedent-0.7.0.tgz#2495ddbaf6eb874abb0e1be9df22d2e5a544326c"
|
||||
integrity sha1-JJXduvbrh0q7Dhvp3yLS5aVEMmw=
|
||||
|
||||
deep-is@~0.1.3:
|
||||
version "0.1.3"
|
||||
resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34"
|
||||
@ -3278,6 +3329,13 @@ enhanced-resolve@^4.1.0:
|
||||
memory-fs "^0.5.0"
|
||||
tapable "^1.0.0"
|
||||
|
||||
enquirer@^2.3.5:
|
||||
version "2.3.5"
|
||||
resolved "https://registry.yarnpkg.com/enquirer/-/enquirer-2.3.5.tgz#3ab2b838df0a9d8ab9e7dff235b0e8712ef92381"
|
||||
integrity sha512-BNT1C08P9XD0vNg3J475yIUG+mVdp9T6towYFHUv897X0KoHBjB1shyrNmhmtHWKP17iSWgo7Gqh7BBuzLZMSA==
|
||||
dependencies:
|
||||
ansi-colors "^3.2.1"
|
||||
|
||||
entities@^2.0.0, entities@~2.0.0:
|
||||
version "2.0.3"
|
||||
resolved "https://registry.yarnpkg.com/entities/-/entities-2.0.3.tgz#5c487e5742ab93c15abb5da22759b8590ec03b7f"
|
||||
@ -3432,7 +3490,7 @@ execa@^1.0.0:
|
||||
signal-exit "^3.0.0"
|
||||
strip-eof "^1.0.0"
|
||||
|
||||
execa@^4.0.0:
|
||||
execa@^4.0.0, execa@^4.0.1:
|
||||
version "4.0.2"
|
||||
resolved "https://registry.yarnpkg.com/execa/-/execa-4.0.2.tgz#ad87fb7b2d9d564f70d2b62d511bee41d5cbb240"
|
||||
integrity sha512-QI2zLa6CjGWdiQsmSkZoGtDx2N+cQIGb3yNolGTdjSQzydzLgYYf8LRuagp7S7fPimjcrzUDSUFd/MgzELMi4Q==
|
||||
@ -3555,6 +3613,13 @@ figgy-pudding@^3.5.1:
|
||||
resolved "https://registry.yarnpkg.com/figgy-pudding/-/figgy-pudding-3.5.2.tgz#b4eee8148abb01dcf1d1ac34367d59e12fa61d6e"
|
||||
integrity sha512-0btnI/H8f2pavGMN8w40mlSKOfTK2SVJmBfBeVIj3kNw0swwgzyRq0d5TJVOwodFmtvpPeWPN/MCcfuWF0Ezbw==
|
||||
|
||||
figures@^3.2.0:
|
||||
version "3.2.0"
|
||||
resolved "https://registry.yarnpkg.com/figures/-/figures-3.2.0.tgz#625c18bd293c604dc4a8ddb2febf0c88341746af"
|
||||
integrity sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==
|
||||
dependencies:
|
||||
escape-string-regexp "^1.0.5"
|
||||
|
||||
file-uri-to-path@1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz#553a7b8446ff6f684359c445f1e37a05dacc33dd"
|
||||
@ -3617,6 +3682,13 @@ find-up@^4.0.0, find-up@^4.1.0:
|
||||
locate-path "^5.0.0"
|
||||
path-exists "^4.0.0"
|
||||
|
||||
find-versions@^3.2.0:
|
||||
version "3.2.0"
|
||||
resolved "https://registry.yarnpkg.com/find-versions/-/find-versions-3.2.0.tgz#10297f98030a786829681690545ef659ed1d254e"
|
||||
integrity sha512-P8WRou2S+oe222TOCHitLy8zj+SIsVJh52VP4lvXkaFVnOFFdoWv1H1Jjvel1aI6NCFOAaeAVm8qrI0odiLcww==
|
||||
dependencies:
|
||||
semver-regex "^2.0.0"
|
||||
|
||||
flatten@^1.0.2:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/flatten/-/flatten-1.0.3.tgz#c1283ac9f27b368abc1e36d1ff7b04501a30356b"
|
||||
@ -3737,6 +3809,11 @@ get-caller-file@^2.0.1:
|
||||
resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e"
|
||||
integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==
|
||||
|
||||
get-own-enumerable-property-symbols@^3.0.0:
|
||||
version "3.0.2"
|
||||
resolved "https://registry.yarnpkg.com/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz#b5fde77f22cbe35f390b4e089922c50bce6ef664"
|
||||
integrity sha512-I0UBV/XOz1XkIJHEUDMZAbzCThU/H8DxmSfmdGcKPnVhu2VfFqr34jr9777IyaTYvxjedWhqVIilEDsCdP5G6g==
|
||||
|
||||
get-package-type@^0.1.0:
|
||||
version "0.1.0"
|
||||
resolved "https://registry.yarnpkg.com/get-package-type/-/get-package-type-0.1.0.tgz#8de2d803cff44df3bc6c456e6668b36c3926e11a"
|
||||
@ -3980,6 +4057,22 @@ human-signals@^1.1.1:
|
||||
resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-1.1.1.tgz#c5b1cd14f50aeae09ab6c59fe63ba3395fe4dfa3"
|
||||
integrity sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==
|
||||
|
||||
husky@>=4:
|
||||
version "4.2.5"
|
||||
resolved "https://registry.yarnpkg.com/husky/-/husky-4.2.5.tgz#2b4f7622673a71579f901d9885ed448394b5fa36"
|
||||
integrity sha512-SYZ95AjKcX7goYVZtVZF2i6XiZcHknw50iXvY7b0MiGoj5RwdgRQNEHdb+gPDPCXKlzwrybjFjkL6FOj8uRhZQ==
|
||||
dependencies:
|
||||
chalk "^4.0.0"
|
||||
ci-info "^2.0.0"
|
||||
compare-versions "^3.6.0"
|
||||
cosmiconfig "^6.0.0"
|
||||
find-versions "^3.2.0"
|
||||
opencollective-postinstall "^2.0.2"
|
||||
pkg-dir "^4.2.0"
|
||||
please-upgrade-node "^3.2.0"
|
||||
slash "^3.0.0"
|
||||
which-pm-runs "^1.0.0"
|
||||
|
||||
iconv-lite@0.4.24:
|
||||
version "0.4.24"
|
||||
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b"
|
||||
@ -4012,6 +4105,14 @@ import-fresh@^2.0.0:
|
||||
caller-path "^2.0.0"
|
||||
resolve-from "^3.0.0"
|
||||
|
||||
import-fresh@^3.1.0:
|
||||
version "3.2.1"
|
||||
resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.2.1.tgz#633ff618506e793af5ac91bf48b72677e15cbe66"
|
||||
integrity sha512-6e1q1cnWP2RXD9/keSkxHScg508CdXqXWgWBaETNhyuBFz+kUZlKboh+ISK+bU++DmbHimVBrOz/zzPe0sZ3sQ==
|
||||
dependencies:
|
||||
parent-module "^1.0.0"
|
||||
resolve-from "^4.0.0"
|
||||
|
||||
import-local@^3.0.2:
|
||||
version "3.0.2"
|
||||
resolved "https://registry.yarnpkg.com/import-local/-/import-local-3.0.2.tgz#a8cfd0431d1de4a2199703d003e3e62364fa6db6"
|
||||
@ -4264,6 +4365,11 @@ is-number@^7.0.0:
|
||||
resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b"
|
||||
integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==
|
||||
|
||||
is-obj@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f"
|
||||
integrity sha1-PkcprB9f3gJc19g6iW2rn09n2w8=
|
||||
|
||||
is-obj@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-2.0.0.tgz#473fb05d973705e3fd9620545018ca8e22ef4982"
|
||||
@ -4293,6 +4399,11 @@ is-regex@^1.0.5:
|
||||
dependencies:
|
||||
has-symbols "^1.0.1"
|
||||
|
||||
is-regexp@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/is-regexp/-/is-regexp-1.0.0.tgz#fd2d883545c46bac5a633e7b9a09e87fa2cb5069"
|
||||
integrity sha1-/S2INUXEa6xaYz57mgnof6LLUGk=
|
||||
|
||||
is-resolvable@^1.0.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/is-resolvable/-/is-resolvable-1.1.0.tgz#fb18f87ce1feb925169c9a407c19318a3206ed88"
|
||||
@ -4989,6 +5100,41 @@ linkify-it@^3.0.1:
|
||||
dependencies:
|
||||
uc.micro "^1.0.1"
|
||||
|
||||
lint-staged@>=10:
|
||||
version "10.2.11"
|
||||
resolved "https://registry.yarnpkg.com/lint-staged/-/lint-staged-10.2.11.tgz#713c80877f2dc8b609b05bc59020234e766c9720"
|
||||
integrity sha512-LRRrSogzbixYaZItE2APaS4l2eJMjjf5MbclRZpLJtcQJShcvUzKXsNeZgsLIZ0H0+fg2tL4B59fU9wHIHtFIA==
|
||||
dependencies:
|
||||
chalk "^4.0.0"
|
||||
cli-truncate "2.1.0"
|
||||
commander "^5.1.0"
|
||||
cosmiconfig "^6.0.0"
|
||||
debug "^4.1.1"
|
||||
dedent "^0.7.0"
|
||||
enquirer "^2.3.5"
|
||||
execa "^4.0.1"
|
||||
listr2 "^2.1.0"
|
||||
log-symbols "^4.0.0"
|
||||
micromatch "^4.0.2"
|
||||
normalize-path "^3.0.0"
|
||||
please-upgrade-node "^3.2.0"
|
||||
string-argv "0.3.1"
|
||||
stringify-object "^3.3.0"
|
||||
|
||||
listr2@^2.1.0:
|
||||
version "2.1.8"
|
||||
resolved "https://registry.yarnpkg.com/listr2/-/listr2-2.1.8.tgz#8af7ebc70cdbe866ddbb6c80909142bd45758f1f"
|
||||
integrity sha512-Op+hheiChfAphkJ5qUxZtHgyjlX9iNnAeFS/S134xw7mVSg0YVrQo1IY4/K+ElY6XgOPg2Ij4z07urUXR+YEew==
|
||||
dependencies:
|
||||
chalk "^4.0.0"
|
||||
cli-truncate "^2.1.0"
|
||||
figures "^3.2.0"
|
||||
indent-string "^4.0.0"
|
||||
log-update "^4.0.0"
|
||||
p-map "^4.0.0"
|
||||
rxjs "^6.5.5"
|
||||
through "^2.3.8"
|
||||
|
||||
loader-runner@^2.4.0:
|
||||
version "2.4.0"
|
||||
resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-2.4.0.tgz#ed47066bfe534d7e84c4c7b9998c2a75607d9357"
|
||||
@ -5089,6 +5235,23 @@ lodash@^4.17.11, lodash@^4.17.13, lodash@^4.17.15:
|
||||
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548"
|
||||
integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==
|
||||
|
||||
log-symbols@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.0.0.tgz#69b3cc46d20f448eccdb75ea1fa733d9e821c920"
|
||||
integrity sha512-FN8JBzLx6CzeMrB0tg6pqlGU1wCrXW+ZXGH481kfsBqer0hToTIiHdjH4Mq8xJUbvATujKCvaREGWpGUionraA==
|
||||
dependencies:
|
||||
chalk "^4.0.0"
|
||||
|
||||
log-update@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/log-update/-/log-update-4.0.0.tgz#589ecd352471f2a1c0c570287543a64dfd20e0a1"
|
||||
integrity sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg==
|
||||
dependencies:
|
||||
ansi-escapes "^4.3.0"
|
||||
cli-cursor "^3.1.0"
|
||||
slice-ansi "^4.0.0"
|
||||
wrap-ansi "^6.2.0"
|
||||
|
||||
loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.4.0:
|
||||
version "1.4.0"
|
||||
resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf"
|
||||
@ -5747,6 +5910,11 @@ onetime@^5.1.0:
|
||||
dependencies:
|
||||
mimic-fn "^2.1.0"
|
||||
|
||||
opencollective-postinstall@^2.0.2:
|
||||
version "2.0.3"
|
||||
resolved "https://registry.yarnpkg.com/opencollective-postinstall/-/opencollective-postinstall-2.0.3.tgz#7a0fff978f6dbfa4d006238fbac98ed4198c3259"
|
||||
integrity sha512-8AV/sCtuzUeTo8gQK5qDZzARrulB3egtLzFgteqB2tcT4Mw7B8Kt7JcDHmltjz6FOAHsvTevk70gZEbhM4ZS9Q==
|
||||
|
||||
optionator@^0.8.1:
|
||||
version "0.8.3"
|
||||
resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495"
|
||||
@ -5823,6 +5991,13 @@ p-map@^3.0.0:
|
||||
dependencies:
|
||||
aggregate-error "^3.0.0"
|
||||
|
||||
p-map@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/p-map/-/p-map-4.0.0.tgz#bb2f95a5eda2ec168ec9274e06a747c3e2904d2b"
|
||||
integrity sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==
|
||||
dependencies:
|
||||
aggregate-error "^3.0.0"
|
||||
|
||||
p-try@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3"
|
||||
@ -5847,6 +6022,13 @@ parallel-transform@^1.1.0:
|
||||
inherits "^2.0.3"
|
||||
readable-stream "^2.1.5"
|
||||
|
||||
parent-module@^1.0.0:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2"
|
||||
integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==
|
||||
dependencies:
|
||||
callsites "^3.0.0"
|
||||
|
||||
parse-asn1@^5.0.0, parse-asn1@^5.1.5:
|
||||
version "5.1.5"
|
||||
resolved "https://registry.yarnpkg.com/parse-asn1/-/parse-asn1-5.1.5.tgz#003271343da58dc94cace494faef3d2147ecea0e"
|
||||
@ -5927,6 +6109,11 @@ path-parse@^1.0.6:
|
||||
resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c"
|
||||
integrity sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==
|
||||
|
||||
path-type@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b"
|
||||
integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==
|
||||
|
||||
pbkdf2@^3.0.3:
|
||||
version "3.1.1"
|
||||
resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.1.1.tgz#cb8724b0fada984596856d1a6ebafd3584654b94"
|
||||
@ -5986,6 +6173,13 @@ platform@1.3.3:
|
||||
resolved "https://registry.yarnpkg.com/platform/-/platform-1.3.3.tgz#646c77011899870b6a0903e75e997e8e51da7461"
|
||||
integrity sha1-ZGx3ARiZhwtqCQPnXpl+jlHadGE=
|
||||
|
||||
please-upgrade-node@^3.2.0:
|
||||
version "3.2.0"
|
||||
resolved "https://registry.yarnpkg.com/please-upgrade-node/-/please-upgrade-node-3.2.0.tgz#aeddd3f994c933e4ad98b99d9a556efa0e2fe942"
|
||||
integrity sha512-gQR3WpIgNIKwBMVLkpMUeR3e1/E1y42bqDQZfql+kDeXd8COYfM8PQA4X6y7a8u9Ua9FHmsrrmirW2vHs45hWg==
|
||||
dependencies:
|
||||
semver-compare "^1.0.0"
|
||||
|
||||
pnp-webpack-plugin@1.6.4:
|
||||
version "1.6.4"
|
||||
resolved "https://registry.yarnpkg.com/pnp-webpack-plugin/-/pnp-webpack-plugin-1.6.4.tgz#c9711ac4dc48a685dabafc86f8b6dd9f8df84149"
|
||||
@ -6679,6 +6873,11 @@ prepend-http@^1.0.0:
|
||||
resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-1.0.4.tgz#d4f4562b0ce3696e41ac52d0e002e57a635dc6dc"
|
||||
integrity sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=
|
||||
|
||||
prettier@2.0.5:
|
||||
version "2.0.5"
|
||||
resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.0.5.tgz#d6d56282455243f2f92cc1716692c08aa31522d4"
|
||||
integrity sha512-7PtVymN48hGcO4fGjybyBSIWDsLU4H4XlvOHfq91pz9kkGlonzwTfYkaIEwiRg/dAJF9YlbsduBAgtYLi+8cFg==
|
||||
|
||||
pretty-format@^25.2.1, pretty-format@^25.5.0:
|
||||
version "25.5.0"
|
||||
resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-25.5.0.tgz#7873c1d774f682c34b8d48b6743a2bf2ac55791a"
|
||||
@ -7128,6 +7327,11 @@ resolve-from@^3.0.0:
|
||||
resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-3.0.0.tgz#b22c7af7d9d6881bc8b6e653335eebcb0a188748"
|
||||
integrity sha1-six699nWiBvItuZTM17rywoYh0g=
|
||||
|
||||
resolve-from@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6"
|
||||
integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==
|
||||
|
||||
resolve-from@^5.0.0:
|
||||
version "5.0.0"
|
||||
resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69"
|
||||
@ -7161,6 +7365,14 @@ resolve@^1.10.0, resolve@^1.14.2, resolve@^1.17.0, resolve@^1.3.2, resolve@^1.8.
|
||||
dependencies:
|
||||
path-parse "^1.0.6"
|
||||
|
||||
restore-cursor@^3.1.0:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-3.1.0.tgz#39f67c54b3a7a58cea5236d95cf0034239631f7e"
|
||||
integrity sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==
|
||||
dependencies:
|
||||
onetime "^5.1.0"
|
||||
signal-exit "^3.0.2"
|
||||
|
||||
ret@~0.1.10:
|
||||
version "0.1.15"
|
||||
resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc"
|
||||
@ -7223,6 +7435,13 @@ run-queue@^1.0.0, run-queue@^1.0.3:
|
||||
dependencies:
|
||||
aproba "^1.1.1"
|
||||
|
||||
rxjs@^6.5.5:
|
||||
version "6.5.5"
|
||||
resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.5.5.tgz#c5c884e3094c8cfee31bf27eb87e54ccfc87f9ec"
|
||||
integrity sha512-WfQI+1gohdf0Dai/Bbmk5L5ItH5tYqm3ki2c5GdWhKjalzjg93N3avFjVStyZZz+A2Em+ZxKH5bNghw9UeylGQ==
|
||||
dependencies:
|
||||
tslib "^1.9.0"
|
||||
|
||||
safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@~5.2.0:
|
||||
version "5.2.1"
|
||||
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6"
|
||||
@ -7322,6 +7541,16 @@ secure-keys@^1.0.0:
|
||||
resolved "https://registry.yarnpkg.com/secure-keys/-/secure-keys-1.0.0.tgz#f0c82d98a3b139a8776a8808050b824431087fca"
|
||||
integrity sha1-8MgtmKOxOah3aogIBQuCRDEIf8o=
|
||||
|
||||
semver-compare@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/semver-compare/-/semver-compare-1.0.0.tgz#0dee216a1c941ab37e9efb1788f6afc5ff5537fc"
|
||||
integrity sha1-De4hahyUGrN+nvsXiPavxf9VN/w=
|
||||
|
||||
semver-regex@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/semver-regex/-/semver-regex-2.0.0.tgz#a93c2c5844539a770233379107b38c7b4ac9d338"
|
||||
integrity sha512-mUdIBBvdn0PLOeP3TEkMH7HHeUP3GjsXCwKarjv/kGmUFOYg1VqEemKhoQpWMu6X2I8kHeuVdGibLGkVK+/5Qw==
|
||||
|
||||
"semver@2 || 3 || 4 || 5", semver@^5.4.1, semver@^5.5.0, semver@^5.5.1, semver@^5.6.0:
|
||||
version "5.7.1"
|
||||
resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7"
|
||||
@ -7440,6 +7669,24 @@ slash@^3.0.0:
|
||||
resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634"
|
||||
integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==
|
||||
|
||||
slice-ansi@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-3.0.0.tgz#31ddc10930a1b7e0b67b08c96c2f49b77a789787"
|
||||
integrity sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==
|
||||
dependencies:
|
||||
ansi-styles "^4.0.0"
|
||||
astral-regex "^2.0.0"
|
||||
is-fullwidth-code-point "^3.0.0"
|
||||
|
||||
slice-ansi@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-4.0.0.tgz#500e8dd0fd55b05815086255b3195adf2a45fe6b"
|
||||
integrity sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==
|
||||
dependencies:
|
||||
ansi-styles "^4.0.0"
|
||||
astral-regex "^2.0.0"
|
||||
is-fullwidth-code-point "^3.0.0"
|
||||
|
||||
slugify@^1.4.0:
|
||||
version "1.4.0"
|
||||
resolved "https://registry.yarnpkg.com/slugify/-/slugify-1.4.0.tgz#c9557c653c54b0c7f7a8e786ef3431add676d2cb"
|
||||
@ -7670,6 +7917,11 @@ strict-uri-encode@^1.0.0:
|
||||
resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz#279b225df1d582b1f54e65addd4352e18faa0713"
|
||||
integrity sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=
|
||||
|
||||
string-argv@0.3.1:
|
||||
version "0.3.1"
|
||||
resolved "https://registry.yarnpkg.com/string-argv/-/string-argv-0.3.1.tgz#95e2fbec0427ae19184935f816d74aaa4c5c19da"
|
||||
integrity sha512-a1uQGz7IyVy9YwhqjZIZu1c8JO8dNIe20xBmSS6qu9kv++k3JGzCVmprbNN5Kn+BgzD5E7YYwg1CcjuJMRNsvg==
|
||||
|
||||
string-hash@1.1.3:
|
||||
version "1.1.3"
|
||||
resolved "https://registry.yarnpkg.com/string-hash/-/string-hash-1.1.3.tgz#e8aafc0ac1855b4666929ed7dd1275df5d6c811b"
|
||||
@ -7749,6 +8001,15 @@ string_decoder@~1.1.1:
|
||||
dependencies:
|
||||
safe-buffer "~5.1.0"
|
||||
|
||||
stringify-object@^3.3.0:
|
||||
version "3.3.0"
|
||||
resolved "https://registry.yarnpkg.com/stringify-object/-/stringify-object-3.3.0.tgz#703065aefca19300d3ce88af4f5b3956d7556629"
|
||||
integrity sha512-rHqiFh1elqCQ9WPLIC8I0Q/g/wj5J1eMkyoiD6eoQApWHP0FtlK7rqnhmabL5VUY9JQCcqwwvlOaSuutekgyrw==
|
||||
dependencies:
|
||||
get-own-enumerable-property-symbols "^3.0.0"
|
||||
is-obj "^1.0.1"
|
||||
is-regexp "^1.0.0"
|
||||
|
||||
strip-ansi@6.0.0, strip-ansi@^6.0.0:
|
||||
version "6.0.0"
|
||||
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.0.tgz#0b1571dd7669ccd4f3e06e14ef1eed26225ae532"
|
||||
@ -7977,6 +8238,11 @@ through2@^2.0.0:
|
||||
readable-stream "~2.3.6"
|
||||
xtend "~4.0.1"
|
||||
|
||||
through@^2.3.8:
|
||||
version "2.3.8"
|
||||
resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5"
|
||||
integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=
|
||||
|
||||
timers-browserify@^2.0.4:
|
||||
version "2.0.11"
|
||||
resolved "https://registry.yarnpkg.com/timers-browserify/-/timers-browserify-2.0.11.tgz#800b1f3eee272e5bc53ee465a04d0e804c31211f"
|
||||
@ -8494,6 +8760,11 @@ which-module@^2.0.0:
|
||||
resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a"
|
||||
integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=
|
||||
|
||||
which-pm-runs@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/which-pm-runs/-/which-pm-runs-1.0.0.tgz#670b3afbc552e0b55df6b7780ca74615f23ad1cb"
|
||||
integrity sha1-Zws6+8VS4LVd9rd4DKdGFfI60cs=
|
||||
|
||||
which@^1.2.9:
|
||||
version "1.3.1"
|
||||
resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a"
|
||||
@ -8604,6 +8875,11 @@ yallist@^4.0.0:
|
||||
resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72"
|
||||
integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==
|
||||
|
||||
yaml@^1.7.2:
|
||||
version "1.10.0"
|
||||
resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.0.tgz#3b593add944876077d4d683fee01081bd9fff31e"
|
||||
integrity sha512-yr2icI4glYaNG+KWONODapy2/jDdMSDnrONSjblABjD9B4Z5LgiircSt8m8sRZFNi08kG9Sm0uSHtEmP3zaEGg==
|
||||
|
||||
yargs-parser@^18.1.1:
|
||||
version "18.1.3"
|
||||
resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-18.1.3.tgz#be68c4975c6b2abf469236b0c870362fab09a7b0"
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user