Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Facet conditions #10

Open
wants to merge 11 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2,991 changes: 2,991 additions & 0 deletions docs/data/mark16-lp.json

Large diffs are not rendered by default.

35 changes: 34 additions & 1 deletion docs/index.html
Original file line number Diff line number Diff line change
@@ -1 +1,34 @@
<!doctype html><html><head><title>Peripleo LaNC</title><meta charset="utf-8"/><meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no"><meta name="peripleo:config" content="peripleo.config.json"><meta name="description" content="A prototype viewer for geo-located collection data. This project is a Foundation project within the AHRC-funded 'Towards a National Collection' Programme"/><meta name="twitter:card" content="summary_large_image"/><meta name="twitter:site" content="@britishlibrary"/><meta name="twitter:title" content="Peripleo | Locating a National Collection"/><meta name="twitter:description" content="A prototype viewer for geo-located collection data. This project is a Foundation project within the AHRC-funded 'Towards a National Collection' Programme"/><meta name="twitter:image" content="https://github.com/britishlibrary/peripleo-lanc/raw/main/public/peripleo-social-preview-bl-lanc.png"/><meta property="og:type" content="website"/><meta property="og:title" content="Peripleo | Locating a National Collection"/><meta property="og:description" content="A prototype viewer for geo-located collection data. This project is a Foundation project within the AHRC-funded 'Towards a National Collection' Programme"/><meta property="og:image" content="https://github.com/britishlibrary/peripleo-lanc/raw/main/public/peripleo-social-preview-bl-lanc.png"/><meta property="og:image:width" content="1000"/><meta property="og:image:height" content="500"/><meta property="og:url" content="https://britishlibrary.github.io/peripleo-lanc/"/><link href="https://unpkg.com/[email protected]/dist/maplibre-gl.css" rel="stylesheet"/><link rel="preconnect" href="https://fonts.googleapis.com"><link rel="preconnect" href="https://fonts.gstatic.com" crossorigin><link href="https://fonts.googleapis.com/css2?family=Quicksand:wght@500;700&display=swap" rel="stylesheet"><script defer="defer" src="peripleo-lanc.js"></script></head><body><div id="app"></div></body></html>
<!DOCTYPE html>
<html>
<head>
<title>Peripleo</title>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<meta name="description" content="Peripleo LaNC. A prototype viewer for geo-located collection data." />
<!-- Twitter card metadata -->
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:site" content="@britishlibrary" />
<meta name="twitter:title" content="Peripleo | Locating a National Collection" />
<meta name="twitter:description" content="A prototype viewer for geo-located collection data." />
<meta name="twitter:image" content="https://github.com/britishlibrary/peripleo-lanc/raw/main/public/peripleo-social-preview.png" />
<!-- OG metadata -->
<meta property="og:type" content="website" />
<meta property="og:title" content="Peripleo | Locating a National Collection" />
<meta property="og:description" content="A prototype viewer for geo-located collection data." />
<meta property="og:image" content="https://github.com/britishlibrary/peripleo-lanc/raw/main/public/peripleo-social-preview.png" />
<meta property="og:image:width" content="1000" />
<meta property="og:image:height" content="500" />
<meta property="og:url" content="https://britishlibrary.github.io/peripleo-lanc/" />
<!-- Imports-->
<link rel="icon" type="image/x-icon" href="./favicon.ico">
<link href='https://unpkg.com/[email protected]/dist/maplibre-gl.css' rel='stylesheet' />
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Quicksand:wght@500;700&display=swap" rel="stylesheet">
<script defer="defer" src="https://britishlibrary.github.io/peripleo-lanc/peripleo-lanc.js"></script>
</head>

