Improvements to tree size measurements
This commit is contained in:
+40
-51
@@ -116,7 +116,13 @@ const daylilies = [
|
|||||||
}).add(geo.offset(lotCorner), geo.east(geo.ft(142)), geo.south(geo.ft(38))),
|
}).add(geo.offset(lotCorner), geo.east(geo.ft(142)), geo.south(geo.ft(38))),
|
||||||
new Daylily("Extra daylily", {
|
new Daylily("Extra daylily", {
|
||||||
gardenOrgId: "",
|
gardenOrgId: "",
|
||||||
}).add(geo.offset(lotCorner), geo.east(geo.ft(1)), geo.south(geo.ft(4))),
|
}).add(geo.offset(lotCorner), geo.east(geo.ft(0.8)), geo.south(geo.ft(3.2))),
|
||||||
|
new Daylily("Extra daylily", {
|
||||||
|
gardenOrgId: "",
|
||||||
|
}).add(geo.offset(lotCorner), geo.east(geo.ft(0.8)), geo.south(geo.ft(3.9))),
|
||||||
|
new Daylily("Extra daylily", {
|
||||||
|
gardenOrgId: "",
|
||||||
|
}).add(geo.offset(lotCorner), geo.east(geo.ft(1.3)), geo.south(geo.ft(3.6))),
|
||||||
new Daylily("Extra daylily", {
|
new Daylily("Extra daylily", {
|
||||||
gardenOrgId: "",
|
gardenOrgId: "",
|
||||||
}).add(geo.offset(lotCorner), geo.east(geo.ft(1)), geo.south(geo.ft(9))),
|
}).add(geo.offset(lotCorner), geo.east(geo.ft(1)), geo.south(geo.ft(9))),
|
||||||
@@ -172,7 +178,7 @@ const flowers = [
|
|||||||
new Flower("Tiny Tortuga Turtlehead", {
|
new Flower("Tiny Tortuga Turtlehead", {
|
||||||
gardenOrgId: "697986",
|
gardenOrgId: "697986",
|
||||||
plantedDate: "2021-09-21",
|
plantedDate: "2021-09-21",
|
||||||
}).add(geo.offset(lotCorner), geo.east(geo.ft(3)), geo.south(geo.ft(8))),
|
}).add(geo.offset(lotCorner), geo.east(geo.ft(2.2)), geo.south(geo.ft(8.2))),
|
||||||
new Flower("Tiny Tortuga Turtlehead", {
|
new Flower("Tiny Tortuga Turtlehead", {
|
||||||
gardenOrgId: "697986",
|
gardenOrgId: "697986",
|
||||||
plantedDate: "2021-09-21",
|
plantedDate: "2021-09-21",
|
||||||
@@ -193,23 +199,19 @@ const houseplants = [
|
|||||||
|
|
||||||
const cutDownTrees = [
|
const cutDownTrees = [
|
||||||
new Tree("Maybe elm", {
|
new Tree("Maybe elm", {
|
||||||
canopyDiameterMeters: 15,
|
measurements: [{ canopyDiameter: geo.ft(49.21), height: geo.ft(49.21) }],
|
||||||
heightMeters: 15,
|
|
||||||
removedDate: "2021-05-05",
|
removedDate: "2021-05-05",
|
||||||
}).add(geo.offset(lotCorner), geo.east(geo.ft(65)), geo.south(geo.ft(-2))),
|
}).add(geo.offset(lotCorner), geo.east(geo.ft(65)), geo.south(geo.ft(-2))),
|
||||||
new Tree("Big pine tree", {
|
new Tree("Big pine tree", {
|
||||||
canopyDiameterMeters: 8,
|
measurements: [{ canopyDiameter: geo.ft(26.25), height: geo.ft(49.21) }],
|
||||||
heightMeters: 15,
|
|
||||||
removedDate: "2021-05-06",
|
removedDate: "2021-05-06",
|
||||||
}).add(geo.offset(lotCorner), geo.east(geo.ft(98)), geo.south(geo.ft(-15))),
|
}).add(geo.offset(lotCorner), geo.east(geo.ft(98)), geo.south(geo.ft(-15))),
|
||||||
new Tree("Walnut by house", {
|
new Tree("Walnut by house", {
|
||||||
canopyDiameterMeters: 6,
|
measurements: [{ canopyDiameter: geo.ft(19.69), height: geo.ft(22.97) }],
|
||||||
heightMeters: 7,
|
|
||||||
removedDate: "2021-05-01",
|
removedDate: "2021-05-01",
|
||||||
}).add(geo.offset(lotCorner), geo.east(geo.ft(32)), geo.south(geo.ft(40))),
|
}).add(geo.offset(lotCorner), geo.east(geo.ft(32)), geo.south(geo.ft(40))),
|
||||||
new Tree("Walnut by shed", {
|
new Tree("Walnut by shed", {
|
||||||
canopyDiameterMeters: 7,
|
measurements: [{ canopyDiameter: geo.ft(22.97), height: geo.ft(22.97) }],
|
||||||
heightMeters: 7,
|
|
||||||
removedDate: "2021-05-01",
|
removedDate: "2021-05-01",
|
||||||
}).add(geo.offset(lotCorner), geo.east(geo.ft(100)), geo.south(geo.ft(40))),
|
}).add(geo.offset(lotCorner), geo.east(geo.ft(100)), geo.south(geo.ft(40))),
|
||||||
];
|
];
|
||||||
@@ -217,134 +219,121 @@ const cutDownTrees = [
|
|||||||
const trees = [
|
const trees = [
|
||||||
new Tree("Northern Empress Japanese Elm", {
|
new Tree("Northern Empress Japanese Elm", {
|
||||||
species: "Northern Empress Japanese Elm",
|
species: "Northern Empress Japanese Elm",
|
||||||
canopyDiameterMeters: 6,
|
measurements: [{ canopyDiameter: geo.ft(19.69), height: geo.ft(22.97) }],
|
||||||
heightMeters: 7,
|
|
||||||
plantedDate: "2021-09-21",
|
plantedDate: "2021-09-21",
|
||||||
pricePaid: 312,
|
pricePaid: 312,
|
||||||
}).add(geo.offset(lotCorner), geo.east(geo.ft(9)), geo.south(geo.ft(16))),
|
}).add(geo.offset(lotCorner), geo.east(geo.ft(9)), geo.south(geo.ft(16))),
|
||||||
new Tree("Hot Wings Maple", {
|
new Tree("Hot Wings Maple", {
|
||||||
species: "Hot Wings Maple",
|
species: "Hot Wings Maple",
|
||||||
canopyDiameterMeters: 5,
|
measurements: [{ canopyDiameter: geo.ft(16.4), height: geo.ft(16.4) }],
|
||||||
heightMeters: 5,
|
|
||||||
gardenOrgId: "536120",
|
gardenOrgId: "536120",
|
||||||
plantedDate: "2021-09-21",
|
plantedDate: "2021-09-21",
|
||||||
pricePaid: 186,
|
pricePaid: 186,
|
||||||
}).add(geo.offset(lotCorner), geo.east(geo.ft(60)), geo.south(geo.ft(40))),
|
}).add(geo.offset(lotCorner), geo.east(geo.ft(60)), geo.south(geo.ft(40))),
|
||||||
new Tree("Prairie Expedition American Elm", {
|
new Tree("Prairie Expedition American Elm", {
|
||||||
species: "Prairie Expedition American Elm",
|
species: "Prairie Expedition American Elm",
|
||||||
canopyDiameterMeters: 5,
|
measurements: [{ canopyDiameter: geo.ft(16.4), height: geo.ft(16.4) }],
|
||||||
heightMeters: 5,
|
|
||||||
gardenOrgId: "736267",
|
gardenOrgId: "736267",
|
||||||
plantedDate: "2021-09-21",
|
plantedDate: "2021-09-21",
|
||||||
pricePaid: 280,
|
pricePaid: 280,
|
||||||
}).add(geo.offset(lotCorner), geo.east(geo.ft(95)), geo.south(geo.ft(15))),
|
}).add(geo.offset(lotCorner), geo.east(geo.ft(95)), geo.south(geo.ft(15))),
|
||||||
|
|
||||||
new Tree("Dwarf Korean Lilac", {
|
new Tree("Dwarf Korean Lilac", {
|
||||||
species: "Dwarf Korean Lilac",
|
species: "Dwarf Korean Lilac",
|
||||||
canopyDiameterMeters: 1.75,
|
measurements: [
|
||||||
heightMeters: 2.5,
|
{ measuredDate: "2026-07-08", canopyDiameter: geo.ft(5.5), height: geo.ft(6.7) },
|
||||||
|
],
|
||||||
gardenOrgId: "79137",
|
gardenOrgId: "79137",
|
||||||
plantedDate: "2021-09-21",
|
plantedDate: "2021-09-21",
|
||||||
pricePaid: 218,
|
pricePaid: 218,
|
||||||
}).add(geo.offset(lotCorner), geo.east(geo.ft(3)), geo.south(geo.ft(3))),
|
}).add(geo.offset(lotCorner), geo.east(geo.ft(3.5)), geo.south(geo.ft(4.8))),
|
||||||
|
|
||||||
new Tree("Dwarf Korean Lilac", {
|
new Tree("Dwarf Korean Lilac", {
|
||||||
species: "Dwarf Korean Lilac",
|
species: "Dwarf Korean Lilac",
|
||||||
canopyDiameterMeters: 1.75,
|
measurements: [{ canopyDiameter: geo.ft(5.74), height: geo.ft(8.2) }],
|
||||||
heightMeters: 2.5,
|
|
||||||
gardenOrgId: "79137",
|
gardenOrgId: "79137",
|
||||||
plantedDate: "2021-09-21",
|
plantedDate: "2021-09-21",
|
||||||
pricePaid: 218,
|
pricePaid: 218,
|
||||||
}).add(geo.offset(lotCorner), geo.east(geo.ft(3)), geo.south(geo.ft(20))),
|
}).add(geo.offset(lotCorner), geo.east(geo.ft(3.7)), geo.south(geo.ft(21.4))),
|
||||||
|
|
||||||
new Tree("Dwarf Korean Lilac", {
|
new Tree("Dwarf Korean Lilac", {
|
||||||
species: "Dwarf Korean Lilac",
|
species: "Dwarf Korean Lilac",
|
||||||
canopyDiameterMeters: 1.75,
|
measurements: [{ canopyDiameter: geo.ft(5.74), height: geo.ft(8.2) }],
|
||||||
heightMeters: 2.5,
|
|
||||||
gardenOrgId: "79137",
|
gardenOrgId: "79137",
|
||||||
plantedDate: "2021-09-21",
|
plantedDate: "2021-09-21",
|
||||||
pricePaid: 218,
|
pricePaid: 218,
|
||||||
}).add(geo.offset(lotCorner), geo.east(geo.ft(3)), geo.south(geo.ft(37))),
|
}).add(geo.offset(lotCorner), geo.east(geo.ft(3.8)), geo.south(geo.ft(33.1))),
|
||||||
|
|
||||||
new Tree("Boulevard Linden", {
|
new Tree("Boulevard Linden", {
|
||||||
species: "Boulevard Linden",
|
species: "Boulevard Linden",
|
||||||
canopyDiameterMeters: 3,
|
measurements: [{ canopyDiameter: geo.ft(9.84), height: geo.ft(19.69) }],
|
||||||
heightMeters: 6,
|
|
||||||
plantedDate: "2021-09-21",
|
plantedDate: "2021-09-21",
|
||||||
pricePaid: 327,
|
pricePaid: 327,
|
||||||
}).add(geo.lngLat(-100.8990003556445, 46.826776648309774)),
|
}).add(geo.lngLat(-100.8990003556445, 46.826776648309774)),
|
||||||
new Tree("Boulevard Linden 2", {
|
new Tree("Boulevard Linden 2", {
|
||||||
species: "Boulevard Linden",
|
species: "Boulevard Linden",
|
||||||
canopyDiameterMeters: 3,
|
measurements: [{ canopyDiameter: geo.ft(9.84), height: geo.ft(19.69) }],
|
||||||
heightMeters: 6,
|
|
||||||
plantedDate: "2021-09-21",
|
plantedDate: "2021-09-21",
|
||||||
pricePaid: 327,
|
pricePaid: 327,
|
||||||
}).add(geo.lngLat(-100.89898269567485, 46.826709328342595)),
|
}).add(geo.lngLat(-100.89898269567485, 46.826709328342595)),
|
||||||
new Tree("Evergreen", {
|
new Tree("Evergreen", {
|
||||||
species: "Evergreen",
|
species: "Evergreen",
|
||||||
canopyDiameterMeters: 8,
|
measurements: [{ canopyDiameter: geo.ft(26.25), height: geo.ft(49.21) }],
|
||||||
heightMeters: 15,
|
|
||||||
}).add(geo.lngLat(-100.89888268258135, 46.826680107011924)),
|
}).add(geo.lngLat(-100.89888268258135, 46.826680107011924)),
|
||||||
];
|
];
|
||||||
|
|
||||||
const bushes = [
|
const bushes = [
|
||||||
new Tree("Medora Juniper 1", {
|
new Tree("Medora Juniper 1", {
|
||||||
species: "Medora Juniper",
|
species: "Medora Juniper",
|
||||||
canopyDiameterMeters: 1.5,
|
measurements: [{ canopyDiameter: geo.ft(4.92), height: geo.ft(8.2) }],
|
||||||
heightMeters: 2.5,
|
|
||||||
plantedDate: "2021-09-21",
|
plantedDate: "2021-09-21",
|
||||||
pricePaid: 96.50,
|
pricePaid: 96.50,
|
||||||
}).inGroup(juniperTreesGroup).add(geo.lngLat(-100.89880933964611, 46.826705259550664)),
|
}).inGroup(juniperTreesGroup).add(geo.lngLat(-100.89880933964611, 46.826705259550664)),
|
||||||
new Tree("Medora Juniper 2", {
|
new Tree("Medora Juniper 2", {
|
||||||
species: "Medora Juniper",
|
species: "Medora Juniper",
|
||||||
canopyDiameterMeters: 1.5,
|
measurements: [{ canopyDiameter: geo.ft(4.92), height: geo.ft(8.2) }],
|
||||||
heightMeters: 2.5,
|
|
||||||
plantedDate: "2021-09-21",
|
plantedDate: "2021-09-21",
|
||||||
pricePaid: 96.50,
|
pricePaid: 96.50,
|
||||||
}).inGroup(juniperTreesGroup).add(geo.lngLat(-100.89877004677517, 46.82670396593881)),
|
}).inGroup(juniperTreesGroup).add(geo.lngLat(-100.89877004677517, 46.82670396593881)),
|
||||||
new Tree("Medora Juniper 3", {
|
new Tree("Medora Juniper 3", {
|
||||||
species: "Medora Juniper",
|
species: "Medora Juniper",
|
||||||
canopyDiameterMeters: 1.5,
|
measurements: [{ canopyDiameter: geo.ft(4.92), height: geo.ft(8.2) }],
|
||||||
heightMeters: 2.5,
|
|
||||||
plantedDate: "2021-09-21",
|
plantedDate: "2021-09-21",
|
||||||
pricePaid: 96.50,
|
pricePaid: 96.50,
|
||||||
}).inGroup(juniperTreesGroup).add(geo.lngLat(-100.898799106227, 46.82669830398086)),
|
}).inGroup(juniperTreesGroup).add(geo.lngLat(-100.898799106227, 46.82669830398086)),
|
||||||
new Tree("Medora Juniper 4", {
|
new Tree("Medora Juniper 4", {
|
||||||
species: "Medora Juniper",
|
species: "Medora Juniper",
|
||||||
canopyDiameterMeters: 1.5,
|
measurements: [{ canopyDiameter: geo.ft(4.92), height: geo.ft(8.2) }],
|
||||||
heightMeters: 2.5,
|
|
||||||
plantedDate: "2021-09-21",
|
plantedDate: "2021-09-21",
|
||||||
pricePaid: 96.50,
|
pricePaid: 96.50,
|
||||||
}).inGroup(juniperTreesGroup).add(geo.lngLat(-100.89878871410515, 46.82669251034885)),
|
}).inGroup(juniperTreesGroup).add(geo.lngLat(-100.89878871410515, 46.82669251034885)),
|
||||||
new Tree("Medora Juniper 5", {
|
new Tree("Medora Juniper 5", {
|
||||||
species: "Medora Juniper",
|
species: "Medora Juniper",
|
||||||
canopyDiameterMeters: 1.5,
|
measurements: [{ canopyDiameter: geo.ft(4.92), height: geo.ft(8.2) }],
|
||||||
heightMeters: 2.5,
|
|
||||||
plantedDate: "2021-09-21",
|
plantedDate: "2021-09-21",
|
||||||
pricePaid: 96.50,
|
pricePaid: 96.50,
|
||||||
}).inGroup(juniperTreesGroup).add(geo.lngLat(-100.8987812086838, 46.82671120797719)),
|
}).inGroup(juniperTreesGroup).add(geo.lngLat(-100.8987812086838, 46.82671120797719)),
|
||||||
new Tree("Black Currant", {
|
new Tree("Black Currant", {
|
||||||
species: "Black Currant",
|
species: "Black Currant",
|
||||||
canopyDiameterMeters: 2,
|
measurements: [{ canopyDiameter: geo.ft(6.56), height: geo.ft(6.56) }],
|
||||||
heightMeters: 2,
|
|
||||||
gardenOrgId: "87767",
|
gardenOrgId: "87767",
|
||||||
}).add(geo.offset(lotCorner), geo.east(geo.ft(107)), geo.south(geo.ft(3))),
|
}).add(geo.offset(lotCorner), geo.east(geo.ft(107)), geo.south(geo.ft(3))),
|
||||||
new Tree("Elderberry", {
|
new Tree("Elderberry", {
|
||||||
species: "Elderberry",
|
species: "Elderberry",
|
||||||
canopyDiameterMeters: 3,
|
measurements: [{ canopyDiameter: geo.ft(9.84), height: geo.ft(9.84) }],
|
||||||
heightMeters: 3,
|
|
||||||
gardenOrgId: "78882",
|
gardenOrgId: "78882",
|
||||||
}).add(geo.offset(lotCorner), geo.east(geo.ft(142)), geo.south(geo.ft(52))),
|
}).add(geo.offset(lotCorner), geo.east(geo.ft(142)), geo.south(geo.ft(52))),
|
||||||
new Tree("Spirea", {
|
new Tree("Spirea", {
|
||||||
species: "Spirea",
|
species: "Spirea",
|
||||||
canopyDiameterMeters: 1.5,
|
measurements: [{ canopyDiameter: geo.ft(4.92), height: geo.ft(3.28) }],
|
||||||
heightMeters: 1,
|
|
||||||
}).add(geo.offset(lotCorner), geo.east(geo.ft(70)), geo.south(geo.ft(31))),
|
}).add(geo.offset(lotCorner), geo.east(geo.ft(70)), geo.south(geo.ft(31))),
|
||||||
new Tree("Spirea", {
|
new Tree("Spirea", {
|
||||||
species: "Spirea",
|
species: "Spirea",
|
||||||
canopyDiameterMeters: 1.5,
|
measurements: [{ canopyDiameter: geo.ft(4.92), height: geo.ft(3.28) }],
|
||||||
heightMeters: 1,
|
|
||||||
}).add(geo.offset(lotCorner), geo.east(geo.ft(74)), geo.south(geo.ft(31))),
|
}).add(geo.offset(lotCorner), geo.east(geo.ft(74)), geo.south(geo.ft(31))),
|
||||||
new Tree("Spirea", {
|
new Tree("Spirea", {
|
||||||
species: "Spirea",
|
species: "Spirea",
|
||||||
canopyDiameterMeters: 1.5,
|
measurements: [{ canopyDiameter: geo.ft(4.92), height: geo.ft(3.28) }],
|
||||||
heightMeters: 1,
|
|
||||||
}).add(geo.offset(lotCorner), geo.east(geo.ft(78)), geo.south(geo.ft(31))),
|
}).add(geo.offset(lotCorner), geo.east(geo.ft(78)), geo.south(geo.ft(31))),
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|||||||
@@ -128,6 +128,9 @@ export const featureTypes = {
|
|||||||
species: "string",
|
species: "string",
|
||||||
cultivar: "string",
|
cultivar: "string",
|
||||||
gardenOrgId: "string",
|
gardenOrgId: "string",
|
||||||
|
measurements: "plantMeasurement[]",
|
||||||
|
canopyDiameter: "number",
|
||||||
|
height: "number",
|
||||||
note: "string",
|
note: "string",
|
||||||
},
|
},
|
||||||
externalLinks: [
|
externalLinks: [
|
||||||
@@ -158,6 +161,9 @@ export const featureTypes = {
|
|||||||
cultivar: "string",
|
cultivar: "string",
|
||||||
bloomColor: "string",
|
bloomColor: "string",
|
||||||
bloomSeason: "string",
|
bloomSeason: "string",
|
||||||
|
measurements: "plantMeasurement[]",
|
||||||
|
canopyDiameter: "number",
|
||||||
|
height: "number",
|
||||||
note: "string",
|
note: "string",
|
||||||
},
|
},
|
||||||
style: {
|
style: {
|
||||||
@@ -179,6 +185,9 @@ export const featureTypes = {
|
|||||||
cultivar: "string",
|
cultivar: "string",
|
||||||
bloomColor: "string",
|
bloomColor: "string",
|
||||||
bloomSeason: "string",
|
bloomSeason: "string",
|
||||||
|
measurements: "plantMeasurement[]",
|
||||||
|
canopyDiameter: "number",
|
||||||
|
height: "number",
|
||||||
note: "string",
|
note: "string",
|
||||||
},
|
},
|
||||||
style: {
|
style: {
|
||||||
@@ -200,14 +209,15 @@ export const featureTypes = {
|
|||||||
genus: "string",
|
genus: "string",
|
||||||
species: "string",
|
species: "string",
|
||||||
cultivar: "string",
|
cultivar: "string",
|
||||||
canopyDiameterMeters: "number",
|
measurements: "plantMeasurement[]",
|
||||||
heightMeters: "number",
|
canopyDiameter: "number",
|
||||||
|
height: "number",
|
||||||
note: "string",
|
note: "string",
|
||||||
},
|
},
|
||||||
style: (details) => ({
|
style: (details) => ({
|
||||||
color: "#426a3d",
|
color: "#426a3d",
|
||||||
weight: 1,
|
weight: 1,
|
||||||
radiusMeters: (details.canopyDiameterMeters ?? 1) / 2,
|
radiusMeters: (details.canopyDiameter ?? 1) / 2,
|
||||||
fillColor: "#7e9d58",
|
fillColor: "#7e9d58",
|
||||||
fillOpacity: 0.62,
|
fillOpacity: 0.62,
|
||||||
}),
|
}),
|
||||||
@@ -221,14 +231,15 @@ export const featureTypes = {
|
|||||||
genus: "string",
|
genus: "string",
|
||||||
species: "string",
|
species: "string",
|
||||||
cultivar: "string",
|
cultivar: "string",
|
||||||
canopyDiameterMeters: "number",
|
measurements: "plantMeasurement[]",
|
||||||
heightMeters: "number",
|
canopyDiameter: "number",
|
||||||
|
height: "number",
|
||||||
note: "string",
|
note: "string",
|
||||||
},
|
},
|
||||||
style: (details) => ({
|
style: (details) => ({
|
||||||
color: "#2f6b3d",
|
color: "#2f6b3d",
|
||||||
weight: 1,
|
weight: 1,
|
||||||
radiusMeters: (details.canopyDiameterMeters ?? 2) / 2,
|
radiusMeters: (details.canopyDiameter ?? 2) / 2,
|
||||||
fillColor: "#5c9e64",
|
fillColor: "#5c9e64",
|
||||||
fillOpacity: 0.55,
|
fillOpacity: 0.55,
|
||||||
}),
|
}),
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { collectGeoJSON, offset, pointsFromLngLat } from "./geometry.js";
|
import { collectGeoJSON, offset, pointsFromLngLat } from "./geometry.js";
|
||||||
import { getFeatureType, listFeatureTypeSchemas } from "./feature-types.js";
|
import { getFeatureType, listFeatureTypeSchemas } from "./feature-types.js";
|
||||||
|
|
||||||
export const YARD_SCHEMA_VERSION = 2;
|
export const YARD_SCHEMA_VERSION = 3;
|
||||||
|
|
||||||
class YardFeature {
|
class YardFeature {
|
||||||
constructor(kind, geometryType, name, details = {}) {
|
constructor(kind, geometryType, name, details = {}) {
|
||||||
@@ -286,7 +286,7 @@ export class FlowerBed extends PolygonFeature {
|
|||||||
|
|
||||||
export class Plant extends PointFeature {
|
export class Plant extends PointFeature {
|
||||||
constructor(name = "Plant", details = {}, kind = "plant") {
|
constructor(name = "Plant", details = {}, kind = "plant") {
|
||||||
super(kind, name, details);
|
super(kind, name, normalizePlantDetails(details));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -324,6 +324,65 @@ export class Tree extends Plant {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function normalizePlantDetails(details) {
|
||||||
|
const {
|
||||||
|
canopyDiameter,
|
||||||
|
height,
|
||||||
|
measurements = [],
|
||||||
|
...restDetails
|
||||||
|
} = details;
|
||||||
|
const normalizedMeasurements = normalizePlantMeasurements(measurements);
|
||||||
|
|
||||||
|
if (!normalizedMeasurements.length && hasPlantSizeMeasurement(details)) {
|
||||||
|
normalizedMeasurements.push(
|
||||||
|
normalizePlantMeasurement({
|
||||||
|
canopyDiameter,
|
||||||
|
height,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const latestMeasurement = normalizedMeasurements.at(-1);
|
||||||
|
|
||||||
|
return {
|
||||||
|
...restDetails,
|
||||||
|
...(normalizedMeasurements.length ? { measurements: normalizedMeasurements } : {}),
|
||||||
|
...(latestMeasurement?.canopyDiameter !== undefined
|
||||||
|
? { canopyDiameter: latestMeasurement.canopyDiameter }
|
||||||
|
: {}),
|
||||||
|
...(latestMeasurement?.height !== undefined
|
||||||
|
? { height: latestMeasurement.height }
|
||||||
|
: {}),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function normalizePlantMeasurements(measurements) {
|
||||||
|
if (!Array.isArray(measurements)) {
|
||||||
|
throw new Error("Plant measurements must be an array");
|
||||||
|
}
|
||||||
|
|
||||||
|
return measurements.map(normalizePlantMeasurement);
|
||||||
|
}
|
||||||
|
|
||||||
|
function normalizePlantMeasurement(measurement) {
|
||||||
|
if (!measurement || typeof measurement !== "object") {
|
||||||
|
throw new Error("Plant measurement entries must be objects");
|
||||||
|
}
|
||||||
|
|
||||||
|
const { canopyDiameter, height, measuredDate, ...restMeasurement } = measurement;
|
||||||
|
|
||||||
|
return {
|
||||||
|
...restMeasurement,
|
||||||
|
...(measuredDate ? { measuredDate } : {}),
|
||||||
|
...(canopyDiameter !== undefined ? { canopyDiameter } : {}),
|
||||||
|
...(height !== undefined ? { height } : {}),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function hasPlantSizeMeasurement(details) {
|
||||||
|
return details.canopyDiameter !== undefined || details.height !== undefined;
|
||||||
|
}
|
||||||
|
|
||||||
export class Sprinkler extends PointFeature {
|
export class Sprinkler extends PointFeature {
|
||||||
constructor(name = "Sprinkler", details = {}) {
|
constructor(name = "Sprinkler", details = {}) {
|
||||||
super("sprinkler", name, details);
|
super("sprinkler", name, details);
|
||||||
@@ -337,6 +396,11 @@ export function collectYardData(features, groups = []) {
|
|||||||
plantedDate: "date",
|
plantedDate: "date",
|
||||||
removedDate: "date",
|
removedDate: "date",
|
||||||
};
|
};
|
||||||
|
collection.measurementFields = {
|
||||||
|
measuredDate: "date",
|
||||||
|
canopyDiameter: "number",
|
||||||
|
height: "number",
|
||||||
|
};
|
||||||
collection.featureTypes = listFeatureTypeSchemas();
|
collection.featureTypes = listFeatureTypeSchemas();
|
||||||
collection.groups = groups.map((group) => ({
|
collection.groups = groups.map((group) => ({
|
||||||
id: group.id,
|
id: group.id,
|
||||||
|
|||||||
+46
-5
@@ -305,7 +305,7 @@ function extendBounds(bounds, coordinates) {
|
|||||||
function buildPopupContent(properties) {
|
function buildPopupContent(properties) {
|
||||||
const { kind, label, name, plantedDate, removedDate, details, parentId, groupIds } = properties;
|
const { kind, label, name, plantedDate, removedDate, details, parentId, groupIds } = properties;
|
||||||
const entries = Object.entries(details ?? {}).filter(
|
const entries = Object.entries(details ?? {}).filter(
|
||||||
([key, value]) => value !== null && value !== undefined && shouldShowDetailField(key),
|
([key, value]) => value !== null && value !== undefined && shouldShowDetailField(key, details),
|
||||||
);
|
);
|
||||||
const lifecycleEntries = [];
|
const lifecycleEntries = [];
|
||||||
const relationshipEntries = [];
|
const relationshipEntries = [];
|
||||||
@@ -344,14 +344,23 @@ function buildPopupContent(properties) {
|
|||||||
return `${title}${subtitle}<div>${detailRows}${linkRows}</div>`;
|
return `${title}${subtitle}<div>${detailRows}${linkRows}</div>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
function shouldShowDetailField(key) {
|
function shouldShowDetailField(key, details = {}) {
|
||||||
|
if (
|
||||||
|
Array.isArray(details.measurements) &&
|
||||||
|
(key === "canopyDiameter" || key === "height")
|
||||||
|
) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return !key.endsWith("Url") && key !== "gardenOrgId";
|
return !key.endsWith("Url") && key !== "gardenOrgId";
|
||||||
}
|
}
|
||||||
|
|
||||||
function formatDetailLabel(key) {
|
function formatDetailLabel(key) {
|
||||||
const labels = {
|
const labels = {
|
||||||
canopyDiameterMeters: "Canopy diameter",
|
canopyDiameter: "Canopy diameter",
|
||||||
heightMeters: "Height",
|
height: "Height",
|
||||||
|
measurements: "Measurements",
|
||||||
|
measuredDate: "Measured",
|
||||||
plantedDate: "Planted",
|
plantedDate: "Planted",
|
||||||
removedDate: "Removed",
|
removedDate: "Removed",
|
||||||
commonName: "Common name",
|
commonName: "Common name",
|
||||||
@@ -373,7 +382,11 @@ function formatDetailLabel(key) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function formatDetailValue(key, value) {
|
function formatDetailValue(key, value) {
|
||||||
if (key === "canopyDiameterMeters" || key === "heightMeters") {
|
if (key === "measurements") {
|
||||||
|
return formatPlantMeasurements(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (key === "canopyDiameter" || key === "height") {
|
||||||
return `${value} m`;
|
return `${value} m`;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -384,6 +397,34 @@ function formatDetailValue(key, value) {
|
|||||||
return String(value);
|
return String(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function formatPlantMeasurements(measurements) {
|
||||||
|
if (!Array.isArray(measurements)) {
|
||||||
|
return String(measurements);
|
||||||
|
}
|
||||||
|
|
||||||
|
return measurements.map(formatPlantMeasurement).join("; ");
|
||||||
|
}
|
||||||
|
|
||||||
|
function formatPlantMeasurement(measurement) {
|
||||||
|
const parts = [];
|
||||||
|
|
||||||
|
if (measurement.measuredDate) {
|
||||||
|
parts.push(formatDetailValue("measuredDate", measurement.measuredDate));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (measurement.canopyDiameter !== undefined) {
|
||||||
|
parts.push(
|
||||||
|
`canopy ${formatDetailValue("canopyDiameter", measurement.canopyDiameter)}`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (measurement.height !== undefined) {
|
||||||
|
parts.push(`height ${formatDetailValue("height", measurement.height)}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
return parts.join(", ");
|
||||||
|
}
|
||||||
|
|
||||||
function escapeHtml(value) {
|
function escapeHtml(value) {
|
||||||
return String(value)
|
return String(value)
|
||||||
.replaceAll("&", "&")
|
.replaceAll("&", "&")
|
||||||
|
|||||||
Reference in New Issue
Block a user