@performant-software/core-data 1.2.0-beta.2 → 1.2.0-beta.20
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/build/index.js +1 -1
- package/build/index.js.map +1 -1
- package/build/main.css +17 -5
- package/package.json +13 -3
- package/postcss.config.js +6 -0
- package/src/components/MediaGallery.js +1 -1
- package/src/components/PlaceDetailsPanel.js +14 -1
- package/src/components/PlaceMarker.js +6 -0
- package/src/components/PlaceResultsList.css +7 -0
- package/src/components/PlaceResultsList.js +178 -0
- package/src/components/{PlaceDetailsPanel.css → RelatedItemsList.css} +5 -5
- package/src/components/RelatedItemsList.js +14 -3
- package/src/components/RelatedList.js +15 -1
- package/src/components/RelatedMedia.js +14 -0
- package/src/components/RelatedOrganizations.js +8 -1
- package/src/components/RelatedPeople.js +8 -1
- package/src/components/RelatedPlaces.js +8 -1
- package/src/components/RelatedTaxonomies.js +8 -1
- package/src/i18n/en.json +27 -0
- package/src/i18n/i18n.js +26 -0
- package/src/index.css +3 -0
- package/src/index.js +4 -0
- package/src/types/Feature.js +10 -0
- package/src/types/typesense/Place.js +14 -0
- package/tailwind.config.js +19 -0
- package/types/components/MediaGallery.js.flow +1 -1
- package/types/components/PlaceDetailsPanel.js.flow +14 -1
- package/types/components/PlaceMarker.js.flow +6 -0
- package/types/components/PlaceResultsList.js.flow +178 -0
- package/types/components/RelatedItemsList.js.flow +14 -3
- package/types/components/RelatedList.js.flow +15 -1
- package/types/components/RelatedMedia.js.flow +14 -0
- package/types/components/RelatedOrganizations.js.flow +8 -1
- package/types/components/RelatedPeople.js.flow +8 -1
- package/types/components/RelatedPlaces.js.flow +8 -1
- package/types/components/RelatedTaxonomies.js.flow +8 -1
- package/types/components/SearchResultsList.js.flow +160 -0
- package/types/i18n/i18n.js.flow +26 -0
- package/types/index.js.flow +4 -0
- package/types/types/Feature.js.flow +10 -0
- package/types/types/typesense/Place.js.flow +14 -0
- package/webpack.config.js +31 -1
|
@@ -2,18 +2,25 @@
|
|
|
2
2
|
|
|
3
3
|
import { Building2 } from 'lucide-react';
|
|
4
4
|
import React from 'react';
|
|
5
|
+
import i18n from '../i18n/i18n';
|
|
5
6
|
import type { AnnotationPage } from '../types/AnnotationPage';
|
|
6
7
|
import type { Organization } from '../types/Organization';
|
|
7
8
|
import RelatedList from './RelatedList';
|
|
8
9
|
|
|
9
10
|
type Props = {
|
|
11
|
+
/**
|
|
12
|
+
* The annotation page containing the Core Data organizations to render.
|
|
13
|
+
*/
|
|
10
14
|
data: AnnotationPage<Organization>
|
|
11
15
|
};
|
|
12
16
|
|
|
17
|
+
/**
|
|
18
|
+
* This component renders the related Core Data organizations records.
|
|
19
|
+
*/
|
|
13
20
|
const RelatedOrganizations = (props: Props) => (
|
|
14
21
|
<RelatedList
|
|
15
22
|
data={props.data}
|
|
16
|
-
emptyMessage={'
|
|
23
|
+
emptyMessage={i18n.t('RelatedOrganizations.labels.empty')}
|
|
17
24
|
renderItem={(organization) => (
|
|
18
25
|
<>
|
|
19
26
|
<Building2
|
|
@@ -2,18 +2,25 @@
|
|
|
2
2
|
|
|
3
3
|
import { UserCircle } from 'lucide-react';
|
|
4
4
|
import React from 'react';
|
|
5
|
+
import i18n from '../i18n/i18n';
|
|
5
6
|
import type { AnnotationPage } from '../types/AnnotationPage';
|
|
6
7
|
import type { Person } from '../types/Person';
|
|
7
8
|
import RelatedList from './RelatedList';
|
|
8
9
|
|
|
9
10
|
type Props = {
|
|
11
|
+
/**
|
|
12
|
+
* The annotation page containing the Core Data people to render.
|
|
13
|
+
*/
|
|
10
14
|
data: AnnotationPage<Person>
|
|
11
15
|
};
|
|
12
16
|
|
|
17
|
+
/**
|
|
18
|
+
* This component renders the related Core Data organizations.
|
|
19
|
+
*/
|
|
13
20
|
const RelatedPeople = (props: Props) => (
|
|
14
21
|
<RelatedList
|
|
15
22
|
data={props.data}
|
|
16
|
-
emptyMessage={'
|
|
23
|
+
emptyMessage={i18n.t('RelatedPeople.labels.empty')}
|
|
17
24
|
renderItem={(person) => (
|
|
18
25
|
<>
|
|
19
26
|
<UserCircle
|
|
@@ -2,18 +2,25 @@
|
|
|
2
2
|
|
|
3
3
|
import { MapPin } from 'lucide-react';
|
|
4
4
|
import React from 'react';
|
|
5
|
+
import i18n from '../i18n/i18n';
|
|
5
6
|
import type { AnnotationPage } from '../types/AnnotationPage';
|
|
6
7
|
import type { Place } from '../types/Place';
|
|
7
8
|
import RelatedList from './RelatedList';
|
|
8
9
|
|
|
9
10
|
type Props = {
|
|
11
|
+
/**
|
|
12
|
+
* The annotation page containing the Core Data places to render.
|
|
13
|
+
*/
|
|
10
14
|
data: AnnotationPage<Place>
|
|
11
15
|
};
|
|
12
16
|
|
|
17
|
+
/**
|
|
18
|
+
* This component renders the related Core Data places.
|
|
19
|
+
*/
|
|
13
20
|
const RelatedPlaces = (props: Props) => (
|
|
14
21
|
<RelatedList
|
|
15
22
|
data={props.data}
|
|
16
|
-
emptyMessage={'
|
|
23
|
+
emptyMessage={i18n.t('RelatedPlaces.labels.empty')}
|
|
17
24
|
renderItem={(place) => (
|
|
18
25
|
<>
|
|
19
26
|
<MapPin
|
|
@@ -2,18 +2,25 @@
|
|
|
2
2
|
|
|
3
3
|
import { ListTree } from 'lucide-react';
|
|
4
4
|
import React from 'react';
|
|
5
|
+
import i18n from '../i18n/i18n';
|
|
5
6
|
import type { AnnotationPage } from '../types/AnnotationPage';
|
|
6
7
|
import RelatedList from './RelatedList';
|
|
7
8
|
import type { Taxonomy } from '../types/Taxonomy';
|
|
8
9
|
|
|
9
10
|
type Props = {
|
|
11
|
+
/**
|
|
12
|
+
* The annotation page containing the Core Data taxonomies to render.
|
|
13
|
+
*/
|
|
10
14
|
data: AnnotationPage<Taxonomy>
|
|
11
15
|
};
|
|
12
16
|
|
|
17
|
+
/**
|
|
18
|
+
* This component renders the related Core Data taxonomies.
|
|
19
|
+
*/
|
|
13
20
|
const RelatedTaxonomies = (props: Props) => (
|
|
14
21
|
<RelatedList
|
|
15
22
|
data={props.data}
|
|
16
|
-
emptyMessage={'
|
|
23
|
+
emptyMessage={i18n.t('RelatedTaxonomies.labels.empty')}
|
|
17
24
|
renderItem={(taxonomy) => (
|
|
18
25
|
<>
|
|
19
26
|
<ListTree
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
// @flow
|
|
2
|
+
|
|
3
|
+
import React, { useMemo } from 'react';
|
|
4
|
+
import { Highlight } from 'react-instantsearch';
|
|
5
|
+
import AutoSizer from 'react-virtualized-auto-sizer';
|
|
6
|
+
import { FixedSizeList } from 'react-window';
|
|
7
|
+
import _ from 'underscore';
|
|
8
|
+
import type { Feature } from '../types/Feature';
|
|
9
|
+
import type { Place } from '../types/typesense/Place';
|
|
10
|
+
import './SearchResultsList.css';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Converts the passed place result to a feature.
|
|
14
|
+
*
|
|
15
|
+
* @param result
|
|
16
|
+
*
|
|
17
|
+
* @returns {{
|
|
18
|
+
* geometry: {coordinates: number[], type: string},
|
|
19
|
+
* id: number,
|
|
20
|
+
* type:
|
|
21
|
+
* string,
|
|
22
|
+
* properties: {
|
|
23
|
+
* ccode: *[],
|
|
24
|
+
* record_id: string,
|
|
25
|
+
* names: *,
|
|
26
|
+
* name: string,
|
|
27
|
+
* id: string,
|
|
28
|
+
* title: string,
|
|
29
|
+
* type: string,
|
|
30
|
+
* uuid: string
|
|
31
|
+
* }
|
|
32
|
+
* }}
|
|
33
|
+
*/
|
|
34
|
+
const toFeature = (result: Place) => ({
|
|
35
|
+
id: parseInt(result.record_id, 10),
|
|
36
|
+
type: 'Feature',
|
|
37
|
+
properties: {
|
|
38
|
+
id: result.record_id,
|
|
39
|
+
ccode: [],
|
|
40
|
+
title: result.name,
|
|
41
|
+
uuid: result.uuid,
|
|
42
|
+
record_id: result.record_id,
|
|
43
|
+
name: result.name,
|
|
44
|
+
names: _.map(result.names, (toponym) => ({ toponym })),
|
|
45
|
+
type: result.type
|
|
46
|
+
},
|
|
47
|
+
geometry: {
|
|
48
|
+
type: 'Point',
|
|
49
|
+
coordinates: result.coordinates.slice().reverse()
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
type HitComponentProps = {
|
|
54
|
+
hit: any,
|
|
55
|
+
isHovered: boolean,
|
|
56
|
+
onClick: () => void
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
const HitComponent = (props: HitComponentProps) => {
|
|
60
|
+
const { hit } = props;
|
|
61
|
+
|
|
62
|
+
const className = useMemo(() => {
|
|
63
|
+
const classNames = [
|
|
64
|
+
'h-[5.5em]',
|
|
65
|
+
'border-b',
|
|
66
|
+
'flex',
|
|
67
|
+
'flex-col',
|
|
68
|
+
'justify-start'
|
|
69
|
+
];
|
|
70
|
+
|
|
71
|
+
if (props.isHovered) {
|
|
72
|
+
classNames.add('bg-teal-700/30');
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
return classNames.join(' ');
|
|
76
|
+
}, [props.isHovered]);
|
|
77
|
+
|
|
78
|
+
return (
|
|
79
|
+
<div
|
|
80
|
+
className={className}
|
|
81
|
+
>
|
|
82
|
+
<button
|
|
83
|
+
className='py-2 px-3 flex-grow text-left inline-flex flex-col'
|
|
84
|
+
onClick={props.onClick}
|
|
85
|
+
type='button'
|
|
86
|
+
>
|
|
87
|
+
<Highlight
|
|
88
|
+
attribute='name'
|
|
89
|
+
className='line-clamp-2'
|
|
90
|
+
hit={hit}
|
|
91
|
+
/>
|
|
92
|
+
<p
|
|
93
|
+
className='text-muted text-xs line-clamp-1'
|
|
94
|
+
>
|
|
95
|
+
<Highlight
|
|
96
|
+
hit={hit}
|
|
97
|
+
attribute='names'
|
|
98
|
+
/>
|
|
99
|
+
</p>
|
|
100
|
+
</button>
|
|
101
|
+
</div>
|
|
102
|
+
);
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
type Props = {
|
|
106
|
+
hits: Array<Place>,
|
|
107
|
+
hover?: Feature<{ id: string }>,
|
|
108
|
+
onHoverChange: (hover?: Feature<{ id: string }>) => void,
|
|
109
|
+
onClick: (result: Place) => void
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
type RowProps = {
|
|
113
|
+
index: number,
|
|
114
|
+
style: any
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
const SearchResultsList = (props: Props) => {
|
|
118
|
+
const {
|
|
119
|
+
hits,
|
|
120
|
+
hover,
|
|
121
|
+
onClick,
|
|
122
|
+
onHoverChange
|
|
123
|
+
} = props;
|
|
124
|
+
|
|
125
|
+
const Row = ({ index, style }: RowProps) => {
|
|
126
|
+
const hit = hits[index];
|
|
127
|
+
const id = parseInt(hit.record_id, 10);
|
|
128
|
+
|
|
129
|
+
return (
|
|
130
|
+
<div
|
|
131
|
+
style={style}
|
|
132
|
+
onPointerEnter={() => onHoverChange(hover?.id === id ? hover : toFeature(hit))}
|
|
133
|
+
onPointerLeave={() => onHoverChange(undefined)}
|
|
134
|
+
>
|
|
135
|
+
<HitComponent
|
|
136
|
+
hit={hit}
|
|
137
|
+
isHovered={hover?.id === parseInt(hit?.record_id, 10)}
|
|
138
|
+
onClick={() => onClick(hit)}
|
|
139
|
+
/>
|
|
140
|
+
</div>
|
|
141
|
+
);
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
return (
|
|
145
|
+
<AutoSizer>
|
|
146
|
+
{({ height, width }) => (
|
|
147
|
+
<FixedSizeList
|
|
148
|
+
height={height}
|
|
149
|
+
itemCount={hits.length}
|
|
150
|
+
width={width}
|
|
151
|
+
itemSize={88}
|
|
152
|
+
>
|
|
153
|
+
{Row}
|
|
154
|
+
</FixedSizeList>
|
|
155
|
+
)}
|
|
156
|
+
</AutoSizer>
|
|
157
|
+
);
|
|
158
|
+
};
|
|
159
|
+
|
|
160
|
+
export default SearchResultsList;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
// @flow
|
|
2
|
+
|
|
3
|
+
import i18next from 'i18next';
|
|
4
|
+
|
|
5
|
+
import en from './en.json';
|
|
6
|
+
|
|
7
|
+
const resources = {
|
|
8
|
+
en: {
|
|
9
|
+
translation: en
|
|
10
|
+
}
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
const i18n = i18next.createInstance();
|
|
14
|
+
|
|
15
|
+
i18n
|
|
16
|
+
.init({
|
|
17
|
+
debug: true,
|
|
18
|
+
fallbackLng: 'en',
|
|
19
|
+
lng: 'en',
|
|
20
|
+
interpolation: {
|
|
21
|
+
escapeValue: false,
|
|
22
|
+
},
|
|
23
|
+
resources
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
export default i18n;
|
package/types/index.js.flow
CHANGED
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
// @flow
|
|
2
2
|
|
|
3
|
+
// CSS
|
|
4
|
+
import './index.css';
|
|
5
|
+
|
|
3
6
|
// Components
|
|
4
7
|
export { default as LoadAnimation } from './components/LoadAnimation';
|
|
5
8
|
export { default as MediaGallery } from './components/MediaGallery';
|
|
6
9
|
export { default as PlaceDetailsPanel } from './components/PlaceDetailsPanel';
|
|
7
10
|
export { default as PlaceMarker } from './components/PlaceMarker';
|
|
11
|
+
export { default as PlaceResultsList } from './components/PlaceResultsList';
|
|
8
12
|
export { default as RelatedItemsList } from './components/RelatedItemsList';
|
|
9
13
|
export { default as RelatedList } from './components/RelatedList';
|
|
10
14
|
export { default as RelatedMedia } from './components/RelatedMedia';
|
package/webpack.config.js
CHANGED
|
@@ -1,3 +1,33 @@
|
|
|
1
1
|
const { configure } = require('@performant-software/webpack-config');
|
|
2
|
+
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
|
|
3
|
+
const path = require('path');
|
|
2
4
|
|
|
3
|
-
|
|
5
|
+
const options = {
|
|
6
|
+
module: {
|
|
7
|
+
rules: [{
|
|
8
|
+
test: /\.(c|le)ss$/,
|
|
9
|
+
use: [
|
|
10
|
+
MiniCssExtractPlugin.loader,
|
|
11
|
+
'css-loader',
|
|
12
|
+
'postcss-loader'
|
|
13
|
+
],
|
|
14
|
+
include: [
|
|
15
|
+
path.resolve(__dirname)
|
|
16
|
+
]
|
|
17
|
+
}]
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
const mergeOptions = {
|
|
22
|
+
module: {
|
|
23
|
+
rules: {
|
|
24
|
+
test: /\.(c|le)ss$/,
|
|
25
|
+
use: {
|
|
26
|
+
loader: 'match',
|
|
27
|
+
options: 'replace',
|
|
28
|
+
},
|
|
29
|
+
},
|
|
30
|
+
},
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
module.exports = configure(__dirname, options, mergeOptions);
|