Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
100 commits
Select commit Hold shift + click to select a range
ecae93e
Initialer Zwischenstand zur Dockerisierung der Client Anwendung
nbennke May 27, 2025
0b60b2c
Use Default Actions
ro3t Jun 12, 2026
ed6699c
Image-Namen aus docker-compose service erzeugen
ro3t Jun 12, 2026
7113df8
Image-Namen vorgeben
ro3t Jun 12, 2026
1a30f75
Image-Namen aus docker-compose service erzeugen
ro3t Jun 12, 2026
dd744f6
latest-Tag beim docker-branch setzen
ro3t Jun 12, 2026
9238a13
latest-Tag beim docker-branch setzen
ro3t Jun 12, 2026
3c9af3c
latest-Tag beim docker-branch setzen
ro3t Jun 12, 2026
3c389d4
latest-Tag beim docker-branch setzen
ro3t Jun 12, 2026
4146010
reformat
ro3t Jun 12, 2026
72cb296
Service-Bezeichnung in docker-compose.yml vereinheitlicht
ro3t Jun 12, 2026
5aa1154
Resouces-Symlink erlauben
ro3t Jun 12, 2026
3a3fe1f
Ruby & Rails-Update
ro3t Jun 10, 2026
14fbd3c
Docker-Build-Branches erweitert
ro3t Jun 16, 2026
1573cd8
Ruby-Version
ro3t Jun 16, 2026
b77466c
Workflows nur ausführen wenn diese extra aufgerufen werden
ro3t Jun 16, 2026
81555dd
Fix: Stylesheet
ro3t Jun 16, 2026
4a97d4e
RefreshStaticJob ins Backoffice verschoben
ro3t Jun 19, 2026
65f74a9
nur `mri` Plattform unterstützt
nbennke Jun 22, 2026
5474f8e
Node Version aus Version File lesen
nbennke Jun 22, 2026
299cb9d
fix indent
nbennke Jun 22, 2026
b6187ef
fix codestyle nach auto correct
nbennke Jun 22, 2026
823c346
Introduce ApplicationResource base class and make ActiveResource mode…
nbennke Jun 22, 2026
0360c4c
nicht mehr notwendige Konfiguration entfernt
nbennke Jun 22, 2026
78946d0
test ohne Inhalt entfernt
nbennke Jun 24, 2026
43b21bc
Metrics/ClassLength für Tests deaktiviert
nbennke Jun 24, 2026
2b165ee
fix frozen string literal issue
nbennke Jun 24, 2026
1aa90b8
rubocop regeln angepasst
nbennke Jun 24, 2026
994652b
einfache Tests für Request Model Logiken ergänzt
nbennke Jun 24, 2026
fdb0b90
Structure Patch für ActiveResource CitySDK nach `/lib` verschoben und…
nbennke Jun 24, 2026
7ea8fb0
fix: rubocop issues
nbennke Jun 24, 2026
86b74ba
Builds mit zugehörigen Tags auf Master, PRs und Tags
nbennke Jun 25, 2026
62bcb0d
Merge branch 'docker' into updates
nbennke Jun 25, 2026
a224cd9
Neues Layout: Menüpunkte konfigurierbar
ro3t Jun 15, 2026
0bc5101
LAiV Anpassungen
ro3t Nov 19, 2025
60bd619
Layer Opacity
ro3t Jun 12, 2026
7bfd236
Zoom-Stufen
ro3t Jun 12, 2026
f61361a
Geocodr Konfiguration
ro3t Jun 12, 2026
53152d8
Fix: Synthax-Error
ro3t Jun 16, 2026
6bd4531
fix: uninitialized constant ActiveresourceCitysdkStructurePatch (Name…
nbennke Jun 25, 2026
6ff866b
Merge branch 'master' into updates
nbennke Jun 26, 2026
dfb614d
fix: Potential CSRF vulnerability due to forgery protection being dis…
nbennke Jun 26, 2026
e7277af
fix: Gems & Dependencies
nbennke Jun 26, 2026
3ef070f
fix: https://github.com/bfpi/klarschiff-client/security/code-scanning/6
nbennke Jun 26, 2026
0c5260b
bundle update --all
nbennke Jun 26, 2026
65d9859
drop custom CodeQL workflow while GitHub's default CodeQL setup is al…
nbennke Jun 26, 2026
7fc7123
fix: Docker build error:
nbennke Jun 26, 2026
309c461
fix syntax für BUNDLE_WITHOUT
nbennke Jun 26, 2026
7e6037c
Merge branch 'master' into updates
nbennke Jun 30, 2026
35c3aec
Apply suggestions from code review
nbennke Jun 30, 2026
22b9442
Merge branch 'updates' into laiv
nbennke Jun 30, 2026
9f6c169
Fix: wechsel zu Static Pages nach der Statistik-Seite
ro3t Jul 6, 2026
79e3749
ErbLint Issues
ro3t Jul 6, 2026
7c5f4b2
RuboCop Konfiguration
ro3t Jul 6, 2026
2eb11b8
RuboCop: Style/FrozenStringLiteralComment
ro3t Jul 6, 2026
ade7be4
RuboCop: Style/StringLiterals
ro3t Jul 6, 2026
6f02e47
RuboCop: Layout/EmptyLineAfterMagicComment
ro3t Jul 6, 2026
2ab2150
RuboCop: Style/StringConcatenation
ro3t Jul 6, 2026
d3ad5df
RuboCop: Layout/EmptyLineAfterGuardClause
ro3t Jul 6, 2026
f3be57c
RuboCop: Layout/EmptyLinesAroundClassBody
ro3t Jul 6, 2026
21f491d
RuboCop: Style/SpecialGlobalVars
ro3t Jul 6, 2026
0405f22
RuboCop: Layout/EmptyLinesAfterModuleInclusion
ro3t Jul 6, 2026
2ab9a69
RuboCop: Rails/ApplicationMailer
ro3t Jul 6, 2026
047a5ec
RuboCop: Style/InverseMethods
ro3t Jul 6, 2026
3111f17
RuboCop: Style/RedundantArgument
ro3t Jul 6, 2026
67e87ac
RuboCop: Layout/CommentIndentation
ro3t Jul 6, 2026
e31f2d8
RuboCop: Rails/Date
ro3t Jul 6, 2026
a29dfe6
RuboCop: Performance/StringIdentifierArgument
ro3t Jul 6, 2026
2265d49
RuboCop: Style/HashSyntax
ro3t Jul 6, 2026
9988687
RuboCop: Style/PercentLiteralDelimiters
ro3t Jul 6, 2026
1e3848f
RuboCop: Rails/Blank
ro3t Jul 6, 2026
2c51a73
RuboCop: Style/NumericPredicate
ro3t Jul 6, 2026
5c0b5b1
RuboCop: Style/SafeNavigation
ro3t Jul 6, 2026
a6c755f
RuboCop: Style/MapIntoArray
ro3t Jul 6, 2026
0a6cc13
RuboCop: Lint/AssignmentInCondition
ro3t Jul 6, 2026
f54428a
RuboCop: Lint/UselessOr
ro3t Jul 6, 2026
2d54cb1
RuboCop: Style/SymbolProc
ro3t Jul 6, 2026
4863898
RuboCop: Performance/Detect
ro3t Jul 6, 2026
666268e
RuboCop: Style/IfWithBooleanLiteralBranches
ro3t Jul 6, 2026
eb390ae
Merge branch 'master' into updates
ro3t Jul 6, 2026
102ed29
Pfad via `join`; false positive Brakeman issue ignoriert
nbennke Jul 6, 2026
4e34d32
use ignore file for brakeman
nbennke Jul 6, 2026
635fb42
Gems aktualisiert
ro3t Jul 6, 2026
25d87ec
Merge branch 'updates' into laiv
ro3t Jul 6, 2026
c8bd74d
Update docker-publish.yml
ro3t Jul 6, 2026
5067066
Anpassung Rubcop Konfiguration: keine Leerzeile nach GuardClause erzw…
nbennke Jul 7, 2026
c52c60a
Deaktivierung ParseError Prüfung für ERBLint zur Vermeidung von False…
nbennke Jul 7, 2026
6148c7c
fix Lint/RescueException: Avoid rescuing the `Exception` class. Perha…
nbennke Jul 7, 2026
8b16ceb
fix Lint/ReturnInVoidContext: Do not return a value in `initialize`.
nbennke Jul 7, 2026
6234720
fix: Layout/LineLength: Line is too long.
nbennke Jul 7, 2026
7b98750
Revert "RuboCop: Rails/ApplicationMailer"
ro3t Jul 7, 2026
b6cf4e6
Merge branch 'updates' into laiv
ro3t Jul 7, 2026
3177b23
Kamera bei Mobilgeräten anfordern
ro3t Jul 8, 2026
586c0b3
Fix RuboCop: Rails/ApplicationMailer
nbennke Jul 8, 2026
a40a6d8
Fix Layout/BlockAlignment & Indent
nbennke Jul 8, 2026
7add7fb
Merge branch 'updates' into laiv
ro3t Jul 8, 2026
a0433dc
Kamera bei Mobilgeräten Konfigurierbar
ro3t Jul 8, 2026
ed26429
fix some css StyleLint issues
nbennke Jul 8, 2026
fe1ab33
Bump required Node version to 24
nbennke Jul 8, 2026
38bdaa9
Merge branch 'master' into laiv
nbennke Jul 8, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/docker-publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ on:
push:
branches:
- master
- laiv
tags:
- 'v[0-9]+.[0-9]+.[0-9]+*'
pull_request:
Expand Down
2 changes: 1 addition & 1 deletion .nvmrc
Original file line number Diff line number Diff line change
@@ -1 +1 @@
18
24
21 changes: 14 additions & 7 deletions app/assets/javascripts/application.coffee.erb
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ $ ->
$(document).on 'click', '.sidebar-toggler', () ->
width = $('.sidebar').width()
zoom = $('.ol-zoom')
scale = $('.ol-scale-line')
scale = $('.ol-scale-line, .ol-scale-bar')
geoloc = $('.geolocation')
addr_search = $('.address-search-field')
$('.sidebar').toggle()
Expand Down Expand Up @@ -189,13 +189,14 @@ $ ->
else
error.push response.error
when 2
unless $('.radio-type').is(':checked')
error.push "<%= I18n.t('requests.desktop.new.error.required.type') %>"
if <%= Settings::Client.skip_type_selection %>
validate_categories(error)
else
unless $('.radio-type').is(':checked')
error.push "<%= I18n.t('requests.desktop.new.error.required.type') %>"
when 3
unless $('#request_service_code_1').val()
error.push "<%= I18n.t('requests.desktop.new.error.required.category') %>"
unless $('#request_description').val().trim() != ''
error.push "<%= I18n.t('requests.desktop.new.error.required.description') %>"
if !<%= Settings::Client.skip_type_selection %>
validate_categories(error)
else

if $(@).data('next') == 1
Expand All @@ -218,6 +219,12 @@ $ ->
KS.buildError(error)
false

validate_categories= (error) ->
unless $('#request_service_code_1').val()
error.push "<%= I18n.t('requests.desktop.new.error.required.category') %>"
unless $('#request_description').val().trim() != ''
error.push "<%= I18n.t('requests.desktop.new.error.required.description') %>"

$('.start-card').find('.btn-primary').toArray()[0].focus() if $('.start-card').is(':visible')

$(document).on 'click', '.update-position', () ->
Expand Down
183 changes: 173 additions & 10 deletions app/assets/javascripts/maps.coffee.erb
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ KS.projection = ->
else
console.log 'Proj4J ist nicht geladen!'

KS.maxZoom = <%= Settings::Map.zoom[:max] %>
KS.projectionWGS84 = ol.proj.get 'EPSG:4326'
#KS.zoomEvent = false
KS.requests_path = "<%= Settings::Route.requests_path %>/"
Expand Down Expand Up @@ -44,6 +43,17 @@ KS.GeolocationControl = () ->
ol.inherits(KS.GeolocationControl, ol.control.Control)

KS.ViewSwitcherControl = () ->
if <%= Settings::Map.overlap_layers %>
elem = KS.ViewSwitcherControlMultiple()
else
elem = KS.ViewSwitcherControlSingle()

new ol.control.Control
element: elem
target: {}.target
ol.inherits(KS.ViewSwitcherControl, ol.control.Control)

KS.ViewSwitcherControlSingle = () ->
span = document.createElement('span')
span.className = 'image'
image = document.createElement('img')
Expand All @@ -68,11 +78,119 @@ KS.ViewSwitcherControl = () ->
elem = document.createElement('div')
elem.className = 'view-switcher ol-control'
elem.appendChild(btn)
elem

new ol.control.Control
element: elem
target: {}.target
ol.inherits(KS.ViewSwitcherControl, ol.control.Control)
KS.ViewSwitcherControlMultiple = () ->
elem = document.createElement('div')
elem.className = 'view-switcher ol-control multiple'
text_span = document.createElement('span')
text_span.className = 'text'
text_span.innerHTML = "<%= I18n.t(:map_settings) %>"
elem.appendChild(text_span)

switchLayers = []
for layer in <%= Settings::Map.wmts_layers.to_json %>
switchLayers.push layer
for layer in <%= Settings::Map.wms_layers.to_json %>
switchLayers.push layer

switchLayers.sort (a, b) ->
a.switcher_sorting - b.switcher_sorting

expand = document.createElement('div')
expand.className = 'expand'
expand.setAttribute 'style', 'display: none'
for layer in switchLayers
if layer.addbefore
for additional in layer.addbefore
if additional == 'hr_spacer'
expand.appendChild document.createElement('hr')
else
additional_text = document.createElement('span')
additional_text.className = 'text'
additional_text.innerHTML = additional
expand.appendChild(additional_text)

child = KS.ViewSwitcherControlMultipleItem(layer)
expand.appendChild child if child

$(expand).on 'change', 'input[data-action=visibility]', (elem) ->
item = event.target
for l in KS.layers.layers
if l.get('id') == item.value
l.setVisible(item.checked)
if item.checked
$('#layer_opacity_' + item.value).show()
else
$('#layer_opacity_' + item.value).hide()

$(expand).on 'change', 'input[data-action=opacity]', (elem) ->
item = $(event.target)
for l in KS.layers.layers
if l.get('id') == item.data('layer')
l.setOpacity(parseFloat(item.val()))

elem.appendChild expand

toggler = document.createElement('div')
toggler.className = 'map-settings-toggler'
text_span = document.createElement('span')
toggler.appendChild(text_span)

toggleMapSettings = () ->
expand = $('.view-switcher .expand')
expand.toggle()
if expand.is(':visible')
expand.addClass('open')
else
expand.removeClass('open')
KS.positionViewSwitcher()

toggler.addEventListener('click', toggleMapSettings, false)
elem.appendChild toggler
elem

KS.ViewSwitcherControlMultipleItem = (layer) ->
div = document.createElement('div')
div.classList.add('form-check')
if layer.parent
div.classList.add('offset-1')
label = document.createElement('label')
label.classList.add('form-check-label')
label_for = ''

label_for = 'layer_overlap_' + layer.id
check = document.createElement('input')
check.setAttribute('type', 'checkbox')
check.setAttribute('name', label_for)
check.setAttribute('id', label_for)
check.setAttribute('value', layer.id)
check.classList.add('form-check-input')
check.setAttribute('checked', 'checked') if layer.visible
check.setAttribute('data-action', 'visibility')
div.appendChild(check)

label.setAttribute('for', label_for)
label.appendChild document.createTextNode(layer.label)
div.appendChild(label)

if layer.opacity_adjustable
range_for = 'layer_opacity_' + layer.id
opacity_range = document.createElement('input')
opacity_range.setAttribute('name', range_for)
opacity_range.setAttribute('id', range_for)
opacity_range.setAttribute('type', 'range')
opacity_range.setAttribute('min', 0)
opacity_range.setAttribute('max', 1)
opacity_range.setAttribute('value', 1)
opacity_range.setAttribute('step', 0.01)
opacity_range.setAttribute('data-layer', layer.id)
opacity_range.setAttribute('data-action', 'opacity')
unless layer.visible
opacity_range.setAttribute('style', 'display: none;')
div.appendChild(opacity_range)

div

class KS.Map
constructor: (@projection = KS.projection()) ->
Expand All @@ -86,13 +204,30 @@ class KS.Map
)
KS.popupCloser = document.getElementById('popup-closer')