<body>
<div id="app"></div>
</body>
</html>
58 changes: 58 additions & 0 deletions docs/map-style-OSM.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
{
"id": "Peripleo",
"name": "Peripleo",
"zoom": 9,
"pitch": 0,
"center": [
0,
51
],
"layers": [
{
"id": "background",
"type": "background",
"paint": {
"background-color": {
"stops": [
[
5,
"rgba(239, 245, 231, 1)"
],
[
14,
"rgba(242, 243, 242, 1)"
]
]
}
},
"layout": {
"visibility": "visible"
},
"minzoom": 0
},
{
"id": "Open-Street-Map",
"type": "raster",
"source": "Open-Street-Map",
"minzoom": 0,
"maxzoom": 22
}
],
"bearing": 0,
"sources": {
"Open-Street-Map": {
"type": "raster",
"tiles": [
"https://tile.openstreetmap.org/{z}/{x}/{y}.png"
],
"tileSize": 256,
"attribution": "OpenStreetMap contributors"
}
},
"version": 8,
"metadata": {
"mapbox:type": "template",
"maptiler:copyright": "None",
"openmaptiles:version": "3.x"
}
}
73 changes: 27 additions & 46 deletions docs/peripleo.config.json
Original file line number Diff line number Diff line change
@@ -1,47 +1,28 @@
{
"initial_bounds": [-7.9, 49.5, 2.2, 59.4],
"ga_id": "G-2HSSF48HYH",
"map_style": "https://api.maptiler.com/maps/outdoor/style.json?key=cqqmcLw28krG9Fl7V3kg",
"data": [
{ "name": "Portable Antiquities Scheme", "format": "LINKED_PLACES", "src": "data/PAS_Warwickshire.lp.json", "logo": "logos/finds.org.uk.png", "attribution":"Findspot Data © <a href=\"https://finds.org.uk/\" target=\"_blank\">Portable Antiquities Scheme</a>" },
{ "name": "Hollar", "format": "LINKED_PLACES", "src": "data/Hollar-1660.lp.json", "attribution":"Hollar 1660 © <a href=\"https://viaeregiae.org/\" target=\"_blank\"><i>Viae Regiae</i> Contributors</a>" },
{ "name": "VisitPlus", "format": "LINKED_PLACES", "src": "data/VisitPlus-UK.lp.json", "attribution":"VisitPlus © <a href=\"https://britishlibrary.github.io/locating-a-national-collection/\" target=\"_blank\"><i>Locating a National Collection</i> Partners & Contributors</a>" },
{ "name": "Mapping Museums", "format": "LINKED_PLACES", "src": "data/Mapping-Museums.lp.json", "attribution":"Museums data © <a href=\"https://museweb.dcs.bbk.ac.uk/home\" target=\"_blank\">Mapping Museums</a>" }
],
"facets": [
"dataset",
"type",
{ "name": "technique", "path": ["relations", "label"], "condition": [ "relationType", "aat:300138082" ] }
],
"link_icons": [
{ "pattern": "www.nationaltrust.org.uk", "img": "../logos/www.nationaltrust.org.uk.png", "label": "National Trust" },
{ "pattern": "www.nationaltrustcollections.org.uk", "img": "../logos/www.nationaltrustcollections.org.uk.svg", "Label": "National Trust" },
{ "pattern": "www.mola.org.uk", "img": "../logos/www.mola.org.uk.png", "label": "MOLA" },
{ "pattern": "www.historicenvironment.scot", "img": "../logos/www.historicenvironment.scot.png", "label": "Historic Environment Scotland" },
{ "pattern": "www.english-heritage.org.uk", "img": "../logos/www.english-heritage.org.uk.png", "label": "English Heritage" },
{ "pattern": "www.britishmuseum.org", "img": "../logos/www.britishmuseum.org.png", "label": "British Museum" },
{ "pattern": "www.flickr.com", "img": "../logos/www.bl.uk.png", "label": "Flickr" },
{ "pattern": "www.bl.uk", "img": "../logos/www.bl.uk.png", "label": "British Library" },
{ "pattern": "access.bl.uk", "img": "../logos/www.bl.uk.png", "label": "British Library" },
{ "pattern": "sounds.bl.uk", "img": "../logos/www.bl.uk.png", "label": "British Library" },
{ "pattern": "britishlibrary.georeferencer.com", "img": "../logos/www.bl.uk.png", "label": "British Library" },
{ "pattern": "hrp.org.uk", "img": "../logos/hrp.org.uk.png", "label": "Historic Royal Palaces" },
{ "pattern": "historicengland.org.uk", "img": "../logos/historicengland.org.uk.png", "label": "Historic England" },
{ "pattern": "finds.org.uk", "img": "../logos/finds.org.uk.png", "label": "Portable Antiquities Scheme" },
{ "pattern": "cadw.gov.wales", "img": "../logos/cadw.gov.wales.png", "label": "CADW" },
{ "pattern": "cadwpublic-api.azurewebsites.net", "img": "../logos/cadw.gov.wales.png", "label": "CADW" },
{ "pattern": "www.geograph.org.uk", "img": "../logos/geograph.org.png", "label": "Geograph" },
{ "pattern": "w3id.org/locolligo/VCH-Places", "img": "../logos/VCH.jpg", "label": "VCH" },
{ "pattern": "w3id.org/locolligo/Mapping-Museums", "img": "../logos/museums.png", "label": "Mapping Museums" },
{ "pattern": "w3id.org", "img": "../logos/w3id.org.png", "label": "W3ID" },
{ "pattern": "openplaques.org", "img": "../logos/openplaques.png", "label": "Open Plaques" },
{ "pattern": "artuk.org", "img": "../logos/ArtUK.org.png", "label": "Art UK" },
{ "pattern": "en.wikipedia.org", "img": "../logos/en.wikipedia.org.png", "label": "Wikipedia" },
{ "pattern": "www.pastplace.org", "img": "../logos/broken-link.png", "label": "PastPlace" },
{ "pattern": "emew.io", "img": "../logos/broken-link.png", "label": "EMEW" },
{ "pattern": "whgazetteer.org", "img": "../logos/whgazetteer.org.svg", "label": "World Historical Gazetteer" },
{ "pattern": "www.geonames.org", "img": "../logos/www.geonames.org.svg", "label": "GeoNames" },
{ "pattern": "sws.geonames.org", "img": "../logos/www.geonames.org.svg", "label": "GeoNames" },
{ "pattern": "www.wikidata.org", "img": "../logos/www.wikidata.org.svg", "label": "Wikidata" }
]
}
"initial_bounds": [-165.021286, -15.163128, 77.029491, 64.184474],
"map_style": "./map-style-OSM.json",
"disableMyLocation": true,
"data": [
{
"name": "Mark16",
"format": "LINKED_PLACES",
"src": "./data/mark16-lp.json",
"attribution": "MARK16 Dataviz © <a href=\"https://mark16.sib.swiss/\" target=\"_blank\"><i>MARK16</i> Partners & Contributors</a>"
}
],
"facets": [
{ "name": "language", "path": ["relations", "lang"], "dynamicCondition": [{"name": "manuscript", "path": "title"}, {"name": "location", "path": "label"}] },
{ "name": "manuscript", "path": ["relations", "title"], "dynamicCondition": [{"name": "language", "path": "lang"}, {"name": "location", "path": "label"}] },
{ "name": "location", "path": ["relations", "label"], "dynamicCondition": [{"name": "language", "path": "lang"}, {"name": "manuscript", "path": "title"}] },
"type"
],
"link_icons": [
{ "pattern": "maps.google.com", "img": "./logos/maps.google.com.png", "label": "Google Maps" },
{ "pattern": "www.geograph.org.uk", "img": "./logos/geograph.org.png", "label": "Geograph" },
{ "pattern": "en.wikipedia.org", "img": "./logos/en.wikipedia.org.png", "label": "Wikipedia" },
{ "pattern": "www.wikidata.org", "img": null, "label": "Wikidata" },
{ "pattern": "www.geonames.org", "img": null, "label": "GeoNames" },
{ "pattern": "sws.geonames.org", "img": null, "label": "GeoNames" }
]
}

