Skip to content

Commit ba110d3

Browse files
vharmainclaude
andcommitted
Move ITRS exposure from segments to LOI, add route-level technical classification
- Remove itrs-exposure from segment feature properties and UI - Add "trail-conditions" LOI category with fall-hazard type carrying ITRS exposure (E1-E4) - Add :itrs-technical-route field to route properties with auto-compute button that calculates max technical value from route segments - Add i18n translations for compute-itrs-technical in fi/en/se Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 9c5cee5 commit ba110d3

File tree

10 files changed

+132
-84
lines changed

10 files changed

+132
-84
lines changed

webapp/src/cljc/lipas/data/activities.cljc

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -953,6 +953,20 @@
953953
:en "less than 0.3 meter wide, very uneven and steep section"}
954954
:color "orange"}})
955955

956+
(def itrs-technical-order
957+
{"1a" 0, "1b" 1, "2" 2, "3" 3, "4" 4, "5" 5})
958+
959+
(defn itrs-technical-max
960+
"Returns the highest ITRS technical value from a seq of values."
961+
[values]
962+
(->> values
963+
(filter some?)
964+
(sort-by itrs-technical-order)
965+
last))
966+
967+
(def itrs-technical-route-options
968+
(into {} (map (fn [[k v]] [k (:label v)]) itrs-technical-options)))
969+
956970
(def itrs-exposure-options
957971
{"1" {:label {:fi "E1 - Vähäinen altistuminen"
958972
:se "E1 - Låg exponering"
@@ -1030,6 +1044,7 @@
10301044
:cycling-route-difficulty
10311045
:itrs-endurance
10321046
:itrs-wilderness
1047+
:itrs-technical-route
10331048
:surface-material
10341049
:unpaved-percentage
10351050
:trail-percentage
@@ -1079,6 +1094,8 @@
10791094
(into [:enum] (keys itrs-endurance-options))]
10801095
[:itrs-wilderness {:optional true}
10811096
(into [:enum] (keys itrs-wilderness-options))]
1097+
[:itrs-technical-route {:optional true}
1098+
(into [:enum] (keys itrs-technical-options))]
10821099
pilgrimage-key-schema])]
10831100
:field
10841101
{:type "routes"
@@ -1163,6 +1180,17 @@
11631180
:en "Route remoteness from services (1-4)"}
11641181
:opts itrs-wilderness-options}}
11651182

1183+
:itrs-technical-route
1184+
{:field
1185+
{:type "select"
1186+
:label {:fi "ITRS Reitin tekninen luokitus"
1187+
:se "ITRS Ruttens tekniska klassificering"
1188+
:en "ITRS Route technical classification"}
1189+
:description {:fi "Reitin vaativin tekninen osuus (lasketaan automaattisesti reittiosista)"
1190+
:se "Ruttens mest tekniskt krävande avsnitt (beräknas automatiskt från ruttsektioner)"
1191+
:en "Most technically demanding section of the route (auto-computed from segments)"}
1192+
:opts itrs-technical-route-options}}
1193+
11661194
:duration
11671195
{:field
11681196
{:type "duration"

webapp/src/cljc/lipas/data/loi.cljc

Lines changed: 48 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -186,8 +186,8 @@
186186
{:label {:fi "Infotaulu" :se "Informationsstavla" :en "Information board"}
187187
:value "information-board"
188188
:props (merge
189-
common-props
190-
accessibility-props)}
189+
common-props
190+
accessibility-props)}
191191

192192
:parking-spot
193193
{:label {:fi "Pysäköintipaikka" :se "Parkeringsplats" :en "Parking spot"}
@@ -409,6 +409,28 @@
409409
:value "bridge"
410410
:props (merge common-props)}}}
411411

