Using checkbox tree control

This commit is contained in:
2026-07-11 20:50:43 -05:00
parent 900e195926
commit 6bd490087b
14 changed files with 680 additions and 118 deletions
+58
View File
@@ -1,6 +1,14 @@
export const featureCategories = {
plants: { label: "Plants", order: 10 },
structures: { label: "Structures", order: 20 },
infrastructure: { label: "Infrastructure", order: 30 },
reference: { label: "Map Reference", order: 40 },
};
export const featureTypes = {
lotBoundary: {
label: "Lot Boundary",
categoryId: "reference",
geometryType: "Polygon",
detailFields: {},
style: {
@@ -13,6 +21,7 @@ export const featureTypes = {
},
fence: {
label: "Fence",
categoryId: "structures",
geometryType: "LineString",
detailFields: {
fenceType: "string",
@@ -25,6 +34,7 @@ export const featureTypes = {
},
yardGrid: {
label: "Yard Grid",
categoryId: "reference",
geometryType: "LineString",
detailFields: {
axis: "string",
@@ -40,6 +50,8 @@ export const featureTypes = {
},
house: {
label: "House",
collectionLabel: "Houses",
categoryId: "structures",
geometryType: "Polygon",
detailFields: {},
style: {
@@ -51,6 +63,8 @@ export const featureTypes = {
},
garage: {
label: "Garage",
collectionLabel: "Garages",
categoryId: "structures",
geometryType: "Polygon",
detailFields: {},
style: {
@@ -62,6 +76,7 @@ export const featureTypes = {
},
porch: {
label: "Porch",
categoryId: "structures",
geometryType: "Polygon",
detailFields: {},
style: {
@@ -73,6 +88,7 @@ export const featureTypes = {
},
deck: {
label: "Deck",
categoryId: "structures",
geometryType: "Polygon",
detailFields: {},
style: {
@@ -84,6 +100,8 @@ export const featureTypes = {
},
walkway: {
label: "Walkway",
collectionLabel: "Walkways",
categoryId: "structures",
geometryType: "Polygon",
detailFields: {},
style: {
@@ -95,6 +113,8 @@ export const featureTypes = {
},
driveway: {
label: "Driveway",
collectionLabel: "Driveways",
categoryId: "structures",
geometryType: "Polygon",
detailFields: {},
style: {
@@ -106,6 +126,8 @@ export const featureTypes = {
},
flowerBed: {
label: "Flower Bed",
collectionLabel: "Flower Beds",
categoryId: "structures",
geometryType: "Polygon",
detailFields: {
soil: "string",
@@ -121,6 +143,7 @@ export const featureTypes = {
},
plant: {
label: "Plant",
categoryId: "plants",
geometryType: "Point",
detailFields: {
commonName: "string",
@@ -152,6 +175,7 @@ export const featureTypes = {
},
flower: {
label: "Flower",
collectionLabel: "Flowers",
parentKind: "plant",
geometryType: "Point",
detailFields: {
@@ -177,6 +201,7 @@ export const featureTypes = {
},
daylily: {
label: "Daylily",
collectionLabel: "Daylilies",
parentKind: "flower",
geometryType: "Point",
detailFields: {
@@ -202,6 +227,7 @@ export const featureTypes = {
},
shrub: {
label: "Shrub",
collectionLabel: "Shrubs",
parentKind: "plant",
geometryType: "Point",
detailFields: {
@@ -224,6 +250,7 @@ export const featureTypes = {
},
tree: {
label: "Tree",
collectionLabel: "Trees",
parentKind: "plant",
geometryType: "Point",
detailFields: {
@@ -246,6 +273,7 @@ export const featureTypes = {
},
sprinkler: {
label: "Sprinkler",
categoryId: "infrastructure",
geometryType: "Point",
detailFields: {
zone: "string",
@@ -259,6 +287,20 @@ export const featureTypes = {
fillOpacity: 0.95,
},
},
bush: {
label: "Bush",
collectionLabel: "Bushes",
parentKind: "plant",
geometryType: "Point",
detailFields: {},
style: (details) => ({
color: "#426a3d",
weight: 1,
radiusMeters: (details.canopyDiameter ?? 1) / 2,
fillColor: "#7e9d58",
fillOpacity: 0.62,
}),
},
};
export function getFeatureType(kind) {
@@ -274,6 +316,8 @@ export function listFeatureTypeSchemas() {
return Object.entries(featureTypes).map(([kind, definition]) => ({
kind,
label: definition.label,
collectionLabel: definition.collectionLabel ?? definition.label,
categoryId: getFeatureCategoryId(kind),
parentKind: definition.parentKind ?? null,
geometryType: definition.geometryType,
detailFields: getInheritedDetailFields(kind),
@@ -283,6 +327,12 @@ export function listFeatureTypeSchemas() {
}));
}
export function listFeatureCategorySchemas() {
return Object.entries(featureCategories)
.map(([id, definition]) => ({ id, ...definition }))
.sort((left, right) => left.order - right.order);
}
export function resolveFeatureStyle(kind, details = {}) {
const { style } = getFeatureType(kind);
return typeof style === "function" ? style(details) : { ...style };
@@ -310,6 +360,14 @@ function getFeatureTypeLineage(kind) {
return lineage;
}
function getFeatureCategoryId(kind) {
const definition = [...getFeatureTypeLineage(kind)].reverse().find((entry) => entry.categoryId);
if (!definition || !featureCategories[definition.categoryId]) {
throw new Error(`Feature type has an unknown or missing category: ${kind}`);
}
return definition.categoryId;
}
function getInheritedDetailFields(kind) {
return Object.assign(
{},