1 change: 1 addition & 0 deletions src/map/controls/Controls.scss
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
}

.p6o-map-modes {
display:none;
position:relative;

.p6o-controls-btn {
Expand Down
68 changes: 57 additions & 11 deletions src/state/search/Facets.js
Original file line number Diff line number Diff line change
@@ -1,20 +1,23 @@
export class Facet {

constructor(name, definition, condition) {
constructor(name, definition, condition, dynamicCondition) {
this.name = name;
this.definition = definition;
this.condition = condition;
this.dynamicCondition = dynamicCondition;
}

}

const toSortedArray = counts => {
const entries = Object.entries(counts);
entries.sort((a, b) => b[1] - a[1]);
entries.sort((a, b) => a[0].localeCompare(b[0]));
return entries;
}

const computeFacet = (items, facetName, fn, postFilter) => {


const counts = {};

const facetedItems = items.map(item => {
Expand Down Expand Up @@ -54,9 +57,9 @@ const computeSimpleFieldFacet = (items, facet, postFilter) =>
const computeCustomFnFacet = (items, facet, postFilter) =>
computeFacet(items, facet.name, facet.definition, postFilter);

const computeNestedFieldFacet = (items, facet, postFilter) => {
const computeNestedFieldFacet = (items, facet, postFilter, dynamicConditions) => {

const getValueRecursive = (obj, path, condition) => {
const getValueRecursive = (obj, path, condition, dynamicConditions) => {
const [ nextSegment, ...pathRest ] = path;

const meetsCondition = obj => {
Expand All @@ -77,31 +80,74 @@ const computeNestedFieldFacet = (items, facet, postFilter) => {
}

const value = obj[nextSegment];

if (pathRest.length === 0 || !value) {
return value;

//if the dynamic condition exists and is not an empty array
if (dynamicConditions && dynamicConditions.length > 0){
let isFilteredItem = true;
//loop over the dynamic condition path/values
dynamicConditions.map(condition =>{
//check that for each condition the manuscript (path) matches one of the values
//if the item does not meet one of the conditions, set to false
isFilteredItem = condition.values.includes(obj[condition.path]);
})
//if the item matched all conditions, return the value to be counted in the facet counts
if (isFilteredItem){
return value;
}
}
else if (!dynamicConditions || dynamicConditions.length == 0){
return value;
}

} else {
return Array.isArray(value) ?

value.filter(meetsCondition)
.map(obj => getValueRecursive(obj, pathRest, condition))
.map(obj => getValueRecursive(obj, pathRest, condition, dynamicConditions))
.filter(value => value) // Remove undefined

:

meetsCondition(value) ?
getValueRecursive(value, pathRest, condition) : [];
getValueRecursive(value, pathRest, condition, dynamicConditions) : [];
}
};

return computeFacet(items, facet.name, item => getValueRecursive(item, facet.definition, facet.condition), postFilter);
return computeFacet(items, facet.name, item => getValueRecursive(item, facet.definition, facet.condition, dynamicConditions), postFilter);
}

export const computeFacetDistribution = (items, facet, postFilter) => {
export const computeFacetDistribution = (items, facet, postFilter, queryFilters) => {
const { definition } = facet;

//create an array of dynamic conditions with the path and values
//the values will create an additional filter for creating the counts to display in a facet
let dynamicConditions= [];

//check if there are filters and the current facet has one or more dynamic conditions
if(Array.isArray(queryFilters) && facet.dynamicCondition){
//for each dynamic condition, select the path and values
facet.dynamicCondition.map(condition => {
let pair = {};
//path
pair["path"] = condition.path;
//values are found in the filter with the same facet as the condition name
let dynamicValues = queryFilters.find(f => f.facet === condition.name);
if (dynamicValues){
pair["values"] = dynamicValues.values;
//assign path/values only if there are values to filter with
dynamicConditions.push(pair);
}

});
}

if (Array.isArray(definition))
return computeNestedFieldFacet(items, facet, postFilter);
//the Language/Manuscript/location facets should each be filtered by the other two!
return computeNestedFieldFacet(items, facet, postFilter, dynamicConditions);
else if (definition instanceof Function)
return computeCustomFnFacet(items, facet, postFilter);
else
return computeSimpleFieldFacet(items, facet, postFilter);
}
}
4 changes: 2 additions & 2 deletions src/state/search/FacetsContext.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export const FacetsContextProvider = props => {
// Built-in facet
return DEFAULT_FACETS.find(f => f.name === definition);
} else if (definition.name && definition.path) {
return new Facet(definition.name, definition.path, definition.condition);
return new Facet(definition.name, definition.path, definition.condition, definition.dynamicCondition);
}
}));
}
Expand All @@ -41,4 +41,4 @@ export const FacetsContextProvider = props => {
</FacetsContext.Provider>
)

}
}
4 changes: 2 additions & 2 deletions src/state/search/useSearch.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ const useSearch = () => {
const facetDistribution =
facet &&
availableFacets.find(f => f.name === facet) &&
computeFacetDistribution(preFilteredItems, availableFacets.find(f => f.name === facet), postFilter);
computeFacetDistribution(preFilteredItems, availableFacets.find(f => f.name === facet), postFilter, filters);

const items = facetDistribution ?
facetDistribution.items : preFilteredItems;
Expand Down Expand Up @@ -175,4 +175,4 @@ const useSearch = () => {

}

export default useSearch;
export default useSearch;