diff --git a/app/assets/javascripts/application.coffee.erb b/app/assets/javascripts/application.coffee.erb index 10e0bb33..ca169258 100644 --- a/app/assets/javascripts/application.coffee.erb +++ b/app/assets/javascripts/application.coffee.erb @@ -123,10 +123,17 @@ $ -> $(document).on 'turbolinks:load', () -> $('#textsizer a').textresizer({ target: '#main-content' }) - $(document).on 'click', '.check-all', () -> - checked = $(@).is(':checked') - $('.' + $(@).data('type')).each () -> - $(@).prop('checked', checked) + $(document).on 'click', 'body ul.nav a:not(.dropdown-toggle)', () -> + if $(this)[0].dataset and $(this)[0].dataset['bsToggle'] and $('.static-overlay').is(':visible') + $('.static-overlay').hide() + $('body ul.nav a').removeClass 'active' + $(this).addClass 'active' + $(this).parents('.dropdown').find('.dropdown-toggle').addClass 'active' + + $(document).on 'click', '.check-all', () -> + checked = $(@).is(':checked') + $('.' + $(@).data('type')).each () -> + $(@).prop('checked', checked) $(document).on 'click', '.sidebar-toggler', () -> width = $('.sidebar').width() diff --git a/app/assets/stylesheets/application.sass b/app/assets/stylesheets/application.sass index 25fe5c27..832fa0d8 100644 --- a/app/assets/stylesheets/application.sass +++ b/app/assets/stylesheets/application.sass @@ -206,6 +206,7 @@ header margin: 5px 0 #logo2 + height: 80px float: right margin: 5px 0 @@ -354,8 +355,13 @@ header .hidden-page display: none +.recent-request + background-color: #d9edf7 + border: 1px solid #bce8f1 + margin-bottom: 1.5em + .statistic-box - width: 90% + width: 100% text-align: center .statistic-box-figure @@ -468,5 +474,13 @@ body.mobile .statistic-overlay display: none +.nav.nav-pills + margin-top: -25px + +.nav-pills .nav-link + background-color: #669cca + color: #fff + margin-right: 0.5em + .dropdown-menu z-index: 1700 diff --git a/app/controllers/requests_controller.rb b/app/controllers/requests_controller.rb index 0f84bf3e..96f71918 100644 --- a/app/controllers/requests_controller.rb +++ b/app/controllers/requests_controller.rb @@ -40,12 +40,12 @@ def index @requests.sort_by!(&:requested_datetime).reverse! @pages = (@requests.count / @per_page.to_f).ceil path = Rails.root.join(Settings::Client.resources_overview_path) - FileUtils.rm_rf path FileUtils.mkdir_p path + FileUtils.rm_rf Dir.glob(path.join('*.html')) all_requests = @requests all_requests.each_slice(@per_page) do |requests| @requests = requests - File.write path.join("#{@page}.html"), render_to_string(layout: !Settings::Client.resources_overview_remote) + File.write path.join("#{@page}.html"), render_to_string(layout: false) @page += 1 end return head :ok diff --git a/app/controllers/starts_controller.rb b/app/controllers/starts_controller.rb index ea43bfd7..99861d73 100644 --- a/app/controllers/starts_controller.rb +++ b/app/controllers/starts_controller.rb @@ -3,9 +3,8 @@ class StartsController < ApplicationController def show @request_id = params[:request] - return redirect_to "#{Settings::Url.ks_server_url}#{map_path request: @request_id, mobile: true}" if login_required? - return redirect_to "#{Settings::Url.ks_server_url}#{map_path}" if Settings::Client.skip_extra_homepage && !@mobile - + return redirect_to map_url(request: @request_id, mobile: true) if login_required? + return redirect_to map_url unless @mobile recent_requests end diff --git a/app/controllers/statics_controller.rb b/app/controllers/statics_controller.rb index 0847c5d1..a04808ce 100644 --- a/app/controllers/statics_controller.rb +++ b/app/controllers/statics_controller.rb @@ -21,6 +21,7 @@ def privacy end def promotion + return head(:not_found) unless Settings::StaticPage.promotion @file_name = 'werbung' render :api end @@ -35,21 +36,19 @@ def requests end def contact + return head(:not_found) unless Settings::StaticPage.contact @file_name = 'contact' render :api end def news + return head(:not_found) unless Settings::StaticPage.news @file_name = 'news' render :api end - def finance - @file_name = 'finance' - render :api - end - def participation + return head(:not_found) unless Settings::StaticPage.participation @file_name = 'participation' render :api end diff --git a/app/views/application/_menue_bottom.html.erb b/app/views/application/_menue_bottom.html.erb index 4cec8a88..4d4e299c 100644 --- a/app/views/application/_menue_bottom.html.erb +++ b/app/views/application/_menue_bottom.html.erb @@ -1,7 +1,6 @@ <%= link_to t(:mobile), [:start, { mobile: true }], data: { turbolinks: false } %> | -<%= link_to t(:api), api_static_path %> | +<%= link_to t(:api), api_static_path, remote: true %> | <% if Settings::Url.ks_demo_url.present? -%> <%= link_to t(:demo), Settings::Url.ks_demo_url, data: { turbolinks: false }, target: '_blank', rel: 'noopener' %> | <% end -%> <%= link_to t(:github), Settings::Url.ks_github_url, data: { turbolinks: false }, target: '_blank', rel: 'noopener' %> | -<%= link_to t(:promotion), %i[promotion static] %> diff --git a/app/views/application/_menue_top_left.html.erb b/app/views/application/_menue_top_left.html.erb index 2bd956fe..e364bb9d 100644 --- a/app/views/application/_menue_top_left.html.erb +++ b/app/views/application/_menue_top_left.html.erb @@ -1,8 +1,44 @@ diff --git a/app/views/application/_menue_top_right.html.erb b/app/views/application/_menue_top_right.html.erb index b960e6bd..882d5ae5 100644 --- a/app/views/application/_menue_top_right.html.erb +++ b/app/views/application/_menue_top_right.html.erb @@ -1,10 +1,8 @@ -<%= link_to t(:list), %i[requests static] %> | -<%= link_to t(:statistic), [:statistics], data: { turbolinks: false } %> | -<%= link_to t(:help), help_static_path %> | +<%= link_to t(:help), help_static_path, remote: true %> | <% if Settings::Url.respond_to?(:external_privacy_url) -%> <%= link_to t(:privacy), Settings::Url.external_privacy_url, target: '_blank', rel: 'noopener' %> | <% else -%> - <%= link_to t(:privacy), privacy_static_path %> | + <%= link_to t(:privacy), privacy_static_path, remote: true %> | <% end -%> -<%= link_to t(:imprint), imprint_static_path %> | -<%= link_to t(:usage), usage_static_path %> +<%= link_to t(:imprint), imprint_static_path, remote: true %> | +<%= link_to t(:usage), usage_static_path, remote: true %> diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index 5a9fcaaa..a89da272 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -150,7 +150,7 @@ - <% unless !Settings::Client.additional_content %> + <% if Settings::Client.additional_content.present? %> <%= Settings::Client.additional_content.html_safe -%> <% end %> diff --git a/app/views/requests/index.html.erb b/app/views/requests/index.html.erb index 6a20453a..c4728d88 100644 --- a/app/views/requests/index.html.erb +++ b/app/views/requests/index.html.erb @@ -6,15 +6,13 @@ @@ -59,36 +54,36 @@ <%= t('.title') %> <% if @requests.present? -%> -
- <% @requests.each do |req| -%> - <%= link_to(url_for([:map, { request: req.id }]), class: 'list-group-item', data: { turbolinks: false }) do %> -

