3 Commits

Author SHA1 Message Date
Eric F
85ddea41e4 fix: restore getPlaceDetails with Nominatim OSM implementation
- Replace stub with working Nominatim OSM place details lookup
- Fixes 'Failed to find Server Action' errors in logs
- Free, no API key required
2026-06-14 08:32:24 -04:00
Eric F
d0c0cc8b0e chore: update pnpm-lock.yaml after leaflet dependency changes 2026-06-13 10:29:25 -04:00
Eric F
e20790dce4 docs: update infrastructure documentation for Leaflet OSM migration 2026-06-12 11:10:09 -04:00
3 changed files with 118 additions and 22 deletions

View File

@@ -142,6 +142,16 @@
| `/home/eric/flexmeasures/docker-compose.yml` | FM core stack |
| `/home/eric/flexmeasures/docker-compose.openadr.yml` | OpenADR VTN/VEN |
| `/home/eric/cariflex/config/docker-compose-citrineos.yml` | CitrineOS stack |
| `/home/eric/cariflex/config/docker-compose-citrineos-ui-noproxy.yml` | UI without Traefik (testing) |
### CitrineOS Operator UI
- **URL**: https://citrineos.digitribe.fr
- **Image**: `citrineos-core-main-citrine-ui:latest` (custom build)
- **Build**: `cd /home/eric/cariflex/tools/citrineos-core-main && docker compose -f docker-compose.local.yml build citrine-ui`
- **Tech stack**: Next.js 15.2, React 19, Refine, Leaflet + OpenStreetMap
- **Map**: Replaced Google Maps with Leaflet + OpenStreetMap (no API key needed)
- **Geocoding**: Nominatim OSM (free, no API key)
- **Dependencies**: `leaflet`, `react-leaflet`, `@types/leaflet`
### Deployment Commands
```bash
@@ -154,6 +164,9 @@ cd /home/eric/flexmeasures && docker compose -f docker-compose.openadr.yml up -d
# CitrineOS stack
cd /home/eric/cariflex/config && docker compose -f docker-compose-citrineos.yml up -d
# Rebuild UI (after code changes)
cd /home/eric/cariflex/tools/citrineos-core-main && docker compose -f docker-compose.local.yml build citrine-ui && docker compose -f docker-compose-citrineos.yml up -d citrineos-operator-ui
# Verify all
docker ps --format "table {{.Names}}\t{{.Status}}" | grep -E "flexmeasures|openadr|citrine|grafana"
```

View File

@@ -38,7 +38,33 @@ export async function getPlaceDetails(
throw new Error('Place ID is required');
}
// Return stub data - Google Places API removed, using OSM/Nominatim instead
try {
// Use Nominatim OSM for place details (free, no API key)
const url = `https://nominatim.openstreetmap.org/lookup?format=json&osm_ids=${placeId}&addressdetails=1`;
const response = await fetch(url, {
headers: { 'User-Agent': 'CitrineOS-Operator-UI/1.0' },
});
if (!response.ok) {
throw new Error(`Nominatim error: ${response.status}`);
}
const data = await response.json();
if (data && data.length > 0) {
const place = data[0];
return {
id: place.place_id?.toString() || placeId,
displayName: { text: place.display_name || '', languageCode: 'en' },
formattedAddress: place.display_name || '',
addressComponents: [],
location: {
latitude: parseFloat(place.lat) || 0,
longitude: parseFloat(place.lon) || 0,
},
types: place.type ? [place.type] : [],
};
}
return {
id: placeId,
displayName: { text: '', languageCode: 'en' },
@@ -46,5 +72,15 @@ export async function getPlaceDetails(
addressComponents: [],
location: { latitude: 0, longitude: 0 },
};
} catch (error) {
console.error('getPlaceDetails error:', error);
return {
id: placeId,
displayName: { text: '', languageCode: 'en' },
formattedAddress: '',
addressComponents: [],
location: { latitude: 0, longitude: 0 },
};
}
});
}

View File

