@imerss/inat-components 2.0.1 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +23 -4
- package/dist/index.d.ts +87 -75
- package/dist/index.js +261 -173
- package/dist/standalone.min.js +1 -1
- package/package.json +10 -12
- package/PUBLISH.md +0 -13
- package/declaration.d.ts +0 -2
- package/public/favicon.ico +0 -0
- package/public/index.html +0 -20
- package/public/logo192.png +0 -0
- package/public/logo512.png +0 -0
- package/public/manifest.json +0 -25
- package/public/robots.txt +0 -3
- package/public/standalone.html +0 -55
- package/rollup.config.js +0 -47
- package/src/__shared/api/common-taxa.ts +0 -57
- package/src/__shared/api/favourites.ts +0 -57
- package/src/__shared/api/index.ts +0 -4
- package/src/__shared/api/recent-observations.ts +0 -44
- package/src/__shared/api/summary.ts +0 -86
- package/src/__shared/constants.ts +0 -6
- package/src/__shared/index.ts +0 -4
- package/src/__shared/typings.ts +0 -83
- package/src/__shared/utils/configUtils.ts +0 -25
- package/src/__shared/utils/dateUtils.ts +0 -14
- package/src/__shared/utils/index.ts +0 -3
- package/src/__shared/utils/numberUtils.ts +0 -1
- package/src/components/common-taxa/__tests__/common-taxa.test.tsx +0 -14
- package/src/components/common-taxa/common-taxa.tsx +0 -73
- package/src/components/error/__tests__/error.test.tsx +0 -9
- package/src/components/error/error.module.scss +0 -7
- package/src/components/error/error.tsx +0 -15
- package/src/components/favourites/__tests__/favourites.test.tsx +0 -13
- package/src/components/favourites/favourites.tsx +0 -73
- package/src/components/hooks/hooks.tsx +0 -34
- package/src/components/loader/__tests__/loader.test.tsx +0 -10
- package/src/components/loader/loader.tsx +0 -26
- package/src/components/no-results/__tests__/no-results.test.tsx +0 -9
- package/src/components/no-results/no-results.tsx +0 -9
- package/src/components/observation/__tests__/observation.test.tsx +0 -14
- package/src/components/observation/observation.module.scss +0 -20
- package/src/components/observation/observation.tsx +0 -30
- package/src/components/recent-observations/__tests__/recent-observations.test.tsx +0 -9
- package/src/components/recent-observations/recent-observations.tsx +0 -84
- package/src/components/seasonality-graph/__tests__/seasonality-graph.test.tsx +0 -9
- package/src/components/seasonality-graph/seasonality-graph.module.scss +0 -7
- package/src/components/seasonality-graph/seasonality-graph.tsx +0 -46
- package/src/components/shared/css/general.module.scss +0 -73
- package/src/components/summary/ObserverList.tsx +0 -24
- package/src/components/summary/__tests__/summary.test.tsx +0 -18
- package/src/components/summary/summary.module.scss +0 -88
- package/src/components/summary/summary.tsx +0 -91
- package/src/components/tabs/__tests__/tabs.test.tsx +0 -16
- package/src/components/tabs/tabs.module.scss +0 -28
- package/src/components/tabs/tabs.tsx +0 -65
- package/src/components/taxon-panel/__tests__/taxon-panel.test.tsx +0 -10
- package/src/components/taxon-panel/taxon-panel.module.scss +0 -7
- package/src/components/taxon-panel/taxon-panel.tsx +0 -110
- package/src/components/year-dropdown/__tests__/year-dropdown.test.tsx +0 -14
- package/src/components/year-dropdown/year-dropdown.module.scss +0 -3
- package/src/components/year-dropdown/year-dropdown.tsx +0 -37
- package/src/hooks/useLoadSourceData.ts +0 -81
- package/src/index.ts +0 -15
- package/src/types/index.d.ts +0 -17
- package/src/types/standalone.d.ts +0 -6
- package/tsconfig.json +0 -6
package/package.json
CHANGED
|
@@ -1,39 +1,38 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@imerss/inat-components",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.0.0",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"types": "./dist/index.d.ts",
|
|
6
|
+
"files": [
|
|
7
|
+
"dist"
|
|
8
|
+
],
|
|
6
9
|
"license": "MIT",
|
|
7
10
|
"scripts": {
|
|
8
11
|
"build": "rollup -c --environment BUILD:production && cd ../inat-components-standalone && npm run build && npm run copyToInatComponentsPackage",
|
|
9
|
-
"clean": "shx rm -rf dist
|
|
12
|
+
"clean": "shx rm -rf dist",
|
|
10
13
|
"watch": "rollup -cw"
|
|
11
14
|
},
|
|
12
15
|
"dependencies": {
|
|
13
16
|
"date-fns": "^2.28.0",
|
|
14
17
|
"isomorphic-unfetch": "^3.1.0",
|
|
15
|
-
"react-spinners": "^0.13.2"
|
|
16
|
-
"sleep-promise": "^9.1.0"
|
|
18
|
+
"react-spinners": "^0.13.2"
|
|
17
19
|
},
|
|
18
20
|
"peerDependencies": {
|
|
19
21
|
"react": ">=18.0.0",
|
|
20
22
|
"react-dom": ">=18.0.0"
|
|
21
23
|
},
|
|
22
24
|
"devDependencies": {
|
|
25
|
+
"@imerss/inat-components-shared": "0.0.0",
|
|
23
26
|
"@modular-css/rollup": "^28.2.2",
|
|
24
|
-
"@rollup/plugin-typescript": "^8.3.3",
|
|
25
27
|
"@rollup/plugin-commonjs": "^24.1.0",
|
|
26
28
|
"@rollup/plugin-json": "^6.0.0",
|
|
27
29
|
"@rollup/plugin-node-resolve": "^15.0.2",
|
|
28
30
|
"@rollup/plugin-replace": "^5.0.2",
|
|
29
|
-
"@
|
|
31
|
+
"@rollup/plugin-typescript": "^8.3.3",
|
|
30
32
|
"@types/cli-progress": "^3.11.0",
|
|
31
33
|
"@types/isomorphic-fetch": "0.0.36",
|
|
32
|
-
"@types/jest": "^28.1.4",
|
|
33
34
|
"@types/react": "^18.0.38",
|
|
34
35
|
"@types/react-dom": "^18.0.5",
|
|
35
|
-
"jest": "^28.1.2",
|
|
36
|
-
"node-sass": "^7.0.1",
|
|
37
36
|
"postcss": "^8.4.14",
|
|
38
37
|
"react-charts": "3.0.0-beta.38",
|
|
39
38
|
"rollup": "^2.79.1",
|
|
@@ -41,8 +40,8 @@
|
|
|
41
40
|
"rollup-plugin-postcss": "^4.0.2",
|
|
42
41
|
"rollup-plugin-terser": "^7.0.2",
|
|
43
42
|
"rollup-plugin-visualizer": "^5.9.0",
|
|
44
|
-
"tslib": "^2.4.0",
|
|
45
43
|
"shx": "0.3.4",
|
|
44
|
+
"tslib": "^2.4.0",
|
|
46
45
|
"typescript": "^4.7.4"
|
|
47
46
|
},
|
|
48
47
|
"publishConfig": {
|
|
@@ -50,8 +49,7 @@
|
|
|
50
49
|
},
|
|
51
50
|
"eslintConfig": {
|
|
52
51
|
"extends": [
|
|
53
|
-
"react-app"
|
|
54
|
-
"react-app/jest"
|
|
52
|
+
"react-app"
|
|
55
53
|
]
|
|
56
54
|
},
|
|
57
55
|
"browserslist": {
|
package/PUBLISH.md
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
### Publishing new versions
|
|
2
|
-
|
|
3
|
-
Here's how to publish a new version of this package.
|
|
4
|
-
|
|
5
|
-
1. Go to the root of the monorepo and run `yarn install`, then `yarn boot`
|
|
6
|
-
2. Update the version in `packages/inat-component`'s package.json
|
|
7
|
-
3. Run `yarn build` to generate a fresh `/dist` folder (you can clean first, but the clean command currently also
|
|
8
|
-
deletes __shared, so you'll need to rebuild from the root if you do that)
|
|
9
|
-
|
|
10
|
-
Step 3 actually generates + copies over the result from the inat-components-standalone package, so in the dist folder
|
|
11
|
-
you should see a standalone.min.js file. All is good!
|
|
12
|
-
|
|
13
|
-
Now you can `npm publish`.
|
package/declaration.d.ts
DELETED
package/public/favicon.ico
DELETED
|
Binary file
|
package/public/index.html
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
<!DOCTYPE html>
|
|
2
|
-
<html lang="en">
|
|
3
|
-
<head>
|
|
4
|
-
<meta charset="utf-8" />
|
|
5
|
-
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
|
|
6
|
-
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
7
|
-
<meta name="theme-color" content="#000000" />
|
|
8
|
-
<meta
|
|
9
|
-
name="description"
|
|
10
|
-
content="Web site created using create-react-app"
|
|
11
|
-
/>
|
|
12
|
-
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
|
|
13
|
-
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
|
|
14
|
-
<title>iNat components</title>
|
|
15
|
-
</head>
|
|
16
|
-
<body>
|
|
17
|
-
<noscript>You need to enable JavaScript to run this app.</noscript>
|
|
18
|
-
<div id="root"></div>
|
|
19
|
-
</body>
|
|
20
|
-
</html>
|
package/public/logo192.png
DELETED
|
Binary file
|
package/public/logo512.png
DELETED
|
Binary file
|
package/public/manifest.json
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"short_name": "React App",
|
|
3
|
-
"name": "Create React App Sample",
|
|
4
|
-
"icons": [
|
|
5
|
-
{
|
|
6
|
-
"src": "favicon.ico",
|
|
7
|
-
"sizes": "64x64 32x32 24x24 16x16",
|
|
8
|
-
"type": "image/x-icon"
|
|
9
|
-
},
|
|
10
|
-
{
|
|
11
|
-
"src": "logo192.png",
|
|
12
|
-
"type": "image/png",
|
|
13
|
-
"sizes": "192x192"
|
|
14
|
-
},
|
|
15
|
-
{
|
|
16
|
-
"src": "logo512.png",
|
|
17
|
-
"type": "image/png",
|
|
18
|
-
"sizes": "512x512"
|
|
19
|
-
}
|
|
20
|
-
],
|
|
21
|
-
"start_url": ".",
|
|
22
|
-
"display": "standalone",
|
|
23
|
-
"theme_color": "#000000",
|
|
24
|
-
"background_color": "#ffffff"
|
|
25
|
-
}
|
package/public/robots.txt
DELETED
package/public/standalone.html
DELETED
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
<html>
|
|
2
|
-
<body>
|
|
3
|
-
|
|
4
|
-
<h1>Standalone example</h1>
|
|
5
|
-
|
|
6
|
-
<div id="inat-components-el"></div>
|
|
7
|
-
|
|
8
|
-
<script>
|
|
9
|
-
inatComponents.initTaxonPanel("inat-components-el", {
|
|
10
|
-
taxon: {
|
|
11
|
-
id: 47157,
|
|
12
|
-
str: "leps"
|
|
13
|
-
},
|
|
14
|
-
place: {
|
|
15
|
-
id: 7085,
|
|
16
|
-
str: "bc"
|
|
17
|
-
},
|
|
18
|
-
dataSource: "url",
|
|
19
|
-
dataSourceBaseUrl: "https://sisyphean.ca/inat",
|
|
20
|
-
itemWidth: 180,
|
|
21
|
-
features: {
|
|
22
|
-
recentObservations: {
|
|
23
|
-
numResults: 100,
|
|
24
|
-
desc: "This page lists the most recent butterfly and moth observations made in BC. Click on any of them to go to the inaturalist site for more information.",
|
|
25
|
-
},
|
|
26
|
-
commonTaxa: {
|
|
27
|
-
numResults: 100,
|
|
28
|
-
numYears: 10,
|
|
29
|
-
desc: "This page lists the most commonly reported species in BC. You can use the dropdown at the top right to filter the results to a particular year."
|
|
30
|
-
},
|
|
31
|
-
favourites: {
|
|
32
|
-
numResults: 100,
|
|
33
|
-
numYears: 10,
|
|
34
|
-
desc: "Any time iNaturalist users encounter an observation they like, they can choose to \"favourite\" it. This page lists the most favourited moth and butterfly observations made in BC."
|
|
35
|
-
},
|
|
36
|
-
stats: {
|
|
37
|
-
numTopObservers: 10,
|
|
38
|
-
observersListClass: "inat-observers-list",
|
|
39
|
-
statsCountSummaryClass: "inat-stats-count-summary",
|
|
40
|
-
}
|
|
41
|
-
},
|
|
42
|
-
generalClasses: {
|
|
43
|
-
tabsElement: "inat-tabs",
|
|
44
|
-
yearsDropdown: "inat-years-dropdown",
|
|
45
|
-
pageHeadings: "inat-page-headings",
|
|
46
|
-
observationLabelTitle: "inat-observation-label-title",
|
|
47
|
-
observationLabelDate: "inat-observation-label-data",
|
|
48
|
-
observationLabelName: "inat-observation-label-name",
|
|
49
|
-
tabDesc: "inat-tab-desc"
|
|
50
|
-
}
|
|
51
|
-
});
|
|
52
|
-
</script>
|
|
53
|
-
|
|
54
|
-
</body>
|
|
55
|
-
</html>
|
package/rollup.config.js
DELETED
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
import typescript from "@rollup/plugin-typescript";
|
|
2
|
-
import postcss from "rollup-plugin-postcss";
|
|
3
|
-
import dts from "rollup-plugin-dts";
|
|
4
|
-
|
|
5
|
-
export default [
|
|
6
|
-
|
|
7
|
-
// front-end components + generate() node utils method, exposed as "@imerss/inat-components"
|
|
8
|
-
{
|
|
9
|
-
input: "src/index.ts",
|
|
10
|
-
output: {
|
|
11
|
-
dir: "dist",
|
|
12
|
-
format: "es"
|
|
13
|
-
},
|
|
14
|
-
|
|
15
|
-
// these let's rollup know that these are external scripts + can be excluded from the final bundle without
|
|
16
|
-
// any warnings. TODO: check these are peer deps.
|
|
17
|
-
external: [
|
|
18
|
-
"react",
|
|
19
|
-
"fs",
|
|
20
|
-
"react-charts",
|
|
21
|
-
"date-fns",
|
|
22
|
-
"react-spinners",
|
|
23
|
-
"react-spinners/MoonLoader.js",
|
|
24
|
-
"isomorphic-unfetch",
|
|
25
|
-
"react/jsx-runtime"
|
|
26
|
-
],
|
|
27
|
-
plugins: [
|
|
28
|
-
postcss({
|
|
29
|
-
modules: true,
|
|
30
|
-
plugins: []
|
|
31
|
-
}),
|
|
32
|
-
typescript()
|
|
33
|
-
],
|
|
34
|
-
},
|
|
35
|
-
|
|
36
|
-
// rolls up all typings for export
|
|
37
|
-
{
|
|
38
|
-
input: "src/index.ts",
|
|
39
|
-
output: {
|
|
40
|
-
dir: "dist",
|
|
41
|
-
format: "es"
|
|
42
|
-
},
|
|
43
|
-
plugins: [
|
|
44
|
-
dts()
|
|
45
|
-
]
|
|
46
|
-
}
|
|
47
|
-
];
|
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
import * as C from "../constants";
|
|
2
|
-
import fetch from "isomorphic-unfetch";
|
|
3
|
-
|
|
4
|
-
export type CommonTaxaCallProps = {
|
|
5
|
-
year: string | number;
|
|
6
|
-
taxonId: string | number;
|
|
7
|
-
placeId: string | number;
|
|
8
|
-
numResults: number;
|
|
9
|
-
};
|
|
10
|
-
|
|
11
|
-
export type CommonTaxData = {
|
|
12
|
-
id: number;
|
|
13
|
-
imageUrl: string;
|
|
14
|
-
taxonName: string;
|
|
15
|
-
taxonCommonName: string;
|
|
16
|
-
obsCount: number;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export type CommonTaxaRespData = {
|
|
20
|
-
totalResults: number;
|
|
21
|
-
results: [CommonTaxData]
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
export const getCommonTaxa = async ({ year, taxonId, placeId, numResults }: CommonTaxaCallProps): Promise<CommonTaxaRespData> => {
|
|
25
|
-
let url = `${C.BASE_API_URL}/v1/observations/species_counts?verifiable=true&spam=false&place_id=${placeId}&taxon_id=${taxonId}&locale=en-US&per_page=${numResults}`;
|
|
26
|
-
if (year !== "all") {
|
|
27
|
-
url += `&d1=${year}-01-01&d2=${year}-12-31`;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
const response = await fetch(url, {
|
|
31
|
-
method: 'GET',
|
|
32
|
-
headers: {
|
|
33
|
-
Accept: 'application/json'
|
|
34
|
-
}
|
|
35
|
-
});
|
|
36
|
-
|
|
37
|
-
const resp = await response.json();
|
|
38
|
-
const sortedTaxa = resp.results.sort((a: any, b: any) => {
|
|
39
|
-
if (a.count > b.count) {
|
|
40
|
-
return -1;
|
|
41
|
-
} else if (a.count < b.count) {
|
|
42
|
-
return 1;
|
|
43
|
-
}
|
|
44
|
-
return 0;
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
return {
|
|
48
|
-
totalResults: resp.total_results,
|
|
49
|
-
results: sortedTaxa.map((row: any) => ({
|
|
50
|
-
id: row.taxon.id,
|
|
51
|
-
imageUrl: row.taxon?.default_photo?.square_url || "",
|
|
52
|
-
obsCount: row.count,
|
|
53
|
-
taxonName: row.taxon.name || "",
|
|
54
|
-
taxonCommonName: row.taxon.preferred_common_name
|
|
55
|
-
}))
|
|
56
|
-
};
|
|
57
|
-
};
|
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
import * as C from "../constants";
|
|
2
|
-
import fetch from "isomorphic-unfetch";
|
|
3
|
-
|
|
4
|
-
export type FavouritesCallProps = {
|
|
5
|
-
year: string | number;
|
|
6
|
-
taxonId: string | number;
|
|
7
|
-
placeId: string | number;
|
|
8
|
-
numResults: number;
|
|
9
|
-
};
|
|
10
|
-
|
|
11
|
-
export type FavouritesData = {
|
|
12
|
-
id: number;
|
|
13
|
-
imageUrl: string;
|
|
14
|
-
taxonName: string;
|
|
15
|
-
taxonCommonName: string;
|
|
16
|
-
obsDate: string;
|
|
17
|
-
obsCount: number;
|
|
18
|
-
observerUsername: string;
|
|
19
|
-
numFaves: number;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
export type FavouritesRespData = {
|
|
23
|
-
totalResults: number;
|
|
24
|
-
results: [FavouritesData]
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
export const getFavourites = async ({ year, taxonId, placeId, numResults }: FavouritesCallProps): Promise<FavouritesRespData> => {
|
|
28
|
-
let url = `${C.BASE_API_URL}/v1/observations?verifiable=true&order_by=votes&order=desc&page=1&spam=false&place_id=${placeId}&taxon_id=${taxonId}&locale=en-US&per_page=${numResults}`;
|
|
29
|
-
if (year !== "all") {
|
|
30
|
-
url += `&d1=${year}-01-01&d2=${year}-12-31`;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
const response = await fetch(url);
|
|
34
|
-
const resp = await response.json();
|
|
35
|
-
|
|
36
|
-
const sortedTaxa = resp.results.filter((i: any) => i.faves.length > 0).sort((a: any, b: any) => {
|
|
37
|
-
if (a.faves.length > b.faves.length) {
|
|
38
|
-
return -1;
|
|
39
|
-
} else if (a.faves.length < b.faves.length) {
|
|
40
|
-
return 1;
|
|
41
|
-
}
|
|
42
|
-
return 0;
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
return {
|
|
46
|
-
totalResults: resp.total_results,
|
|
47
|
-
results: sortedTaxa.map((row: any) => ({
|
|
48
|
-
id: row.id,
|
|
49
|
-
imageUrl: row.observation_photos[0].photo.url || "",
|
|
50
|
-
obsDate: row.observed_on_string,
|
|
51
|
-
obsUrl: row.uri,
|
|
52
|
-
taxonName: row.taxon.name || "",
|
|
53
|
-
taxonCommonName: row.taxon.preferred_common_name,
|
|
54
|
-
numFaves: row.faves.length
|
|
55
|
-
}))
|
|
56
|
-
};
|
|
57
|
-
};
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
import fetch from "isomorphic-unfetch";
|
|
2
|
-
import * as C from "../constants";
|
|
3
|
-
|
|
4
|
-
export type RecentObservationsCallProps = {
|
|
5
|
-
taxonId: string | number;
|
|
6
|
-
placeId: string | number;
|
|
7
|
-
numResults: number;
|
|
8
|
-
};
|
|
9
|
-
|
|
10
|
-
export type RecentObservationData = {
|
|
11
|
-
id: number;
|
|
12
|
-
imageUrl: string;
|
|
13
|
-
obsUrl: string;
|
|
14
|
-
obsDate: string;
|
|
15
|
-
taxonName: string;
|
|
16
|
-
taxonCommonName: string;
|
|
17
|
-
observerUsername: string;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
export type RecentObservationsRespData = {
|
|
21
|
-
totalResults: number;
|
|
22
|
-
results: [RecentObservationData]
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
export const getRecentObservations = async ({ taxonId, placeId, numResults }: RecentObservationsCallProps): Promise<RecentObservationsRespData> => {
|
|
26
|
-
const url = `${C.BASE_API_URL}/v1/observations?photos=true&per_page=${numResults}&taxon_id=${taxonId}&place_id=${placeId}&order=desc&order_by=observed_on`;
|
|
27
|
-
const response = await fetch(url);
|
|
28
|
-
const obs = await response.json();
|
|
29
|
-
|
|
30
|
-
return {
|
|
31
|
-
totalResults: obs.total_results,
|
|
32
|
-
results: obs.results.map((obs: any) => {
|
|
33
|
-
return {
|
|
34
|
-
id: obs.id,
|
|
35
|
-
imageUrl: obs.observation_photos[0].photo.url,
|
|
36
|
-
obsUrl: obs.uri,
|
|
37
|
-
obsDate: obs.observed_on_string,
|
|
38
|
-
taxonName: obs?.taxon?.name || "",
|
|
39
|
-
taxonCommonName: obs?.taxon.preferred_common_name,
|
|
40
|
-
observerUsername: obs.user.login
|
|
41
|
-
}
|
|
42
|
-
})
|
|
43
|
-
};
|
|
44
|
-
};
|
|
@@ -1,86 +0,0 @@
|
|
|
1
|
-
import fetch from "isomorphic-unfetch";
|
|
2
|
-
import * as C from '../constants';
|
|
3
|
-
|
|
4
|
-
export type SummaryApiProps = {
|
|
5
|
-
taxonId: number;
|
|
6
|
-
placeId: number;
|
|
7
|
-
year: string | number;
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
export const getSummary = async ({ taxonId, placeId, year }: SummaryApiProps): Promise<any> => {
|
|
11
|
-
const observers = await getObserverSummary(taxonId, placeId, year);
|
|
12
|
-
const observations = await getObservationSummary(taxonId, placeId, year);
|
|
13
|
-
const seasonalityData = await getSeasonalityData(taxonId, placeId, year);
|
|
14
|
-
|
|
15
|
-
return {
|
|
16
|
-
observers,
|
|
17
|
-
observations,
|
|
18
|
-
seasonalityData
|
|
19
|
-
};
|
|
20
|
-
};
|
|
21
|
-
|
|
22
|
-
export type Observer = {
|
|
23
|
-
id: number;
|
|
24
|
-
userName: string;
|
|
25
|
-
numObservations: number;
|
|
26
|
-
iconUrl: string | null;
|
|
27
|
-
}
|
|
28
|
-
export type SummaryData = {
|
|
29
|
-
totalCount: number;
|
|
30
|
-
top: [Observer];
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
export const getObserverSummary = async (taxonId: number, placeId: number, year: string | number): Promise<SummaryData> => {
|
|
34
|
-
let url = `${C.BASE_API_URL}/v1/observations/observers?verifiable=true&order_by=votes&order=desc&page=1&spam=false&place_id=${placeId}&taxon_id=${taxonId}&locale=en-US&per_page=10`;
|
|
35
|
-
|
|
36
|
-
if (year !== "all") {
|
|
37
|
-
url += `&d1=${year}-01-01&d2=${year}-12-31`;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
const response = await fetch(url);
|
|
41
|
-
const data = await response.json();
|
|
42
|
-
|
|
43
|
-
return {
|
|
44
|
-
totalCount: data.total_results,
|
|
45
|
-
top: data.results.map((result: any) => ({
|
|
46
|
-
id: result.user.id,
|
|
47
|
-
userName: result.user.login,
|
|
48
|
-
numObservations: result.observation_count,
|
|
49
|
-
iconUrl: result.user.icon_url
|
|
50
|
-
}))
|
|
51
|
-
};
|
|
52
|
-
};
|
|
53
|
-
|
|
54
|
-
export const getObservationSummary = async(taxonId: number, placeId: number, year: string | number) => {
|
|
55
|
-
let url = `${C.BASE_API_URL}/v1/observations?photos=true&per_page=1&taxon_id=${taxonId}&place_id=${placeId}&order=desc&order_by=observed_on`;
|
|
56
|
-
if (year !== "all") {
|
|
57
|
-
url += `&d1=${year}-01-01&d2=${year}-12-31`;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
const response = await fetch(url);
|
|
61
|
-
const data = await response.json();
|
|
62
|
-
|
|
63
|
-
return {
|
|
64
|
-
totalCount: data.total_results
|
|
65
|
-
};
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
export type SeasonalityData = {
|
|
69
|
-
monthOfYear: {
|
|
70
|
-
[monthNum: string]: number
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
export const getSeasonalityData = async (taxonId: number, placeId: number, year: string | number): Promise<SeasonalityData> => {
|
|
75
|
-
let url = `${C.BASE_API_URL}/v1/observations/histogram?verifiable=true&taxon_id=${taxonId}&place_id=${placeId}&locale=en-US&date_field=observed&interval=month_of_year`;
|
|
76
|
-
if (year !== "all") {
|
|
77
|
-
url += `&d1=${year}-01-01&d2=${year}-12-31`;
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
const response = await fetch(url);
|
|
81
|
-
const resp = await response.json();
|
|
82
|
-
|
|
83
|
-
return {
|
|
84
|
-
monthOfYear: resp.results.month_of_year
|
|
85
|
-
};
|
|
86
|
-
};
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
export const BASE_API_URL = 'https://api.inaturalist.org';
|
|
2
|
-
export const NUM_RESULTS = 100;
|
|
3
|
-
export const DEFAULT_NUM_YEARS = 10;
|
|
4
|
-
export const BASE_URL = "https://www.inaturalist.org"; // /people/name_here
|
|
5
|
-
export const ERROR_LOG_FILENAME = "inat-components-error.log";
|
|
6
|
-
export const DEFAULT_ITEM_WIDTH = 150;
|
package/src/__shared/index.ts
DELETED
package/src/__shared/typings.ts
DELETED
|
@@ -1,83 +0,0 @@
|
|
|
1
|
-
export enum Feature {
|
|
2
|
-
commonTaxa = "commonTaxa",
|
|
3
|
-
favourites = "favourites",
|
|
4
|
-
recentObservations = "recentObservations",
|
|
5
|
-
stats = "stats"
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
export enum DataSourceEnum {
|
|
9
|
-
autoLoad = "autoLoad",
|
|
10
|
-
url = "url"
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
export type DataSource = `${DataSourceEnum}`;
|
|
14
|
-
|
|
15
|
-
// used for places + taxons
|
|
16
|
-
export type ItemConfig = {
|
|
17
|
-
id: number;
|
|
18
|
-
str: string;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
export type GeneralClasses = {
|
|
22
|
-
tabsElement?: string;
|
|
23
|
-
yearsDropdown?: string;
|
|
24
|
-
pageHeadings?: string;
|
|
25
|
-
tabDesc?: string;
|
|
26
|
-
observationLabelTitle?: string;
|
|
27
|
-
observationLabelDate?: string;
|
|
28
|
-
observationLabelName?: string;
|
|
29
|
-
observationCount?: string;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
export type BaseComponentProps = {
|
|
33
|
-
taxonId?: number;
|
|
34
|
-
placeId?: number;
|
|
35
|
-
numResults?: number;
|
|
36
|
-
source?: DataSource;
|
|
37
|
-
dataUrl?: string;
|
|
38
|
-
className?: string;
|
|
39
|
-
itemWidth?: number;
|
|
40
|
-
components?: {
|
|
41
|
-
label?: any;
|
|
42
|
-
error?: any;
|
|
43
|
-
loader?: any;
|
|
44
|
-
};
|
|
45
|
-
generalClasses?: GeneralClasses;
|
|
46
|
-
tabDesc?: string;
|
|
47
|
-
};
|
|
48
|
-
|
|
49
|
-
export type RecentObservationsConfig = {
|
|
50
|
-
feature: Feature.recentObservations,
|
|
51
|
-
title?: string;
|
|
52
|
-
numResults?: number;
|
|
53
|
-
desc?: string;
|
|
54
|
-
className?: string;
|
|
55
|
-
}
|
|
56
|
-
export type CommonTaxaConfig = {
|
|
57
|
-
feature: Feature.commonTaxa,
|
|
58
|
-
title?: string;
|
|
59
|
-
numResults?: number;
|
|
60
|
-
numYears?: number;
|
|
61
|
-
desc?: string;
|
|
62
|
-
className?: string;
|
|
63
|
-
}
|
|
64
|
-
export type FavouritesConfig = {
|
|
65
|
-
feature: Feature.favourites;
|
|
66
|
-
title?: string;
|
|
67
|
-
numResults?: number;
|
|
68
|
-
numYears?: number;
|
|
69
|
-
desc?: string;
|
|
70
|
-
className?: string;
|
|
71
|
-
}
|
|
72
|
-
export type StatsConfig = {
|
|
73
|
-
feature: Feature.stats;
|
|
74
|
-
title?: string;
|
|
75
|
-
numTopObservers?: number;
|
|
76
|
-
numYears?: number;
|
|
77
|
-
desc?: string;
|
|
78
|
-
className?: string;
|
|
79
|
-
observersListClass?: string;
|
|
80
|
-
statsCountSummaryClass?: string;
|
|
81
|
-
};
|
|
82
|
-
|
|
83
|
-
export type TaxonPanelFeatures = (RecentObservationsConfig|CommonTaxaConfig|FavouritesConfig|StatsConfig)[];
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import { Feature, ItemConfig } from "../typings";
|
|
2
|
-
|
|
3
|
-
/*
|
|
4
|
-
* Note that right now the source filenames aren't configurable.
|
|
5
|
-
*/
|
|
6
|
-
export const getSourceFile = (api: Feature, taxon: ItemConfig, place: ItemConfig, year?: string | number): string => {
|
|
7
|
-
if (!taxon || !place) {
|
|
8
|
-
return '';
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
const yearStr = year === "all" ? "allyears" : year;
|
|
12
|
-
|
|
13
|
-
let filename = "";
|
|
14
|
-
if (api === Feature.recentObservations) {
|
|
15
|
-
filename = `${taxon.str}-${place.str}-recent.json`;
|
|
16
|
-
} else if (api === Feature.commonTaxa) {
|
|
17
|
-
filename = `${taxon.str}-${place.str}-${yearStr}-commonTaxa.json`;
|
|
18
|
-
} else if (api === Feature.favourites) {
|
|
19
|
-
filename = `${taxon.str}-${place.str}-${yearStr}-favourites.json`;
|
|
20
|
-
} else if (api === Feature.stats) {
|
|
21
|
-
filename = `${taxon.str}-${place.str}-${yearStr}-stats.json`;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
return filename;
|
|
25
|
-
};
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import { format } from "date-fns";
|
|
2
|
-
|
|
3
|
-
export const getCurrentYear = () => new Date().getFullYear();
|
|
4
|
-
|
|
5
|
-
// not 100% this shows the date in the right timezone, but it's fine for BC
|
|
6
|
-
export const formatDate = (date: string, dateFormat = "MMM do, h:mm b"): any => {
|
|
7
|
-
let formattedDate = "";
|
|
8
|
-
try {
|
|
9
|
-
formattedDate = format(Date.parse(date), dateFormat);
|
|
10
|
-
} catch (e) {
|
|
11
|
-
console.log("Failed to parse date: ", date);
|
|
12
|
-
}
|
|
13
|
-
return formattedDate;
|
|
14
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export const numberWithCommas = (x: number) => (x || 0).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import {render} from '@testing-library/react';
|
|
2
|
-
|
|
3
|
-
import { CommonTaxa } from '../common-taxa';
|
|
4
|
-
|
|
5
|
-
const defaultProps = {
|
|
6
|
-
year: 2022
|
|
7
|
-
};
|
|
8
|
-
|
|
9
|
-
describe('CommonTaxa', () => {
|
|
10
|
-
it('should render successfully', () => {
|
|
11
|
-
const {baseElement} = render(<CommonTaxa {...defaultProps} />);
|
|
12
|
-
expect(baseElement).toBeTruthy();
|
|
13
|
-
});
|
|
14
|
-
});
|