Skip to content
Merged
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
4 changes: 0 additions & 4 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,6 @@ VITE_MACROSTRAT_API_DOMAIN='https://macrostrat.org'

VITE_ROCKD_API_URL='https://dev.rockd.org/api/v2/'

# For matomo analytics
VITE_MATOMO_API_URL='<our-matomo-api-url>'
VITE_MATOMO_API_TOKEN='<your-matomo-api-token>'

# Needed for map ingestion system
# SECRET_KEY='Replace with api signing key'

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@
"@macrostrat/mapbox-react": "^2.5.0",
"@macrostrat/mapbox-utils": "^1.4.0",
"@macrostrat/style-system": "^0.2.0",
"@macrostrat/ui-components": "^4.1.2",
"@macrostrat/ui-components": "^4.4.4",
"@supabase/postgrest-js": "^1.11.0",
"@universal-middleware/express": "^0.0.2",
"@vitejs/plugin-react": "^4.0.4",
Expand Down
279 changes: 5 additions & 274 deletions pages/explore/+Page.client.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { useMapRef } from "@macrostrat/mapbox-react";
import { Spinner, Icon, Divider, Button } from "@blueprintjs/core";
import { Spinner, Icon, Button } from "@blueprintjs/core";
import { SETTINGS } from "~/settings";
import {buildInspectorStyle } from "@macrostrat/map-interface";
import { buildMacrostratStyle } from "@macrostrat/map-styles";
import { mergeStyles } from "@macrostrat/mapbox-utils";
import { useDarkMode, DarkModeButton } from "@macrostrat/ui-components";
import mapboxgl from "mapbox-gl";
import { useCallback, useEffect, useState, useMemo } from "react";
import { useCallback, useEffect, useState } from "react";
import h from "./main.module.sass";
import { useRockdAPI, Image, pageCarousel, createCheckins } from "~/components";
import "@macrostrat/style-system";
Expand All @@ -18,6 +18,9 @@ import {
} from "@macrostrat/map-interface";
import { mapboxAccessToken } from "~/settings";

import { AutoComplete } from "./autocomplete";
import { deletePins } from "./utils";
import { FeatureDetails } from "./featuredcheckins";

