Skip to content

Commit e575d45

Browse files
committed
Revert Cesium tutorials to 939847e baseline
1 parent 1ed2f26 commit e575d45

1 file changed

Lines changed: 14 additions & 191 deletions

File tree

tutorials/parquet_cesium.qmd

Lines changed: 14 additions & 191 deletions
Original file line numberDiff line numberDiff line change
@@ -22,34 +22,6 @@ This page demonstrates how geospatial data can be dynamically accessed from a re
2222
#cesiumContainer {
2323
aspect-ratio: 1/1;
2424
}
25-
#sampleDetails {
26-
margin-top: 1.5rem;
27-
}
28-
#sampleDetails .sample-grid {
29-
display: grid;
30-
gap: 1rem;
31-
}
32-
@media (min-width: 768px) {
33-
#sampleDetails .sample-grid {
34-
grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
35-
}
36-
}
37-
#sampleDetails .sample-card {
38-
border: 1px solid #d9d9d9;
39-
border-radius: 0.5rem;
40-
padding: 0.75rem;
41-
background: #fafafa;
42-
}
43-
#sampleDetails .sample-card h3 {
44-
margin-top: 0;
45-
font-size: 1.05rem;
46-
}
47-
#sampleDetails .sample-card img {
48-
max-width: 140px;
49-
border-radius: 0.25rem;
50-
display: block;
51-
margin-top: 0.5rem;
52-
}
5325
</style>
5426