412+
"trail-conditions"
413+
{:label {:fi "Reittiolosuhteet" :se "Ruttförhållanden" :en "Trail conditions"}
414+
:types
415+
{:fall-hazard
416+
{:label {:fi "Putoamisvaara" :se "Fallrisk" :en "Fall hazard"}
417+
:value "fall-hazard"
418+
:props (merge common-props
419+
{:itrs-exposure
420+
{:schema (into [:enum] ["1" "2" "3" "4"])
421+
:field
422+
{:type "select"
423+
:label {:fi "ITRS Putoamisvaara"
424+
:se "ITRS Fallrisk"
425+
:en "ITRS Exposure"}
426+
:description {:fi "Putoamisvaaran luokitus (E1-E4)"
427+
:se "Klassificering av fallrisk (E1-E4)"
428+
:en "Fall risk classification (E1-E4)"}
429+
:opts {"1" {:fi "E1 - Vähäinen" :se "E1 - Låg" :en "E1 - Low"}
430+
"2" {:fi "E2 - Kohtalainen" :se "E2 - Måttlig" :en "E2 - Moderate"}
431+
"3" {:fi "E3 - Korkea" :se "E3 - Hög" :en "E3 - High"}
432+
"4" {:fi "E4 - Äärimmäinen" :se "E4 - Extrem" :en "E4 - Extreme"}}}}})}}}
433+
412434
"natural-attractions-and-geo-objects"
413435
{:label {:fi "Luonnonnähtävyydet / geokohteet" :se "Natursevärdheter / Geologiska platser" :en "Natural Attractions / Geological sites"}
414436
:types
@@ -494,27 +516,27 @@
494516
(def csv-data
495517
(into [csv-headers]
496518
(for [[category-code category] categories
497-
[_ type] (:types category)
498-
[prop-k prop] (:props type)]
499-
[category-code
500-
(get-in category [:label :fi])
501-
(get-in category [:label :se])
502-
(get-in category [:label :en])
503-
(get-in category [:description :fi])
504-
(get-in category [:description :se])
505-
(get-in category [:description :en])
506-
(:value type)
507-
(:value type)
508-
(get-in type [:label :fi])
509-
(get-in type [:label :se])
510-
(get-in type [:label :en])
511-
(get-in type [:description :fi])
512-
(get-in type [:description :se])
513-
(get-in type [:description :en])
514-
(name prop-k)
515-
(get-in prop [:field :label :fi])
516-
(get-in prop [:field :label :se])
517-
(get-in prop [:field :label :en])
518-
(get-in prop [:field :description :fi])
519-
(get-in prop [:field :description :se])
520-
(get-in prop [:field :description :en])])))
519+
[_ type] (:types category)
520+
[prop-k prop] (:props type)]
521+
[category-code
522+
(get-in category [:label :fi])
523+
(get-in category [:label :se])
524+
(get-in category [:label :en])
525+
(get-in category [:description :fi])
526+
(get-in category [:description :se])
527+
(get-in category [:description :en])
528+
(:value type)
529+
(:value type)
530+
(get-in type [:label :fi])
531+
(get-in type [:label :se])
532+
(get-in type [:label :en])
533+
(get-in type [:description :fi])
534+
(get-in type [:description :se])
535+
(get-in type [:description :en])
536+
(name prop-k)
537+
(get-in prop [:field :label :fi])
538+
(get-in prop [:field :label :se])
539+
(get-in prop [:field :label :en])
540+
(get-in prop [:field :description :fi])
541+
(get-in prop [:field :description :se])
542+
(get-in prop [:field :description :en])])))

webapp/src/cljc/lipas/i18n/en/map.edn

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
:itrs-segment "ITRS classification",
3131
:itrs-technical "ITRS Technical",
3232
:itrs-exposure "ITRS Exposure",
33+
:compute-itrs-technical "Compute from segments",
3334
:split-linestring "Split",
3435
:travel-direction "Define travel direction",
3536
:zoom-closer "Please zoom closer",

webapp/src/cljc/lipas/i18n/fi/map.edn

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
:itrs-segment "ITRS-luokitus",
3131
:itrs-technical "ITRS Teknisyys",
3232
:itrs-exposure "ITRS Altistuminen",
33+
:compute-itrs-technical "Laske reittiosista",
3334
:split-linestring "Katkaise reittiosa",
3435
:travel-direction "Määritä kulkusuunta",
3536
:zoom-closer "Kartta täytyy zoomata lähemmäs",

webapp/src/cljc/lipas/i18n/se/map.edn

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
:itrs-segment "ITRS-klassificering",
3030
:itrs-technical "ITRS Teknisk",
3131
:itrs-exposure "ITRS Exponering",
32+
:compute-itrs-technical "Beräkna från ruttsektioner",
3233
:split-linestring "Klippa ruttdel",
3334
:travel-direction "Bestäm riktningen",
3435
:zoom-closer "Zooma in",

webapp/src/cljc/lipas/schema/sports_sites/location.cljc

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,8 +71,7 @@
7171
[:type-code {:optional true} :int]
7272
[:route-part-difficulty {:optional true} :string]
7373
[:travel-direction {:optional true} :string]
74-
[:itrs-technical {:optional true} :string]
75-
[:itrs-exposure {:optional true} :string]]))
74+
[:itrs-technical {:optional true} :string]]))
7675