mapView = new ol.View
options = {
projection: @projection
center: <%= Settings::Map.center %>
zoom: <%= Settings::Map.zoom[:initial] %>
maxZoom: KS.maxZoom
minZoom: <%= Settings::Map.zoom[:min] %>
enableRotation: false
}

minZoom = <%= Settings::Map.zoom[:min] if Settings::Map.zoom %>
maxZoom = <%= Settings::Map.zoom[:max] if Settings::Map.zoom %>
initialZoom = <%= Settings::Map.zoom[:initial] if Settings::Map.zoom %>

minResolution = <%= Settings::Map.resolution ? Settings::Map.resolution[:min] : false %>
maxResolution = <%= Settings::Map.resolution ? Settings::Map.resolution[:max] : false %>
initialResolution = <%= Settings::Map.resolution ? Settings::Map.resolution[:initial] : false %>

if minResolution && maxResolution && initialResolution
options['minResolution'] = minResolution
options['maxResolution'] = maxResolution
options['resolution'] = initialResolution
else
options['minZoom'] = minZoom if minZoom
options['maxZoom'] = maxZoom if maxZoom
options['zoom'] = initialZoom if initialZoom

mapView = new ol.View(options)

if region = KS.getUrlParam('region')
$.ajax(url: "#{KS.areas_path}&region=#{region}&search_class=authority", dataType: 'json').done (response) ->
Expand All @@ -112,7 +247,15 @@ class KS.Map
return @olMap