5527
```{ojs}
@@ -202,13 +174,7 @@ class CView {
202174
this.selectHandler.setInputAction((e) => {
203175
const selectPoint = this.viewer.scene.pick(e.position);
204176
if (Cesium.defined(selectPoint) && selectPoint.hasOwnProperty("primitive")) {
205-
console.log("Clicked point ID:", selectPoint.id);
206-
// Store the clicked ID in the viewer instance for now
207-
this.clickedId = selectPoint.id;
208-
// Dispatch a custom event that can be picked up by Observable
209-
document.dispatchEvent(new CustomEvent('pointSelected', {
210-
detail: { pointId: selectPoint.id }
211-
}));
177+
mutable clickedPointId = selectPoint.id;
212178
}
213179
},Cesium.ScreenSpaceEventType.LEFT_CLICK);
214180
@@ -227,125 +193,19 @@ async function getGeoRecord(pid) {
227193
}
228194
const q = `SELECT row_id, pid, otype, latitude, longitude FROM nodes WHERE otype='GeospatialCoordLocation' AND pid=?`;
229195
const result = await db.queryRow(q, [pid]);
230-
console.log('Loaded geo record for PID', pid, result);
231196
return result;
232197
}
233198
234-
async function samplesAtLocation(rowid) {
199+
async function locationUsedBy(rowid){
235200
if (rowid === undefined || rowid === null) {
236201
return [];
237202
}
238-
console.log('samplesAtLocation invoked with row_id', rowid);
239-
const query = `
240-
WITH edges AS (
241-
SELECT s, p, unnest(o) AS o1
242-
FROM nodes
243-
WHERE otype = '_edge_'
244-
), events AS (
245-
SELECT s AS event_row_id
246-
FROM edges
247-
WHERE p = 'sample_location' AND o1 = ?
248-
), sample_links AS (
249-
SELECT s AS sample_row_id, o1 AS event_row_id
250-
FROM edges
251-
WHERE p = 'produced_by' AND o1 IN (SELECT event_row_id FROM events)
252-
), sample_nodes AS (
253-
SELECT row_id, pid, label, description, thumbnail_url, alternate_identifiers
254-
FROM nodes
255-
WHERE row_id IN (SELECT sample_row_id FROM sample_links)
256-
), event_nodes AS (
257-
SELECT row_id, label, project
258-
FROM nodes
259-
WHERE row_id IN (SELECT event_row_id FROM events)
260-
), concept_edges AS (
261-
SELECT s, p, o1
262-
FROM edges
263-
WHERE s IN (SELECT row_id FROM sample_nodes)
264-
AND p IN ('has_sample_object_type','has_material_category','has_context_category','keywords')
265-
), concept_labels AS (
266-
SELECT row_id, label
267-
FROM nodes
268-
WHERE row_id IN (SELECT o1 FROM concept_edges)
269-
), keyword_text AS (
270-
SELECT ce.s, LIST(DISTINCT cl.label) AS keywords
271-
FROM concept_edges ce
272-
JOIN concept_labels cl ON ce.o1 = cl.row_id
273-
WHERE ce.p = 'keywords'
274-
GROUP BY ce.s
275-
), sampling_sites AS (
276-
SELECT s AS event_row_id, o1 AS site_row_id
277-
FROM edges
278-
WHERE p = 'sampling_site' AND s IN (SELECT event_row_id FROM events)
279-
), site_nodes AS (
280-
SELECT row_id, label
281-
FROM nodes
282-
WHERE row_id IN (SELECT site_row_id FROM sampling_sites)
283-
)
284-
SELECT
285-
sn.pid,
286-
sn.label,
287-
sn.description,
288-
sn.thumbnail_url,
289-
MAX(CASE WHEN ce.p = 'has_sample_object_type' THEN cl.label END) AS sample_object_type,
290-
MAX(CASE WHEN ce.p = 'has_material_category' THEN cl.label END) AS material_category,
291-
MAX(CASE WHEN ce.p = 'has_context_category' THEN cl.label END) AS context_category,
292-
kt.keywords,
293-
en.project,
294-
en.label AS event_label,
295-
snl.label AS site_label
296-
FROM sample_nodes sn
297-
LEFT JOIN sample_links sl ON sn.row_id = sl.sample_row_id
298-
LEFT JOIN event_nodes en ON sl.event_row_id = en.row_id
299-
LEFT JOIN concept_edges ce ON sn.row_id = ce.s
300-
LEFT JOIN concept_labels cl ON ce.o1 = cl.row_id
301-
LEFT JOIN keyword_text kt ON sn.row_id = kt.s
302-
LEFT JOIN sampling_sites ss ON sl.event_row_id = ss.event_row_id
303-
LEFT JOIN site_nodes snl ON ss.site_row_id = snl.row_id
304-
GROUP BY sn.pid, sn.label, sn.description, sn.thumbnail_url, kt.keywords, en.project, en.label, snl.label
305-
ORDER BY coalesce(sn.label, sn.pid)
306-
LIMIT 6;
307-
`;
308-
try {
309-
const result = await db.query(query, [rowid]);
310-
const rows = result?.toArray ? result.toArray() : result;
311-
console.log(`Samples retrieved for location ${rowid}:`, rows);
312-
return Array.isArray(rows) ? rows : [];
313-
} catch (error) {
314-
console.error('Failed to load sample data for location', rowid, error);
315-
return [];
316-
}
203+
const q = `select pid, otype from nodes where row_id in (select nodes.s from nodes where list_contains(nodes.o, ?));`;
204+
return db.query(q, [rowid]);
317205
}
318206
319-
// Use a viewof pattern to create a reactive clickedPointId
320-
viewof clickedPointId = {
321-
const input = html`<input type="hidden" value="unset">`;
322-
323-
// Listen for point selection events and update the input value
324-
document.addEventListener('pointSelected', (event) => {
325-
input.value = event.detail.pointId;
326-
input.dispatchEvent(new Event('input'));
327-
});
328-
329-
return input;
330-
}
331-
332-
// Access the current value
333-
clickedPointId;
334-
335-
selectedGeoRecord = {
336-
// This will re-execute whenever clickedPointId changes
337-
const result = await getGeoRecord(clickedPointId);
338-
return result;
339-
}
340-
341-
selectedSamples = {
342-
// This will re-execute whenever selectedGeoRecord changes
343-
if (selectedGeoRecord?.row_id) {
344-
const samples = await samplesAtLocation(selectedGeoRecord.row_id);
345-
return samples;
346-
}
347-
return [];
348-
}
207+
mutable clickedPointId = "unset";
208+
selectedGeoRecord = await getGeoRecord(clickedPointId);
349209
350210
md`Retrieved ${pointdata.length} locations from ${parquet_path}.`;
351211
```
@@ -378,51 +238,14 @@ viewof pointdata = {
378238

379239
:::
380240

241+
The click point ID is "${clickedPointId}".
242+
381243
```{ojs}
382244
//| echo: false
383-
// Enhanced UI with sample information
384-
html`<section id="sampleDetails">
385-
<h2>Selected Location</h2>
386-
${clickedPointId === "unset" ?
387-
html`<p>Click a point on the map to view nearby sample records.</p>` :
388-
html`${(() => {
389-
const locationPid = selectedGeoRecord?.pid || clickedPointId;
390-
const resolver = locationPid?.startsWith('http') ? locationPid : `https://n2t.net/${encodeURIComponent(locationPid)}`;
391-
const lat = selectedGeoRecord?.latitude != null ? selectedGeoRecord.latitude.toFixed(4) : 'N/A';
392-
const lon = selectedGeoRecord?.longitude != null ? selectedGeoRecord.longitude.toFixed(4) : 'N/A';
393-
const samples = Array.isArray(selectedSamples) ? selectedSamples : [];
394-
return html`<div>
395-
<p><strong>Point PID:</strong> <a href="${resolver}" target="_blank" rel="noopener">${locationPid}</a></p>
396-
<p><strong>Coordinates:</strong> ${lat}, ${lon}</p>
397-
<p><strong>Sample records found:</strong> ${samples.length}</p>
398-
${samples.length
399-
? html`<div class="sample-grid">
400-
${samples.map(sample => {
401-
const displayLabel = sample.label || sample.pid;
402-
const sampleLink = sample.pid?.startsWith('http') ? sample.pid : `https://n2t.net/${encodeURIComponent(sample.pid)}`;
403-
const typeParts = [sample.sample_object_type, sample.material_category].filter(Boolean);
404-
const collectionParts = [sample.project, sample.site_label, sample.event_label].filter(Boolean);
405-
const context = sample.context_category;
406-
const keywordData = sample.keywords;
407-
const keywords = Array.isArray(keywordData)
408-
? keywordData.filter(Boolean)
409-
: typeof keywordData === 'string'
410-
? keywordData.split(',').map(d => d.trim()).filter(Boolean)
411-
: [];
412-
return html`<article class="sample-card">
413-
<h3><a href="${sampleLink}" target="_blank" rel="noopener">${displayLabel}</a></h3>
414-
${sample.description ? html`<p>${sample.description}</p>` : null}
415-
${typeParts.length ? html`<p><strong>Type</strong>: ${typeParts.join(' · ')}</p>` : null}
416-
${context ? html`<p><strong>Context</strong>: ${context}</p>` : null}
417-
${collectionParts.length ? html`<p><strong>Collection</strong>: ${collectionParts.join(' · ')}</p>` : null}
418-
${keywords.length ? html`<p><strong>Keywords</strong>: ${keywords.join(', ')}</p>` : null}
419-
${sample.thumbnail_url ? html`<img src="${sample.thumbnail_url}" alt="Thumbnail for ${displayLabel}" loading="lazy">` : null}
420-
</article>`;
421-
})}
422-
</div>`
423-
: html`<p><em>No sample records were linked to this location.</em></p>`}
424-
</div>`;
425-
})()}`
426-
}
427-
</section>`
245+
md`\`\`\`
246+
${JSON.stringify(selectedGeoRecord, null, 2)}
247+
\`\`\`
248+
`
428249
```
250+
251+

0 commit comments

Comments
 (0)