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
9 changes: 9 additions & 0 deletions public/reearth.yml
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,15 @@ extensions:
description: "Specify the fields to display in the infobox, please use field keys separated by commas. Left empty to show all fields."
type: string
ui: multiline
- id: title_hidden_fields
title: Title Hidden Fields
description: "Specify the fields to hide their titles from the infobox, please use field keys separated by commas."
type: string
ui: multiline
- id: title_field
title: Title Field
description: "Specify the field to use as the title in the infobox."
type: string
- id: inspector_block
type: infoboxBlock
name: CMS Data Inspector Block
15 changes: 7 additions & 8 deletions src/extensions/inspector_block/inspector_block.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,27 +3,26 @@ import html_main from "@distui/inspector_block/main/index.html?raw";
import { GlobalThis } from "@/shared/reearthTypes";

type UIMessage = {
action: "getProperties";
action: "getInspector";
};

const reearth = (globalThis as unknown as GlobalThis).reearth;
reearth.ui.show(html_main);

const sendProperties = () => {
const sendInspector = () => {
reearth.ui.postMessage({
action: "getProperties",
action: "getInspector",
payload:
reearth.layers.selectedFeature?.properties?.__inspector_fields ||
undefined,
reearth.layers.selectedFeature?.properties?.__inspector || undefined,
});
};

reearth.layers.on("select", sendProperties);
reearth.layers.on("select", sendInspector);

reearth.extension.on("message", (message: unknown) => {
const msg = message as UIMessage;

if (msg.action === "getProperties") {
sendProperties();
if (msg.action === "getInspector") {
sendInspector();
}
});
42 changes: 23 additions & 19 deletions src/extensions/inspector_block/main/App.tsx
Original file line number Diff line number Diff line change
@@ -1,32 +1,36 @@
import useHooks from "./hooks";
import PropertyValue, { SingleValueProperty } from "./PropertyValue";
import PropertyItem from "./PropertyItem";

function App() {
const { properties } = useHooks();
const { inspector } = useHooks();

if (!properties) {
if (!inspector) {
return null;
}

return (
<div className="flex flex-col gap-4 text-sm text-gray-700">
{properties.map((prop) => (
<div key={prop.id} className="flex flex-col gap-1">
<div className="font-bold text-black">{prop.name ?? prop.key}</div>
{Array.isArray(prop.value) ? (
<div className="flex flex-col gap-1">
{prop.value.map((item, index) => (
<PropertyValue
key={index}
property={{ ...prop, value: item }}
/>
))}
{inspector.title && (
<div className="text-lg font-bold">{inspector.title}</div>
)}
{inspector.properties.map((property) =>
property.type === "group" ? (
<div key={property.id} className="flex flex-col gap-2">
{!property.hideTitle && (
<div className="font-bold text-black">
{property.name ?? property.key}
</div>
)}
<div key={property.id} className="flex flex-col gap-2">
{property.children?.map((child) => (
<PropertyItem key={child.id} property={child} />
)) ?? null}
</div>
) : (
<PropertyValue property={prop as SingleValueProperty} />
)}
</div>
))}
</div>
) : (
<PropertyItem key={property.id} property={property} />
)
)}
</div>
);
}
Expand Down
43 changes: 43 additions & 0 deletions src/extensions/inspector_block/main/PropertyItem.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { FC } from "react";

import { Property } from "./hooks";
import PropertyValue, { SingleValueProperty } from "./PropertyValue";

type PropertyItemProps = {
property: Property;
};

const PropertyItem: FC<PropertyItemProps> = ({ property }) => {
if (
property.hideTitle &&
(property.value === undefined ||
property.value === "" ||
property.value === null)
) {
return null;
}

return (
<div key={property.id} className="flex flex-col gap-1">
{!property.hideTitle && (
<div className="font-bold text-black">
{property.name ?? property.key}
</div>
)}
{Array.isArray(property.value) ? (
<div className="flex flex-col gap-1">
{property.value.map((item, index) => (
<PropertyValue
key={index}
property={{ ...property, value: item }}
/>
))}
</div>
) : (
<PropertyValue property={property as SingleValueProperty} />
)}
</div>
);
};

export default PropertyItem;
2 changes: 1 addition & 1 deletion src/extensions/inspector_block/main/PropertyValue.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -73,5 +73,5 @@ const PropertyValue: FC<Props> = ({ property }) => {
export default PropertyValue;

const isImageUrl = (url: string) => {
return /\.(jpeg|jpg|gif|png|svg)$/.test(url);
return /\.(jpeg|jpg|gif|png|svg)$/.test(url.toLowerCase());
};
19 changes: 13 additions & 6 deletions src/extensions/inspector_block/main/hooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { useEffect, useState } from "react";

import { postMsg } from "@/shared/utils";

export type Field = {
export type Property = {
id: string;
key: string;
type: string;
Expand All @@ -15,18 +15,25 @@ export type Field = {
| number[]
| boolean[];
name: string;
hideTitle?: boolean;
children?: Property[];
};

export type Inspector = {
title?: string;
properties: Property[];
};

export default () => {
const [properties, setProperties] = useState<Field[] | null>(null);
const [inspector, setInspector] = useState<Inspector | null>(null);

useEffect(() => {
postMsg("getProperties");
postMsg("getInspector");
}, []);

const handleMessage = (e: MessageEvent) => {
if (e.data.action === "getProperties") {
setProperties(e.data.payload);
if (e.data.action === "getInspector") {
setInspector(e.data.payload);
}
};

Expand All @@ -38,6 +45,6 @@ export default () => {
}, []);

return {
properties,
inspector,
};
};
60 changes: 56 additions & 4 deletions src/extensions/visualizer/visualizer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ type VisualizationConfig = {

type InspectorConfig = {
display_fields?: string;
title_hidden_fields?: string;
title_field?: string;
};

type WidgetProperty = {
Expand All @@ -27,6 +29,8 @@ type ItemField = {
type: string;
value: unknown;
name?: string;
group?: string;
children?: ItemField[];
};

type Item = {
Expand Down Expand Up @@ -132,9 +136,13 @@ const generateGeoJSON = (
// Convert items to GeoJSON features
const inspectorConfig =
(reearth.extension?.widget?.property as WidgetProperty)?.inspector || {};

const displayFields = inspectorConfig.display_fields
? inspectorConfig.display_fields.split(",").map((f) => f.trim())
: [];
const titleHiddenFields = inspectorConfig.title_hidden_fields
? inspectorConfig.title_hidden_fields.split(",").map((f) => f.trim())
: [];

const features = items
.map((item) => {
Expand All @@ -146,8 +154,18 @@ const generateGeoJSON = (
properties[field.key] = field.value;
});

// Add filtered fields for inspector
properties.__inspector_fields = filterFields(item.fields, displayFields);
// Add property for inspector
properties.__inspector = {
title: inspectorConfig.title_field
? item.fields.find((f) => f.key === inspectorConfig.title_field)
?.value
: undefined,
properties: processProperties(
item.fields,
displayFields,
titleHiddenFields
),
};

// Get location
const coordinates = [];
Expand All @@ -163,7 +181,7 @@ const generateGeoJSON = (
return null;
}

coordinates.push(lng, lat);
coordinates.push(Number(lng), Number(lat));
} else if (config.location_type === "lng_lat_array_field") {
const latLngArray = item.fields.find(
(f) => f.key === config.longitude_latitude_array_field_key
Expand All @@ -172,7 +190,7 @@ const generateGeoJSON = (
console.log(`Invalid Longitude & Latitude array for item ${item.id}`);
return null;
}
coordinates.push(latLngArray[0], latLngArray[1]);
coordinates.push(Number(latLngArray[0]), Number(latLngArray[1]));
} else if (config.location_type === "geojson_field") {
try {
const geojson = item.fields.find(
Expand Down Expand Up @@ -264,3 +282,37 @@ const filterFields = (
}
return filteredFields;
};

const processProperties = (
originalFields: ItemField[],
displayFieldKeys: string[],
titleHiddenFieldKeys: string[]
) => {
const fieldsToProcess = filterFields(originalFields, displayFieldKeys).map(
(field) => ({
...field,
hideTitle: titleHiddenFieldKeys.includes(field.key),
})
);

const result = [];
const byGroup = new Map();

for (const field of fieldsToProcess) {
if (field.group) {
const list = byGroup.get(field.group) || [];
list.push(field);
byGroup.set(field.group, list);
} else {
result.push(field);
}
}

for (const field of result) {
if (field.type === "group") {
field.children = byGroup.get(field.value) ?? [];
}
}

return result;
};
2 changes: 1 addition & 1 deletion src/shared/global.css
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ input[type="number"] {
@layer utilities {
.prose {
@apply text-xs leading-relaxed max-w-none;
font-size: 12px;
font-size: 14px;
}

.prose p {
Expand Down