addControls = (map) ->
map.addControl new ol.control.ScaleLine
if <%= Settings::Map.scale_bar %>
scaleLineControl = new ol.control.ScaleLine(
bar: true
text: true
minWidth: 80
)
map.addControl scaleLineControl
else
map.addControl new ol.control.ScaleLine

map.on 'pointermove', (e) ->
pixel = map.getEventPixel(e.originalEvent)
Expand Down Expand Up @@ -349,10 +492,16 @@ class KS.Layers
constructor: (map, overlay = true) ->
@active = 0
@layers = []

for layer in <%= Settings::Map.wmts_layers.to_json %>
do (layer, @layers) ->
@layers.push new ol.layer.Tile
id: layer.id
type: layer.type
label: layer.label
sorting: layer.sorting
switcher_sorting: layer.switcher_sorting || layer.sorting
opacity_adjustable: layer.opacity_adjustable
extent: layer.extent
source: new ol.source.WMTS
url: layer.url
Expand All @@ -370,14 +519,23 @@ class KS.Layers
do (layer, @layers) ->
@layers.push new ol.layer.Image
id: layer.id
type: layer.type
label: layer.label
switcher_sorting: layer.switcher_sorting || layer.sorting
opacity_adjustable: layer.opacity_adjustable
sorting: layer.sorting
extent: layer.extent
source: new ol.source.ImageWMS
url: layer.url
params:
"LAYERS": layer.content
"FORMAT": layer.format
attributions: if layer.attribution? then layer.attribution else null
visible: layer.visible