7776
(def line-string-feature
7877
(m/schema

webapp/src/cljs/lipas/ui/map/events.cljs

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -906,17 +906,6 @@
906906
(update-feature-properties fs fid dissoc :itrs-technical)))))]
907907
{:fx [[:dispatch [::update-geometries lipas-id geoms]]]})))
908908

909-
(rf/reg-event-fx ::set-itrs-exposure
910-
(fn [{:keys [db]} [_ lipas-id fid v]]
911-
(let [geoms (-> db
912-
(get-in [:map :mode :geoms])
913-
(update :features
914-
(fn [fs]
915-
(if (seq v)
916-
(update-feature-properties fs fid assoc :itrs-exposure v)
917-
(update-feature-properties fs fid dissoc :itrs-exposure)))))]
918-
{:fx [[:dispatch [::update-geometries lipas-id geoms]]]})))
919-
920909
;; Reverse geocoding
921910

922911
(rf/reg-event-fx ::resolve-address

webapp/src/cljs/lipas/ui/map/styles.cljs

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -370,15 +370,11 @@
370370
label-style]))
371371

372372
(defn itrs-segment-style-fn
373-
[feature tr hover? _selected?]
374-
(let [locale (tr)
375-
technical (if-let [x (.get feature "itrs-technical")]
373+
[feature _tr hover? _selected?]
374+
(let [technical (if-let [x (.get feature "itrs-technical")]
376375
(str "T" x)
377376
"-")
378-
exposure (if-let [x (.get feature "itrs-exposure")]
379-
(str "E" x)
380-
"-")
381-
label (str "ITRS: " technical " / " exposure)
377+
label (str "ITRS: " technical)
382378
label-style (.clone route-part-label-style)
383379
_ (.. label-style
384380
(getText)

webapp/src/cljs/lipas/ui/map/views.cljs

Lines changed: 2 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -646,8 +646,7 @@
646646
tr @(rf/subscribe [:lipas.ui.subs/translator])
647647
locale (tr)
648648
properties @(rf/subscribe [::subs/edit-geom-properties fid])
649-
technical-value (:itrs-technical properties)
650-
exposure-value (:itrs-exposure properties)]
649+
technical-value (:itrs-technical properties)]
651650
[:> Paper
652651
{:sx
653652
#js {:padding 2
@@ -658,37 +657,12 @@
658657
:fullWidth true
659658
:value (or technical-value "")
660659
:onChange (fn [e]
661-
(rf/dispatch [::events/set-itrs-technical lipas-id fid (.. e -target -value)]))
662-
:sx #js {:marginBottom 2}}
660+
(rf/dispatch [::events/set-itrs-technical lipas-id fid (.. e -target -value)]))}
663661
[:> MenuItem
664662
{:key "empty"
665663
:value ""}
666664
"-"]
667665
(for [[k {:keys [label description]}] activities-data/itrs-technical-options]
668-
[:> MenuItem
669-
{:key k
670-
:value k
671-
:sx #js {:flexDirection "column"
672-
:alignItems "flex-start"
673-
:maxWidth "350px"}}
674-
[:> Typography
675-
(get label locale)]
676-
[:> Typography
677-
{:sx #js {:fontSize "body2.fontSize"
678-
:whiteSpace "normal"}}
679-
(get description locale)]])]
680-
[:> TextField
681-
{:label (tr :map/itrs-exposure)
682-
:select true
683-
:fullWidth true
684-
:value (or exposure-value "")
685-
:onChange (fn [e]
686-
(rf/dispatch [::events/set-itrs-exposure lipas-id fid (.. e -target -value)]))}
687-
[:> MenuItem
688-
{:key "empty"
689-
:value ""}
690-
"-"]
691-
(for [[k {:keys [label description]}] activities-data/itrs-exposure-options]
692666
[:> MenuItem
693667
{:key k
694668
:value k

webapp/src/cljs/lipas/ui/sports_sites/activities/views.cljs

Lines changed: 47 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
[lipas.ui.components.buttons :as lui-btn]
1313
[lipas.ui.components.forms :refer [->display-tf]]
1414
[lipas.ui.components.text-fields :as lui-tf]
15+
[lipas.data.activities :as activities-data]
1516
[lipas.ui.config :as config]
1617
["@mui/material/Button$default" :as Button]
1718
["@mui/material/Chip$default" :as Chip]
@@ -891,10 +892,11 @@
891892
#{:arrival :rules :rules-structured :permits-rules-guidelines :highlights})
892893

893894
(def ^:private itrs-field-ks
894-
#{:itrs-endurance :itrs-wilderness})
895+
#{:itrs-endurance :itrs-wilderness :itrs-technical-route})
895896

896897
(defn route-form
897-
[{:keys [tr locale lipas-id type-code route-props state read-only? edit-itrs? field-sorter]}]
898+
[{:keys [tr locale lipas-id type-code route-props state read-only? edit-itrs? field-sorter
899+
compute-itrs-technical]}]
898900
[nice-form {:read-only? read-only?}
899901
(doall
900902
(for [[prop-k {:keys [field show]}] (sort-by field-sorter utils/reverse-cmp route-props)
@@ -909,6 +911,10 @@
909911
field-read-only? (if itrs-field?
910912
(or read-only? (not edit-itrs?))
911913
read-only?)
914+
set-field (fn [& args]
915+
(let [path (butlast args)
916+
v (last args)]
917+
(swap! state assoc-in path v)))
912918
field-component [make-field
913919
{:read-only? field-read-only?
914920
:key prop-k
@@ -917,14 +923,27 @@
917923
:edit-data @state
918924
:display-data @state
919925
:locale locale
920-
:set-field (fn [& args]
921-
(let [path (butlast args)
922-
v (last args)]
923-
(swap! state assoc-in path v)))
926+
:set-field set-field
924927
:lipas-id lipas-id}]]
925-
(if itrs-locked?
928+
(cond
929+
itrs-locked?
926930
[mui/tooltip {:title (tr :lipas.sports-site/itrs-edit-requires-role)}
927931
[:span field-component]]
932+
933+
(and (= :itrs-technical-route prop-k) edit-itrs? (not read-only?) compute-itrs-technical)
934+
[mui/grid {:container true :alignItems "center" :spacing 1 :wrap "nowrap"}
935+
[mui/grid {:item true :xs true}
936+
field-component]
937+
[mui/grid {:item true}
938+
[mui/tooltip {:title (tr :map/compute-itrs-technical)}
939+
[mui/icon-button
940+
{:size "small"
941+
:on-click (fn []
942+
(when-let [v (compute-itrs-technical)]
943+
(set-field :itrs-technical-route v)))}
944+
[mui/icon "calculate"]]]]]
945+
946+
:else
928947
field-component)))))])
929948

930949
(defn single-route
@@ -940,7 +959,8 @@
940959
(set-field [new-state])))]
941960

942961
(let [tr (<== [:lipas.ui.subs/translator])
943-
field-sorter (<== [::subs/field-sorter activity-k])]
962+
field-sorter (<== [::subs/field-sorter activity-k])
963+
geoms (<== [::subs/geoms read-only?])]
944964

945965
[route-form
946966
{:locale locale
@@ -951,7 +971,15 @@
951971
:read-only? read-only?
952972
:edit-itrs? edit-itrs?
953973
:route-props route-props
954-
:state route-form-state}])
974+
:state route-form-state
975+
:compute-itrs-technical
976+
(fn []
977+
(let [fids (set (:fids @route-form-state))
978+
features (:features geoms)
979+
values (->> features
980+
(filter #(contains? fids (:id %)))
981+
(map #(get-in % [:properties :itrs-technical])))]
982+
(activities-data/itrs-technical-max values)))}])
955983

956984
(finally
957985
(remove-watch route-form-state :lol))))
@@ -968,6 +996,7 @@
968996
selected-route-id (<== [::subs/selected-route-id])
969997

970998
field-sorter (<== [::subs/field-sorter activity-k])
999+
geoms (<== [::subs/geoms read-only?])
9711000

9721001
editing? (not read-only?)]
9731002

@@ -1032,7 +1061,15 @@
10321061
:read-only? read-only?
10331062
:edit-itrs? edit-itrs?
10341063
:route-props route-props
1035-
:state route-form-state}]
1064+
:state route-form-state
1065+
:compute-itrs-technical
1066+
(fn []
1067+
(let [route-fids (set (:fids @route-form-state))
1068+
features (:features geoms)
1069+
values (->> features
1070+
(filter #(contains? route-fids (:id %)))
1071+
(map #(get-in % [:properties :itrs-technical])))]
1072+
(activities-data/itrs-technical-max values)))}]
10361073

10371074
;; Buttons
10381075
[:> Grid {:container true :spacing 1}

0 commit comments

Comments
 (0)