- <%= image_tag(image_path(req.icon_list), alt: "#{req.service.type}, #{req.extended_attributes.detailed_status}") %> - #<%= req.id %> <%= req.service.group %> – <%= req.service_name %> – <%= l(req.requested_datetime.to_date) %> - <%= mark_photo_required(req) %> - -

-

- <% if req.description.present? -%> - <%= Request.human_attribute_name(:description) %>
- <%= req.description %>
- <% end -%> +

+ <% @requests.each do |req| -%> + <%= link_to(url_for([:map, { request: req.id }]), class: 'list-group-item', data: { turbolinks: false }) do %> +

+ <%= image_tag(image_path(req.icon_list), alt: "#{req.service.type}, #{req.extended_attributes.detailed_status}") %> + #<%= req.id %> <%= req.service.group %> – <%= req.service_name %> – <%= l(req.requested_datetime.to_date) %> + <%= mark_photo_required(req) %> + +

+

+ <% if req.description.present? -%> + <%= Request.human_attribute_name(:description) %>
+ <%= req.description %>
+ <% end -%> - <%= Request.human_attribute_name(:status) %>
- <%= status(req) %>
+ <%= Request.human_attribute_name(:status) %>
+ <%= status(req) %>
- <% if (notes = req.status_notes).present? -%> - <%= Request.human_attribute_name(:status_notes) %>
- <%= notes.html_safe %>
- <% end -%> -