@layers.sort (a, b) ->
a.get('sorting') - b.get('sorting')

@layers.push new ol.layer.Vector
id: "features"
source: new ol.source.Cluster
Expand Down Expand Up @@ -683,8 +841,13 @@ if id = KS.getUrlParam('request')
url += '&mobile=true'
$.ajax(url: url, dataType: 'script')

KS.positionViewSwitcher= () ->
if $('.view-switcher.multiple').size() > 0
$('.map-card').css('top', $('.view-switcher.multiple').height() + 60);

$ ->
KS.olMap = new KS.Map
KS.positionViewSwitcher()

$(document).on('click', 'a.describe', (event) ->
if (layer = KS.layers.findById('new_feature')) && (features = layer.getSource().getFeatures()).length > 0
Expand Down
35 changes: 34 additions & 1 deletion app/assets/stylesheets/application.sass
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
*= require_tree .
*= require_self
*/

@font-face
font-family: 'PT Sans'
src: url(asset-path('PTS55F_W.ttf'))
Expand Down Expand Up @@ -291,6 +291,39 @@ header
.sidebar-toggler.open span:before
content: '\F104'

.view-switcher .map-settings-toggler
background-color: #d9edf7
border-bottom: 1px solid #bce8f1
border-bottom-right-radius: 4px
border-right: 1px solid #bce8f1
border-top: 1px solid #bce8f1
border-top-right-radius: 4px
cursor: pointer
left: 25%
padding: 0 20px
position: absolute
text-align: center
top: 100%
width: 50%
z-index: 1010

.view-switcher .map-settings-toggler span:before
font-family: 'Font Awesome 5 Free'
font-weight: 900
content: "\F107"

.view-switcher
.expand.open + .map-settings-toggler span:before
content: "\F106"

.view-switcher span.text
display: block
font-weight: bold
text-align: center

.view-switcher .expand span.text
margin-bottom: 0.5em

.address-search-field
position: absolute
background-color: #337ab7
Expand Down
Loading