Skip to content

Commit 3a93104

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 264a389 commit 3a93104

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
@@ -899,17 +899,6 @@
899899
(update-feature-properties fs fid dissoc :itrs-technical)))))]
900900
{:fx [[:dispatch [::update-geometries lipas-id geoms]]]})))
901901

902-
(rf/reg-event-fx ::set-itrs-exposure
903-
(fn [{:keys [db]} [_ lipas-id fid v]]
904-
(let [geoms (-> db
905-
(get-in [:map :mode :geoms])
906-
(update :features
907-
(fn [fs]
908-
(if (seq v)
909-
(update-feature-properties fs fid assoc :itrs-exposure v)
910-
(update-feature-properties fs fid dissoc :itrs-exposure)))))]
911-
{:fx [[:dispatch [::update-geometries lipas-id geoms]]]})))
912-
913902
;; Reverse geocoding
914903

915904
(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
@@ -610,8 +610,7 @@
610610
tr @(rf/subscribe [:lipas.ui.subs/translator])
611611
locale (tr)
612612
properties @(rf/subscribe [::subs/edit-geom-properties fid])
613-
technical-value (:itrs-technical properties)
614-
exposure-value (:itrs-exposure properties)]
613+
technical-value (:itrs-technical properties)]
615614
[:> Paper
616615
{:sx
617616
#js {:padding 2
@@ -622,37 +621,12 @@
622621
:fullWidth true
623622
:value (or technical-value "")
624623
:onChange (fn [e]
625-
(rf/dispatch [::events/set-itrs-technical lipas-id fid (.. e -target -value)]))
626-
:sx #js {:marginBottom 2}}
624+
(rf/dispatch [::events/set-itrs-technical lipas-id fid (.. e -target -value)]))}
627625
[:> MenuItem
628626
{:key "empty"
629627
:value ""}
630628
"-"]
631629
(for [[k {:keys [label description]}] activities-data/itrs-technical-options]
632-
[:> MenuItem
633-
{:key k
634-
:value k
635-
:sx #js {:flexDirection "column"
636-
:alignItems "flex-start"
637-
:maxWidth "350px"}}
638-
[:> Typography
639-
(get label locale)]
640-
[:> Typography
641-
{:sx #js {:fontSize "body2.fontSize"
642-
:whiteSpace "normal"}}
643-
(get description locale)]])]
644-
[:> TextField
645-
{:label (tr :map/itrs-exposure)
646-
:select true
647-
:fullWidth true
648-
:value (or exposure-value "")
649-
:onChange (fn [e]
650-
(rf/dispatch [::events/set-itrs-exposure lipas-id fid (.. e -target -value)]))}
651-
[:> MenuItem
652-
{:key "empty"
653-
:value ""}
654-
"-"]
655-
(for [[k {:keys [label description]}] activities-data/itrs-exposure-options]
656630
[:> MenuItem
657631
{:key k
658632
: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
@@ -7,6 +7,7 @@
77
[lipas.ui.components.buttons :as lui-btn]
88
[lipas.ui.components.forms :refer [->display-tf]]
99
[lipas.ui.components.text-fields :as lui-tf]
10+
[lipas.data.activities :as activities-data]
1011
[lipas.ui.config :as config]
1112
[lipas.ui.mui :as mui]
1213
[lipas.ui.sports-sites.activities.events :as events]
@@ -871,10 +872,11 @@
871872
#{:arrival :rules :rules-structured :permits-rules-guidelines :highlights})
872873

873874
(def ^:private itrs-field-ks
874-
#{:itrs-endurance :itrs-wilderness})
875+
#{:itrs-endurance :itrs-wilderness :itrs-technical-route})
875876

876877
(defn route-form
877-
[{:keys [tr locale lipas-id type-code route-props state read-only? edit-itrs? field-sorter]}]
878+
[{:keys [tr locale lipas-id type-code route-props state read-only? edit-itrs? field-sorter
879+
compute-itrs-technical]}]
878880
[nice-form {:read-only? read-only?}
879881
(doall
880882
(for [[prop-k {:keys [field show]}] (sort-by field-sorter utils/reverse-cmp route-props)
@@ -889,6 +891,10 @@
889891
field-read-only? (if itrs-field?
890892
(or read-only? (not edit-itrs?))
891893
read-only?)
894+
set-field (fn [& args]
895+
(let [path (butlast args)
896+
v (last args)]
897+
(swap! state assoc-in path v)))
892898
field-component [make-field
893899
{:read-only? field-read-only?
894900
:key prop-k
@@ -897,14 +903,27 @@
897903
:edit-data @state
898904
:display-data @state
899905
:locale locale
900-
:set-field (fn [& args]
901-
(let [path (butlast args)
902-
v (last args)]
903-
(swap! state assoc-in path v)))
906+
:set-field set-field
904907
:lipas-id lipas-id}]]
905-
(if itrs-locked?
908+
(cond
909+
itrs-locked?
906910
[mui/tooltip {:title (tr :lipas.sports-site/itrs-edit-requires-role)}
907911
[:span field-component]]
912+
913+
(and (= :itrs-technical-route prop-k) edit-itrs? (not read-only?) compute-itrs-technical)
914+
[mui/grid {:container true :alignItems "center" :spacing 1 :wrap "nowrap"}
915+
[mui/grid {:item true :xs true}
916+
field-component]
917+
[mui/grid {:item true}
918+
[mui/tooltip {:title (tr :map/compute-itrs-technical)}
919+
[mui/icon-button
920+
{:size "small"
921+
:on-click (fn []
922+
(when-let [v (compute-itrs-technical)]
923+
(set-field :itrs-technical-route v)))}
924+
[mui/icon "calculate"]]]]]
925+
926+
:else
908927
field-component)))))])
909928

910929
(defn single-route
@@ -920,7 +939,8 @@
920939
(set-field [new-state])))]
921940

922941
(let [tr (<== [:lipas.ui.subs/translator])
923-
field-sorter (<== [::subs/field-sorter activity-k])]
942+
field-sorter (<== [::subs/field-sorter activity-k])
943+
geoms (<== [::subs/geoms read-only?])]
924944

925945
[route-form
926946
{:locale locale
@@ -931,7 +951,15 @@
931951
:read-only? read-only?
932952
:edit-itrs? edit-itrs?
933953
:route-props route-props
934-
:state route-form-state}])
954+
:state route-form-state
955+
:compute-itrs-technical
956+
(fn []
957+
(let [fids (set (:fids @route-form-state))
958+
features (:features geoms)
959+
values (->> features
960+
(filter #(contains? fids (:id %)))
961+
(map #(get-in % [:properties :itrs-technical])))]
962+
(activities-data/itrs-technical-max values)))}])
935963

936964
(finally
937965
(remove-watch route-form-state :lol))))
@@ -948,6 +976,7 @@
948976
selected-route-id (<== [::subs/selected-route-id])
949977

950978
field-sorter (<== [::subs/field-sorter activity-k])
979+
geoms (<== [::subs/geoms read-only?])
951980

952981
editing? (not read-only?)]
953982

@@ -1012,7 +1041,15 @@
10121041
:read-only? read-only?
10131042
:edit-itrs? edit-itrs?
10141043
:route-props route-props
1015-
:state route-form-state}]
1044+
:state route-form-state
1045+
:compute-itrs-technical
1046+
(fn []
1047+
(let [route-fids (set (:fids @route-form-state))
1048+
features (:features geoms)
1049+
values (->> features
1050+
(filter #(contains? route-fids (:id %)))
1051+
(map #(get-in % [:properties :itrs-technical])))]
1052+
(activities-data/itrs-technical-max values)))}]
10161053

10171054
;; Buttons
10181055
[mui/grid {:container true :spacing 1}

0 commit comments

Comments
 (0)