- <% end %> - <% end -%> -
+ <% if (notes = req.status_notes).present? -%> + <%= Request.human_attribute_name(:status_notes) %>
+ <%= notes.html_safe %>
+ <% end -%> +

+ <% end %> + <% end -%> +
<% else -%> -
- <%= t('.empty_result') %> -
+
+ <%= t('.empty_result') %> +
<% end -%> diff --git a/app/views/starts/_desktop.html.erb b/app/views/starts/_desktop.html.erb deleted file mode 100644 index 8b140cb5..00000000 --- a/app/views/starts/_desktop.html.erb +++ /dev/null @@ -1,31 +0,0 @@ -
-

<%= t('.headline', city_short: Settings::Client.city_short) %>

-
-
-
- <%= render(partial: 'recent_requests') %> -
-
- <% Dir.glob("#{Settings::Client.resources_path}/starts/*").each do |file| %> - <%= render(file: file).html_safe %> - <% end -%> -
-
-
<%= t('.statistics') %>
-
-
- <%= render(partial: 'shared/statistic', locals: { css_col: 'col-3' }) %> -
-
- <% if File.exist?(neuigkeiten = "#{ Settings::Client.resources_path }/neuigkeiten.html") -%> -
-
-
<%= t('.news') %>
-
-
    - <%= render(file: neuigkeiten).html_safe %> -