@@ -81,7 +81,7 @@ importers:
version: 6.6.5
sequelize-typescript:
specifier: ^2.1.6
version: 2.1.6(@types/node@25.9.1)(@types/validator@13.15.10)(reflect-metadata@0.2.2)(sequelize@6.37.8)
version: 2.1.6(@types/node@25.9.1)(@types/validator@13.15.10)(reflect-metadata@0.2.2)(sequelize@6.37.8(sqlite3@5.1.7))
tsconfig-paths:
specifier: ^4.2.0
version: 4.2.0
@@ -194,7 +194,7 @@ importers:
version: 6.37.8(pg-hstore@2.3.4)(pg@8.11.3)(sqlite3@5.1.7)
sequelize-typescript:
specifier: 2.1.6
version: 2.1.6(@types/node@25.9.1)(@types/validator@13.15.10)(reflect-metadata@0.2.2)(sequelize@6.37.8)
version: 2.1.6(@types/node@25.9.1)(@types/validator@13.15.10)(reflect-metadata@0.2.2)(sequelize@6.37.8(sqlite3@5.1.7))
ts-node:
specifier: 10.9.2
version: 10.9.2(@types/node@25.9.1)(typescript@6.0.3)
@@ -319,6 +319,9 @@ importers:
'@tanstack/react-table':
specifier: 8.21.3
version: 8.21.3(react-dom@19.1.4(react@19.1.4))(react@19.1.4)
'@types/leaflet':
specifier: ^1.9.21
version: 1.9.21
'@vis.gl/react-google-maps':
specifier: 1.5.1
version: 1.5.1(react-dom@19.1.4(react@19.1.4))(react@19.1.4)
@@ -364,6 +367,9 @@ importers:
js-cookie:
specifier: 3.0.5
version: 3.0.5
leaflet:
specifier: ^1.9.4
version: 1.9.4
lodash:
specifier: ^4.18.1
version: 4.18.1
@@ -406,6 +412,9 @@ importers:
react-hook-form:
specifier: 7.65.0
version: 7.65.0(react@19.1.4)
react-leaflet:
specifier: ^5.0.0
version: 5.0.0(leaflet@1.9.4)(react-dom@19.1.4(react@19.1.4))(react@19.1.4)
react-redux:
specifier: 9.2.0
version: 9.2.0(@types/react@19.1.4)(react@19.1.4)(redux@5.0.1)
@@ -698,7 +707,7 @@ importers:
version: 6.37.8(pg-hstore@2.3.4)(pg@8.11.3)(sqlite3@5.1.7)
sequelize-typescript:
specifier: 2.1.6
version: 2.1.6(@types/node@25.9.1)(@types/validator@13.15.10)(reflect-metadata@0.2.2)(sequelize@6.37.8)
version: 2.1.6(@types/node@25.9.1)(@types/validator@13.15.10)(reflect-metadata@0.2.2)(sequelize@6.37.8(sqlite3@5.1.7))
ssh2-sftp-client:
specifier: ^10.0.3
version: 10.0.3
@@ -3304,6 +3313,13 @@ packages:
'@reach/observe-rect@1.2.0':
resolution: {integrity: sha512-Ba7HmkFgfQxZqqaeIWWkNK0rEhpxVQHIoVyW1YDSkGsGIXzcaW4deC8B0pZrNSSyLTdIk7y+5olKt5+g0GmFIQ==}
'@react-leaflet/core@3.0.0':
resolution: {integrity: sha512-3EWmekh4Nz+pGcr+xjf0KNyYfC3U2JjnkWsh0zcqaexYqmmB5ZhH37kz41JXGmKzpaMZCnPofBBm64i+YrEvGQ==}
peerDependencies:
leaflet: ^1.9.0
react: ^19.0.0
react-dom: ^19.0.0
'@redis/bloom@1.2.0':
resolution: {integrity: sha512-HG2DFjYKbpNmVXsa0keLHp/3leGJz1mjh09f2RLGGLQZzSHpkmZWuwJbAvo3QcRY8p80m5+ZdXZdYOSBLlp7Cg==}
peerDependencies:
@@ -3940,6 +3956,9 @@ packages:
'@types/jsrsasign@10.5.15':
resolution: {integrity: sha512-3stUTaSRtN09PPzVWR6aySD9gNnuymz+WviNHoTb85dKu+BjaV4uBbWWGykBBJkfwPtcNZVfTn2lbX00U+yhpQ==}
'@types/leaflet@1.9.21':
resolution: {integrity: sha512-TbAd9DaPGSnzp6QvtYngntMZgcRk+igFELwR2N99XZn7RXUdKgsXMR+28bUO0rPsWp8MIu/f47luLIQuSLYv/w==}
'@types/lodash.debounce@4.0.9':
resolution: {integrity: sha512-Ma5JcgTREwpLRwMM+XwBR7DaWe96nC38uCBDFKZWbNKD+osjVzdpnUSwBcqCptrp16sSOLBAUb50Car5I0TCsQ==}
@@ -6987,6 +7006,9 @@ packages:
resolution: {integrity: sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw==}
engines: {node: '>= 0.6.3'}
leaflet@1.9.4:
resolution: {integrity: sha512-nxS1ynzJOmOlHp+iL3FyWqK89GtNL8U8rvlMOsQdTTssxZwCXh8N2NB3GDQOL+YR3XnWyZAxwQixURb+FA74PA==}
levn@0.4.1:
resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==}
engines: {node: '>= 0.8.0'}
@@ -8214,6 +8236,13 @@ packages:
react-is@19.1.4:
resolution: {integrity: sha512-4oz30Hl3G6Ji4MpJEMwfXCjsfjAarc9nUPLmSXJLDjHbQRTeXMgf8UAPcrsUYVV+7E7mPHqNfhi5KVVMhl+zcg==}
react-leaflet@5.0.0:
resolution: {integrity: sha512-CWbTpr5vcHw5bt9i4zSlPEVQdTVcML390TjeDG0cK59z1ylexpqC6M1PJFjV8jD7CF+ACBFsLIDs6DRMoLEofw==}
peerDependencies:
leaflet: ^1.9.0
react: ^19.0.0
react-dom: ^19.0.0
react-reconciler@0.29.2:
resolution: {integrity: sha512-zZQqIiYgDCTP/f1N/mAR10nJGrPD2ZR+jDSEsKWJHYC7Cm2wodlwbR3upZRdC3cjIjSlTLNVyO7Iu0Yy7t2AYg==}
engines: {node: '>=0.10.0'}
@@ -12262,6 +12291,12 @@ snapshots:
'@reach/observe-rect@1.2.0': {}
'@react-leaflet/core@3.0.0(leaflet@1.9.4)(react-dom@19.1.4(react@19.1.4))(react@19.1.4)':
dependencies:
leaflet: 1.9.4
react: 19.1.4
react-dom: 19.1.4(react@19.1.4)
'@redis/bloom@1.2.0(@redis/client@1.6.1)':
dependencies:
'@redis/client': 1.6.1
@@ -12920,6 +12955,10 @@ snapshots:
'@types/jsrsasign@10.5.15': {}
'@types/leaflet@1.9.21':
dependencies:
'@types/geojson': 7946.0.16
'@types/lodash.debounce@4.0.9':
dependencies:
'@types/lodash': 4.17.24
@@ -14934,8 +14973,8 @@ snapshots:
'@typescript-eslint/parser': 8.60.1(eslint@9.16.0(jiti@2.7.0))(typescript@6.0.3)
eslint: 9.16.0(jiti@2.7.0)
eslint-import-resolver-node: 0.3.10
eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.60.1(eslint@9.16.0(jiti@2.7.0))(typescript@6.0.3))(eslint@9.16.0(jiti@2.7.0)))(eslint@9.16.0(jiti@2.7.0))
eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.60.1(eslint@9.16.0(jiti@2.7.0))(typescript@6.0.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.16.0(jiti@2.7.0))
eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0)(eslint@9.16.0(jiti@2.7.0))
eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.17.0(eslint@9.16.0(jiti@2.7.0))(typescript@6.0.3))(eslint@9.16.0(jiti@2.7.0))
eslint-plugin-jsx-a11y: 6.10.2(eslint@9.16.0(jiti@2.7.0))
eslint-plugin-react: 7.37.5(eslint@9.16.0(jiti@2.7.0))
eslint-plugin-react-hooks: 5.2.0(eslint@9.16.0(jiti@2.7.0))
@@ -14958,7 +14997,7 @@ snapshots:
transitivePeerDependencies:
- supports-color
eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.60.1(eslint@9.16.0(jiti@2.7.0))(typescript@6.0.3))(eslint@9.16.0(jiti@2.7.0)))(eslint@9.16.0(jiti@2.7.0)):
eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0)(eslint@9.16.0(jiti@2.7.0)):
dependencies:
'@nolyfill/is-core-module': 1.0.39
debug: 4.4.3(supports-color@5.5.0)
@@ -14969,22 +15008,21 @@ snapshots:
tinyglobby: 0.2.17
unrs-resolver: 1.12.2
optionalDependencies:
eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.60.1(eslint@9.16.0(jiti@2.7.0))(typescript@6.0.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.16.0(jiti@2.7.0))
eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.17.0(eslint@9.16.0(jiti@2.7.0))(typescript@6.0.3))(eslint@9.16.0(jiti@2.7.0))
transitivePeerDependencies:
- supports-color
eslint-module-utils@2.13.0(@typescript-eslint/parser@8.60.1(eslint@9.16.0(jiti@2.7.0))(typescript@6.0.3))(eslint-import-resolver-node@0.3.10)(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.60.1(eslint@9.16.0(jiti@2.7.0))(typescript@6.0.3))(eslint@9.16.0(jiti@2.7.0)))(eslint@9.16.0(jiti@2.7.0)))(eslint@9.16.0(jiti@2.7.0)):
eslint-module-utils@2.13.0(@typescript-eslint/parser@8.17.0(eslint@9.16.0(jiti@2.7.0))(typescript@6.0.3))(eslint-import-resolver-node@0.3.10)(eslint@9.16.0(jiti@2.7.0)):
dependencies:
debug: 3.2.7
optionalDependencies:
'@typescript-eslint/parser': 8.60.1(eslint@9.16.0(jiti@2.7.0))(typescript@6.0.3)
'@typescript-eslint/parser': 8.17.0(eslint@9.16.0(jiti@2.7.0))(typescript@6.0.3)
eslint: 9.16.0(jiti@2.7.0)
eslint-import-resolver-node: 0.3.10
eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.60.1(eslint@9.16.0(jiti@2.7.0))(typescript@6.0.3))(eslint@9.16.0(jiti@2.7.0)))(eslint@9.16.0(jiti@2.7.0))
transitivePeerDependencies:
- supports-color
eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.60.1(eslint@9.16.0(jiti@2.7.0))(typescript@6.0.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.16.0(jiti@2.7.0)):
eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.17.0(eslint@9.16.0(jiti@2.7.0))(typescript@6.0.3))(eslint@9.16.0(jiti@2.7.0)):
dependencies:
'@rtsao/scc': 1.1.0
array-includes: 3.1.9
@@ -14995,7 +15033,7 @@ snapshots:
doctrine: 2.1.0
eslint: 9.16.0(jiti@2.7.0)
eslint-import-resolver-node: 0.3.10
eslint-module-utils: 2.13.0(@typescript-eslint/parser@8.60.1(eslint@9.16.0(jiti@2.7.0))(typescript@6.0.3))(eslint-import-resolver-node@0.3.10)(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.60.1(eslint@9.16.0(jiti@2.7.0))(typescript@6.0.3))(eslint@9.16.0(jiti@2.7.0)))(eslint@9.16.0(jiti@2.7.0)))(eslint@9.16.0(jiti@2.7.0))
eslint-module-utils: 2.13.0(@typescript-eslint/parser@8.17.0(eslint@9.16.0(jiti@2.7.0))(typescript@6.0.3))(eslint-import-resolver-node@0.3.10)(eslint@9.16.0(jiti@2.7.0))
hasown: 2.0.4
is-core-module: 2.16.2
is-glob: 4.0.3
@@ -15007,7 +15045,7 @@ snapshots:
string.prototype.trimend: 1.0.9
tsconfig-paths: 3.15.0
optionalDependencies:
'@typescript-eslint/parser': 8.60.1(eslint@9.16.0(jiti@2.7.0))(typescript@6.0.3)
'@typescript-eslint/parser': 8.17.0(eslint@9.16.0(jiti@2.7.0))(typescript@6.0.3)
transitivePeerDependencies:
- eslint-import-resolver-typescript
- eslint-import-resolver-webpack
@@ -16487,6 +16525,8 @@ snapshots:
dependencies:
readable-stream: 2.3.8
leaflet@1.9.4: {}
levn@0.4.1:
dependencies:
prelude-ls: 1.2.1
@@ -17761,6 +17801,13 @@ snapshots:
react-is@19.1.4: {}
react-leaflet@5.0.0(leaflet@1.9.4)(react-dom@19.1.4(react@19.1.4))(react@19.1.4):
dependencies:
'@react-leaflet/core': 3.0.0(leaflet@1.9.4)(react-dom@19.1.4(react@19.1.4))(react@19.1.4)
leaflet: 1.9.4
react: 19.1.4
react-dom: 19.1.4(react@19.1.4)
react-reconciler@0.29.2(react@18.3.1):
dependencies:
loose-envify: 1.4.0
@@ -18217,7 +18264,7 @@ snapshots:
sequelize-pool@7.1.0: {}
sequelize-typescript@2.1.6(@types/node@25.9.1)(@types/validator@13.15.10)(reflect-metadata@0.2.2)(sequelize@6.37.8):
sequelize-typescript@2.1.6(@types/node@25.9.1)(@types/validator@13.15.10)(reflect-metadata@0.2.2)(sequelize@6.37.8(sqlite3@5.1.7)):
dependencies:
'@types/node': 25.9.1
'@types/validator': 13.15.10