specs:
aasm (5.5.0)
concurrent-ruby (~> 1.0)
- actioncable (7.2.2)
- actionpack (= 7.2.2)
- activesupport (= 7.2.2)
+ actioncable (7.2.2.1)
+ actionpack (= 7.2.2.1)
+ activesupport (= 7.2.2.1)
nio4r (~> 2.0)
websocket-driver (>= 0.6.1)
zeitwerk (~> 2.6)
- actionmailbox (7.2.2)
- actionpack (= 7.2.2)
- activejob (= 7.2.2)
- activerecord (= 7.2.2)
- activestorage (= 7.2.2)
- activesupport (= 7.2.2)
+ actionmailbox (7.2.2.1)
+ actionpack (= 7.2.2.1)
+ activejob (= 7.2.2.1)
+ activerecord (= 7.2.2.1)
+ activestorage (= 7.2.2.1)
+ activesupport (= 7.2.2.1)
mail (>= 2.8.0)
- actionmailer (7.2.2)
- actionpack (= 7.2.2)
- actionview (= 7.2.2)
- activejob (= 7.2.2)
- activesupport (= 7.2.2)
+ actionmailer (7.2.2.1)
+ actionpack (= 7.2.2.1)
+ actionview (= 7.2.2.1)
+ activejob (= 7.2.2.1)
+ activesupport (= 7.2.2.1)
mail (>= 2.8.0)
rails-dom-testing (~> 2.2)
- actionpack (7.2.2)
- actionview (= 7.2.2)
- activesupport (= 7.2.2)
+ actionpack (7.2.2.1)
+ actionview (= 7.2.2.1)
+ activesupport (= 7.2.2.1)
nokogiri (>= 1.8.5)
racc
rack (>= 2.2.4, < 3.2)
useragent (~> 0.16)
actionpack-page_caching (1.2.4)
actionpack (>= 4.0.0)
- actiontext (7.2.2)
- actionpack (= 7.2.2)
- activerecord (= 7.2.2)
- activestorage (= 7.2.2)
- activesupport (= 7.2.2)
+ actiontext (7.2.2.1)
+ actionpack (= 7.2.2.1)
+ activerecord (= 7.2.2.1)
+ activestorage (= 7.2.2.1)
+ activesupport (= 7.2.2.1)
globalid (>= 0.6.0)
nokogiri (>= 1.8.5)
- actionview (7.2.2)
- activesupport (= 7.2.2)
+ actionview (7.2.2.1)
+ activesupport (= 7.2.2.1)
builder (~> 3.1)
erubi (~> 1.11)
rails-dom-testing (~> 2.2)
rails-html-sanitizer (~> 1.6)
active_record_union (1.3.0)
activerecord (>= 4.0)
- activejob (7.2.2)
- activesupport (= 7.2.2)
+ activejob (7.2.2.1)
+ activesupport (= 7.2.2.1)
globalid (>= 0.3.6)
- activemodel (7.2.2)
- activesupport (= 7.2.2)
- activerecord (7.2.2)
- activemodel (= 7.2.2)
- activesupport (= 7.2.2)
+ activemodel (7.2.2.1)
+ activesupport (= 7.2.2.1)
+ activerecord (7.2.2.1)
+ activemodel (= 7.2.2.1)
+ activesupport (= 7.2.2.1)
timeout (>= 0.4.0)
- activerecord-import (1.8.1)
+ activerecord-import (2.0.0)
activerecord (>= 4.2)
- activestorage (7.2.2)
- actionpack (= 7.2.2)
- activejob (= 7.2.2)
- activerecord (= 7.2.2)
- activesupport (= 7.2.2)
+ activestorage (7.2.2.1)
+ actionpack (= 7.2.2.1)
+ activejob (= 7.2.2.1)
+ activerecord (= 7.2.2.1)
+ activesupport (= 7.2.2.1)
marcel (~> 1.0)
- activesupport (7.2.2)
+ activesupport (7.2.2.1)
base64
benchmark (>= 0.3)
bigdecimal
autoprefixer-rails (10.4.19.0)
execjs (~> 2)
aws-eventstream (1.3.0)
- aws-partitions (1.1016.0)
+ aws-partitions (1.1019.0)
aws-sdk-core (3.214.0)
aws-eventstream (~> 1, >= 1.3.0)
aws-partitions (~> 1, >= 1.992.0)
aws-sdk-kms (1.96.0)
aws-sdk-core (~> 3, >= 3.210.0)
aws-sigv4 (~> 1.5)
- aws-sdk-s3 (1.175.0)
+ aws-sdk-s3 (1.176.0)
aws-sdk-core (~> 3, >= 3.210.0)
aws-sdk-kms (~> 1)
aws-sigv4 (~> 1.5)
activerecord (>= 3.0, < 9.0)
delayed_job (>= 3.0, < 5)
docile (1.4.1)
- doorkeeper (5.8.0)
+ doorkeeper (5.8.1)
railties (>= 5)
doorkeeper-i18n (5.2.7)
doorkeeper (>= 5.2)
factory_bot_rails (6.4.4)
factory_bot (~> 6.5)
railties (>= 5.0.0)
- faraday (2.12.1)
+ faraday (2.12.2)
faraday-net_http (>= 2.0, < 3.5)
json
logger
mini_portile2 (2.8.8)
mini_racer (0.9.0)
libv8-node (~> 18.19.0.0)
- minitest (5.25.2)
+ minitest (5.25.4)
minitest-focus (1.4.0)
minitest (>= 4, < 6)
msgpack (1.7.5)
net-smtp (0.5.0)
net-protocol
nio4r (2.7.4)
- nokogiri (1.16.8)
+ nokogiri (1.17.1)
mini_portile2 (~> 2.8.2)
racc (~> 1.4)
oauth (1.1.0)
pg (1.5.9)
popper_js (2.11.8)
progress (3.6.0)
- pstore (0.1.3)
+ pstore (0.1.4)
psych (5.2.1)
date
stringio
rackup (1.0.1)
rack (< 3)
webrick
- rails (7.2.2)
- actioncable (= 7.2.2)
- actionmailbox (= 7.2.2)
- actionmailer (= 7.2.2)
- actionpack (= 7.2.2)
- actiontext (= 7.2.2)
- actionview (= 7.2.2)
- activejob (= 7.2.2)
- activemodel (= 7.2.2)
- activerecord (= 7.2.2)
- activestorage (= 7.2.2)
- activesupport (= 7.2.2)
+ rails (7.2.2.1)
+ actioncable (= 7.2.2.1)
+ actionmailbox (= 7.2.2.1)
+ actionmailer (= 7.2.2.1)
+ actionpack (= 7.2.2.1)
+ actiontext (= 7.2.2.1)
+ actionview (= 7.2.2.1)
+ activejob (= 7.2.2.1)
+ activemodel (= 7.2.2.1)
+ activerecord (= 7.2.2.1)
+ activestorage (= 7.2.2.1)
+ activesupport (= 7.2.2.1)
bundler (>= 1.15.0)
- railties (= 7.2.2)
+ railties (= 7.2.2.1)
rails-controller-testing (1.0.5)
actionpack (>= 5.0.1.rc1)
actionview (>= 5.0.1.rc1)
rails_param (1.3.1)
actionpack (>= 3.2.0)
activesupport (>= 3.2.0)
- railties (7.2.2)
- actionpack (= 7.2.2)
- activesupport (= 7.2.2)
+ railties (7.2.2.1)
+ actionpack (= 7.2.2.1)
+ activesupport (= 7.2.2.1)
irb (~> 1.13)
rackup (>= 1.0.0)
rake (>= 12.2)
concurrent-ruby (~> 1.0)
unicode-display_width (2.6.0)
uri (0.13.1)
- useragent (0.16.10)
+ useragent (0.16.11)
validates_email_format_of (1.8.2)
i18n (>= 0.8.0)
simpleidn
if (OSM.MATOMO) {
map.on("layeradd", function (e) {
if (e.layer.options) {
- var goal = OSM.MATOMO.goals[e.layer.options.keyid];
+ var goal = OSM.MATOMO.goals[e.layer.options.layerId];
if (goal) {
$("body").trigger("matomogoal", goal);
for (const [property, value] of Object.entries(layerDefinition)) {
if (property === "credit") {
layerOptions.attribution = makeAttribution(value);
- } else if (property === "keyId") {
- layerOptions.keyid = value;
} else if (property === "nameId") {
layerOptions.name = I18n.t(`javascripts.map.base.${value}`);
} else if (property === "apiKeyId") {
getMapBaseLayerId: function () {
var baseLayerId;
this.eachLayer(function (layer) {
- if (layer.options && layer.options.keyid) baseLayerId = layer.options.keyid;
+ if (layer.options && layer.options.layerId) baseLayerId = layer.options.layerId;
});
return baseLayerId;
},
+++ /dev/null
-$map-sidebar-icons: (
-
- /* Nodes (and ways as areas) */
-
- ".aeroway.aerodrome": ("filename": "aerodrome.p.16.png"),
-
- ".amenity.atm": ("filename": "amenity_atm.16.png", "invert": true),
- ".amenity.bank": ("filename": "amenity_bank.16.png", "invert": true),
- ".amenity.bar": ("filename": "amenity_bar.16.png", "invert": true),
- ".amenity.bench": ("filename": "amenity_bench.16.png", "invert": true),
- ".amenity.biergarten": ("filename": "amenity_biergarten.16.png", "invert": true),
- ".amenity.bicycle_parking": ("filename": "amenity_bicycle_parking.16.png"),
- ".amenity.bicycle_rental": ("filename": "transport_rental_bicycle.16.png"),
- ".amenity.bus_station": ("filename": "bus_station.n.16.png"),
- ".amenity.cafe": ("filename": "amenity_cafe.16.png", "invert": true),
- ".amenity.car_rental": ("filename": "transport_rental_car.16.png"),
- ".amenity.car_sharing": ("filename": "car_share.p.16.png"),
- ".amenity.childcare": ("filename": "amenity_childcare.p.16.png"),
- ".amenity.cinema": ("filename": "amenity_cinema.16.png", "invert": true),
- ".amenity.courthouse": ("filename": "amenity_courthouse.16.png", "invert": true),
- ".amenity.dentist": ("filename": "amenity_dentist.16.png"),
- ".amenity.doctors": ("filename": "amenity_doctors.16.png"),
- ".amenity.drinking_water": ("filename": "amenity_drinking_water.16.png", "invert": true),
- ".amenity.fast_food": ("filename": "amenity_fast_food.16.png", "invert": true),
- ".amenity.fire_station": ("filename": "amenity_fire_station.16.png", "invert": true),
- ".amenity.fuel": ("filename": "amenity_fuel.16.png"),
- ".amenity.hospital": ("filename": "amenity_hospital.16.png"),
- ".amenity.kindergarten": ("filename": "amenity_childcare.p.16.png"),
- ".amenity.library": ("filename": "library.p.16.png", "invert": true),
- ".amenity.nightclub": ("filename": "amenity_nightclub.16.png", "invert": true),
- ".amenity.parking": ("filename": "parking.p.16.png"),
- ".amenity.pharmacy": ("filename": "amenity_pharmacy.16.png"),
- ".amenity.place_of_worship": ("filename": "amenity_place_of_worship.16.png", "invert": true),
- ".amenity.police": ("filename": "amenity_police.16.png", "invert": true),
- ".amenity.post_box": ("filename": "post_box.p.16.png", "invert": true),
- ".amenity.post_office": ("filename": "post_office.p.16.png", "invert": true),
- ".amenity.prison": ("filename": "amenity_prison.16.png", "invert": true),
- ".amenity.pub": ("filename": "amenity_pub.16.png", "invert": true),
- ".amenity.restaurant": ("filename": "amenity_restaurant.16.png", "invert": true),
- ".amenity.recycling": ("filename": "amenity_recycling.16.png", "invert": true),
- ".amenity.school": ("filename": "education_school.p.16.png"),
- ".amenity.shelter": ("filename": "shelter2.p.16.png"),
- ".amenity.taxi": ("filename": "amenity_taxi.16.png"),
- ".amenity.telephone": ("filename": "telephone.p.16.png", "invert": true),
- ".amenity.theatre": ("filename": "amenity_theatre.16.png", "invert": true),
- ".amenity.toilets": ("filename": "amenity_toilets.16.png", "invert": true),
- ".amenity.townhall": ("filename": "amenity_townhall.16.png", "invert": true),
- ".amenity.university": ("filename": "education_university.p.16.png"),
- ".amenity.veterinary": ("filename": "health_veterinary.p.16.png"),
- ".amenity.waste_basket": ("filename": "amenity_waste_basket.16.png", "invert": true),
-
- ".barrier.gate": ("filename": "gate2.p.16.png", "invert": true),
-
- ".highway.bus_stop": ("filename": "highway_bus_stop.16.png"),
- ".highway.mini_roundabout": ("filename": "mini_round.p.16.png"),
- ".highway.traffic_signals": ("filename": "traffic_light.png", "invert": true),
- ".highway.turning_circle": ("filename": "turning_circle.p.16.png"),
-
- ".historic.archaeological_site": ("filename": "historic_archaeological_site.16.png", "invert": true),
- ".historic.castle": ("filename": "tourist_castle.p.16.png", "invert": true),
- ".historic.memorial": ("filename": "historic_memorial.16.png", "invert": true),
- ".historic.monument": ("filename": "historic_monument.16.png", "invert": true),
- ".historic.ruins": ("filename": "tourist_ruins.p.16.png", "invert": true),
- ".historic.wreck": ("filename": "tourist_wreck.p.16.png", "invert": true),
-
- ".man_made.lighthouse": ("filename": "man_made_lighthouse.16.png"),
- ".man_made.water_tower": ("filename": "man_made_water_tower.16.png", "invert": true),
- ".man_made.windmill": ("filename": "man_made_windmill.16.png", "invert": true),
-
- ".natural.tree": ("filename": "tree.p.16.png"),
-
- ".office.diplomatic": ("filename": "office_diplomatic.16.png"),
- ".office.estate_agent": ("filename": "shop_estateagent.16.png"),
-
- ".railway.halt": ("filename": "halt.p.16.png"),
- ".railway.station": ("filename": "station.p.16.png"),
- ".railway.level_crossing": ("filename": "level_crossing.p.16.png", "invert": true),
-
- ".shop": ("filename": "shop_convenience.p.16.png"),
- ".shop.alcohol": ("filename": "shop_alcohol.16.png"),
- ".shop.bakery": ("filename": "shop_bakery.16.png"),
- ".shop.bicycle": ("filename": "shop_bicycle.16.png"),
- ".shop.books": ("filename": "shop_books.16.png"),
- ".shop.butcher": ("filename": "shop_butcher.p.16.png"),
- ".shop.clothes": ("filename": "shop_clothes.16.png"),
- ".shop.car_parts": ("filename": "shop_car_parts.16.png"),
- ".shop.car_repair": ("filename": "shop_car_repair.16.png"),
- ".shop.convenience": ("filename": "shop_convenience.p.16.png"),
- ".shop.doityourself": ("filename": "shop_doityourself.16.png"),
- ".shop.electronics": ("filename": "shop_electronics.16.png"),
- ".shop.estate_agent": ("filename": "shop_estateagent.16.png"),
- ".shop.fashion": ("filename": "shop_clothes.16.png"),
- ".shop.florist": ("filename": "shop_florist.16.png"),
- ".shop.furniture": ("filename": "shop_furniture.16.png"),
- ".shop.garden_centre": ("filename": "shop_florist.16.png"),
- ".shop.gift": ("filename": "shop_gift.16.png"),
- ".shop.greengrocer": ("filename": "shop_greengrocer.p.16.png"),
- ".shop.hardware": ("filename": "shop_doityourself.16.png"),
- ".shop.hairdresser": ("filename": "shop_hairdresser.16.png"),
- ".shop.jewelry": ("filename": "shop_jewelry.16.png"),
- ".shop.mobile_phone": ("filename": "shop_mobile_phone.16.png"),
- ".shop.optician": ("filename": "shop_optician.16.png"),
- ".shop.pet": ("filename": "shop_pet.16.png"),
- ".shop.seafood": ("filename": "shop_seafood.16.png"),
- ".shop.shoes": ("filename": "shop_shoes.16.png"),
- ".shop.supermarket": ("filename": "shop_supermarket.p.16.png"),
-
- ".tourism.alpine_hut": ("filename": "tourism_alpine_hut.16.png"),
- ".tourism.camp_site": ("filename": "tourism_camp_site.16.png"),
- ".tourism.caravan_site": ("filename": "tourism_caravan_site.16.png"),
- ".tourism.hostel": ("filename": "tourism_hostel.16.png"),
- ".tourism.hotel": ("filename": "tourism_hotel.16.png"),
- ".tourism.motel": ("filename": "tourism_motel.16.png"),
- ".tourism.museum": ("filename": "tourism_museum.16.png", "invert": true),
- ".tourism.picnic_site": ("filename": "tourism_picnic_site.16.png", "invert": true),
- ".tourism.viewpoint": ("filename": "view_point.p.16.png", "invert": true),
- ".tourism.wilderness_hut": ("filename": "tourism_wilderness_hut.16.png"),
-
- /* Ways */
-
- ".aeroway.runway": ("filename": "runway.20.png"),
- ".aeroway.taxiway": ("filename": "taxiway.20.png"),
-
- ".barrier.wall": ("filename": "wall.20.png"),
-
- ".building": ("filename": "building.png"),
-
- ".highway.bridleway": ("filename": "bridleway.20.png"),
- ".highway.cycleway": ("filename": "cycleway.20.png"),
- ".highway.footway": ("filename": "footway.20.png"),
- ".highway.motorway": ("filename": "motorway.20.png"),
- ".highway.motorway_link": ("filename": "motorway.20.png"),
- ".highway.path": ("filename": "path.20.png"),
- ".highway.pedestrian": ("filename": "service.20.png"),
- ".highway.primary": ("filename": "primary.20.png"),
- ".highway.primary_link": ("filename": "primary.20.png"),
- ".highway.residential": ("filename": "unclassified.20.png"),
- ".highway.secondary": ("filename": "secondary.20.png"),
- ".highway.secondary_link": ("filename": "secondary.20.png"),
- ".highway.service": ("filename": "service.20.png"),
- ".highway.tertiary": ("filename": "tertiary.20.png"),
- ".highway.track": ("filename": "track.20.png"),
- ".highway.trunk": ("filename": "trunk.20.png"),
- ".highway.trunk_link": ("filename": "trunk.20.png"),
- ".highway.unclassified": ("filename": "unclassified.20.png"),
-
- ".landuse.brownfield": ("filename": "brownfield.png"),
- ".landuse.cemetery": ("filename": "cemetery.png"),
- ".landuse.commercial": ("filename": "commercial.png"),
- ".landuse.farmland": ("filename": "farmland.png"),
- ".landuse.farmyard": ("filename": "farmyard.png"),
- ".landuse.forest": ("filename": "forest.png"),
- ".landuse.grass": ("filename": "grass.png"),
- ".landuse.industrial": ("filename": "industrial.png"),
- ".landuse.meadow": ("filename": "meadow.png"),
- ".landuse.military": ("filename": "military.png"),
- ".landuse.residential": ("filename": "residential.png"),
- ".landuse.retail": ("filename": "retail.png"),
- ".landuse.tourism": ("filename": "tourism.png"),
-
- ".leisure.golf_course": ("filename": "golf.png"),
- ".leisure.park": ("filename": "park.png"),
- ".leisure.picnic_table": ("filename": "tourism_picnic_site.16.png", "invert": true),
- ".leisure.playground": ("filename": "leisure_playground.16.png", "invert": true),
- ".leisure.pitch": ("filename": "pitch.png"),
- ".leisure.nature_reserve": ("filename": "reserve.png"),
- ".leisure.water_park": ("filename": "leisure_water_park.16.png", "invert": true),
-
- ".natural.grassland": ("filename": "grassland.png"),
- ".natural.heath": ("filename": "heathland.png"),
- ".natural.scrub": ("filename": "scrub.png"),
- ".natural.water": ("filename": "lake.png"),
- ".natural.wood": ("filename": "wood.png"),
-
- ".railway.light_rail": ("filename": "light_rail.20.png"),
- ".railway.rail": ("filename": "rail.20.png"),
- ".railway.subway": ("filename": "subway.20.png"),
- ".railway.tram": ("filename": "tram.20.png"),
-
-)
@use "sass:map";
@import "parameters";
-@import "browse";
@import "bootstrap";
@import "rails_bootstrap_forms";
/* Rules for map sidebar icons */
-.browse-section {
- .node::before,
- .way::before,
- .relation::before {
- display: inline-block;
- width: 25px;
- margin-left: -25px;
- }
+.browse-section .browse-element-list {
+ line-height: 1.25rem;
- .node, .way, .relation {
- margin-left: 25px;
+ .browse-icon {
+ height: 1.25rem;
}
- .node::before { content: image-url('browse/node.svg'); }
- .way::before { content: image-url('browse/way.svg'); }
- .relation::before { content: image-url('browse/relation.svg'); }
-}
-
-@each $class, $item in $map-sidebar-icons {
- .browse-section #{$class}::before {
- content: image-url('browse/#{map.get($item, "filename")}');
+ .d-flex > .browse-icon {
+ height: max(20px, 1.25rem);
}
- @if map.get($item, "invert") {
- @include color-mode(dark) {
- .browse-section #{$class}::before {
- filter: invert(.8) hue-rotate(180deg);
- }
+ @include color-mode(dark) {
+ .browse-icon-invertible {
+ filter: invert(.8) hue-rotate(180deg);
}
}
}
module BrowseHelper
+ def element_icon(type, object)
+ selected_icon_data = { :filename => "#{type}.svg", :priority => 1 }
+
+ unless object.redacted?
+ target_tags = object.tags.find_all { |k, _v| BROWSE_ICONS.key? k }.sort
+ title = target_tags.map { |k, v| "#{k}=#{v}" }.to_sentence unless target_tags.empty?
+
+ target_tags.each do |k, v|
+ icon_data = BROWSE_ICONS[k][v] || BROWSE_ICONS[k][:*]
+ selected_icon_data = icon_data if icon_data && icon_data[:priority] > selected_icon_data[:priority]
+ end
+ end
+
+ image_tag "browse/#{selected_icon_data[:filename]}",
+ :size => 20,
+ :class => ["align-bottom object-fit-none browse-icon", { "browse-icon-invertible" => selected_icon_data[:invert] }],
+ :title => title
+ end
+
def element_single_current_link(type, object)
- link_to object, { :class => element_class(type, object), :title => element_title(object), :rel => (link_follow(object) if type == "node") } do
+ link_to object, { :rel => (link_follow(object) if type == "node") } do
element_strikethrough object do
printable_element_name object
end
end
end
- def element_list_item(type, object, &block)
- tag.li :class => element_class(type, object), :title => element_title(object) do
- element_strikethrough object, &block
+ def element_list_item(type, object, &)
+ tag.li(tag.div(element_icon(type, object) + tag.div(:class => "align-self-center", &), :class => "d-flex gap-1"))
+ end
+
+ def element_list_item_with_strikethrough(type, object, &)
+ element_list_item type, object do
+ element_strikethrough object, &
end
end
end
end
- def element_class(type, object)
- classes = [type]
- classes += icon_tags(object).flatten.map { |t| h(t) } unless object.redacted?
- classes.join(" ")
- end
-
- def element_title(object)
- if object.redacted?
- ""
- else
- h(icon_tags(object).map { |k, v| "#{k}=#{v}" }.to_sentence)
- end
- end
-
def link_follow(object)
"nofollow" if object.tags.empty?
end
private
- ICON_TAGS = %w[aeroway amenity barrier building highway historic landuse leisure man_made natural office railway shop tourism waterway].freeze
-
- def icon_tags(object)
- object.tags.find_all { |k, _v| ICON_TAGS.include? k }.sort
- end
-
def name_locales(object)
object.tags.keys.map { |k| Regexp.last_match(1) if k =~ /^name:(.*)$/ }.flatten
end
end
end
+ def block_short_status(block)
+ if block.active?
+ if block.needs_view?
+ if block.ends_at > Time.now.utc
+ t("user_blocks.helper.short.active_unread")
+ else
+ t("user_blocks.helper.short.expired_unread")
+ end
+ else
+ t("user_blocks.helper.short.active")
+ end
+ else
+ if block.revoker_id.nil?
+ if block.updated_at > block.ends_at
+ t("user_blocks.helper.short.read_html", :time => block_short_time_in_past(block.updated_at))
+ else
+ t("user_blocks.helper.short.ended")
+ end
+ else
+ t("user_blocks.helper.short.revoked_html", :name => link_to(block.revoker.display_name, block.revoker,
+ :class => "username d-inline-block text-truncate text-wrap align-bottom",
+ :dir => "auto"))
+ end
+ end
+ end
+
+ def block_short_time_in_future(time)
+ tag.time l(time.to_date),
+ :datetime => time.xmlschema,
+ :title => t("user_blocks.helper.short.time_in_future_title",
+ :time_absolute => l(time, :format => :friendly),
+ :time_relative => time_ago_in_words(time))
+ end
+
+ def block_short_time_in_past(time)
+ tag.time l(time.to_date),
+ :datetime => time.xmlschema,
+ :title => t("user_blocks.helper.short.time_in_past_title",
+ :time_absolute => l(time, :format => :friendly),
+ :time_relative => time_ago_in_words(time, :scope => :"datetime.distance_in_words_ago"))
+ end
+
def block_duration_in_words(duration)
# Ensure the requested duration isn't negative, even by a millisecond
duration = 0 if duration.negative?
-<li><%= linked_name = link_to printable_element_name(containing_relation.relation), containing_relation.relation, :class => "relation"
- if containing_relation.member_role.blank?
- linked_name
- else
- t ".entry_role_html", :relation_name => linked_name, :relation_role => containing_relation.member_role
- end %>
-</li>
+<%= element_list_item "relation", containing_relation.relation do %>
+ <%= linked_name = link_to printable_element_name(containing_relation.relation), containing_relation.relation
+ if containing_relation.member_role.blank?
+ linked_name
+ else
+ t ".entry_role_html", :relation_name => linked_name, :relation_role => containing_relation.member_role
+ end %>
+<% end %>
<% unless node.ways.empty? %>
<details <%= "open" if node.ways.count < 10 %>>
<summary><%= t "browse.part_of_ways", :count => node.ways.uniq.count %></summary>
- <ul class="list-unstyled">
+ <ul class="list-unstyled browse-element-list">
<% node.ways.uniq.each do |way| %>
- <li><%= element_single_current_link "way", way %></li>
+ <%= element_list_item "way", way do %>
+ <%= element_single_current_link "way", way %>
+ <% end %>
<% end %>
</ul>
</details>
<% unless node.containing_relation_members.empty? %>
<details <%= "open" if node.containing_relation_members.count < 10 %>>
<summary><%= t "browse.part_of_relations", :count => node.containing_relation_members.uniq.count %></summary>
- <ul class="list-unstyled">
+ <ul class="list-unstyled browse-element-list">
<%= render :partial => "browse/containing_relation", :collection => node.containing_relation_members.uniq %>
</ul>
</details>
<h4><%= t "browse.part_of" %></h4>
<details <%= "open" if relation.containing_relation_members.count < 10 %>>
<summary><%= t "browse.part_of_relations", :count => relation.containing_relation_members.uniq.count %></summary>
- <ul class="list-unstyled">
+ <ul class="list-unstyled browse-element-list">
<%= render :partial => "browse/containing_relation", :collection => relation.containing_relation_members.uniq %>
</ul>
</details>
<h4><%= t ".members" %></h4>
<details <%= "open" if relation.relation_members.count < 10 %>>
<summary><%= t ".members_count", :count => relation.relation_members.count %></summary>
- <ul class="list-unstyled">
+ <ul class="list-unstyled browse-element-list">
<%= render :partial => "browse/relation_member", :collection => relation.relation_members %>
</ul>
</details>
<% linked_name = link_to printable_element_name(relation_member.member), relation_member.member, { :rel => link_follow(relation_member.member) }
type_str = t ".type.#{relation_member.member_type.downcase}" %>
-<%= element_list_item relation_member.member_type.downcase, relation_member.member do %>
+<%= element_list_item_with_strikethrough relation_member.member_type.downcase, relation_member.member do %>
<%= if relation_member.member_role.blank?
t ".entry_html", :type => type_str, :name => linked_name
else
<h4><%= t "browse.part_of" %></h4>
<details <%= "open" if way.containing_relation_members.count < 10 %>>
<summary><%= t "browse.part_of_relations", :count => way.containing_relation_members.uniq.count %></summary>
- <ul class="list-unstyled">
+ <ul class="list-unstyled browse-element-list">
<%= render :partial => "browse/containing_relation", :collection => way.containing_relation_members.uniq %>
</ul>
</details>
<h4><%= t ".nodes" %></h4>
<details <%= "open" if way.way_nodes.count < 10 %>>
<summary><%= t ".nodes_count", :count => way.way_nodes.count %></summary>
- <ul class="list-unstyled">
+ <ul class="list-unstyled browse-element-list">
<% way.way_nodes.each do |wn| %>
- <li>
+ <%= element_list_item "node", wn.node do %>
<%= element_single_current_link "node", wn.node %>
<% related_ways = wn.node.ways.reject { |w| w.id == wn.way_id } %>
+ <% icon_connector = " " %>
<% if related_ways.size > 0 then %>
(<%= t ".also_part_of_html",
:count => related_ways.size,
- :related_ways => to_sentence(related_ways.map { |w| element_single_current_link "way", w }) %>)
+ :related_ways => to_sentence(related_ways.map { |w| element_icon("way", w) + icon_connector + element_single_current_link("way", w) }) %>)
<% end %>
- </li>
+ <% end %>
<% end %>
</ul>
</details>
<%= turbo_frame_tag "changeset_#{type.pluralize}" do %>
<%= render :partial => "paging_nav", :locals => { :type => type, :pages => pages } %>
- <ul class="list-unstyled" data-turbo="false">
+ <ul class="list-unstyled browse-element-list" data-turbo="false">
<% elements.each do |element| %>
- <%= element_list_item type, element do
- t "printable_name.current_and_old_links_html",
+ <%= element_list_item_with_strikethrough type, element do %>
+ <%= t "printable_name.current_and_old_links_html",
:current_link => link_to(printable_element_name(element), :controller => type.pluralize, :action => :show, :id => element.id[0]),
- :old_link => link_to(printable_element_version(element), :controller => "old_#{type.pluralize}", :action => :show, :id => element.id[0], :version => element.version)
- end %>
+ :old_link => link_to(printable_element_version(element), :controller => "old_#{type.pluralize}", :action => :show, :id => element.id[0], :version => element.version) %>
+ <% end %>
<% end %>
</ul>
<% end %>
<td><%= link_to block.creator.display_name, block.creator, :class => "username d-inline-block text-truncate text-wrap", :dir => "auto" %></td>
<% end %>
<td><%= h truncate(block.reason) %></td>
- <td><%= h block_status(block) %></td>
- <td>
- <% if block.revoker_id.nil? %>
- <%= t(".not_revoked") %>
- <% else %>
- <%= link_to block.revoker.display_name, block.revoker, :class => "username d-inline-block text-truncate text-wrap", :dir => "auto" %>
- <% end %>
- </td>
+ <td><%= block_short_time_in_past(block.created_at) %></td>
+ <% if block.ends_at > Time.now.utc %>
+ <td><%= block_short_time_in_future(block.ends_at) %></td>
+ <% else %>
+ <td><%= block_short_time_in_past(block.ends_at) %></td>
+ <% end %>
+ <td><%= h block_short_status(block) %></td>
<td><%= link_to t(".show"), block %></td>
<td><% if can?(:edit, block) %><%= link_to t(".edit"), edit_user_block_path(block) %><% end %></td>
</tr>
<th><%= t ".creator_name" %></th>
<% end %>
<th><%= t ".reason" %></th>
+ <th><%= t ".start" %></th>
+ <th><%= t ".end" %></th>
<th><%= t ".status" %></th>
- <th><%= t ".revoker_name" %></th>
<th></th>
<th></th>
</tr>
--- /dev/null
+aeroway:
+ aerodrome: { filename: "aerodrome.p.16.png" }
+
+ runway: { filename: "runway.20.png" }
+ taxiway: { filename: "taxiway.20.png" }
+
+amenity:
+ atm: { filename: "amenity_atm.16.png", invert: true }
+ bank: { filename: "amenity_bank.16.png", invert: true }
+ bar: { filename: "amenity_bar.16.png", invert: true }
+ bench: { filename: "amenity_bench.16.png", invert: true }
+ biergarten: { filename: "amenity_biergarten.16.png", invert: true }
+ bicycle_parking: { filename: "amenity_bicycle_parking.16.png" }
+ bicycle_rental: { filename: "transport_rental_bicycle.16.png" }
+ bus_station: { filename: "bus_station.n.16.png" }
+ cafe: { filename: "amenity_cafe.16.png", invert: true }
+ car_rental: { filename: "transport_rental_car.16.png" }
+ car_sharing: { filename: "car_share.p.16.png" }
+ childcare: { filename: "amenity_childcare.p.16.png" }
+ cinema: { filename: "amenity_cinema.16.png", invert: true }
+ courthouse: { filename: "amenity_courthouse.16.png", invert: true }
+ dentist: { filename: "amenity_dentist.16.png" }
+ doctors: { filename: "amenity_doctors.16.png" }
+ drinking_water: { filename: "amenity_drinking_water.16.png", invert: true }
+ fast_food: { filename: "amenity_fast_food.16.png", invert: true }
+ fire_station: { filename: "amenity_fire_station.16.png", invert: true }
+ fuel: { filename: "amenity_fuel.16.png" }
+ hospital: { filename: "amenity_hospital.16.png" }
+ kindergarten: { filename: "amenity_childcare.p.16.png" }
+ library: { filename: "library.p.16.png", invert: true }
+ nightclub: { filename: "amenity_nightclub.16.png", invert: true }
+ parking: { filename: "parking.p.16.png" }
+ pharmacy: { filename: "amenity_pharmacy.16.png" }
+ place_of_worship: { filename: "amenity_place_of_worship.16.png", invert: true }
+ police: { filename: "amenity_police.16.png", invert: true }
+ post_box: { filename: "post_box.p.16.png", invert: true }
+ post_office: { filename: "post_office.p.16.png", invert: true }
+ prison: { filename: "amenity_prison.16.png", invert: true }
+ pub: { filename: "amenity_pub.16.png", invert: true }
+ restaurant: { filename: "amenity_restaurant.16.png", invert: true }
+ recycling: { filename: "amenity_recycling.16.png", invert: true }
+ school: { filename: "education_school.p.16.png" }
+ shelter: { filename: "shelter2.p.16.png" }
+ taxi: { filename: "amenity_taxi.16.png" }
+ telephone: { filename: "telephone.p.16.png", invert: true }
+ theatre: { filename: "amenity_theatre.16.png", invert: true }
+ toilets: { filename: "amenity_toilets.16.png", invert: true }
+ townhall: { filename: "amenity_townhall.16.png", invert: true }
+ university: { filename: "education_university.p.16.png" }
+ veterinary: { filename: "health_veterinary.p.16.png" }
+ waste_basket: { filename: "amenity_waste_basket.16.png", invert: true }
+
+barrier:
+ gate: { filename: "gate2.p.16.png", invert: true }
+
+ wall: { filename: "wall.20.png" }
+
+building:
+ :*: { filename: "building.png" }
+
+highway:
+ bus_stop: { filename: "highway_bus_stop.16.png" }
+ mini_roundabout: { filename: "mini_round.p.16.png" }
+ traffic_signals: { filename: "traffic_light.png", invert: true }
+ turning_circle: { filename: "turning_circle.p.16.png" }
+
+ bridleway: { filename: "bridleway.20.png" }
+ cycleway: { filename: "cycleway.20.png" }
+ footway: { filename: "footway.20.png" }
+ motorway: { filename: "motorway.20.png" }
+ motorway_link: { filename: "motorway.20.png" }
+ path: { filename: "path.20.png" }
+ pedestrian: { filename: "service.20.png" }
+ primary: { filename: "primary.20.png" }
+ primary_link: { filename: "primary.20.png" }
+ residential: { filename: "unclassified.20.png" }
+ secondary: { filename: "secondary.20.png" }
+ secondary_link: { filename: "secondary.20.png" }
+ service: { filename: "service.20.png" }
+ tertiary: { filename: "tertiary.20.png" }
+ track: { filename: "track.20.png" }
+ trunk: { filename: "trunk.20.png" }
+ trunk_link: { filename: "trunk.20.png" }
+ unclassified: { filename: "unclassified.20.png" }
+
+historic:
+ archaeological_site: { filename: "historic_archaeological_site.16.png", invert: true }
+ castle: { filename: "tourist_castle.p.16.png", invert: true }
+ memorial: { filename: "historic_memorial.16.png", invert: true }
+ monument: { filename: "historic_monument.16.png", invert: true }
+ ruins: { filename: "tourist_ruins.p.16.png", invert: true }
+ wreck: { filename: "tourist_wreck.p.16.png", invert: true }
+
+landuse:
+ brownfield: { filename: "brownfield.png" }
+ cemetery: { filename: "cemetery.png" }
+ commercial: { filename: "commercial.png" }
+ farmland: { filename: "farmland.png" }
+ farmyard: { filename: "farmyard.png" }
+ forest: { filename: "forest.png" }
+ grass: { filename: "grass.png" }
+ industrial: { filename: "industrial.png" }
+ meadow: { filename: "meadow.png" }
+ military: { filename: "military.png" }
+ residential: { filename: "residential.png" }
+ retail: { filename: "retail.png" }
+ tourism: { filename: "tourism.png" }
+
+leisure:
+ golf_course: { filename: "golf.png" }
+ park: { filename: "park.png" }
+ picnic_table: { filename: "tourism_picnic_site.16.png", invert: true }
+ playground: { filename: "leisure_playground.16.png", invert: true }
+ pitch: { filename: "pitch.png" }
+ nature_reserve: { filename: "reserve.png" }
+ water_park: { filename: "leisure_water_park.16.png", invert: true }
+
+man_made:
+ lighthouse: { filename: "man_made_lighthouse.16.png" }
+ water_tower: { filename: "man_made_water_tower.16.png", invert: true }
+ windmill: { filename: "man_made_windmill.16.png", invert: true }
+
+natural:
+ tree: { filename: "tree.p.16.png" }
+
+ grassland: { filename: "grassland.png" }
+ heath: { filename: "heathland.png" }
+ scrub: { filename: "scrub.png" }
+ water: { filename: "lake.png" }
+ wood: { filename: "wood.png" }
+
+office:
+ diplomatic: { filename: "office_diplomatic.16.png" }
+ estate_agent: { filename: "shop_estateagent.16.png" }
+
+railway:
+ halt: { filename: "halt.p.16.png" }
+ station: { filename: "station.p.16.png" }
+ level_crossing: { filename: "level_crossing.p.16.png", invert: true }
+
+ light_rail: { filename: "light_rail.20.png" }
+ rail: { filename: "rail.20.png" }
+ subway: { filename: "subway.20.png" }
+ tram: { filename: "tram.20.png" }
+
+shop:
+ :*: { filename: "shop_convenience.p.16.png", priority: 20 }
+ alcohol: { filename: "shop_alcohol.16.png" }
+ bakery: { filename: "shop_bakery.16.png" }
+ bicycle: { filename: "shop_bicycle.16.png" }
+ books: { filename: "shop_books.16.png" }
+ butcher: { filename: "shop_butcher.p.16.png" }
+ clothes: { filename: "shop_clothes.16.png" }
+ car_parts: { filename: "shop_car_parts.16.png" }
+ car_repair: { filename: "shop_car_repair.16.png" }
+ convenience: { filename: "shop_convenience.p.16.png" }
+ doityourself: { filename: "shop_doityourself.16.png" }
+ electronics: { filename: "shop_electronics.16.png" }
+ estate_agent: { filename: "shop_estateagent.16.png" }
+ fashion: { filename: "shop_clothes.16.png" }
+ florist: { filename: "shop_florist.16.png" }
+ furniture: { filename: "shop_furniture.16.png" }
+ garden_centre: { filename: "shop_florist.16.png" }
+ gift: { filename: "shop_gift.16.png" }
+ greengrocer: { filename: "shop_greengrocer.p.16.png" }
+ hardware: { filename: "shop_doityourself.16.png" }
+ hairdresser: { filename: "shop_hairdresser.16.png" }
+ jewelry: { filename: "shop_jewelry.16.png" }
+ mobile_phone: { filename: "shop_mobile_phone.16.png" }
+ optician: { filename: "shop_optician.16.png" }
+ pet: { filename: "shop_pet.16.png" }
+ seafood: { filename: "shop_seafood.16.png" }
+ shoes: { filename: "shop_shoes.16.png" }
+ supermarket: { filename: "shop_supermarket.p.16.png" }
+
+tourism:
+ alpine_hut: { filename: "tourism_alpine_hut.16.png" }
+ camp_site: { filename: "tourism_camp_site.16.png" }
+ caravan_site: { filename: "tourism_caravan_site.16.png" }
+ hostel: { filename: "tourism_hostel.16.png" }
+ hotel: { filename: "tourism_hotel.16.png" }
+ motel: { filename: "tourism_motel.16.png" }
+ museum: { filename: "tourism_museum.16.png", invert: true }
+ picnic_site: { filename: "tourism_picnic_site.16.png", invert: true }
+ viewpoint: { filename: "view_point.p.16.png", invert: true }
+ wilderness_hut: { filename: "tourism_wilderness_hut.16.png" }
--- /dev/null
+begin
+ BROWSE_ICONS = YAML.load_file(Rails.root.join("config/browse_icons.yml")).transform_values do |tag_key_data|
+ transformed_tag_key_data = {}
+ tag_key_data.each do |tag_value, tag_value_data|
+ tag_value_data = tag_value_data.deep_symbolize_keys
+ tag_value_data[:priority] ||= tag_value == :* ? 10 : 100
+ transformed_tag_key_data[tag_value] = tag_value_data
+ end
+ transformed_tag_key_data
+ end
+rescue StandardError
+ BROWSE_ICONS = {}.freeze
+end
- leafletOsmId: "Mapnik"
code: "M"
- keyId: "mapnik"
+ layerId: "mapnik"
nameId: "standard"
credit:
id: "make_a_donation"
- leafletOsmId: "CyclOSM"
code: "Y"
- keyId: "cyclosm"
+ layerId: "cyclosm"
nameId: "cyclosm"
credit:
id: "cyclosm_credit"
- leafletOsmId: "CycleMap"
code: "C"
- keyId: "cyclemap"
+ layerId: "cyclemap"
nameId: "cycle_map"
apiKeyId: "THUNDERFOREST_KEY"
credit:
- leafletOsmId: "TransportMap"
code: "T"
- keyId: "transportmap"
+ layerId: "transportmap"
nameId: "transport_map"
apiKeyId: "THUNDERFOREST_KEY"
credit:
- leafletOsmId: "TracestrackTopo"
code: "P"
- keyId: "tracestracktopo"
+ layerId: "tracestracktopo"
nameId: "tracestracktop_topo"
apiKeyId: "TRACESTRACK_KEY"
credit:
- leafletOsmId: "HOT"
code: "H"
- keyId: "hot"
+ layerId: "hot"
nameId: "hot"
credit:
id: "hotosm_credit"
years:
one: "%{count} year"
other: "%{count} years"
+ short:
+ ended: "ended"
+ revoked_html: "revoked by %{name}"
+ active: "active"
+ active_unread: "active unread"
+ expired_unread: "expired unread"
+ read_html: "read at %{time}"
+ time_in_future_title: "%{time_absolute}; in %{time_relative}"
+ time_in_past_title: "%{time_absolute}; %{time_relative}"
blocks_on:
title: "Blocks on %{name}"
heading_html: "List of Blocks on %{name}"
reason: "Reason for block:"
revoker: "Revoker:"
block:
- not_revoked: "(not revoked)"
show: "Show"
edit: "Edit"
page:
display_name: "Blocked User"
creator_name: "Creator"
reason: "Reason for block"
+ start: "Start"
+ end: "End"
status: "Status"
- revoker_name: "Revoked by"
navigation:
all_blocks: "All Blocks"
blocks_on_me: "Blocks on Me"
assert_equal "<s>test</s>", deleted_output
end
- def test_element_class
+ def test_element_icon
node = create(:node, :with_history, :version => 2)
node_v1 = node.old_nodes.find_by(:version => 1)
node_v2 = node.old_nodes.find_by(:version => 2)
add_old_tags_selection(node_v2)
add_old_tags_selection(node_v1)
- assert_equal "node", element_class("node", create(:node))
- assert_equal "node", element_class("node", create(:node, :deleted))
-
- assert_equal "node building yes shop gift tourism museum", element_class("node", node)
- assert_equal "node building yes shop gift tourism museum", element_class("node", node_v2)
- assert_equal "node", element_class("node", node_v1)
- end
-
- def test_element_title
- node = create(:node, :with_history, :version => 2)
- node_v1 = node.old_nodes.find_by(:version => 1)
- node_v2 = node.old_nodes.find_by(:version => 2)
- node_v1.redact!(create(:redaction))
-
- add_tags_selection(node)
- add_old_tags_selection(node_v2)
- add_old_tags_selection(node_v1)
-
- assert_equal "", element_title(create(:node))
- assert_equal "", element_title(create(:node, :deleted))
-
- assert_equal "building=yes, shop=gift, and tourism=museum", element_title(node)
- assert_equal "building=yes, shop=gift, and tourism=museum", element_title(node_v2)
- assert_equal "", element_title(node_v1)
- end
-
- def test_icon_tags
- node = create(:node, :with_history, :version => 2)
- node_v1 = node.old_nodes.find_by(:version => 1)
- node_v2 = node.old_nodes.find_by(:version => 2)
- node_v1.redact!(create(:redaction))
+ icon = element_icon("node", create(:node))
+ icon_dom = Rails::Dom::Testing.html_document_fragment.parse(icon)
+ assert_dom icon_dom, "img:root", :count => 1 do
+ assert_dom "> @title", 0
+ end
- add_tags_selection(node)
+ icon = element_icon("node", create(:node, :deleted))
+ icon_dom = Rails::Dom::Testing.html_document_fragment.parse(icon)
+ assert_dom icon_dom, "img:root", :count => 1 do
+ assert_dom "> @title", 0
+ end
- tags = icon_tags(node)
- assert_equal 3, tags.count
- assert_includes tags, %w[building yes]
- assert_includes tags, %w[tourism museum]
- assert_includes tags, %w[shop gift]
+ icon = element_icon("node", node)
+ icon_dom = Rails::Dom::Testing.html_document_fragment.parse(icon)
+ assert_dom icon_dom, "img:root", :count => 1 do
+ assert_dom "> @title", "building=yes, shop=gift, and tourism=museum"
+ end
- add_old_tags_selection(node_v2)
- add_old_tags_selection(node_v1)
+ icon = element_icon("node", node_v2)
+ icon_dom = Rails::Dom::Testing.html_document_fragment.parse(icon)
+ assert_dom icon_dom, "img:root", :count => 1 do
+ assert_dom "> @title", "building=yes, shop=gift, and tourism=museum"
+ end
- tags = icon_tags(node_v2)
- assert_equal 3, tags.count
- assert_includes tags, %w[building yes]
- assert_includes tags, %w[tourism museum]
- assert_includes tags, %w[shop gift]
-
- tags = icon_tags(node_v1)
- assert_equal 3, tags.count
- assert_includes tags, %w[building yes]
- assert_includes tags, %w[tourism museum]
- assert_includes tags, %w[shop gift]
+ icon = element_icon("node", node_v1)
+ icon_dom = Rails::Dom::Testing.html_document_fragment.parse(icon)
+ assert_dom icon_dom, "img:root", :count => 1 do
+ assert_dom "> @title", 0
+ end
end
private