-
- <% end -%> -
-
diff --git a/app/views/starts/_mobile.html.erb b/app/views/starts/_mobile.html.erb index 19f5bfd4..44c5d5c3 100644 --- a/app/views/starts/_mobile.html.erb +++ b/app/views/starts/_mobile.html.erb @@ -11,6 +11,11 @@ <%= t('.hints') %> +
+
+ <%= link_to t('.button'), map_path(mobile: @mobile), class: 'btn btn-lg btn-primary', data: { turbolinks: false } %> +
+
@@ -18,8 +23,3 @@
-
-
- <%= link_to t('.button'), map_path(mobile: @mobile), class: 'btn btn-lg btn-primary', data: { turbolinks: false } %> -
-
diff --git a/config/brakeman.ignore b/config/brakeman.ignore index 0c8e8021..57ffdf8a 100644 --- a/config/brakeman.ignore +++ b/config/brakeman.ignore @@ -3,44 +3,78 @@ { "warning_type": "File Access", "warning_code": 16, - "fingerprint": "32ea586fcef640f60945ff20c084a412ed5fe5a7a03ca65a80bb6980c77284b5", + "fingerprint": "a6c1f01a977526e7686d7946cebad7c9bc67d975b1247133b0ddade447d078f0", "check_name": "FileAccess", "message": "Model attribute used in file name", - "file": "app/controllers/requests_controller.rb", - "line": 43, + "file": "config/initializers/i18n.rb", + "line": 4, "link": "https://brakemanscanner.org/docs/warning_types/file_access/", - "code": "FileUtils.rm_rf(Rails.root.join(Settings::Client.resources_overview_path))", + "code": "Dir[Rails.root.join(Settings::Client.resources_path, \"locales/*.yml\")]", "render_path": null, + "location": null, + "user_input": "Settings::Client.resources_path", + "confidence": "Weak", + "cwe_id": [ + 22 + ], + "note": "resources_path is read from config/settings.yml, no user defined content possible." + }, + { + "warning_type": "Cross-Site Scripting", + "warning_code": 2, + "fingerprint": "abf4a35cfbfdd26a1060a891953a7e3096d197bc748d50ccfde5e7baa1b988a7", + "check_name": "CrossSiteScripting", + "message": "Unescaped model attribute", + "file": "app/views/layouts/application.html.erb", + "line": 154, + "link": "https://brakemanscanner.org/docs/warning_types/cross_site_scripting", + "code": "Settings::Client.additional_content", + "render_path": [ + { + "type": "controller", + "class": "ApplicationController", + "method": "set_mobile", + "line": 17, + "file": "app/controllers/application_controller.rb", + "rendered": { + "name": "layouts/application", + "file": "app/views/layouts/application.html.erb" + } + } + ], "location": { - "type": "method", - "class": "RequestsController", - "method": "index" + "type": "template", + "template": "layouts/application" }, - "user_input": "Settings::Client.resources_overview_path", + "user_input": "Settings::Client.additional_content", "confidence": "Weak", "cwe_id": [ - 22 + 79 ], - "note": "resources_overview_path is read from config/settings.yml, no user defined content possible." + "note": "addittional_content is read from config/settings.yml, no user defined content possible." }, { "warning_type": "File Access", "warning_code": 16, - "fingerprint": "a6c1f01a977526e7686d7946cebad7c9bc67d975b1247133b0ddade447d078f0", + "fingerprint": "e18e6b5206f491ab6e54022a8c36e2cf4a35990e913ef43b10e5fdbdbf56c432", "check_name": "FileAccess", "message": "Model attribute used in file name", - "file": "config/initializers/i18n.rb", - "line": 4, + "file": "app/controllers/requests_controller.rb", + "line": 44, "link": "https://brakemanscanner.org/docs/warning_types/file_access/", - "code": "Dir[Rails.root.join(Settings::Client.resources_path, \"locales/*.yml\")]", + "code": "Dir.glob(Rails.root.join(Settings::Client.resources_overview_path).join(\"*.html\"))", "render_path": null, - "location": null, - "user_input": "Settings::Client.resources_path", + "location": { + "type": "method", + "class": "RequestsController", + "method": "index" + }, + "user_input": "Settings::Client.resources_overview_path", "confidence": "Weak", "cwe_id": [ 22 ], - "note": "resources_path is read from config/settings.yml, no user defined content possible." + "note": "resources_overview_path is read from config/settings.yml, no user defined content possible." }, { "warning_type": "File Access", @@ -49,7 +83,7 @@ "check_name": "FileAccess", "message": "Model attribute used in file name", "file": "app/controllers/requests_controller.rb", - "line": 44, + "line": 43, "link": "https://brakemanscanner.org/docs/warning_types/file_access/", "code": "FileUtils.mkdir_p(Rails.root.join(Settings::Client.resources_overview_path))", "render_path": null, diff --git a/config/locales/de.yml b/config/locales/de.yml index 45e0de26..4fd2899b 100644 --- a/config/locales/de.yml +++ b/config/locales/de.yml @@ -16,7 +16,7 @@ de: kod_protocol_from_user: 'KOD-Protokoll von %{user}' license: Lizenz list: Liste - locate: Ortung + locate: Orte mich mobile: mobil not_assignable: nicht zuordenbar page_meta_description: "Melden Sie Probleme in der Infrastruktur der %{city_long}, die dann von der Stadtverwaltung bearbeitet werden." @@ -30,6 +30,15 @@ de: statistic: Statistik usage: Nutzungsbedingungen username: Benutzername + request: Karte + watch: Beobachtung Meldungen + contact: Kontakt + info: Informationen + list: Alle Meldungen + news: Neuigkeiten + promotion: Werbematerialien + participation: Mitglied werden + recent_requests: Kürzlich gemeldet activemodel: attributes: @@ -89,7 +98,7 @@ de: continue: Weiter create: Erstellen describe: Beschreiben - new_request: Start! + new_request: Neue Meldung erstellen resume: Übernehmen perma_link: "Permalink auf Meldung #%{req_id}" ok: OK @@ -248,8 +257,8 @@ de: maps: desktop: - address_search: Adressensuche - search: Suche + address_search: Adresssuche + search: Adresssuche filter: nach Meldung filtern notes: @@ -333,6 +342,7 @@ de: error: Fehler bei neuer Meldung start_request: new_request: Bitte klicken Sie auf eine Meldung in der Karte oder erstellen Sie eine neue Meldung. + explanation_html: "" no_complex_requests: Keine komplexen städtebaulichen oder verkehrsplanerischen Sachverhalte! no_emergencies: Keine Notfälle! no_personal_requests: Keine persönlichen Anfragen (z. B. Adressänderungen oder Leistungsanträge)! diff --git a/config/settings.sample.yml b/config/settings.sample.yml index ca2caef6..7e79aa5d 100644 --- a/config/settings.sample.yml +++ b/config/settings.sample.yml @@ -16,14 +16,12 @@ development: &default key: hro login_required: false multi_requests_enabled: false - skip_extra_homepage: false name: Klarschiff city_long: Demostadt city_short: Demo resources_path: /srv/www/htdocs/klarschiff_resources/ resources_url: https://demo.klarschiff.de/resources/ resources_overview_path: /srv/www/htdocs/klarschiff_resources/requests/ - resources_overview_remote: false logo_url: /resources/images/logo.png observations_area_limit: 35 recent_requests: 6 @@ -50,6 +48,12 @@ development: &default max_image_size: 5242880 show_privacy_policy: false + static_pages: + contact: false + news: false + participation: false + promotion: false + vote: min_requirement: 20