export function Page() {
return h(
Expand Down Expand Up @@ -410,278 +413,6 @@ function createFilteredCheckins(filteredData, setInspectPosition) {
return createCheckins(filteredData?.filteredData, mapRef, setInspectPosition);
}

function AutoComplete({setFilteredData, autocompleteOpen, setAutocompleteOpen}) {
const mapRef = useMapRef();
const map = mapRef.current;
const [input, setInput] = useState('');
const [close, setClose] = useState(false);
const [page, setPage] = useState(1);

// test
const [peopleIds, setPeople] = useState([]);
const [structures, setStructures] = useState([]);
const [lithologyAttributes, setLithologyAttributes] = useState([]);
const [stratNameOrphans, setStratNameOrphans] = useState([]);
const [lithologyIds, setLithologies] = useState([]);
// const [taxaIds, setTaxa] = useState([]); // fails
// const [intervalIds, setIntervals] = useState([]); // fails
// const [stratNameConcepts, setStratNameConcepts] = useState([]); // fails
// const [minerals, setMinerals] = useState([]); // fails
// const [lithologyTypes, setLithologyTypes] = useState([]); // doesn't exist
// const [lithologyClasses, setLithologyClasses] = useState([]); // doesn't exist

const lithParam = "lith_id=" + lithologyIds.map(item => item.id).join(',');
const peopleParam = "person_id=" + peopleIds.map(item => item.id).join(',');
const stratNameOrphanParam = "strat_name_orphan_id=" + stratNameOrphans.map(item => item.id).join(',');
const lithologyAttributeParam = "lith_att_id=" + lithologyAttributes.map(item => item.id).join(',');
const structureParam = "structure_id=" + structures.map(item => item.id).join(',');
// const taxaParam = "taxon_id=" + taxaIds.map(item => item.id).join(','); // fails
// const intervalParam = "int_id=" + intervalIds.map(item => item.id).join(','); // fails
// const stratNameConceptParam = "strat_name_concept_id=" + stratNameConcepts.map(item => item.id).join(','); // fails
// const mineralParam = "mineral_id=" + minerals.map(item => item.id).join(','); // fails
// const lithologyTypeParam = "=" + lithologyTypes.map(item => item.id).join(','); // doesn't exist
// const lithologyClassParam = "=" + lithologyClasses.map(item => item.id).join(','); // doesn't exist

// develop query
const finalParams = useMemo(() => {
const params = [
lithParam,
peopleParam,
lithologyAttributeParam,
stratNameOrphanParam,
structureParam
].filter(param => /\d/.test(param));

return params.join('&');
}, [lithologyIds, peopleIds, lithologyAttributes, stratNameOrphans, structures]);

const queryString = useMemo(() => {
return finalParams ? `/protected/checkins?${finalParams}` : null;
}, [finalParams]);


// get data
const data = useRockdAPI(queryString + "&page=" + page)?.success.data;
const nextData = useRockdAPI(queryString + "&page=" + (page + 1))?.success.data;

// add markers for filtered checkins
let coordinates = [];
let lngs = [];
let lats = [];

useEffect(() => {
if(data && data.length > 0 && queryString) {
setFilteredData({
current: data,
next: {
data: nextData,
page: page,
setPage: setPage
}
});

data.forEach((checkin) => {
coordinates.push([checkin.lng, checkin.lat]);
lngs.push(checkin.lng);
lats.push(checkin.lat);
});

deletePins('.filtered_pin');

if (!close) {
let stop = 0;
coordinates.forEach((coord) => {
stop++;
// marker
const el = document.createElement('div');
el.className = 'filtered_pin';
el.style.backgroundColor = 'green';
el.style.borderRadius = '50%';
el.style.border = '2px solid white';
el.style.width = '15px';
el.style.height = '15px';

// Create marker
new mapboxgl.Marker(el)
.setLngLat(coord)
.addTo(map);
});
}

map.fitBounds([
[ Math.max(...lngs), Math.max(...lats) ],
[ Math.min(...lngs), Math.min(...lats) ]
], {
maxZoom: 12,
duration: 0,
padding: 75
});
} else {
deletePins('.filtered_pin');

setFilteredData(null);
}
}, [data, nextData, queryString]);

// rest
const handleInputChange = (event) => {
setAutocompleteOpen(true);
setInput(event.target.value);
setClose(false);
setPage(1);
};

let result = null;

try {
result = useRockdAPI("/autocomplete/" + input);
} catch (e) {
return null;
}

let searchBar = h('div.search-bar', [
h('input', { type: "text", placeholder: "Search name", onChange: handleInputChange }),
h('div.x-icon', [
h(Icon, { icon: "cross", onClick: () => {
let input = document.querySelector('input');
input.value = "";
setAutocompleteOpen(false);
setClose(true);
setFilteredData(null);
setPage(1);
deletePins('.filtered_pin');
}
}),
]),
]);

const sectionConfigs = [
{ label: 'People', data: peopleIds, setter: setPeople },
{ label: 'Strat Name Orphans', data: stratNameOrphans, setter: setStratNameOrphans },
{ label: 'Structures', data: structures, setter: setStructures },
{ label: 'Lithologies', data: lithologyIds, setter: setLithologies },
{ label: 'Lithology Attributes', data: lithologyAttributes, setter: setLithologyAttributes },
// { label: 'Taxa', data: taxaIds, setter: setTaxa },
// { label: 'Intervals', data: intervalIds, setter: setIntervals },
// { label: 'Lithology Types', data: lithologyTypes, setter: setLithologyTypes },
// { label: 'Lithology Classes', data: lithologyClasses, setter: setLithologyClasses },
// { label: 'Strat Name Concepts', data: stratNameConcepts, setter: setStratNameConcepts },
// { label: 'Minerals', data: minerals, setter: setMinerals },
];

const sections = sectionConfigs
.filter(({ data }) => data.length > 0)
.map(({ label, data, setter }) =>
h('div', [
h('h3', label),
createFilteredItems(data, setter, setPage)
])
);

const filterContainer = sections.length != 0 ? h("div.filter-container", [
h('h2', "Filters"),
h('ul', [
sections
]),
]) : null;

if(!result || close) return h('div', {className: "autocomplete"}, [
searchBar
]);
result = result.success.data;

let results;

if(autocompleteOpen) {
const lithologies = renderSection("Lithologies", "lithologies", result?.lithologies, setLithologies, lithologyIds, setAutocompleteOpen);
const strat_name_orphans = renderSection("Stratigraphic Name Orphans", "strat_name_orphans", result?.strat_name_orphans, setStratNameOrphans, stratNameOrphans, setAutocompleteOpen);
const structures_items = renderSection("Structures", "structures", result?.structures, setStructures, structures, setAutocompleteOpen);
const lithology_attributes = renderSection("Lithology Attributes", "lithology_attributes", result?.lithology_attributes, setLithologyAttributes, lithologyAttributes, setAutocompleteOpen);
const people = renderSection("People", "people", result?.people, setPeople, peopleIds, setAutocompleteOpen);
// sections commented out that don't work or don't exist
// const intervals = renderSection("Intervals", "intervals", result?.intervals, setIntervals, intervalIds, setAutocompleteOpen);
// const lithology_types = renderSection("Lithology Types", "lithology_types", result?.lithology_types, setLithologyTypes, lithologyTypes, setAutocompleteOpen);
// const lithology_classes = renderSection("Lithology Classes", "lithology_classes", result?.lithology_classes, setLithologyClasses, lithologyClasses, setAutocompleteOpen);
// const strat_name_concepts = renderSection("Stratigraphic Name Concepts", "strat_name_concepts", result?.strat_name_concepts, setStratNameConcepts, stratNameConcepts, setAutocompleteOpen);
// const minerals_items = renderSection("Minerals", "minerals", result?.minerals, setMinerals, minerals, setAutocompleteOpen);
// const taxa = renderSection("Taxa", "taxa", result?.taxa, setTaxa, taxaIds, setAutocompleteOpen);

// result
results = h('div.results', [
people,
lithologies,
lithology_attributes,
strat_name_orphans,
structures_items,
// minerals_items,
// taxa,
// intervals,
// strat_name_concepts,
// lithology_types,
// lithology_classes,
]);
}

/*
useEffect(() => {
setLithologyData(useRockdAPI("/proctected/checkins?lith_id=" + lithologies.map(item => item.id).join(',') + "&all=100"));
}, [lithologies]);
*/

const wrapper = h('div.autocomplete-wrapper', [
filterContainer,
results,
]);

return h('div.autocomplete', [
searchBar,
wrapper,
]);
}

function createFilteredItems(arr, set, setPage) {
return arr.map((item) => {
return h("li.filter-item", [
h('div', item.name),
h(Icon, { className: 'red-cross', icon: "cross", style: {color: "red"}, onClick: () => {
set(arr.filter((person) => person != item));
setPage(1);
}
})
])
})
}

function createFilteredNames(result, set, existing, setAutocompleteOpen) {
return result.map((item) =>
h('li', {
onClick: () => {
if (!existing.includes(item)) {
setAutocompleteOpen(false);
set(existing.concat([item]));
}
}
}, item.name)
)
}

function deletePins(str) {
let previous = document.querySelectorAll(str);
previous.forEach((marker) => {
marker.remove();
});
}

function renderSection(label, key, resultList, setFn, existingIds, setAutocompleteOpen) {
return resultList?.length > 0
? h(`div.${key}`, [
h('h2', label),
h('ul', createFilteredNames(resultList, setFn, existingIds, setAutocompleteOpen))
])
: null;
}


export function MapContainer({style, mapPosition, onSelectPosition, setSelectedCheckin, overlay}) {
return h(
"div.map-container",
Expand Down
Loading