├── .gitignore
├── INSTALL.txt
├── LICENSE.txt
├── README.md
├── Vagrantfile
├── __init__.py
├── city-streets.osm
├── config
├── init.body.json
├── init.config.json
├── init.location-import.list
├── init.region.json
├── stopwords_de.txt
├── stopwords_de_global.txt
├── stopwords_terms.txt
├── synonyms.txt
├── synonyms_global.txt
└── synonyms_terms.txt
├── config_dist.py
├── install-vagrant.sh
├── install.sh
├── manage.py
├── minify.sh
├── requirements.txt
├── runserver.py
├── scripts
├── __init__.py
├── depublish_attachment.py
├── elasticsearch_import.py
├── export_files.py
├── generate_data_dump.py
├── generate_fulltext.py
├── generate_georeferences.py
├── generate_thumbs.py
├── generate_xml_sitemaps.py
├── init_webapp.py
├── osm_import.py
├── osm_import_es.py
└── remove_thumbs.py
└── webapp
├── __init__.py
├── api.py
├── date_range.py
├── db.py
├── forms.py
├── oparl.py
├── static
├── css
│ ├── jquery-ui.min.css
│ ├── jquery-ui.structure.min.css
│ ├── jquery-ui.theme.min.css
│ ├── leaflet.css
│ ├── leaflet.min.css
│ ├── style.css
│ └── style.min.css
├── img
│ ├── awards
│ │ ├── deutschland-land-der-ideen-small.jpg
│ │ └── deutschland-land-der-ideen.jpg
│ ├── facebook-f.png
│ ├── footer
│ │ ├── facebook.png
│ │ ├── line.png
│ │ ├── mail.png
│ │ ├── okf-de-orig.png
│ │ ├── okf-de.png
│ │ ├── rss.png
│ │ └── twitter.png
│ ├── github-octocat.png
│ ├── gradient.png
│ ├── jquery-ui
│ │ ├── ui-bg_diagonals-thick_18_b81900_40x40.png
│ │ ├── ui-bg_diagonals-thick_20_666666_40x40.png
│ │ ├── ui-bg_flat_10_000000_40x100.png
│ │ ├── ui-bg_glass_100_f6f6f6_1x400.png
│ │ ├── ui-bg_glass_100_fdf5ce_1x400.png
│ │ ├── ui-bg_glass_65_ffffff_1x400.png
│ │ ├── ui-bg_gloss-wave_35_f6a828_500x100.png
│ │ ├── ui-bg_highlight-soft_100_eeeeee_1x100.png
│ │ ├── ui-bg_highlight-soft_75_ffe45c_1x100.png
│ │ ├── ui-icons_222222_256x240.png
│ │ ├── ui-icons_228ef1_256x240.png
│ │ ├── ui-icons_ef8c08_256x240.png
│ │ ├── ui-icons_ffd27a_256x240.png
│ │ └── ui-icons_ffffff_256x240.png
│ ├── leaflet
│ │ ├── layers-2x.png
│ │ ├── layers.png
│ │ ├── marker-icon-2x.png
│ │ ├── marker-icon.png
│ │ ├── marker-shadow.png
│ │ ├── zoom-in.png
│ │ └── zoom-out.png
│ ├── loader-35.gif
│ ├── loader-smooth-32.gif
│ ├── logo
│ │ ├── FaviconBase.png
│ │ ├── OffenesKoelnLogo.png
│ │ ├── OpenRuhrLogo.png
│ │ ├── PolitikBeiUns.png
│ │ ├── PolitikBeiUnsAlt.png
│ │ ├── favicon.ico
│ │ └── favicon_old.ico
│ ├── og.jpg
│ ├── og.psd
│ ├── sponsoring
│ │ ├── acme-inc.png
│ │ ├── anatom5.png
│ │ ├── linuxhotel.png
│ │ └── serverloft.png
│ ├── team
│ │ ├── du.jpg
│ │ ├── ernesto.jpg
│ │ └── marian.jpg
│ ├── twitter-bird.png
│ ├── ueber
│ │ ├── ueber-anlagenvorschau.jpg
│ │ ├── ueber-api.jpg
│ │ ├── ueber-daten.jpg
│ │ ├── ueber-indeinernaehe.jpg
│ │ ├── ueber-persistenteurls.jpg
│ │ └── ueber-suche.jpg
│ ├── widget-close.png
│ └── widget-close.psd
└── js
│ ├── ajaxq.js
│ ├── ajaxq.min.js
│ ├── file_details.js
│ ├── file_details.min.js
│ ├── jquery-ui.min.js
│ ├── leaflet.js
│ ├── map.js
│ ├── map.min.js
│ ├── paper_details.js
│ ├── paper_details.min.js
│ ├── pdfobject.js
│ ├── script.js
│ ├── script.min.js
│ ├── search.js
│ └── search.min.js
├── templates
├── admin.html
├── admin_bodies.html
├── admin_body_edit.html
├── admin_body_new.html
├── admin_config.html
├── admin_region_edit.html
├── admin_region_new.html
├── admin_regions.html
├── admin_response.html
├── api.html
├── daten.html
├── datenschutz.html
├── disclaimer.html
├── file_details.html
├── hilfe.html
├── impressum.html
├── index.html
├── layout.html
├── oparl.html
├── paper_details.html
├── robots.txt
├── suche.html
└── ueber.html
├── util.py
└── views.py
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | *.pyc
3 | config.py
4 | venv/
5 | temp/*
6 | .vagrant
7 | ._*
8 | *.komodoproject
9 | *.komodotools
10 | webapp/static/thumbs
11 | webapp/static/dateien/*
12 | webapp/static/daten/*
13 | webapp/static/sitemap/*
14 | scripts/osm-import/bin
15 | scripts/osm-import/lib
16 | scripts/osm-import/config
17 | scripts/osm-import/*.poly
18 | scripts/osm-import/*.osm
19 | scripts/osm-import/osmfilter
20 | scripts/osm-import/osmosis
21 |
22 |
--------------------------------------------------------------------------------
/INSTALL.txt:
--------------------------------------------------------------------------------
1 | # Java Current for Elasticsearch
2 | add-apt-repository ppa:webupd8team/java
3 | apt-get update
4 | apt-get install oracle-java8-installer
5 |
6 | # Elasticsearch
7 | wget -qO - https://packages.elasticsearch.org/GPG-KEY-elasticsearch | sudo apt-key add -
8 | echo 'deb http://packages.elasticsearch.org/elasticsearch/1.4/debian stable main' | sudo tee /etc/apt/sources.list.d/elasticsearch.list
9 | apt-get install elasticsearch
10 | sudo update-rc.d elasticsearch defaults 95 10
11 |
12 | # MongoDB
13 | sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 7F0CEB10
14 | echo 'deb http://downloads-distro.mongodb.org/repo/ubuntu-upstart dist 10gen' | sudo tee /etc/apt/sources.list.d/mongodb.list
15 | apt-get install mongodb-10gen
16 |
17 | # More Packages
18 | apt-get install git memcached python-virtualenv build-essential python-dev libxml2-dev libxslt1-dev ghostscript poppler-utils libpng12-dev libfreetype6-dev protobuf-compiler libprotobuf-dev
19 |
20 | # Users and dirs
21 | adduser --quiet ris
22 | mkdir /srv/www
23 | mkdir /srv/www/ris-scraper
24 | chown ris:ris -R /srv/www/ris-scraper/
25 | mkdir /srv/www/ris-web
26 | chown ris:ris -R /srv/www/ris-web/
27 |
28 | # Webinterface
29 | sudo -i -u ris
30 | cd /srv/www/ris-web/
31 | git clone https://github.com/okfde/ris-web.git
32 | cp config_dist.py config.py
33 | vim config.py # Set Values
34 |
35 | virtualenv --no-site-packages venv
36 | pip install -update setuptools pip
37 | # Bugfix for matplotlib
38 | sudo ln -s /usr/include/freetype2/ft2build.h /usr/include/
39 | pip install numpy
40 | pip install -r requirements.txt
41 |
42 | # Scraper
43 | sudo -i -u ris
44 | cd /srv/www/ris-web/
45 | git clone https://github.com/okfde/ris-scraper.git
--------------------------------------------------------------------------------
/LICENSE.txt:
--------------------------------------------------------------------------------
1 | Copyright (c) 2012 - 2015, Marian Steinbach, Ernesto Ruge
2 | All rights reserved.
3 |
4 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
5 |
6 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
7 |
8 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
9 |
10 | 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
11 |
12 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Offenes Ratsinformationssystem
2 |
3 | ## Über dieses Repository
4 |
5 | Dies ist das github-Repository für das [Offene Ratsinformationssystem](http://politik-bei-uns.de/).
6 |
7 | Hier gibt es:
8 |
9 | - Dokumentation (im [Wiki](https://github.com/okfde/ris-web/wiki))
10 | - Die API (auf der [Oparl Seite](http://oparl.org/))
11 | - [Issue-Tracking](https://github.com/okfde/ris-web/issues), also die Erfassung und Zuweisung von Fehlern
12 | - Die [Installationsanleitung](https://github.com/okfde/ris-web/blob/master/INSTALL.txt)
13 | - Quellcode
14 |
15 | Der Bereich **Quellcode** enthält folgende Dateien:
16 |
17 | - webapp: Die Web-Applikation
18 | - scripts: Unterstützende Werkzeuge und Helferlein
19 | - config: Startkonfiguration, Startdatenbank
20 |
21 | Der **Scraper**, mit dem die Daten aus dem Ratsinformationssystemen der Unternehmen SessionNet und AllRis ausgelesen werden, ist ein eigenes Projekt auf Github:
22 |
23 | [https://github.com/okfde/ris-scraper/](https://github.com/okfde/ris-scraper/)
24 |
25 | ###Installation mit Vagrant (z.B. für OSX, Windows)
26 |
27 | Mit den folgenden Schritten kannst du ris-web in einer virtuellen Maschine installieren.
28 |
29 | 0. ris-web und ris-scraper clonen und in das ris-web Verzeichnis wechseln
30 | ```
31 | $ git clone https://github.com/okfde/ris-scraper.git
32 | $ git clone https://github.com/okfde/ris-web.git
33 | $ cd ris-web
34 | ```
35 | 1. [VirtualBox](https://www.virtualbox.org/) installieren
36 | 2. [Vagrant](http://vagrantup.com/) installieren
37 | 3. Vagrant Box runterladen und provisionieren
38 |
39 | ```
40 | $ vagrant plugin install vagrant-vbguest
41 | $ vagrant up
42 | ```
43 | 4. ris-web starten:
44 |
45 | ```
46 | $ vagrant ssh
47 | $ venvs/ris-web/bin/python /vagrant/runserver.py
48 | ```
49 |
50 | Now you should see ris-web up and running at [http://localhost:23000](http://localhost:23000)
51 |
52 | ###Lizenz
53 |
54 | Der Code steht unter der [http://opensource.org/licenses/BSD-3-Clause](BSD 3-Clause License)
55 |
56 | ###Geschichte
57 |
58 | Dieses Projekt ist eine Weiterentwicklung des von Marian Steinbach gestarteten Projektes [Offenes Köln](https://github.com/marians/offeneskoeln/)
--------------------------------------------------------------------------------
/Vagrantfile:
--------------------------------------------------------------------------------
1 | # -*- mode: ruby -*-
2 | # vi: set ft=ruby :
3 |
4 | Vagrant.configure(2) do |config|
5 | config.vm.box = "notgary/ubuntu-14-04-base"
6 |
7 | # Create a forwarded port mapping which allows access to a specific port
8 | # within the machine from a port on the host machine. In the example below,
9 | # accessing "localhost:8080" will access port 80 on the guest machine.
10 | config.vm.network "forwarded_port", guest: 23000, host: 23000
11 |
12 | # Create a private network, which allows host-only access to the machine
13 | # using a specific IP.
14 | # config.vm.network "private_network", ip: "192.168.33.10"
15 |
16 | # Create a public network, which generally matched to bridged network.
17 | # Bridged networks make the machine appear as another physical device on
18 | # your network.
19 | # config.vm.network "public_network"
20 |
21 | # Share an additional folder to the guest VM. The first argument is
22 | # the path on the host to the actual folder. The second argument is
23 | # the path on the guest to mount the folder. And the optional third
24 | # argument is a set of non-required options.
25 | # config.vm.synced_folder "../data", "/vagrant_data"
26 | config.vm.synced_folder "../ris-scraper", "/ris-scraper"
27 |
28 | # Enable provisioning with a shell script. Additional provisioners such as
29 | # Puppet, Chef, Ansible, Salt, and Docker are also available. Please see the
30 | # documentation for more information about their specific syntax and use.
31 | # config.vm.provision "shell", inline: <<-SHELL
32 | # sudo apt-get update
33 | # sudo apt-get install -y apache2
34 | # SHELL
35 | config.vm.provision "shell", inline: <<-SHELL
36 | bash /vagrant/install-vagrant.sh
37 | SHELL
38 | end
39 |
--------------------------------------------------------------------------------
/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/politik-bei-uns/politik-bei-uns-web-old/730f137e23b2a9afd8fbe888b4d9037670361d44/__init__.py
--------------------------------------------------------------------------------
/city-streets.osm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/politik-bei-uns/politik-bei-uns-web-old/730f137e23b2a9afd8fbe888b4d9037670361d44/city-streets.osm
--------------------------------------------------------------------------------
/config/init.body.json:
--------------------------------------------------------------------------------
1 | {
2 | "config": {
3 | "county": "KREIS NAME",
4 | "scraper": {
5 | "base_url": "ORIGINAL RIS URL",
6 | "paper_type_strings": [],
7 | "party_alias": [
8 | [
9 | "FROM",
10 | "TO"
11 | ]
12 | ],
13 | "result_strings": [
14 | [
15 | "FROM",
16 | "TO"
17 | ]
18 | ],
19 | "type": "sessionnet-php"
20 | },
21 | "search_ignore_files": [
22 | "STRING"
23 | ]
24 | },
25 | "name": "CITY NAME",
26 | "rgs": "059110000000"
27 | }
--------------------------------------------------------------------------------
/config/init.config.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "api_url": "http://your-server",
4 | "base_url": "http://your-server",
5 | "es_paper_index": "paper",
6 | "file_extensions": [
7 | [
8 | "application/pdf",
9 | "pdf"
10 | ],
11 | [
12 | "image/tiff",
13 | "tif"
14 | ],
15 | [
16 | "image/jpeg",
17 | "jpg"
18 | ],
19 | [
20 | "application/vnd.ms-powerpoint",
21 | "pptx"
22 | ],
23 | [
24 | "application/msword",
25 | "doc"
26 | ],
27 | [
28 | "application/zip",
29 | "zip"
30 | ]
31 | ],
32 | "file_folder": "/srv/www/ris-web/webapp/static/files/",
33 | "gs_cmd": "/usr/bin/gs",
34 | "map_attribution": "Map Data © OpenStreetMap contributors, Tiles courtesy of MapQuest .",
35 | "map_tile_url_schema": "http://otile1.mqcdn.com/tiles/1.0.0/map/{z}/{x}/{y}.jpg",
36 | "map_zoomlevel_max": 18,
37 | "map_zoomlevel_min": "4",
38 | "pdf_to_text_cmd": "/usr/bin/pdftotext",
39 | "region_default": "5482ec449bcda40691218ef1",
40 | "scraper": {
41 | "log_base_dir": ".",
42 | "log_level": "DEBUG",
43 | "sessionnet-asp": {
44 | "urls": {
45 | "AGENDAITEM_DETAIL_PARSE_PATTERN": "to0050.asp?__ktonr={agendaitem_id:d}",
46 | "AGENDAITEM_DETAIL_PRINT_PATTERN": "%sto0050.asp?__ktonr=%d",
47 | "CALENDAR_MONTH_PARSE_PATTERN": "si0040.asp?__cjahr={year:d}&__cmonat={month:d}",
48 | "CALENDAR_MONTH_PRINT_PATTERN": "%ssi0040.asp?__cjahr=%d&__cmonat=%d",
49 | "FILE_DOWNLOAD_TARGET": [
50 | "ydocstart.asp",
51 | "getfile.asp"
52 | ],
53 | "MEETING_DETAIL_PARSE_PATTERN": "to0040.asp?__ksinr={meeting_id:d}",
54 | "MEETING_DETAIL_PRINT_PATTERN": "%sto0040.asp?__ksinr=%d",
55 | "ORGANIZATION_DETAIL_PARSE_PATTERN": "kp0040.asp?__kgrnr={committee_id:d}",
56 | "ORGANIZATION_DETAIL_PARSE_PATTERN_FULL": "kp0040.asp?__cwp=1&__kgrnr={committee_id:d}",
57 | "ORGANIZATION_DETAIL_PRINT_PATTERN": "%skp0040.asp?__kgrnr=%d",
58 | "ORGANIZATION_DETAIL_PRINT_PATTERN_FULL": "%skp0040.asp?__cwpall=1&__kgrnr=%d",
59 | "PAPER_DETAIL_PARSE_PATTERN": "vo0050.asp?__kvonr={paper_id:d}",
60 | "PAPER_DETAIL_PRINT_PATTERN": "%svo0050.asp?__kvonr=%d",
61 | "PERSON_DETAIL_PARSE_PATTERN": "kp0051.asp?__kpenr={person_id:d}",
62 | "PERSON_DETAIL_PARSE_PATTERN_ALT": "kp0050.asp?__kpenr={person_id:d}&grnr=0",
63 | "PERSON_DETAIL_PRINT_PATTERN": "%skp0051.asp?__kpenr=%d",
64 | "PERSON_DETAIL_PRINT_PATTERN_ALT": "%skp0050.asp?__kpenr=%d&grnr=0",
65 | "PERSON_ORGANIZATION_PARSE_PATTERN": "kp0050.asp?__cwpall=1&__kpenr={person_id:d}",
66 | "PERSON_ORGANIZATION_PRINT_PATTERN": "%skp0050.asp?__cwpall=1&__kpenr=%d",
67 | "PERSON_OVERVIEW_PARSE_PATTERN": "kp0041.asp?__cwpall=1",
68 | "PERSON_OVERVIEW_PRINT_PATTERN": "%skp0041.asp?__cwpall=1"
69 | },
70 | "xpath": {
71 | "MEETING_DETAIL_AGENDAITEM_ROWS": "//*[@class='smccontenttable smc_page_to0040_contenttable']/tbody/tr",
72 | "MEETING_DETAIL_AGENDAITEM_ROWS_PAPER_LINK": ".//a",
73 | "MEETING_DETAIL_FILES": "//*[@id='smccontent']//table",
74 | "MEETING_DETAIL_FILES_CONTAINER_CLASSNAME": "smcdocbox",
75 | "MEETING_DETAIL_IDENTIFIER_TD": "//*[@id=\"smctablevorgang\"]/tbody//td",
76 | "MEETING_DETAIL_ORGANIZATION_LINK": "//li[@class='smcmenucontext_fct_gremium']/a",
77 | "MEETING_DETAIL_TITLE": "//h1",
78 | "PAPER_DETAIL_AGENDA_ROWS": "//*[@class='smccontenttable smc_page_vo0050_contenttable']/tbody/tr",
79 | "PAPER_DETAIL_FILES": "//*[@id='smccontent']//table",
80 | "PAPER_DETAIL_FILES_CONTAINER_CLASSNAME": "smcdocbox",
81 | "PAPER_DETAIL_IDENTIFIER_TD": "//*[@id='smctablevorgang']/tbody//td",
82 | "PAPER_DETAIL_TITLE": "//h1",
83 | "PERSONLIST_LINES": "//table[@id='smc_page_kp0041_contenttable1']//tr",
84 | "PERSON_ORGANIZATION_LINES": "//table[@id='smc_page_kp0050_contenttable1']//tr"
85 | }
86 | },
87 | "sessionnet-php": {
88 | "urls": {
89 | "AGENDAITEM_DETAIL_PARSE_PATTERN": "to0050.php?__ktonr={agendaitem_id:d}",
90 | "AGENDAITEM_DETAIL_PRINT_PATTERN": "%sto0050.php?__ktonr=%d",
91 | "CALENDAR_MONTH_PARSE_PATTERN": "si0040.php?__cjahr={year:d}&__cmonat={month:d}",
92 | "CALENDAR_MONTH_PRINT_PATTERN": "%ssi0040.php?__cjahr=%d&__cmonat=%d",
93 | "FILE_DOWNLOAD_TARGET": [
94 | "ydocstart.php",
95 | "getfile.php"
96 | ],
97 | "MEETING_DETAIL_PARSE_PATTERN": "to0040.php?__ksinr={meeting_id:d}",
98 | "MEETING_DETAIL_PRINT_PATTERN": "%sto0040.php?__ksinr=%d",
99 | "ORGANIZATION_DETAIL_PARSE_PATTERN": "kp0040.php?__kgrnr={committee_id:d}",
100 | "ORGANIZATION_DETAIL_PARSE_PATTERN_FULL": "kp0040.php?__cwp=1&__kgrnr={committee_id:d}",
101 | "ORGANIZATION_DETAIL_PRINT_PATTERN": "%skp0040.php?__kgrnr=%d",
102 | "ORGANIZATION_DETAIL_PRINT_PATTERN_FULL": "%skp0040.php?__cwpall=1&__kgrnr=%d",
103 | "PAPER_DETAIL_PARSE_PATTERN": "vo0050.php?__kvonr={paper_id:d}",
104 | "PAPER_DETAIL_PRINT_PATTERN": "%svo0050.php?__kvonr=%d",
105 | "PERSON_DETAIL_PARSE_PATTERN": "kp0051.php?__kpenr={person_id:d}",
106 | "PERSON_DETAIL_PARSE_PATTERN_ALT": "kp0050.php?__kpenr={person_id:d}&grnr=0",
107 | "PERSON_DETAIL_PRINT_PATTERN": "%skp0051.php?__kpenr=%d",
108 | "PERSON_DETAIL_PRINT_PATTERN_ALT": "%skp0050.php?__kpenr=%d&grnr=0",
109 | "PERSON_ORGANIZATION_PARSE_PATTERN": "kp0050.php?__cwpall=1&__kpenr={person_id:d}",
110 | "PERSON_ORGANIZATION_PRINT_PATTERN": "%skp0050.php?__cwpall=1&__kpenr=%d",
111 | "PERSON_OVERVIEW_PARSE_PATTERN": "kp0041.php?__cwpall=1",
112 | "PERSON_OVERVIEW_PRINT_PATTERN": "%skp0041.php?__cwpall=1"
113 | },
114 | "xpath": {
115 | "MEETING_DETAIL_AGENDAITEM_ROWS": "//*[@class='smccontenttable smc_page_to0040_contenttable']/tbody/tr",
116 | "MEETING_DETAIL_AGENDAITEM_ROWS_PAPER_LINK": ".//a",
117 | "MEETING_DETAIL_FILES": "//*[@id='smccontent']//table",
118 | "MEETING_DETAIL_FILES_CONTAINER_CLASSNAME": "smcdocbox",
119 | "MEETING_DETAIL_IDENTIFIER_TD": "//*[@id=\"smctablevorgang\"]/tbody//td",
120 | "MEETING_DETAIL_ORGANIZATION_LINK": "//li[@class='smcmenucontext_fct_gremium']/a",
121 | "MEETING_DETAIL_TITLE": "//h1",
122 | "PAPER_DETAIL_AGENDA_ROWS": "//*[@class='smccontenttable smc_page_vo0050_contenttable']/tbody/tr",
123 | "PAPER_DETAIL_FILES": "//*[@id='smccontent']//table",
124 | "PAPER_DETAIL_FILES_CONTAINER_CLASSNAME": "smcdocbox",
125 | "PAPER_DETAIL_IDENTIFIER_TD": "//*[@id='smctablevorgang']/tbody//td",
126 | "PAPER_DETAIL_TITLE": "//h1",
127 | "PERSONLIST_LINES": "//table[@id='smc_page_kp0041_contenttable1']//tr",
128 | "PERSON_ORGANIZATION_LINES": "//table[@id='smc_page_kp0050_contenttable1']//tr"
129 | }
130 | },
131 | "user_agent_name": "OParl Scraper 0,1",
132 | "wait_time": 0.2
133 | },
134 | "sitemap_folder": "/srv/www/ris-web/webapp/static/sitemap",
135 | "stopwords_path": "/srv/www/ris-web/config/synonyms_global.txt",
136 | "synonyms_path": "/srv/www/ris-web/config/stopwords_de_global.txt",
137 | "thumbs_path": "/srv/www/ris-web/webapp/static/thumbs/",
138 | "thumbs_sizes": [
139 | 800,
140 | 300,
141 | 150
142 | ],
143 | "thumbs_suffix": "jpg",
144 | "thumbs_url": "/static/thumbs",
145 | "thumbs_valid_types": [
146 | "jpg",
147 | "pdf",
148 | "tif",
149 | "bmp",
150 | "png",
151 | "gif"
152 | ]
153 | }
154 | ]
155 |
--------------------------------------------------------------------------------
/config/init.location-import.list:
--------------------------------------------------------------------------------
1 | OSM Relations: http://wiki.openstreetmap.org/wiki/WikiProject_Germany/Grenzen/Nordrhein-Westfalen
2 |
3 | CITY=bochum CITYID=54626a479bcda406fb531236 REGBEZ=arnsberg-regbez FOLDER=nordrhein-westfalen OSM_RELATION=62644
4 | CITY=bottrop REGBEZ=muenster OSM_RELATION=62634
5 | CITY=duisburg REGBEZ=duesseldorf OSM_RELATION=62456
6 | CITY=koeln CITYID=549404fa9bcda405c6f78ecc REGBEZ=koeln-regbez FOLDER=nordrhein-westfalen OSM_RELATION=62578
7 | CITY=moers CITYID=547f8f369bcda406edffe62c REGBEZ=duesseldorf-regbez FOLDER=nordrhein-westfalen OSM_RELATION=58623
8 | CITY=schwelm REGBEZ=arnsberg OSM_RELATION=162833
9 | CITY=witten REGBEZ=arnsberg OSM_RELATION=162826
--------------------------------------------------------------------------------
/config/init.region.json:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/politik-bei-uns/politik-bei-uns-web-old/730f137e23b2a9afd8fbe888b4d9037670361d44/config/init.region.json
--------------------------------------------------------------------------------
/config/stopwords_de.txt:
--------------------------------------------------------------------------------
1 | als
2 | am
3 | an
4 | auch
5 | auf
6 | aus
7 | bei
8 | bereits
9 | bis
10 | bzw
11 | da
12 | damit
13 | das
14 | dass
15 | dem
16 | den
17 | der
18 | des
19 | die
20 | dies
21 | diese
22 | diesem
23 | dieser
24 | durch
25 | ein
26 | eine
27 | einem
28 | einen
29 | einer
30 | eines
31 | es
32 | für
33 | ggf
34 | hat
35 | hier
36 | im
37 | in
38 | ist
39 | ja
40 | kann
41 | keine
42 | mehr
43 | mit
44 | nach
45 | nein
46 | nicht
47 | noch
48 | nr
49 | nur
50 | oder
51 | sich
52 | sie
53 | siehe
54 | sind
55 | so
56 | sowie
57 | um
58 | und
59 | unter
60 | vom
61 | von
62 | vor
63 | weiter
64 | weitere
65 | werden
66 | wie
67 | wird
68 | zu
69 | zum
70 | zur
71 | über
72 | wurden
73 | wurde
74 |
75 |
--------------------------------------------------------------------------------
/config/stopwords_de_global.txt:
--------------------------------------------------------------------------------
1 | als
2 | am
3 | an
4 | auch
5 | auf
6 | aus
7 | bei
8 | bereits
9 | bis
10 | bzw
11 | da
12 | damit
13 | das
14 | dass
15 | dem
16 | den
17 | der
18 | des
19 | die
20 | dies
21 | diese
22 | diesem
23 | dieser
24 | durch
25 | ein
26 | eine
27 | einem
28 | einen
29 | einer
30 | eines
31 | es
32 | für
33 | ggf
34 | hat
35 | hier
36 | im
37 | in
38 | ist
39 | ja
40 | kann
41 | keine
42 | mehr
43 | mit
44 | nach
45 | nein
46 | nicht
47 | noch
48 | nr
49 | nur
50 | oder
51 | sich
52 | sie
53 | siehe
54 | sind
55 | so
56 | sowie
57 | um
58 | und
59 | unter
60 | vom
61 | von
62 | vor
63 | weiter
64 | weitere
65 | werden
66 | wie
67 | wird
68 | zu
69 | zum
70 | zur
71 | über
72 | wurden
73 | wurde
74 |
75 |
--------------------------------------------------------------------------------
/config/synonyms.txt:
--------------------------------------------------------------------------------
1 | # Allgemeine Synonyme für die Suche
2 | #
3 | # Alle Begriffe, die in einer Zeile angegeben werden, werden bei der einfachen
4 | # Suche nach Stichwörtern völlig identisch behandelt.
5 | #
6 | # Copyright (c) 2012 Marian Steinbach
7 | #
8 | # Hiermit wird unentgeltlich jeder Person, die eine Kopie der Software und
9 | # der zugehörigen Dokumentationen (die "Software") erhält, die Erlaubnis
10 | # erteilt, sie uneingeschränkt zu benutzen, inklusive und ohne Ausnahme, dem
11 | # Recht, sie zu verwenden, kopieren, ändern, fusionieren, verlegen,
12 | # verbreiten, unterlizenzieren und/oder zu verkaufen, und Personen, die diese
13 | # Software erhalten, diese Rechte zu geben, unter den folgenden Bedingungen:
14 | #
15 | # Der obige Urheberrechtsvermerk und dieser Erlaubnisvermerk sind in allen
16 | # Kopien oder Teilkopien der Software beizulegen.
17 | #
18 | # Die Software wird ohne jede ausdrückliche oder implizierte Garantie
19 | # bereitgestellt, einschließlich der Garantie zur Benutzung für den
20 | # vorgesehenen oder einen bestimmten Zweck sowie jeglicher Rechtsverletzung,
21 | # jedoch nicht darauf beschränkt. In keinem Fall sind die Autoren oder
22 | # Copyrightinhaber für jeglichen Schaden oder sonstige Ansprüche haftbar zu
23 | # machen, ob infolge der Erfüllung eines Vertrages, eines Delikts oder anders
24 | # im Zusammenhang mit der Software oder sonstiger Verwendung der Software
25 | # entstanden.
26 |
27 | # Köln-spezifische Synonyme
28 |
29 | militärring, militärringstraße
30 | domplatte, roncalliplatz
31 | kvb, Kölner Verkehrsbetriebe
32 | spielplatzpaten, spielplatzpatin, spielplatzpatinnen
33 | heliosgelände, helios-gelände
34 |
35 | # Allgemeine Synonyme
36 |
37 | str, straße, strasse
38 | go, gemeindeordnung
39 | bv, bezirksvertretung
40 | top, tagesordnungspunkt
41 | einschl, einschließlich
42 | inkl, inklusive
43 | lsa, lichtsignalanlage, ampel, lichtzeichenanlage, lichtsignalgeber
44 | fgü, fußgängerüberweg, zebrastreifen
45 | planung, planungen, pläne, plan
46 | fnp, flächennutzungsplan
47 | areal, gelände
48 | hpl, haushaltsplan
49 | heizpilz, heizstrahler
50 | sportvereine, sportverein, sportclub
51 | handy, mobiltelefon
52 | holland, niederlande
53 | üpl, überplanmäßig
54 |
--------------------------------------------------------------------------------
/config/synonyms_global.txt:
--------------------------------------------------------------------------------
1 | # Allgemeine Synonyme für die Suche
2 | #
3 | # Alle Begriffe, die in einer Zeile angegeben werden, werden bei der einfachen
4 | # Suche nach Stichwörtern völlig identisch behandelt.
5 | #
6 | # Copyright (c) 2012 Marian Steinbach
7 | #
8 | # Hiermit wird unentgeltlich jeder Person, die eine Kopie der Software und
9 | # der zugehörigen Dokumentationen (die "Software") erhält, die Erlaubnis
10 | # erteilt, sie uneingeschränkt zu benutzen, inklusive und ohne Ausnahme, dem
11 | # Recht, sie zu verwenden, kopieren, ändern, fusionieren, verlegen,
12 | # verbreiten, unterlizenzieren und/oder zu verkaufen, und Personen, die diese
13 | # Software erhalten, diese Rechte zu geben, unter den folgenden Bedingungen:
14 | #
15 | # Der obige Urheberrechtsvermerk und dieser Erlaubnisvermerk sind in allen
16 | # Kopien oder Teilkopien der Software beizulegen.
17 | #
18 | # Die Software wird ohne jede ausdrückliche oder implizierte Garantie
19 | # bereitgestellt, einschließlich der Garantie zur Benutzung für den
20 | # vorgesehenen oder einen bestimmten Zweck sowie jeglicher Rechtsverletzung,
21 | # jedoch nicht darauf beschränkt. In keinem Fall sind die Autoren oder
22 | # Copyrightinhaber für jeglichen Schaden oder sonstige Ansprüche haftbar zu
23 | # machen, ob infolge der Erfüllung eines Vertrages, eines Delikts oder anders
24 | # im Zusammenhang mit der Software oder sonstiger Verwendung der Software
25 | # entstanden.
26 |
27 | # Köln-spezifische Synonyme
28 |
29 | militärring, militärringstraße
30 | domplatte, roncalliplatz
31 | kvb, Kölner Verkehrsbetriebe
32 | spielplatzpaten, spielplatzpatin, spielplatzpatinnen
33 | heliosgelände, helios-gelände
34 |
35 | # Allgemeine Synonyme
36 |
37 | str, straße, strasse
38 | go, gemeindeordnung
39 | bv, bezirksvertretung
40 | top, tagesordnungspunkt
41 | einschl, einschließlich
42 | inkl, inklusive
43 | lsa, lichtsignalanlage, ampel, lichtzeichenanlage, lichtsignalgeber
44 | fgü, fußgängerüberweg, zebrastreifen
45 | planung, planungen, pläne, plan
46 | fnp, flächennutzungsplan
47 | areal, gelände
48 | hpl, haushaltsplan
49 | heizpilz, heizstrahler
50 | sportvereine, sportverein, sportclub
51 | handy, mobiltelefon
52 | holland, niederlande
53 | üpl, überplanmäßig
54 |
--------------------------------------------------------------------------------
/config/synonyms_terms.txt:
--------------------------------------------------------------------------------
1 | # Synonym-Datei für die Schlagworte
2 | #
3 | # Mit dieser Datei werden verschiedene Schreibweisen des selben Begriffs
4 | # normalisiert. Der Pfeil => zeigt auf die gültige Schreibweise.
5 | #
6 | # Details unter https://github.com/marians/offeneskoeln/wiki/Schlagworte/
7 | #
8 | bebauungsplanes => bebauungsplan
9 | beschlussvorschlages => beschlussvorschlag
10 | die grünen => grüne
11 | die linke => dielinke
12 | die linke.köln => dielinke
13 | eigentums => eigentum
14 | graffittifrei => graffitti
15 | graffittifreie => graffitti
16 | grundstück => grundstücke
17 | grünanlage => grünanlagen
18 | grünen => grüne
19 | grünfläche => grünflächen
20 | grünstreifens => grünstreifen
21 | kalker => kalk
22 | kindern => kinder
23 | kinderspielplätzen => spielplätze
24 | linke.köln => dielinke
25 | planungen => planung
26 | pro köln => proköln
27 | schule => schulen
28 | spielplatz => spielplätze
29 | stadtbezirkes => stadtbezirk
30 | stellen => stelle
31 | stellungnahmen
32 | str => straßen
33 | straße => straßen
34 | zuschusses => zuschuss
35 | zuschussfähige => zuschussfähig
36 | flächen => fläche
37 | unfall => unfälle
38 | informationsfreiheitsrechts => informationsfreiheitsrecht
39 | informations => information
40 | skateparks => skatepark
41 | jugendlichen => jugendliche
42 | plangebietes => plangebiet
43 | verfahrens => verfahren
44 | festsetzungen => festsetzung
45 | nutzungen => nutzung
46 | masterplans => masterplan
47 | masterplanes => masterplan
48 | hartz-iv => hartz4
49 | hartz iv => hartz4
50 | dienstleistung => dienstleistungen
--------------------------------------------------------------------------------
/config_dist.py:
--------------------------------------------------------------------------------
1 | # encoding: utf-8
2 |
3 | """
4 | Copyright (c) 2012 - 2015, Marian Steinbach, Ernesto Ruge
5 | All rights reserved.
6 |
7 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
8 |
9 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
10 |
11 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
12 |
13 | 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
14 |
15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
16 | """
17 |
18 | import locale
19 |
20 | LOCALE = 'de_DE.UTF8'
21 |
22 | BOOTSTRAP_SERVE_LOCAL = True
23 |
24 | MONGO_HOST = 'localhost'
25 | MONGO_PORT = 27017
26 | MONGO_USERNAME = ''
27 | MONGO_PASSWORD = ''
28 | MONGO_DBNAME = 'ris'
29 |
30 | ES_HOST = 'localhost'
31 | ES_PORT = 9200
32 |
33 | BASIC_AUTH_USERNAME = 'YOUR-USERNAME'
34 | BASIC_AUTH_PASSWORD = 'YOUR-PASSWORD'
35 | SECRET_KEY = 'RANDOM-STRING'
36 | BOOTSTRAP_SERVE_LOCAL = True
37 |
38 | BASE_DIR = '/srv/www/ris-web'
39 |
40 | stopwords_path = "/srv/www/ris-web/config/synonyms_global.txt"
41 | synonyms_path = "/srv/www/ris-web/config/stopwords_de_global.txt"
42 | thumbs_path = "/srv/www/ris-web/webapp/static/thumbs/"
--------------------------------------------------------------------------------
/install-vagrant.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # Java Current for Elasticsearch
4 | sudo apt-get update
5 | sudo apt-get install python-software-properties software-properties-common
6 | sudo add-apt-repository ppa:webupd8team/java
7 | sudo apt-get update
8 | sudo apt-get install -y oracle-java8-installer
9 |
10 | # Elasticsearch
11 | wget -qO - https://packages.elasticsearch.org/GPG-KEY-elasticsearch | sudo apt-key add -
12 | echo 'deb http://packages.elasticsearch.org/elasticsearch/1.4/debian stable main' | sudo tee /etc/apt/sources.list.d/elasticsearch.list
13 | sudo apt-get update
14 | sudo apt-get install -y elasticsearch
15 | sudo update-rc.d elasticsearch defaults 95 10
16 |
17 | # MongoDB
18 | sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 7F0CEB10
19 | echo 'deb http://downloads-distro.mongodb.org/repo/ubuntu-upstart dist 10gen' | sudo tee /etc/apt/sources.list.d/mongodb.list
20 | sudo apt-get update
21 | sudo apt-get install -y mongodb-10gen
22 |
23 | # More Packages
24 | sudo apt-get install -y git memcached python-virtualenv build-essential python-dev libxml2-dev libxslt1-dev ghostscript poppler-utils libpng12-dev libfreetype6-dev protobuf-compiler libprotobuf-dev libjpeg-dev
25 |
26 | mkdir venvs
27 |
28 | # Einrichtung des Webinterfaces
29 | virtualenv venvs/ris-web
30 | venvs/ris-web/bin/pip install --upgrade setuptools pip
31 | venvs/ris-web/bin/pip install numpy
32 | venvs/ris-web/bin/pip install -r /vagrant/requirements.txt
33 |
34 | #echo "Erstelle Konfiguration"
35 | #cp config_dist.py config.py
36 | #replace="BASIC_AUTH_USERNAME = '$username'"#sed -i "46s/.*/$replace/" config.py
37 | #replace="BASIC_AUTH_PASSWORD = '$password'"
38 | #sed -i "47s/.*/$replace/" config.py
39 | #secret_key=$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 32 | head -n 1)
40 | #replace="SECRET_KEY = '$secret_key'"
41 | #sed -i "48s/.*/$replace/" config.py
42 |
43 | # Einichtung des Scrapers
44 | virtualenv venvs/ris-scraper
45 | venvs/ris-scraper/bin/pip install --upgrade setuptools pip
46 | venvs/ris-scraper/bin/pip install -r /ris-scraper/requirements.txt
47 |
48 | # Importiere Konfiguration
49 | mongoimport --db ris --collection config --type json --jsonArray --file /vagrant/config/init.config.json
50 |
--------------------------------------------------------------------------------
/install.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | #echo "In welchen existierenden Ordner sollen Weboberfläche und Scraper installiert werden? (z.B. /srv/www)"
4 |
5 | #read basepath
6 |
7 | #if [ ! -d $basepath ]
8 | # then
9 | # echo "Dieser Ordner existiert nich."
10 | # exit 0
11 | #fi
12 |
13 | mkdir /srv/www
14 | basepath="/srv/www"
15 |
16 | #echo "Unter welchem Host kann die Weboberfläche später abgerufen werden? Für Testumgebungen: Port 23000 nicht vergessen. (z.B. localhost:23000)"
17 | #read basehost
18 |
19 | #echo "Welcher Admin-Nutzername soll genutzt werden?"
20 | #read username
21 |
22 | #echo "Welches Admin-Passwort soll genutzt werden?"
23 | #read password
24 |
25 | # Java Current for Elasticsearch
26 | echo "Installiere Oracle Java 8 für ElasticSearch"
27 | apt-get update
28 | apt-get install software-properties-common
29 | add-apt-repository ppa:webupd8team/java
30 | apt-get update
31 | apt-get install -y oracle-java8-installer
32 |
33 | # Elasticsearch
34 | echo "Installiere ElasticSearch"
35 | wget -qO - https://packages.elasticsearch.org/GPG-KEY-elasticsearch | sudo apt-key add -
36 | echo 'deb http://packages.elasticsearch.org/elasticsearch/1.4/debian stable main' | sudo tee /etc/apt/sources.list.d/elasticsearch.list
37 | apt-get update
38 | apt-get install -y elasticsearch
39 | update-rc.d elasticsearch defaults 95 10
40 |
41 | # MongoDB
42 | echo "Installiere MongoDB"
43 | sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 7F0CEB10
44 | echo 'deb http://downloads-distro.mongodb.org/repo/ubuntu-upstart dist 10gen' | sudo tee /etc/apt/sources.list.d/mongodb.list
45 | apt-get update
46 | apt-get install -y mongodb-10gen
47 |
48 | # More Packages
49 | echo "Installiere weitere Pakete"
50 | apt-get install -y git memcached python-virtualenv build-essential python-dev libxml2-dev libxslt1-dev ghostscript poppler-utils libpng12-dev libfreetype6-dev protobuf-compiler libprotobuf-dev libjpeg-dev
51 | echo "Füge Systemnutzer hinzu und erstelle Pfade"
52 |
53 | mkdir $basepath/ris-scraper
54 | chown ris:ris -R $basepath/ris-scraper/
55 | mkdir $basepath/ris-web
56 | chown ris:ris -R $basepath/ris-web/
57 |
58 | # Einrichtung des Webinterfaces
59 | sudo -u ris bash << EOF
60 | export HOME=/home/ris
61 | cd $basepath/ris-web
62 | echo "Downloade Webinterface"
63 | git clone https://github.com/okfde/ris-web.git .
64 | echo "Erstelle Virtual Enviroment für Webinterface"
65 | virtualenv venv
66 | echo "Installiere benötigte Pakete in Virtual Enviroment"
67 | $basepath/ris-web/venv/bin/pip install --upgrade setuptools pip
68 | $basepath/ris-web/venv/bin/pip install numpy
69 | $basepath/ris-web/venv/bin/pip install -r requirements.txt
70 | EOF
71 | #echo "Erstelle Konfiguration"
72 | #cp config_dist.py config.py
73 | #replace="BASIC_AUTH_USERNAME = '$username'"
74 | #sed -i "46s/.*/$replace/" config.py
75 | #replace="BASIC_AUTH_PASSWORD = '$password'"
76 | #sed -i "47s/.*/$replace/" config.py
77 | #secret_key=$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 32 | head -n 1)
78 | #replace="SECRET_KEY = '$secret_key'"
79 | #sed -i "48s/.*/$replace/" config.py
80 |
81 |
82 | # Einichtung des Scrapers
83 | sudo -u ris bash << EOF
84 | export HOME=/home/ris
85 | cd $basepath/ris-scraper
86 | echo "Downloade Scraper"
87 | git clone https://github.com/okfde/ris-scraper.git .
88 | echo "Erstelle Virtual Enviroment für Scraper"
89 | virtualenv venv
90 | echo "Installiere benötigte Pakete in Virtual Enviroment"
91 | $basepath/ris-scraper/venv/bin/pip install --upgrade setuptools pip
92 | $basepath/ris-scraper/venv/bin/pip install -r requirements.txt
93 | EOF
94 |
95 | # Importiere Konfiguration
96 | mongoimport --db ris --collection config --type json --jsonArray --file $basepath/ris-web/config/init.config.json
97 |
98 |
--------------------------------------------------------------------------------
/manage.py:
--------------------------------------------------------------------------------
1 | # encoding: utf-8
2 |
3 | """
4 | Copyright (c) 2012 - 2015, Ernesto Ruge
5 | All rights reserved.
6 |
7 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
8 |
9 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
10 |
11 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
12 |
13 | 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
14 |
15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
16 | """
17 |
18 | from flask.ext.script import Manager
19 |
20 | from webapp import app
21 | from webapp import util
22 | from scripts import init_webapp as init_webapp_script
23 | from scripts import osm_import as osm_import_script
24 | from scripts import osm_import_es as osm_import_es_script
25 |
26 | manager = Manager(app)
27 |
28 | @manager.command
29 | def init():
30 | init_webapp_script.run()
31 |
32 | @manager.command
33 | def verify_created_modified():
34 | util.verify_created_modified()
35 |
36 | @manager.command
37 | def osm_import(city_id):
38 | osm_import_script.run(city_id)
39 |
40 | @manager.command
41 | def osm_import_es():
42 | osm_import_es_script.run()
43 |
44 |
45 | if __name__ == "__main__":
46 | manager.run()
--------------------------------------------------------------------------------
/minify.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # css
4 | /usr/bin/yui-compressor /srv/www/ris-web/webapp/static/css/style.css -o /srv/www/ris-web/webapp/static/css/style.min.css
5 | /usr/bin/yui-compressor /srv/www/ris-web/webapp/static/css/leaflet.css -o /srv/www/ris-web/webapp/static/css/leaflet.min.css
6 |
7 | # js
8 | /usr/bin/yui-compressor /srv/www/ris-web/webapp/static/js/ajaxq.js -o /srv/www/ris-web/webapp/static/js/ajaxq.min.js
9 | /usr/bin/yui-compressor /srv/www/ris-web/webapp/static/js/file_details.js -o /srv/www/ris-web/webapp/static/js/file_details.min.js
10 | /usr/bin/yui-compressor /srv/www/ris-web/webapp/static/js/map.js -o /srv/www/ris-web/webapp/static/js/map.min.js
11 | /usr/bin/yui-compressor /srv/www/ris-web/webapp/static/js/paper_details.js -o /srv/www/ris-web/webapp/static/js/paper_details.min.js
12 | /usr/bin/yui-compressor /srv/www/ris-web/webapp/static/js/script.js -o /srv/www/ris-web/webapp/static/js/script.min.js
13 | /usr/bin/yui-compressor /srv/www/ris-web/webapp/static/js/search.js -o /srv/www/ris-web/webapp/static/js/search.min.js
14 |
15 |
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
1 | Flask
2 | Flask-PyMongo
3 | flask-mongo-sessions
4 | pyes
5 | Werkzeug
6 | ordereddict
7 | datetime
8 | python-dateutil
9 | lxml
10 | translitcodec
11 | pytz
12 | cssselect
13 | requests
14 | Flask-Basicauth
15 | Flask-WTF
16 | Flask-Bootstrap
17 | Flask-Cache
18 | elasticsearch
19 | numpy
20 | matplotlib
21 | imposm.parser
22 | python-memcached
23 | pillow
24 | git+git://github.com/werner2101/python-osm.git
25 | Flask-Elasticsearch
26 | Flask-Script
--------------------------------------------------------------------------------
/runserver.py:
--------------------------------------------------------------------------------
1 | from webapp import app
2 |
3 | app.run(debug=True, host='0.0.0.0',port=23000)
4 |
--------------------------------------------------------------------------------
/scripts/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/politik-bei-uns/politik-bei-uns-web-old/730f137e23b2a9afd8fbe888b4d9037670361d44/scripts/__init__.py
--------------------------------------------------------------------------------
/scripts/depublish_attachment.py:
--------------------------------------------------------------------------------
1 | # encoding: utf-8
2 |
3 | """
4 | Copyright (c) 2012 - 2015, Marian Steinbach, Ernesto Ruge
5 | All rights reserved.
6 |
7 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
8 |
9 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
10 |
11 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
12 |
13 | 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
14 |
15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
16 | """
17 |
18 | import sys
19 | sys.path.append('./')
20 |
21 | import config as sysconfig
22 | import os
23 | from pymongo import MongoClient
24 | import gridfs
25 | import bson
26 | import gridfs
27 | import datetime
28 | import shutil
29 | from generate_thumbs import subfolders_for_file
30 |
31 |
32 | ALLOWED_CODES = [
33 | 'COPYRIGHT',
34 | 'COPYRIGHT_RISK',
35 | 'NONPUBLIC_DOCUMENT',
36 | 'PRIVACY'
37 | ]
38 |
39 | def get_config(db):
40 | """
41 | Returns Config JSON
42 | """
43 | config = db.config.find_one()
44 | if '_id' in config:
45 | del config['_id']
46 | return config
47 |
48 |
49 | def depublish(config, fs, file_id, code, message):
50 | aid = bson.ObjectId(file_id)
51 | if not file_exists(aid):
52 | sys.stderr.write("No file found with _id='%s'\n" %
53 | file_id)
54 | return
55 | body_id = modify_file(fs, aid, code, message)
56 | remove_thumbnails(config, body_id, file_id)
57 |
58 |
59 | def file_exists(file_id):
60 | """
61 | Return True if file exists, False otherwise
62 | """
63 | find = db.file.find_one(file_id)
64 | if find is not None:
65 | return True
66 | return False
67 |
68 |
69 | def modify_file(fs, file_id, code, message):
70 | """
71 | Write depublish info,
72 | remove fulltext and thumbnails,
73 | remove file from GridFS
74 | """
75 | doc = db.file.find_one(file_id)
76 | # Delete file from gridfs
77 | if 'file' in doc:
78 | fs.delete(doc['file'].id)
79 | # Modify file document
80 | db.file.update(
81 | {'_id': file_id},
82 | {
83 | '$set': {
84 | 'depublication': {
85 | 'date': datetime.datetime.utcnow(),
86 | 'code': code,
87 | 'comment': message
88 | }
89 | },
90 | '$unset': {
91 | 'fulltext': 1,
92 | 'thumbnails': 1,
93 | 'file': 1
94 | }
95 | })
96 | return str(doc['body'].id)
97 |
98 |
99 | def remove_thumbnails(config, body_id, file_id):
100 | """
101 | Deletes the thumbnail folder for this file
102 | """
103 | path = (config['thumbs_path'] + os.sep + body_id + os.sep + subfolders_for_file(file_id))
104 | shutil.rmtree(path)
105 |
106 |
107 | if __name__ == '__main__':
108 | import argparse
109 | parser = argparse.ArgumentParser(description='Depublish an file')
110 | parser.add_argument('-id', '--fileid', dest='id', metavar='ID',
111 | type=str,
112 | help='ID of the file entry, e.g. 515f2d34c9791e3320c0eea2')
113 | parser.add_argument('-c', '--code', dest='code', metavar='CODE', type=str,
114 | help='One of COPYRIGHT, COPYRIGHT_RISK, NONPUBLIC_DOCUMENT, PRIVACY')
115 | parser.add_argument('-m', '--message', dest='message',
116 | type=str, metavar='MESSAGE', help='Additional explanation')
117 |
118 | args = parser.parse_args()
119 |
120 | error = False
121 |
122 | if args.id is None:
123 | sys.stderr.write("No file ID given.\n")
124 | error = True
125 |
126 | if args.code is None:
127 | sys.stderr.write("No reason CODE given.\n")
128 | error = True
129 | else:
130 | if args.code not in ALLOWED_CODES:
131 | sys.stderr.write("Given CODE is invalid.\n")
132 | error = True
133 |
134 | if args.message is None:
135 | sys.stderr.write("No MESSAGE given.\n")
136 | error = True
137 |
138 | if error:
139 | sys.stderr.write("\n")
140 | parser.print_help()
141 | sys.exit(1)
142 |
143 | connection = MongoClient(sysconfig.MONGO_HOST, sysconfig.MONGO_PORT)
144 | db = connection[sysconfig.MONGO_DBNAME]
145 | fs = gridfs.GridFS(db)
146 | config = get_config(db)
147 |
148 | depublish(config, fs, args.id, args.code, args.message)
149 |
--------------------------------------------------------------------------------
/scripts/export_files.py:
--------------------------------------------------------------------------------
1 | # encoding: utf-8
2 |
3 | """
4 | Copyright (c) 2012 - 2015, Marian Steinbach, Ernesto Ruge
5 | All rights reserved.
6 |
7 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
8 |
9 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
10 |
11 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
12 |
13 | 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
14 |
15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
16 | """
17 |
18 | import sys
19 | sys.path.append('./')
20 |
21 | import os
22 | os.environ['CITY_CONF']='/opt/ris-web/city/template.py'
23 |
24 | import config
25 | import inspect
26 | import argparse
27 | import datetime
28 | from webapp import date_range
29 | from pymongo import MongoClient
30 | import gridfs
31 | import subprocess
32 | import config
33 | from bson import DBRef, ObjectId
34 |
35 |
36 | def get_config(db):
37 | """
38 | Returns Config JSON
39 | """
40 | config = db.config.find_one()
41 | if '_id' in config:
42 | del config['_id']
43 | return config
44 |
45 | def merge_dict(x, y):
46 | merged = dict(x,**y)
47 | xkeys = x.keys()
48 | for key in xkeys:
49 | if type(x[key]) is types.DictType and y.has_key(key):
50 | merged[key] = merge_dict(x[key],y[key])
51 | return merged
52 |
53 | def save_file(fs, file_id, path):
54 | """
55 | Copy a file from MongoDB GridFS to a local file system path
56 | """
57 | file_data = fs.get(file_id)
58 | tempf = open(path, 'wb')
59 | tempf.write(file_data.read())
60 | tempf.close()
61 | return path
62 |
63 | def create_download_package(extconfig, db, fs, body_id):
64 | """
65 | daterange: a datetime tuple compatible string
66 | folder: The target folder and final output filename prefix
67 | """
68 | print "Generating data dump for body %s" % body_id
69 | try:
70 | os.unlink(extconfig['files_dump_folder'] + os.sep + body_id + '.tar.bz2')
71 | except Exception, e:
72 | pass
73 | tmp_folder = (extconfig['files_dump_folder'] + os.sep + body_id + os.sep)
74 | if not os.path.exists(tmp_folder):
75 | os.makedirs(tmp_folder)
76 |
77 | for file in db.fs.files.find({'body': DBRef('body', ObjectId(body_id))}):
78 | file_id = file['_id']
79 | ending = file['filename'].split('.')
80 | if len(ending) > 1:
81 | ending = '.' + ending[-1]
82 | else:
83 | ending = ''
84 | path = tmp_folder + str(file_id) + ending
85 | save_file(fs, file_id, path)
86 | execute('tar -cjf %s.tar.bz2 -C %s .' % (extconfig['files_dump_folder'] + os.sep + body_id, tmp_folder))
87 | execute('rm -rf %s' % tmp_folder)
88 |
89 |
90 | def execute(cmd):
91 | output, error = subprocess.Popen(
92 | cmd.split(' '), stdout=subprocess.PIPE,
93 | stderr=subprocess.PIPE).communicate()
94 | if error is not None and error.strip() != '':
95 | print >> sys.stderr, "Command: " + cmd
96 | print >> sys.stderr, "Error: " + error
97 |
98 |
99 | if __name__ == '__main__':
100 | parser = argparse.ArgumentParser(description='Generate a database dump')
101 | parser.add_argument('-b', dest='body_id', default=None)
102 | options = parser.parse_args()
103 | body_id = options.body_id
104 |
105 | connection = MongoClient(config.MONGO_HOST, config.MONGO_PORT)
106 | db = connection[config.MONGO_DBNAME]
107 | fs = gridfs.GridFS(db)
108 | extconfig = get_config(db)
109 |
110 | if body_id:
111 | folder = extconfig['data_dump_folder'] + os.sep + body_id + os.sep
112 | if not os.path.exists(folder):
113 | os.makedirs(folder)
114 | create_download_package(extconfig, db, fs, str(body['_id']))
115 | else:
116 | for body in db.body.find():
117 | folder = extconfig['data_dump_folder'] + os.sep + str(body['_id'])
118 | if not os.path.exists(folder):
119 | os.makedirs(folder)
120 | create_download_package(extconfig, db, fs, str(body['_id']))
121 |
122 |
--------------------------------------------------------------------------------
/scripts/generate_data_dump.py:
--------------------------------------------------------------------------------
1 | # encoding: utf-8
2 |
3 | """
4 | Copyright (c) 2012 - 2015, Marian Steinbach, Ernesto Ruge
5 | All rights reserved.
6 |
7 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
8 |
9 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
10 |
11 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
12 |
13 | 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
14 |
15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
16 | """
17 |
18 | import sys
19 | sys.path.append('./')
20 |
21 | import os
22 | import inspect
23 | import argparse
24 | import config
25 | import subprocess
26 | import datetime
27 | import shutil
28 | import config
29 | from pymongo import MongoClient
30 |
31 | def get_config(db):
32 | """
33 | Returns Config JSON
34 | """
35 | config = db.config.find_one()
36 | if '_id' in config:
37 | del config['_id']
38 | return config
39 |
40 | def merge_dict(x, y):
41 | merged = dict(x,**y)
42 | xkeys = x.keys()
43 | for key in xkeys:
44 | if type(x[key]) is types.DictType and y.has_key(key):
45 | merged[key] = merge_dict(x[key],y[key])
46 | return merged
47 |
48 |
49 | def execute(cmd):
50 | output, error = subprocess.Popen(
51 | cmd.split(' '), stdout=subprocess.PIPE,
52 | stderr=subprocess.PIPE).communicate()
53 | if error is not None and error.strip() != '':
54 | print >> sys.stderr, "Command: " + cmd
55 | print >> sys.stderr, "Error: " + error
56 |
57 |
58 | def create_dump(extconfig, folder, body_id):
59 | """
60 | Drops dumps in folder/config.DB_NAME
61 | """
62 | cmd = (extconfig['mongodump_cmd'] + ' --host ' + config.MONGO_HOST + ' --db ' + config.MONGO_DBNAME +
63 | ' --out ' + folder + " --query {'body':DBRef('body',ObjectId('" + body_id + "'))}")
64 |
65 | for collection in extconfig['data_dump_tables']:
66 | thiscmd = cmd + ' --collection ' + collection
67 | execute(thiscmd)
68 |
69 |
70 | def compress_folder(extconfig, folder, body_id):
71 | filename = str(body_id) + '.tar.bz2'
72 | execute('rm -f ' + extconfig['data_dump_folder'] + os.sep + filename)
73 | cmd = ('tar -cjf ' + extconfig['data_dump_folder'] + os.sep + filename + ' -C ' + folder +
74 | os.sep + config.MONGO_DBNAME + os.sep + ' .')
75 | execute(cmd)
76 | execute('rm -rf %s' % folder)
77 |
78 |
79 | if __name__ == '__main__':
80 | parser = argparse.ArgumentParser(description='Generate a database dump')
81 | parser.add_argument('-b', dest='body_id', default=None)
82 | options = parser.parse_args()
83 | body_id = options.body_id
84 |
85 | connection = MongoClient(config.MONGO_HOST, config.MONGO_PORT)
86 | db = connection[config.MONGO_DBNAME]
87 | extconfig = get_config(db)
88 |
89 | if body_id:
90 | folder = extconfig['data_dump_folder'] + os.sep + body_id + os.sep
91 | if not os.path.exists(folder):
92 | os.makedirs(folder)
93 | create_dump(extconfig, folder, body_id)
94 | compress_folder(extconfig, folder, body_id)
95 | else:
96 | for body in db.body.find():
97 | folder = extconfig['data_dump_folder'] + os.sep + str(body['_id'])
98 | if not os.path.exists(folder):
99 | os.makedirs(folder)
100 | create_dump(extconfig, folder, str(body['_id']))
101 | compress_folder(extconfig, folder, str(body['_id']))
102 |
--------------------------------------------------------------------------------
/scripts/generate_fulltext.py:
--------------------------------------------------------------------------------
1 | # encoding: utf-8
2 |
3 | """
4 | Copyright (c) 2012 - 2015, Marian Steinbach, Ernesto Ruge
5 | All rights reserved.
6 |
7 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
8 |
9 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
10 |
11 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
12 |
13 | 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
14 |
15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
16 | """
17 |
18 | import sys
19 | sys.path.append('./')
20 |
21 | import os
22 | import inspect
23 | import config
24 | import tempfile
25 | import subprocess
26 | from pymongo import MongoClient
27 | import gridfs
28 | import datetime
29 | import time
30 | import argparse
31 | from bson import ObjectId, DBRef
32 | import types
33 |
34 | STATS = {
35 | 'attachments_without_fulltext': 0,
36 | 'attachments_with_outdated_fulltext': 0,
37 | 'fulltext_created': 0,
38 | 'fulltext_not_created': 0,
39 | 'wrong_mimetype': 0
40 | }
41 |
42 | def get_config(db, body_id):
43 | """
44 | Returns Config JSON
45 | """
46 | config = db.config.find_one()
47 | if '_id' in config:
48 | del config['_id']
49 | local_config = db.body.find_one({'_id': ObjectId(body_id)})
50 | if 'config' in local_config:
51 | config = merge_dict(config, local_config['config'])
52 | del local_config['config']
53 | config['city'] = local_config
54 | return config
55 |
56 | def merge_dict(x, y):
57 | merged = dict(x,**y)
58 | xkeys = x.keys()
59 | for key in xkeys:
60 | if type(x[key]) is types.DictType and y.has_key(key):
61 | merged[key] = merge_dict(x[key],y[key])
62 | return merged
63 |
64 | def generate_fulltext(db, config, body_id):
65 | """Generiert Volltexte für die gesamte file-Collection"""
66 |
67 | # Files mit veralteten Volltexten
68 | query = {'fulltextGenerated': {'$exists': True}, 'depublication': {'$exists': False}, 'body': DBRef('body', ObjectId(body_id))}
69 | for single_file in db.file.find(query):
70 | # Dateiinfo abholen
71 | file_data = db.fs.files.find_one({'_id': single_file['file'].id})
72 | if file_data['uploadDate'] > single_file['fulltextGenerated']:
73 | # Volltext muss erneuert werden
74 | STATS['attachments_with_outdated_fulltext'] += 1
75 | generate_fulltext_for_file(db, config, single_file)
76 |
77 | # Files ohne Volltext
78 | query = {'fulltextGenerated': {'$exists': False}, 'body': DBRef('body', ObjectId(body_id))}
79 | for single_file in db.file.find(query):
80 | STATS['attachments_without_fulltext'] += 1
81 | generate_fulltext_for_file(db, config, single_file)
82 |
83 |
84 | def store_tempfile(file_id, db):
85 | file = db.file.find_one({'_id': file_id})
86 | file_data = fs.get(file['file'].id)
87 | temppath = tempdir + os.sep + str(file_data._id)
88 | tempf = open(temppath, 'wb')
89 | tempf.write(file_data.read())
90 | tempf.close()
91 | return temppath
92 |
93 |
94 | def generate_fulltext_for_file(db, config, single_file):
95 | """
96 | Generiert Text-Export fuer ein bestimmtes Attachment
97 | """
98 | # temporaere Datei des Attachments anlegen
99 | print "Processing file_id=%s" % (single_file['_id'])
100 | if 'file' not in single_file:
101 | print "Fatal Error: file missing in file object"
102 | else:
103 | path = store_tempfile(single_file['_id'], db)
104 |
105 | if single_file['mimetype'] == 'application/pdf':
106 | cmd = config['pdf_to_text_cmd'] + ' -nopgbrk -enc UTF-8 ' + path + ' -'
107 | elif single_file['mimetype'] == 'application/msword':
108 | cmd = config['abiword_cmd'] + ' --to=txt --to-name=fd://1 ' + path
109 | else:
110 | cmd = None
111 | STATS['wrong_mimetype'] += 1
112 |
113 | if cmd:
114 | text = execute(cmd)
115 | if text is not None:
116 | text = text.strip()
117 | text = text.decode('utf-8')
118 | text = text.replace(u"\u00a0", " ")
119 |
120 | # delete temp file
121 | os.unlink(path)
122 | now = datetime.datetime.utcnow()
123 | update = {
124 | '$set': {
125 | 'fulltextGenerated': now,
126 | 'modified': now
127 | }
128 | }
129 | if cmd:
130 | if text is None or text == '':
131 | STATS['fulltext_not_created'] += 1
132 | else:
133 | update['$set']['fulltext'] = text
134 | STATS['fulltext_created'] += 1
135 | db.file.update({'_id': single_file['_id']}, update)
136 |
137 |
138 | def execute(cmd):
139 | new_env = os.environ.copy()
140 | new_env['XDG_RUNTIME_DIR'] = '/tmp/'
141 | output, error = subprocess.Popen(
142 | cmd.split(' '), stdout=subprocess.PIPE,
143 | stderr=subprocess.PIPE, env=new_env).communicate()
144 | if error is not None and error.strip() != '' and 'WARNING **: clutter failed 0, get a life.' not in error:
145 | print >> sys.stderr, "Command: " + cmd
146 | print >> sys.stderr, "Error: " + error
147 | return output
148 |
149 |
150 | def milliseconds():
151 | """Return current time as milliseconds int"""
152 | return int(round(time.time() * 1000))
153 |
154 |
155 | def print_stats():
156 | for key in STATS.keys():
157 | print "%s: %d" % (key, STATS[key])
158 |
159 | if __name__ == '__main__':
160 | parser = argparse.ArgumentParser(
161 | description='Generate Fulltext for given Body ID')
162 | parser.add_argument(dest='body_id', help=("e.g. 54626a479bcda406fb531236"))
163 | options = parser.parse_args()
164 | body_id = options.body_id
165 | connection = MongoClient(config.MONGO_HOST, config.MONGO_PORT)
166 | db = connection[config.MONGO_DBNAME]
167 | fs = gridfs.GridFS(db)
168 | config = get_config(db, body_id)
169 | tempdir = tempfile.mkdtemp()
170 | generate_fulltext(db, config, body_id)
171 | os.rmdir(tempdir)
172 | print_stats()
173 |
--------------------------------------------------------------------------------
/scripts/generate_xml_sitemaps.py:
--------------------------------------------------------------------------------
1 | # encoding: utf-8
2 |
3 | """
4 | Copyright (c) 2012 - 2015, Marian Steinbach, Ernesto Ruge
5 | All rights reserved.
6 |
7 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
8 |
9 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
10 |
11 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
12 |
13 | 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
14 |
15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
16 | """
17 |
18 | import sys
19 | sys.path.append('./')
20 |
21 | import config
22 | import os
23 | import inspect
24 | import argparse
25 | import datetime
26 | import subprocess
27 | from pymongo import MongoClient
28 | import urllib
29 | import config
30 | from bson import DBRef
31 |
32 |
33 | def get_config(db):
34 | """
35 | Returns Config JSON
36 | """
37 | config = db.config.find_one()
38 | if '_id' in config:
39 | del config['_id']
40 | return config
41 |
42 | def merge_dict(x, y):
43 | merged = dict(x,**y)
44 | xkeys = x.keys()
45 | for key in xkeys:
46 | if type(x[key]) is types.DictType and y.has_key(key):
47 | merged[key] = merge_dict(x[key],y[key])
48 | return merged
49 |
50 | def execute(cmd):
51 | output, error = subprocess.Popen(
52 | cmd.split(' '), stdout=subprocess.PIPE,
53 | stderr=subprocess.PIPE).communicate()
54 | if error is not None and error.strip() != '':
55 | print >> sys.stderr, "Command: " + cmd
56 | print >> sys.stderr, "Error: " + error
57 |
58 | def generate_sitemaps(config):
59 | limit = 50000
60 | sitemaps = []
61 | urls = []
62 | bodies = []
63 |
64 | # tidy up
65 | for the_file in os.listdir(config['sitemap_folder']):
66 | file_path = os.path.join(config['sitemap_folder'], the_file)
67 | try:
68 | os.unlink(file_path)
69 | except Exception, e:
70 | print e
71 |
72 | # gather bodies
73 | for body in db.body.find({}):
74 | bodies.append(body['_id'])
75 |
76 | # gather file URLs
77 | for body in bodies:
78 | print "Generating file sitemap for body %s" % body
79 | for file in db.file.find({'body': DBRef('body', body), 'depublication': {'$exists': False}}):
80 | if 'file' in file:
81 | fileentry = db.fs.files.find_one(file['file'].id)
82 | thisfile = {
83 | 'path': "%s/file/%s" % (config['base_url'], file['_id']),
84 | 'lastmod': fileentry['uploadDate']
85 | }
86 | urls.append(thisfile)
87 |
88 | # create sitemap(s) with individual file URLs
89 | sitemap_count = 1
90 | while len(urls) > 0:
91 | shortlist = []
92 | while len(shortlist) < limit and len(urls) > 0:
93 | shortlist.append(urls.pop(0))
94 | sitemap_name = 'files_%s_%d' % (body, sitemap_count)
95 | generate_sitemap(shortlist, sitemap_name)
96 | sitemaps.append(sitemap_name)
97 | sitemap_count += 1
98 |
99 | urls = []
100 | for body in bodies:
101 | print "Generating paper sitemap for body %s" % body
102 | # gather paper URLs
103 | for paper in db.paper.find({'body': DBRef('body', body)}):
104 | thisfile = {
105 | 'path': "%s/paper/%s" % (config['base_url'], paper['_id']),
106 | 'lastmod': paper['modified']
107 | }
108 | urls.append(thisfile)
109 |
110 | # create sitemap(s) with individual attachment URLs
111 | sitemap_count = 1
112 | while len(urls) > 0:
113 | shortlist = []
114 | while len(shortlist) < limit and len(urls) > 0:
115 | shortlist.append(urls.pop(0))
116 | sitemap_name = 'papers_%s_%d' % (body, sitemap_count)
117 | generate_sitemap(shortlist, sitemap_name)
118 | sitemaps.append(sitemap_name)
119 | sitemap_count += 1
120 |
121 |
122 | # Create meta-sitemap
123 | meta_sitemap_path = config['sitemap_folder'] + os.sep + 'sitemap.xml'
124 | f = open(meta_sitemap_path, 'w')
125 | f.write("""
126 | """)
127 | for sitemap_name in sitemaps:
128 | f.write("""\n
129 | %s/static/sitemap/%s.xml.gz
130 | """ % (config['base_url'], sitemap_name))
131 | f.write("\n \n")
132 | f.close()
133 |
134 |
135 | def generate_sitemap(files, name):
136 | sitemap_path = (config['sitemap_folder'] + os.sep + name + '.xml')
137 | f = open(sitemap_path, 'w')
138 | f.write("""
139 | """)
140 | for entry in files:
141 | f.write("""\n
142 | %s
143 | %s
144 | """ % (entry['path'], entry['lastmod'].strftime('%Y-%m-%d')))
145 | f.write(" \n")
146 | f.close()
147 | cmd = "gzip %s" % sitemap_path
148 | execute(cmd)
149 |
150 |
151 | if __name__ == '__main__':
152 | connection = MongoClient(config.MONGO_HOST, config.MONGO_PORT)
153 | db = connection[config.MONGO_DBNAME]
154 | config = get_config(db)
155 | generate_sitemaps(config)
156 |
--------------------------------------------------------------------------------
/scripts/init_webapp.py:
--------------------------------------------------------------------------------
1 | # encoding: utf-8
2 |
3 | """
4 | Copyright (c) 2012 - 2015, Ernesto Ruge
5 | All rights reserved.
6 |
7 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
8 |
9 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
10 |
11 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
12 |
13 | 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
14 |
15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
16 | """
--------------------------------------------------------------------------------
/scripts/osm_import.py:
--------------------------------------------------------------------------------
1 | # encoding: utf-8
2 |
3 | """
4 | Copyright (c) 2012 - 2015, Ernesto Ruge
5 | All rights reserved.
6 |
7 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
8 |
9 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
10 |
11 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
12 |
13 | 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
14 |
15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
16 | """
17 |
18 | import os, shutil, subprocess, urllib, inspect
19 | from osm import pyosm, multipolygon
20 | from imposm.parser import OSMParser
21 | from pymongo import MongoClient
22 | from bson.son import SON
23 | from bson import ObjectId, DBRef
24 | from webapp import mongo, app
25 | import config
26 |
27 | # Wir legen alle nodes in diesem dict ab. Das bedeutet, dass wir
28 | # ausreichend Arbeitsspeicher voraussetzen.
29 | nodes = {}
30 |
31 | class NodeCollector(object):
32 | def coords(self, coords):
33 | for osmid, lon, lat in coords:
34 | if osmid not in nodes:
35 | nodes[osmid] = {
36 | 'osmid': osmid,
37 | 'location': [lon, lat]
38 | }
39 | nodes[osmid]['lat'] = lat
40 | nodes[osmid]['lon'] = lat
41 |
42 | class StreetCollector(object):
43 | wanted_nodes = {}
44 | streets = []
45 |
46 | def ways(self, ways):
47 | #global nodes
48 | for osmid, tags, refs in ways:
49 | if 'highway' not in tags or 'name' not in tags:
50 | # Wenn der way keinen "highway" tag hat oder keinen
51 | # Namen, ist er für uns nicht interessant.
52 | continue
53 | street = {
54 | 'osmid': osmid,
55 | 'name': tags['name'],
56 | 'nodes': []
57 | }
58 | if 'postal_code' in tags:
59 | street['postalcode'] = tags['postal_code']
60 | for ref in refs:
61 | if ref not in nodes:
62 | continue
63 | self.wanted_nodes[ref] = True
64 | street['nodes'].append(ref)
65 | self.streets.append(street)
66 |
67 | def run(city_id):
68 | tmp_base_path = '/srv/www/ris-web/temp/osm-import/'
69 | reuse_old_data = False
70 | if not reuse_old_data:
71 | # remove old data
72 | if os.path.exists(tmp_base_path):
73 | shutil.rmtree(tmp_base_path)
74 | os.makedirs(tmp_base_path)
75 | os.chdir(tmp_base_path)
76 |
77 | # download osmosis
78 | subprocess.call('wget -N http://bretth.dev.openstreetmap.org/osmosis-build/osmosis-latest.tgz', shell=True)
79 | subprocess.call('tar xzf osmosis-latest.tgz', shell=True)
80 | shutil.rmtree(tmp_base_path + 'script')
81 | os.remove(tmp_base_path + 'osmosis-latest.tgz')
82 | os.remove(tmp_base_path + 'readme.txt')
83 | os.remove(tmp_base_path + 'copying.txt')
84 | os.remove(tmp_base_path + 'changes.txt')
85 | os.remove(tmp_base_path + 'package.iml')
86 |
87 | # download geofabrik data
88 | subprocess.call('wget -N -O city-regbez-latest.osm.bz2 http://download.geofabrik.de/europe/germany/%s' % app.config['bodies'][city_id]['geofabrik_data'], shell=True)
89 | subprocess.call('bunzip2 city-regbez-latest.osm.bz2', shell=True)
90 | #os.rename('%s-latest.osm' % (regbez), 'city-regbez-latest.osm')
91 |
92 | # download osmfilter
93 | subprocess.call('wget -O - http://m.m.i24.cc/osmfilter.c |cc -x c - -O3 -o osmfilter', shell=True)
94 |
95 | # create city.poly
96 | API='http://www.openstreetmap.org/api/0.6'
97 | osmfile = urllib.urlopen('%s/relation/%s/full' % (API, app.config['bodies'][city_id]['osm_relation']))
98 | osmobj = pyosm.OSMXMLFile(osmfile)
99 | mp = multipolygon.multipolygon(osmobj.relations[int(app.config['bodies'][city_id]['osm_relation'])])
100 | mp.write_osmosis_file(tmp_base_path + 'city.poly')
101 |
102 | # run osmosis to get city.osm
103 | subprocess.call('bin/osmosis --read-xml file="city-regbez-latest.osm" --bounding-polygon file="city.poly" --write-xml file="city.osm"', shell=True)
104 |
105 | # filter streets
106 | subprocess.call('./osmfilter city.osm --keep="highway=primary =secondary =tertiary =residential =unclassified =road =living-street =pedestrian" --drop-author --drop-version > city-streets.osm', shell=True)
107 |
108 | os.chdir(tmp_base_path)
109 | mongo.db.locations.remove({'body': DBRef('body', ObjectId(city_id))})
110 | mongo.db.locations.ensure_index('osmid')
111 | mongo.db.locations.ensure_index('name')
112 | mongo.db.locations.ensure_index([('nodes.location', '2dsphere')])
113 |
114 | print "Sammle Nodes..."
115 | nodecollector = NodeCollector()
116 | p = OSMParser(concurrency=2, coords_callback=nodecollector.coords)
117 | p.parse('city-streets.osm')
118 |
119 | print "Sammle Straßen..."
120 | streetcollector = StreetCollector()
121 | p = OSMParser(concurrency=2, ways_callback=streetcollector.ways)
122 | p.parse('city-streets.osm')
123 |
124 | # Iteriere über alle gesammelten nodes und finde die,
125 | # welche von anderen Objekten referenziert werden.
126 | wanted_nodes = {}
127 | non_existing_nodes = 0
128 | for ref in streetcollector.wanted_nodes.keys():
129 | if ref in nodes:
130 | wanted_nodes[ref] = nodes[ref]
131 | else:
132 | non_existing_nodes += 1
133 |
134 | # reduziere das nodes dict auf das wesentliche
135 | wanted_nodes.values()
136 |
137 | for street in streetcollector.streets:
138 | for n in range(len(street['nodes'])):
139 | street['nodes'][n] = {
140 | 'osmid': street['nodes'][n],
141 | 'location': SON([
142 | ('type', 'Point'),
143 | ('coordinates', wanted_nodes[street['nodes'][n]]['location'])
144 | ])
145 | }
146 | street['body'] = DBRef('body', ObjectId(city_id))
147 | mongo.db.locations.save(street)
148 |
--------------------------------------------------------------------------------
/scripts/osm_import_es.py:
--------------------------------------------------------------------------------
1 | # encoding: utf-8
2 |
3 | """
4 | Copyright (c) 2012 - 2015, Ernesto Ruge
5 | All rights reserved.
6 |
7 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
8 |
9 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
10 |
11 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
12 |
13 | 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
14 |
15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
16 | """
17 |
18 | from pymongo import MongoClient
19 | from elasticsearch import Elasticsearch
20 | import json
21 | from datetime import datetime
22 | from bson import ObjectId, DBRef
23 | from webapp import app, mongo, es, db
24 |
25 | class MyEncoder(json.JSONEncoder):
26 | def default(self, obj):
27 | if isinstance(obj, datetime.datetime):
28 | return obj.isoformat()
29 | elif isinstance(obj, ObjectId):
30 | return str(obj)
31 | elif isinstance(obj, DBRef):
32 | return {
33 | 'collection': obj.collection,
34 | '_id': obj.id
35 | }
36 | return obj.__dict__
37 |
38 |
39 | def run():
40 | now = datetime.utcnow()
41 | new_index = app.config['es_location_index'] + '-' + now.strftime('%Y%m%d-%H%M')
42 | try:
43 | es.indices.delete_index(new_index)
44 | except:
45 | pass
46 |
47 | bodies = db.get_body()
48 | new_bodies = {}
49 | for body in bodies:
50 | new_bodies[str(body['_id'])] = body
51 | bodies = new_bodies
52 |
53 | index_init = {
54 | 'settings': {
55 | 'index': {
56 | 'analysis': {
57 | 'analyzer': {
58 | 'my_simple_german_analyzer': {
59 | 'type': 'custom',
60 | 'tokenizer': 'standard',
61 | 'filter': ['standard', 'lowercase', 'my_synonym', 'my_stop']
62 | }
63 | },
64 | 'filter': {
65 | 'my_synonym': {
66 | 'type': 'synonym',
67 | 'synonyms_path': app.config['synonyms_path']
68 | },
69 | 'my_stop': {
70 | 'type': 'stop',
71 | 'stopwords_path': app.config['stopwords_path']
72 | }
73 | }
74 | }
75 | }
76 | },
77 | 'mappings': {
78 | 'street': {
79 | '_source': {'enabled': True},
80 | '_all': {'enabled': True},
81 | 'properties': {
82 | 'bodyId': {
83 | 'store': True,
84 | 'type': 'string',
85 | 'index': 'not_analyzed'
86 | },
87 | 'bodyName': {
88 | 'store': True,
89 | 'type': 'string',
90 | 'index': 'analyzed',
91 | 'analyzer': 'my_simple_german_analyzer'
92 | },
93 | 'name': {
94 | 'store': True,
95 | 'type': 'string',
96 | 'index': 'analyzed',
97 | 'analyzer': 'my_simple_german_analyzer'
98 | },
99 | 'postalcode': {
100 | 'store': True,
101 | 'type': 'string',
102 | 'index': 'analyzed',
103 | 'analyzer': 'my_simple_german_analyzer'
104 | },
105 | 'point': {
106 | 'store': True,
107 | 'type': 'geo_point'
108 | },
109 | 'points': {
110 | 'store': True,
111 | 'type': 'geo_point'
112 | }
113 | }
114 | }
115 | }
116 | }
117 | print "Creating index %s" % new_index
118 | es.indices.create(index=new_index, ignore=400, body=index_init)
119 |
120 | streets = {}
121 | for location in mongo.db.locations.find({}):
122 | if 'name' in location:
123 | if location['name'] not in streets:
124 | streets[location['name']] = {}
125 | if 'postalcode' in location:
126 | current_postalcode = location['postalcode']
127 | else:
128 | current_postalcode = 'misc'
129 | if current_postalcode not in streets[location['name']]:
130 | streets[location['name']][current_postalcode] = {
131 | 'name': location['name'],
132 | 'bodyId': str(location['body'].id),
133 | 'bodyName': bodies[str(location['body'].id)]['name'],
134 | 'points': []
135 | }
136 | if current_postalcode != 'misc':
137 | streets[location['name']][current_postalcode]['postalcode'] = current_postalcode
138 | for node in location['nodes']:
139 | if node['location']['type'] == 'Point':
140 | streets[location['name']][current_postalcode]['points'].append(node['location']['coordinates'])
141 | else:
142 | print "unknown node type: %s" % node['location']['type']
143 | else:
144 | print "node without name found"
145 |
146 | for street_plz_key, street_plz in streets.iteritems():
147 | for street_key, street in street_plz.iteritems():
148 | street['point'] = street['points'][0]
149 | es.index(index=new_index,
150 | doc_type='street',
151 | body=street)
152 |
153 | # Setze nach dem Indexieren Alias auf neuen Index
154 | # z.B. 'location-20130414-1200' -> 'location-latest'
155 | latest_name = app.config['es_location_index'] + '-latest'
156 | latest_before = es.indices.get_alias(latest_name)
157 | alias_update = []
158 | for single_before in latest_before:
159 | alias_update.append({
160 | 'remove': {
161 | 'index': single_before,
162 | 'alias': latest_name
163 | }
164 | })
165 | alias_update.append({
166 | 'add': {
167 | 'index': new_index,
168 | 'alias': latest_name
169 | }
170 | })
171 | print "Aliasing index %s to '%s'" % (new_index, latest_name)
172 | es.indices.update_aliases({ 'actions': alias_update })
173 | index_before = es.indices.get('%s*' % app.config['es_location_index'])
174 | for single_index in index_before:
175 | if new_index != single_index:
176 | print "Deleting index %s" % single_index
177 | es.indices.delete(single_index)
--------------------------------------------------------------------------------
/scripts/remove_thumbs.py:
--------------------------------------------------------------------------------
1 | # encoding: utf-8
2 |
3 | """
4 | Copyright (c) 2012 - 2015, Marian Steinbach, Ernesto Ruge
5 | All rights reserved.
6 |
7 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
8 |
9 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
10 |
11 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
12 |
13 | 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
14 |
15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
16 | """
17 |
18 | import sys
19 | sys.path.append('./')
20 |
21 | from pymongo import MongoClient
22 | import config
23 | import os
24 | import inspect
25 | import argparse
26 |
27 | cmd_subfolder = os.path.realpath(os.path.abspath(os.path.join(os.path.split(inspect.getfile( inspect.currentframe() ))[0],"../city")))
28 | if cmd_subfolder not in sys.path:
29 | sys.path.insert(0, cmd_subfolder)
30 |
31 | if __name__ == '__main__':
32 | parser = argparse.ArgumentParser(
33 | description='Generate Fulltext for given City Conf File')
34 | parser.add_argument(dest='city', help=("e.g. bochum"))
35 | options = parser.parse_args()
36 | city = options.city
37 | cityconfig = __import__(city)
38 | connection = MongoClient(config.DB_HOST, config.DB_PORT)
39 | db = connection[config.DB_NAME]
40 | query = {'thumbnails': {'$exists': True}, "rs" : cityconfig.RS}
41 | modification = {
42 | '$unset': {
43 | 'thumbnails': 1,
44 | 'thumbnails_created': 1
45 | }
46 | }
47 | for doc in db.attachments.find(query):
48 | db.attachments.update({'_id': doc['_id']}, modification)
49 |
--------------------------------------------------------------------------------
/webapp/__init__.py:
--------------------------------------------------------------------------------
1 | # encoding: utf-8
2 |
3 | """
4 | Copyright (c) 2012 - 2015, Marian Steinbach, Ernesto Ruge
5 | All rights reserved.
6 |
7 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
8 |
9 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
10 |
11 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
12 |
13 | 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
14 |
15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
16 | """
17 |
18 | from flask import Flask
19 | from flask.ext.pymongo import PyMongo
20 | from flask.ext.bootstrap import Bootstrap
21 | from flask.ext.basicauth import BasicAuth
22 | from flask.ext.cache import Cache
23 | from flask.ext.mongo_sessions import MongoDBSessionInterface
24 | from flask.ext.elasticsearch import FlaskElasticsearch
25 |
26 |
27 | app = Flask(__name__)
28 | app.config.from_pyfile('../config.py')
29 |
30 | # Cache
31 | cache = Cache(app, config={'CACHE_TYPE': 'memcached', 'CACHE_MEMCACHED_SERVERS': ['127.0.0.1:11211']})
32 | cache.init_app(app)
33 |
34 | # Bootstrap
35 | bootstrap = Bootstrap(app)
36 |
37 | # SimpleAuth
38 | basic_auth = BasicAuth(app)
39 |
40 | # Database + Search Server
41 | mongo = PyMongo(app)
42 | es = FlaskElasticsearch(app)
43 |
44 | # Sessions and Configuration
45 | import db
46 | with app.app_context():
47 | app.session_interface = MongoDBSessionInterface(app, mongo.db, 'flasksessions')
48 | app.config.update(db.get_config())
49 |
50 | import webapp.views
51 | import webapp.api
52 | import webapp.oparl
--------------------------------------------------------------------------------
/webapp/date_range.py:
--------------------------------------------------------------------------------
1 | # encoding: utf-8
2 |
3 | """
4 | Copyright (c) 2012 - 2015, Marian Steinbach, Ernesto Ruge
5 | All rights reserved.
6 |
7 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
8 |
9 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
10 |
11 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
12 |
13 | 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
14 |
15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
16 | """
17 |
18 | import datetime
19 | from calendar import monthrange
20 |
21 |
22 | def to_dates(param):
23 | """
24 | This function takes a date URL parameter in various string formats
25 | and converts it to a normalized and validated date range. A list
26 | with two elements is returned, lower and upper date boundary.
27 |
28 | Valid inputs are, for example:
29 | 2012 => Jan 1 20012 - Dec 31 2012 (whole year)
30 | 201201 => Jan 1 2012 - Jan 31 2012 (whole month)
31 | 2012101 => Jan 1 2012 - Jan 1 2012 (whole day)
32 | 2011-2011 => same as "2011", which means whole year 2012
33 | 2011-2012 => Jan 1 2011 - Dec 31 2012 (two years)
34 | 201104-2012 => Apr 1 2011 - Dec 31 2012
35 | 201104-201203 => Apr 1 2011 - March 31 2012
36 | 20110408-2011 => Apr 8 2011 - Dec 31 2011
37 | 20110408-201105 => Apr 8 2011 - May 31 2011
38 | 20110408-20110507 => Apr 8 2011 - May 07 2011
39 | 2011- => Jan 1 2012 - Dec 31 9999 (unlimited)
40 | 201104- => Apr 1 2011 - Dec 31 9999 (unlimited)
41 | 20110408- => Apr 8 2011 - Dec 31 9999 (unlimited)
42 | -2011 Jan 1 0000 - Dez 31 2011
43 | -201104 Jan 1 0000 - Apr 30, 2011
44 | -20110408 Jan 1 0000 - Apr 8, 2011
45 | """
46 | pos = param.find('-')
47 | lower, upper = (None, None)
48 | if pos == -1:
49 | # no seperator given
50 | lower, upper = (param, param)
51 | else:
52 | lower, upper = param.split('-')
53 | ret = (expand_date_param(lower, 'lower'), expand_date_param(upper, 'upper'))
54 | return ret
55 |
56 |
57 | def expand_date_param(param, lower_upper):
58 | """
59 | Expands an (possibly) incomplete date string to either the lowest
60 | or highest possible contained date and returns
61 | datetime.date for that string.
62 |
63 | 0753 (lowest) => 0753-01-01
64 | 2012 (highest) => 2012-12-31
65 | 2012 (lowest) => 2012-01-01
66 | 201208 (highest) => 2012-08-31
67 | etc.
68 | """
69 | year = 0
70 | month = 0
71 | day = 0
72 | if len(param) == 0:
73 | if lower_upper == 'lower':
74 | year = datetime.MINYEAR
75 | month = 1
76 | day = 1
77 | else:
78 | year = datetime.MAXYEAR
79 | month = 12
80 | day = 31
81 | elif len(param) == 4:
82 | year = int(param)
83 | if lower_upper == 'lower':
84 | month = 1
85 | day = 1
86 | else:
87 | month = 12
88 | day = 31
89 | elif len(param) == 6:
90 | year = int(param[0:4])
91 | month = int(param[4:6])
92 | if lower_upper == 'lower':
93 | day = 1
94 | else:
95 | (firstday, dayspermonth) = monthrange(year, month)
96 | day = dayspermonth
97 | elif len(param) == 8:
98 | year = int(param[0:4])
99 | month = int(param[4:6])
100 | day = int(param[6:8])
101 | else:
102 | # wrong input length
103 | return None
104 | # force numbers into valid ranges
105 | year = min(datetime.MAXYEAR, max(datetime.MINYEAR, year))
106 | month = min(12, max(1, month))
107 | (firstday, dayspermonth) = monthrange(year, month)
108 | day = min(dayspermonth, max(1, day))
109 | return datetime.date(year=year, month=month, day=day)
110 |
111 |
112 | def test():
113 | print to_dates('2012')
114 | print to_dates('201201')
115 | print to_dates('20121001')
116 | print to_dates('2011-2011')
117 | print to_dates('2011-2012')
118 | print to_dates('201104-2012')
119 | print to_dates('201104-201203')
120 | print to_dates('20110408-2011')
121 | print to_dates('2011-')
122 | print to_dates('201104-')
123 | print to_dates('20110408-')
124 | print to_dates('-2011')
125 | print to_dates('-201104')
126 | print to_dates('-20110408')
127 | print to_dates('200902')
128 | print to_dates('201002')
129 | print to_dates('201102')
130 | print to_dates('201202')
131 | print to_dates('201302')
132 |
--------------------------------------------------------------------------------
/webapp/forms.py:
--------------------------------------------------------------------------------
1 | # encoding: utf-8
2 |
3 | """
4 | Copyright (c) 2012 - 2015, Ernesto Ruge
5 | All rights reserved.
6 |
7 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
8 |
9 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
10 |
11 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
12 |
13 | 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
14 |
15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
16 | """
17 |
18 | from flask.ext.wtf import Form
19 | from wtforms import validators
20 | from wtforms import SubmitField, TextField, SelectField, FileField, TextAreaField, HiddenField, BooleanField, DecimalField, FloatField, IntegerField
21 | from webapp import app, db
22 |
23 | class ConfigForm(Form):
24 | config = TextAreaField(
25 | label=u'Konfiguration als JSON',
26 | validators=[validators.Required(), validators.Length(max=32000)],
27 | description='')
28 | submit = SubmitField(
29 | label=u'Daten speichern')
30 |
31 | class BodyForm(Form):
32 | config = TextAreaField(
33 | label=u'Konfiguration als JSON',
34 | validators=[validators.Required(), validators.Length(max=32000)],
35 | description='')
36 | submit = SubmitField(
37 | label=u'Daten speichern')
38 |
39 | class RegionForm(Form):
40 | name = TextField(
41 | label=u'Name',
42 | validators=[validators.Required(), validators.Length(max=32000)],
43 | description='')
44 | type = IntegerField(
45 | label=u'Typus (im OSM Sinne). Stadt = 1, Region = 2',
46 | validators=[validators.Required(), validators.NumberRange(min=1, max=2)],
47 | description='',
48 | default=0)
49 | active = IntegerField(
50 | label=u'Ist die Region aktiv?',
51 | validators=[validators.NumberRange(min=0, max=1)],
52 | description='',
53 | default=0)
54 | bodies = TextAreaField(
55 | label=u'Bodies, pro Zeile eine ID',
56 | validators=[validators.Required(), validators.Length(max=32000)],
57 | description='')
58 | keywords = TextAreaField(
59 | label=u'Keywords, pro Zeile ein String',
60 | validators=[validators.Required(), validators.Length(max=32000)],
61 | description='')
62 | lat = FloatField(
63 | label=u'Lat',
64 | validators=[validators.Required(), validators.NumberRange(min=47.2, max=55.0)],
65 | description='',
66 | default=0.0)
67 | lon = FloatField(
68 | label=u'Lon',
69 | validators=[validators.Required(), validators.NumberRange(min=5.5, max=15.1)],
70 | description='',
71 | default=0.0)
72 | zoom = IntegerField(
73 | label=u'Zoom',
74 | validators=[validators.Required(), validators.NumberRange(min=1, max=18)],
75 | description='',
76 | default=0)
77 | submit = SubmitField(
78 | label=u'Daten speichern')
--------------------------------------------------------------------------------
/webapp/static/css/leaflet.min.css:
--------------------------------------------------------------------------------
1 | .leaflet-map-pane,.leaflet-tile,.leaflet-marker-icon,.leaflet-marker-shadow,.leaflet-tile-pane,.leaflet-tile-container,.leaflet-overlay-pane,.leaflet-shadow-pane,.leaflet-marker-pane,.leaflet-popup-pane,.leaflet-overlay-pane svg,.leaflet-zoom-box,.leaflet-image-layer,.leaflet-layer{position:absolute;left:0;top:0}.leaflet-container{overflow:hidden;-ms-touch-action:none}.leaflet-tile,.leaflet-marker-icon,.leaflet-marker-shadow{-webkit-user-select:none;-moz-user-select:none;user-select:none;-webkit-user-drag:none}.leaflet-marker-icon,.leaflet-marker-shadow{display:block}.leaflet-container img{max-width:none!important}.leaflet-container img.leaflet-image-layer{max-width:15000px!important}.leaflet-tile{filter:inherit;visibility:hidden}.leaflet-tile-loaded{visibility:inherit}.leaflet-zoom-box{width:0;height:0}.leaflet-overlay-pane svg{-moz-user-select:none}.leaflet-tile-pane{z-index:2}.leaflet-objects-pane{z-index:3}.leaflet-overlay-pane{z-index:4}.leaflet-shadow-pane{z-index:5}.leaflet-marker-pane{z-index:6}.leaflet-popup-pane{z-index:7}.leaflet-vml-shape{width:1px;height:1px}.lvml{behavior:url(#default#VML);display:inline-block;position:absolute}.leaflet-control{position:relative;z-index:7;pointer-events:auto}.leaflet-top,.leaflet-bottom{position:absolute;z-index:1000;pointer-events:none}.leaflet-top{top:0}.leaflet-right{right:0}.leaflet-bottom{bottom:0}.leaflet-left{left:0}.leaflet-control{float:left;clear:both}.leaflet-right .leaflet-control{float:right}.leaflet-top .leaflet-control{margin-top:10px}.leaflet-bottom .leaflet-control{margin-bottom:10px}.leaflet-left .leaflet-control{margin-left:10px}.leaflet-right .leaflet-control{margin-right:10px}.leaflet-fade-anim .leaflet-tile,.leaflet-fade-anim .leaflet-popup{opacity:0;-webkit-transition:opacity .2s linear;-moz-transition:opacity .2s linear;-o-transition:opacity .2s linear;transition:opacity .2s linear}.leaflet-fade-anim .leaflet-tile-loaded,.leaflet-fade-anim .leaflet-map-pane .leaflet-popup{opacity:1}.leaflet-zoom-anim .leaflet-zoom-animated{-webkit-transition:-webkit-transform .25s cubic-bezier(0,0,0.25,1);-moz-transition:-moz-transform .25s cubic-bezier(0,0,0.25,1);-o-transition:-o-transform .25s cubic-bezier(0,0,0.25,1);transition:transform .25s cubic-bezier(0,0,0.25,1)}.leaflet-zoom-anim .leaflet-tile,.leaflet-pan-anim .leaflet-tile,.leaflet-touching .leaflet-zoom-animated{-webkit-transition:none;-moz-transition:none;-o-transition:none;transition:none}.leaflet-zoom-anim .leaflet-zoom-hide{visibility:hidden}.leaflet-clickable{cursor:pointer}.leaflet-container{cursor:-webkit-grab;cursor:-moz-grab}.leaflet-popup-pane,.leaflet-control{cursor:auto}.leaflet-dragging .leaflet-container,.leaflet-dragging .leaflet-clickable{cursor:move;cursor:-webkit-grabbing;cursor:-moz-grabbing}.leaflet-container{background:#ddd;outline:0}.leaflet-container a{color:#0078a8}.leaflet-container a.leaflet-active{outline:2px solid orange}.leaflet-zoom-box{border:2px dotted #38f;background:rgba(255,255,255,0.5)}.leaflet-container{font:12px/1.5 "Helvetica Neue",Arial,Helvetica,sans-serif}.leaflet-bar{box-shadow:0 1px 5px rgba(0,0,0,0.65);border-radius:4px}.leaflet-bar a,.leaflet-bar a:hover{background-color:#fff;border-bottom:1px solid #ccc;width:26px;height:26px;line-height:26px;display:block;text-align:center;text-decoration:none;color:black}.leaflet-bar a,.leaflet-control-layers-toggle{background-position:50% 50%;background-repeat:no-repeat;display:block}.leaflet-bar a:hover{background-color:#f4f4f4}.leaflet-bar a:first-child{border-top-left-radius:4px;border-top-right-radius:4px}.leaflet-bar a:last-child{border-bottom-left-radius:4px;border-bottom-right-radius:4px;border-bottom:0}.leaflet-bar a.leaflet-disabled{cursor:default;background-color:#f4f4f4;color:#bbb}.leaflet-touch .leaflet-bar a{width:30px;height:30px;line-height:30px}.leaflet-control-zoom-in,.leaflet-control-zoom-out{font:bold 18px 'Lucida Console',Monaco,monospace;text-indent:1px}.leaflet-control-zoom-out{font-size:20px}.leaflet-touch .leaflet-control-zoom-in{font-size:22px}.leaflet-touch .leaflet-control-zoom-out{font-size:24px}.leaflet-control-layers{box-shadow:0 1px 5px rgba(0,0,0,0.4);background:#fff;border-radius:5px}.leaflet-control-layers-toggle{background-image:url(images/layers.png);width:36px;height:36px}.leaflet-retina .leaflet-control-layers-toggle{background-image:url(images/layers-2x.png);background-size:26px 26px}.leaflet-touch .leaflet-control-layers-toggle{width:44px;height:44px}.leaflet-control-layers .leaflet-control-layers-list,.leaflet-control-layers-expanded .leaflet-control-layers-toggle{display:none}.leaflet-control-layers-expanded .leaflet-control-layers-list{display:block;position:relative}.leaflet-control-layers-expanded{padding:6px 10px 6px 6px;color:#333;background:#fff}.leaflet-control-layers-selector{margin-top:2px;position:relative;top:1px}.leaflet-control-layers label{display:block}.leaflet-control-layers-separator{height:0;border-top:1px solid #ddd;margin:5px -10px 5px -6px}.leaflet-container .leaflet-control-attribution{background:#fff;background:rgba(255,255,255,0.7);margin:0}.leaflet-control-attribution,.leaflet-control-scale-line{padding:0 5px;color:#333}.leaflet-control-attribution a{text-decoration:none}.leaflet-control-attribution a:hover{text-decoration:underline}.leaflet-container .leaflet-control-attribution,.leaflet-container .leaflet-control-scale{font-size:11px}.leaflet-left .leaflet-control-scale{margin-left:5px}.leaflet-bottom .leaflet-control-scale{margin-bottom:5px}.leaflet-control-scale-line{border:2px solid #777;border-top:0;line-height:1.1;padding:2px 5px 1px;font-size:11px;white-space:nowrap;overflow:hidden;-moz-box-sizing:content-box;box-sizing:content-box;background:#fff;background:rgba(255,255,255,0.5)}.leaflet-control-scale-line:not(:first-child){border-top:2px solid #777;border-bottom:0;margin-top:-2px}.leaflet-control-scale-line:not(:first-child):not(:last-child){border-bottom:2px solid #777}.leaflet-touch .leaflet-control-attribution,.leaflet-touch .leaflet-control-layers,.leaflet-touch .leaflet-bar{box-shadow:none}.leaflet-touch .leaflet-control-layers,.leaflet-touch .leaflet-bar{border:2px solid rgba(0,0,0,0.2);background-clip:padding-box}.leaflet-popup{position:absolute;text-align:center}.leaflet-popup-content-wrapper{padding:1px;text-align:left;border-radius:12px}.leaflet-popup-content{margin:13px 19px;line-height:1.4}.leaflet-popup-content p{margin:18px 0}.leaflet-popup-tip-container{margin:0 auto;width:40px;height:20px;position:relative;overflow:hidden}.leaflet-popup-tip{width:17px;height:17px;padding:1px;margin:-10px auto 0;-webkit-transform:rotate(45deg);-moz-transform:rotate(45deg);-ms-transform:rotate(45deg);-o-transform:rotate(45deg);transform:rotate(45deg)}.leaflet-popup-content-wrapper,.leaflet-popup-tip{background:white;box-shadow:0 3px 14px rgba(0,0,0,0.4)}.leaflet-container a.leaflet-popup-close-button{position:absolute;top:0;right:0;padding:4px 4px 0 0;text-align:center;width:18px;height:14px;font:16px/14px Tahoma,Verdana,sans-serif;color:#c3c3c3;text-decoration:none;font-weight:bold;background:transparent}.leaflet-container a.leaflet-popup-close-button:hover{color:#999}.leaflet-popup-scrolled{overflow:auto;border-bottom:1px solid #ddd;border-top:1px solid #ddd}.leaflet-oldie .leaflet-popup-content-wrapper{zoom:1}.leaflet-oldie .leaflet-popup-tip{width:24px;margin:0 auto;-ms-filter:"progid:DXImageTransform.Microsoft.Matrix(M11=0.70710678, M12=0.70710678, M21=-0.70710678, M22=0.70710678)";filter:progid:DXImageTransform.Microsoft.Matrix(M11=0.70710678,M12=0.70710678,M21=-0.70710678,M22=0.70710678)}.leaflet-oldie .leaflet-popup-tip-container{margin-top:-1px}.leaflet-oldie .leaflet-control-zoom,.leaflet-oldie .leaflet-control-layers,.leaflet-oldie .leaflet-popup-content-wrapper,.leaflet-oldie .leaflet-popup-tip{border:1px solid #999}.leaflet-div-icon{background:#fff;border:1px solid #666}
--------------------------------------------------------------------------------
/webapp/static/img/awards/deutschland-land-der-ideen-small.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/politik-bei-uns/politik-bei-uns-web-old/730f137e23b2a9afd8fbe888b4d9037670361d44/webapp/static/img/awards/deutschland-land-der-ideen-small.jpg
--------------------------------------------------------------------------------
/webapp/static/img/awards/deutschland-land-der-ideen.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/politik-bei-uns/politik-bei-uns-web-old/730f137e23b2a9afd8fbe888b4d9037670361d44/webapp/static/img/awards/deutschland-land-der-ideen.jpg
--------------------------------------------------------------------------------
/webapp/static/img/facebook-f.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/politik-bei-uns/politik-bei-uns-web-old/730f137e23b2a9afd8fbe888b4d9037670361d44/webapp/static/img/facebook-f.png
--------------------------------------------------------------------------------
/webapp/static/img/footer/facebook.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/politik-bei-uns/politik-bei-uns-web-old/730f137e23b2a9afd8fbe888b4d9037670361d44/webapp/static/img/footer/facebook.png
--------------------------------------------------------------------------------
/webapp/static/img/footer/line.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/politik-bei-uns/politik-bei-uns-web-old/730f137e23b2a9afd8fbe888b4d9037670361d44/webapp/static/img/footer/line.png
--------------------------------------------------------------------------------
/webapp/static/img/footer/mail.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/politik-bei-uns/politik-bei-uns-web-old/730f137e23b2a9afd8fbe888b4d9037670361d44/webapp/static/img/footer/mail.png
--------------------------------------------------------------------------------
/webapp/static/img/footer/okf-de-orig.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/politik-bei-uns/politik-bei-uns-web-old/730f137e23b2a9afd8fbe888b4d9037670361d44/webapp/static/img/footer/okf-de-orig.png
--------------------------------------------------------------------------------
/webapp/static/img/footer/okf-de.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/politik-bei-uns/politik-bei-uns-web-old/730f137e23b2a9afd8fbe888b4d9037670361d44/webapp/static/img/footer/okf-de.png
--------------------------------------------------------------------------------
/webapp/static/img/footer/rss.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/politik-bei-uns/politik-bei-uns-web-old/730f137e23b2a9afd8fbe888b4d9037670361d44/webapp/static/img/footer/rss.png
--------------------------------------------------------------------------------
/webapp/static/img/footer/twitter.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/politik-bei-uns/politik-bei-uns-web-old/730f137e23b2a9afd8fbe888b4d9037670361d44/webapp/static/img/footer/twitter.png
--------------------------------------------------------------------------------
/webapp/static/img/github-octocat.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/politik-bei-uns/politik-bei-uns-web-old/730f137e23b2a9afd8fbe888b4d9037670361d44/webapp/static/img/github-octocat.png
--------------------------------------------------------------------------------
/webapp/static/img/gradient.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/politik-bei-uns/politik-bei-uns-web-old/730f137e23b2a9afd8fbe888b4d9037670361d44/webapp/static/img/gradient.png
--------------------------------------------------------------------------------
/webapp/static/img/jquery-ui/ui-bg_diagonals-thick_18_b81900_40x40.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/politik-bei-uns/politik-bei-uns-web-old/730f137e23b2a9afd8fbe888b4d9037670361d44/webapp/static/img/jquery-ui/ui-bg_diagonals-thick_18_b81900_40x40.png
--------------------------------------------------------------------------------
/webapp/static/img/jquery-ui/ui-bg_diagonals-thick_20_666666_40x40.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/politik-bei-uns/politik-bei-uns-web-old/730f137e23b2a9afd8fbe888b4d9037670361d44/webapp/static/img/jquery-ui/ui-bg_diagonals-thick_20_666666_40x40.png
--------------------------------------------------------------------------------
/webapp/static/img/jquery-ui/ui-bg_flat_10_000000_40x100.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/politik-bei-uns/politik-bei-uns-web-old/730f137e23b2a9afd8fbe888b4d9037670361d44/webapp/static/img/jquery-ui/ui-bg_flat_10_000000_40x100.png
--------------------------------------------------------------------------------
/webapp/static/img/jquery-ui/ui-bg_glass_100_f6f6f6_1x400.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/politik-bei-uns/politik-bei-uns-web-old/730f137e23b2a9afd8fbe888b4d9037670361d44/webapp/static/img/jquery-ui/ui-bg_glass_100_f6f6f6_1x400.png
--------------------------------------------------------------------------------
/webapp/static/img/jquery-ui/ui-bg_glass_100_fdf5ce_1x400.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/politik-bei-uns/politik-bei-uns-web-old/730f137e23b2a9afd8fbe888b4d9037670361d44/webapp/static/img/jquery-ui/ui-bg_glass_100_fdf5ce_1x400.png
--------------------------------------------------------------------------------
/webapp/static/img/jquery-ui/ui-bg_glass_65_ffffff_1x400.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/politik-bei-uns/politik-bei-uns-web-old/730f137e23b2a9afd8fbe888b4d9037670361d44/webapp/static/img/jquery-ui/ui-bg_glass_65_ffffff_1x400.png
--------------------------------------------------------------------------------
/webapp/static/img/jquery-ui/ui-bg_gloss-wave_35_f6a828_500x100.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/politik-bei-uns/politik-bei-uns-web-old/730f137e23b2a9afd8fbe888b4d9037670361d44/webapp/static/img/jquery-ui/ui-bg_gloss-wave_35_f6a828_500x100.png
--------------------------------------------------------------------------------
/webapp/static/img/jquery-ui/ui-bg_highlight-soft_100_eeeeee_1x100.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/politik-bei-uns/politik-bei-uns-web-old/730f137e23b2a9afd8fbe888b4d9037670361d44/webapp/static/img/jquery-ui/ui-bg_highlight-soft_100_eeeeee_1x100.png
--------------------------------------------------------------------------------
/webapp/static/img/jquery-ui/ui-bg_highlight-soft_75_ffe45c_1x100.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/politik-bei-uns/politik-bei-uns-web-old/730f137e23b2a9afd8fbe888b4d9037670361d44/webapp/static/img/jquery-ui/ui-bg_highlight-soft_75_ffe45c_1x100.png
--------------------------------------------------------------------------------
/webapp/static/img/jquery-ui/ui-icons_222222_256x240.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/politik-bei-uns/politik-bei-uns-web-old/730f137e23b2a9afd8fbe888b4d9037670361d44/webapp/static/img/jquery-ui/ui-icons_222222_256x240.png
--------------------------------------------------------------------------------
/webapp/static/img/jquery-ui/ui-icons_228ef1_256x240.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/politik-bei-uns/politik-bei-uns-web-old/730f137e23b2a9afd8fbe888b4d9037670361d44/webapp/static/img/jquery-ui/ui-icons_228ef1_256x240.png
--------------------------------------------------------------------------------
/webapp/static/img/jquery-ui/ui-icons_ef8c08_256x240.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/politik-bei-uns/politik-bei-uns-web-old/730f137e23b2a9afd8fbe888b4d9037670361d44/webapp/static/img/jquery-ui/ui-icons_ef8c08_256x240.png
--------------------------------------------------------------------------------
/webapp/static/img/jquery-ui/ui-icons_ffd27a_256x240.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/politik-bei-uns/politik-bei-uns-web-old/730f137e23b2a9afd8fbe888b4d9037670361d44/webapp/static/img/jquery-ui/ui-icons_ffd27a_256x240.png
--------------------------------------------------------------------------------
/webapp/static/img/jquery-ui/ui-icons_ffffff_256x240.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/politik-bei-uns/politik-bei-uns-web-old/730f137e23b2a9afd8fbe888b4d9037670361d44/webapp/static/img/jquery-ui/ui-icons_ffffff_256x240.png
--------------------------------------------------------------------------------
/webapp/static/img/leaflet/layers-2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/politik-bei-uns/politik-bei-uns-web-old/730f137e23b2a9afd8fbe888b4d9037670361d44/webapp/static/img/leaflet/layers-2x.png
--------------------------------------------------------------------------------
/webapp/static/img/leaflet/layers.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/politik-bei-uns/politik-bei-uns-web-old/730f137e23b2a9afd8fbe888b4d9037670361d44/webapp/static/img/leaflet/layers.png
--------------------------------------------------------------------------------
/webapp/static/img/leaflet/marker-icon-2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/politik-bei-uns/politik-bei-uns-web-old/730f137e23b2a9afd8fbe888b4d9037670361d44/webapp/static/img/leaflet/marker-icon-2x.png
--------------------------------------------------------------------------------
/webapp/static/img/leaflet/marker-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/politik-bei-uns/politik-bei-uns-web-old/730f137e23b2a9afd8fbe888b4d9037670361d44/webapp/static/img/leaflet/marker-icon.png
--------------------------------------------------------------------------------
/webapp/static/img/leaflet/marker-shadow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/politik-bei-uns/politik-bei-uns-web-old/730f137e23b2a9afd8fbe888b4d9037670361d44/webapp/static/img/leaflet/marker-shadow.png
--------------------------------------------------------------------------------
/webapp/static/img/leaflet/zoom-in.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/politik-bei-uns/politik-bei-uns-web-old/730f137e23b2a9afd8fbe888b4d9037670361d44/webapp/static/img/leaflet/zoom-in.png
--------------------------------------------------------------------------------
/webapp/static/img/leaflet/zoom-out.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/politik-bei-uns/politik-bei-uns-web-old/730f137e23b2a9afd8fbe888b4d9037670361d44/webapp/static/img/leaflet/zoom-out.png
--------------------------------------------------------------------------------
/webapp/static/img/loader-35.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/politik-bei-uns/politik-bei-uns-web-old/730f137e23b2a9afd8fbe888b4d9037670361d44/webapp/static/img/loader-35.gif
--------------------------------------------------------------------------------
/webapp/static/img/loader-smooth-32.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/politik-bei-uns/politik-bei-uns-web-old/730f137e23b2a9afd8fbe888b4d9037670361d44/webapp/static/img/loader-smooth-32.gif
--------------------------------------------------------------------------------
/webapp/static/img/logo/FaviconBase.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/politik-bei-uns/politik-bei-uns-web-old/730f137e23b2a9afd8fbe888b4d9037670361d44/webapp/static/img/logo/FaviconBase.png
--------------------------------------------------------------------------------
/webapp/static/img/logo/OffenesKoelnLogo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/politik-bei-uns/politik-bei-uns-web-old/730f137e23b2a9afd8fbe888b4d9037670361d44/webapp/static/img/logo/OffenesKoelnLogo.png
--------------------------------------------------------------------------------
/webapp/static/img/logo/OpenRuhrLogo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/politik-bei-uns/politik-bei-uns-web-old/730f137e23b2a9afd8fbe888b4d9037670361d44/webapp/static/img/logo/OpenRuhrLogo.png
--------------------------------------------------------------------------------
/webapp/static/img/logo/PolitikBeiUns.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/politik-bei-uns/politik-bei-uns-web-old/730f137e23b2a9afd8fbe888b4d9037670361d44/webapp/static/img/logo/PolitikBeiUns.png
--------------------------------------------------------------------------------
/webapp/static/img/logo/PolitikBeiUnsAlt.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/politik-bei-uns/politik-bei-uns-web-old/730f137e23b2a9afd8fbe888b4d9037670361d44/webapp/static/img/logo/PolitikBeiUnsAlt.png
--------------------------------------------------------------------------------
/webapp/static/img/logo/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/politik-bei-uns/politik-bei-uns-web-old/730f137e23b2a9afd8fbe888b4d9037670361d44/webapp/static/img/logo/favicon.ico
--------------------------------------------------------------------------------
/webapp/static/img/logo/favicon_old.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/politik-bei-uns/politik-bei-uns-web-old/730f137e23b2a9afd8fbe888b4d9037670361d44/webapp/static/img/logo/favicon_old.ico
--------------------------------------------------------------------------------
/webapp/static/img/og.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/politik-bei-uns/politik-bei-uns-web-old/730f137e23b2a9afd8fbe888b4d9037670361d44/webapp/static/img/og.jpg
--------------------------------------------------------------------------------
/webapp/static/img/og.psd:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/politik-bei-uns/politik-bei-uns-web-old/730f137e23b2a9afd8fbe888b4d9037670361d44/webapp/static/img/og.psd
--------------------------------------------------------------------------------
/webapp/static/img/sponsoring/acme-inc.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/politik-bei-uns/politik-bei-uns-web-old/730f137e23b2a9afd8fbe888b4d9037670361d44/webapp/static/img/sponsoring/acme-inc.png
--------------------------------------------------------------------------------
/webapp/static/img/sponsoring/anatom5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/politik-bei-uns/politik-bei-uns-web-old/730f137e23b2a9afd8fbe888b4d9037670361d44/webapp/static/img/sponsoring/anatom5.png
--------------------------------------------------------------------------------
/webapp/static/img/sponsoring/linuxhotel.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/politik-bei-uns/politik-bei-uns-web-old/730f137e23b2a9afd8fbe888b4d9037670361d44/webapp/static/img/sponsoring/linuxhotel.png
--------------------------------------------------------------------------------
/webapp/static/img/sponsoring/serverloft.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/politik-bei-uns/politik-bei-uns-web-old/730f137e23b2a9afd8fbe888b4d9037670361d44/webapp/static/img/sponsoring/serverloft.png
--------------------------------------------------------------------------------
/webapp/static/img/team/du.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/politik-bei-uns/politik-bei-uns-web-old/730f137e23b2a9afd8fbe888b4d9037670361d44/webapp/static/img/team/du.jpg
--------------------------------------------------------------------------------
/webapp/static/img/team/ernesto.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/politik-bei-uns/politik-bei-uns-web-old/730f137e23b2a9afd8fbe888b4d9037670361d44/webapp/static/img/team/ernesto.jpg
--------------------------------------------------------------------------------
/webapp/static/img/team/marian.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/politik-bei-uns/politik-bei-uns-web-old/730f137e23b2a9afd8fbe888b4d9037670361d44/webapp/static/img/team/marian.jpg
--------------------------------------------------------------------------------
/webapp/static/img/twitter-bird.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/politik-bei-uns/politik-bei-uns-web-old/730f137e23b2a9afd8fbe888b4d9037670361d44/webapp/static/img/twitter-bird.png
--------------------------------------------------------------------------------
/webapp/static/img/ueber/ueber-anlagenvorschau.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/politik-bei-uns/politik-bei-uns-web-old/730f137e23b2a9afd8fbe888b4d9037670361d44/webapp/static/img/ueber/ueber-anlagenvorschau.jpg
--------------------------------------------------------------------------------
/webapp/static/img/ueber/ueber-api.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/politik-bei-uns/politik-bei-uns-web-old/730f137e23b2a9afd8fbe888b4d9037670361d44/webapp/static/img/ueber/ueber-api.jpg
--------------------------------------------------------------------------------
/webapp/static/img/ueber/ueber-daten.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/politik-bei-uns/politik-bei-uns-web-old/730f137e23b2a9afd8fbe888b4d9037670361d44/webapp/static/img/ueber/ueber-daten.jpg
--------------------------------------------------------------------------------
/webapp/static/img/ueber/ueber-indeinernaehe.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/politik-bei-uns/politik-bei-uns-web-old/730f137e23b2a9afd8fbe888b4d9037670361d44/webapp/static/img/ueber/ueber-indeinernaehe.jpg
--------------------------------------------------------------------------------
/webapp/static/img/ueber/ueber-persistenteurls.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/politik-bei-uns/politik-bei-uns-web-old/730f137e23b2a9afd8fbe888b4d9037670361d44/webapp/static/img/ueber/ueber-persistenteurls.jpg
--------------------------------------------------------------------------------
/webapp/static/img/ueber/ueber-suche.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/politik-bei-uns/politik-bei-uns-web-old/730f137e23b2a9afd8fbe888b4d9037670361d44/webapp/static/img/ueber/ueber-suche.jpg
--------------------------------------------------------------------------------
/webapp/static/img/widget-close.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/politik-bei-uns/politik-bei-uns-web-old/730f137e23b2a9afd8fbe888b4d9037670361d44/webapp/static/img/widget-close.png
--------------------------------------------------------------------------------
/webapp/static/img/widget-close.psd:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/politik-bei-uns/politik-bei-uns-web-old/730f137e23b2a9afd8fbe888b4d9037670361d44/webapp/static/img/widget-close.psd
--------------------------------------------------------------------------------
/webapp/static/js/ajaxq.js:
--------------------------------------------------------------------------------
1 | // AjaxQ jQuery Plugin
2 | // Copyright (c) 2012 Foliotek Inc.
3 | // MIT License
4 | // https://github.com/Foliotek/ajaxq
5 |
6 | (function($) {
7 |
8 | var queues = {};
9 | var activeReqs = {};
10 |
11 | // Register an $.ajaxq function, which follows the $.ajax interface, but allows a queue name which will force only one request per queue to fire.
12 | $.ajaxq = function(qname, opts) {
13 |
14 | if (typeof opts === "undefined") {
15 | throw ("AjaxQ: queue name is not provided");
16 | }
17 |
18 | // Will return a Deferred promise object extended with success/error/callback, so that this function matches the interface of $.ajax
19 | var deferred = $.Deferred(),
20 | promise = deferred.promise();
21 |
22 | promise.success = promise.done;
23 | promise.error = promise.fail;
24 | promise.complete = promise.always;
25 |
26 | // Create a deep copy of the arguments, and enqueue this request.
27 | var clonedOptions = $.extend(true, {}, opts);
28 | enqueue(function() {
29 | // Send off the ajax request now that the item has been removed from the queue
30 | var jqXHR = $.ajax.apply(window, [clonedOptions]);
31 |
32 | // Notify the returned deferred object with the correct context when the jqXHR is done or fails
33 | // Note that 'always' will automatically be fired once one of these are called: http://api.jquery.com/category/deferred-object/.
34 | jqXHR.done(function() {
35 | deferred.resolve.apply(this, arguments);
36 | });
37 | jqXHR.fail(function() {
38 | deferred.reject.apply(this, arguments);
39 | });
40 |
41 | jqXHR.always(dequeue); // make sure to dequeue the next request AFTER the done and fail callbacks are fired
42 | return jqXHR;
43 | });
44 |
45 | return promise;
46 |
47 |
48 | // If there is no queue, create an empty one and instantly process this item.
49 | // Otherwise, just add this item onto it for later processing.
50 | function enqueue(cb) {
51 | if (!queues[qname]) {
52 | queues[qname] = [];
53 | var xhr = cb();
54 | activeReqs[qname] = xhr;
55 | }
56 | else {
57 | queues[qname].push(cb);
58 | }
59 | }
60 |
61 | // Remove the next callback from the queue and fire it off.
62 | // If the queue was empty (this was the last item), delete it from memory so the next one can be instantly processed.
63 | function dequeue() {
64 | if (!queues[qname]) {
65 | return;
66 | }
67 | var nextCallback = queues[qname].shift();
68 | if (nextCallback) {
69 | var xhr = nextCallback();
70 | activeReqs[qname] = xhr;
71 | }
72 | else {
73 | delete queues[qname];
74 | delete activeReqs[qname];
75 | }
76 | }
77 | };
78 |
79 | // Register a $.postq and $.getq method to provide shortcuts for $.get and $.post
80 | // Copied from jQuery source to make sure the functions share the same defaults as $.get and $.post.
81 | $.each( [ "getq", "postq" ], function( i, method ) {
82 | $[ method ] = function( qname, url, data, callback, type ) {
83 |
84 | if ( $.isFunction( data ) ) {
85 | type = type || callback;
86 | callback = data;
87 | data = undefined;
88 | }
89 |
90 | return $.ajaxq(qname, {
91 | type: method === "postq" ? "post" : "get",
92 | url: url,
93 | data: data,
94 | success: callback,
95 | dataType: type
96 | });
97 | };
98 | });
99 |
100 | var isQueueRunning = function(qname) {
101 | return queues.hasOwnProperty(qname);
102 | };
103 |
104 | var isAnyQueueRunning = function() {
105 | for (var i in queues) {
106 | if (isQueueRunning(i)) return true;
107 | }
108 | return false;
109 | };
110 |
111 | $.ajaxq.isRunning = function(qname) {
112 | if (qname) return isQueueRunning(qname);
113 | else return isAnyQueueRunning();
114 | };
115 |
116 | $.ajaxq.getActiveRequest = function(qname) {
117 | if (!qname) throw ("AjaxQ: queue name is required");
118 |
119 | return activeReqs[qname];
120 | };
121 |
122 | $.ajaxq.abort = function(qname) {
123 | if (!qname) throw ("AjaxQ: queue name is required");
124 |
125 | var current = $.ajaxq.getActiveRequest(qname);
126 | delete queues[qname];
127 | delete activeReqs[qname];
128 | if (current) current.abort();
129 | };
130 |
131 | $.ajaxq.clear = function(qname) {
132 | if (!qname) {
133 | for (var i in queues) {
134 | if (queues.hasOwnProperty(i)) {
135 | queues[i] = [];
136 | }
137 | }
138 | }
139 | else {
140 | if (queues[qname]) {
141 | queues[qname] = [];
142 | }
143 | }
144 | };
145 |
146 | })(jQuery);
147 |
--------------------------------------------------------------------------------
/webapp/static/js/ajaxq.min.js:
--------------------------------------------------------------------------------
1 | (function(e){var d={};var c={};e.ajaxq=function(l,i){if(typeof i==="undefined"){throw ("AjaxQ: queue name is not provided")}var h=e.Deferred(),k=h.promise();k.success=k.done;k.error=k.fail;k.complete=k.always;var f=e.extend(true,{},i);g(function(){var m=e.ajax.apply(window,[f]);m.done(function(){h.resolve.apply(this,arguments)});m.fail(function(){h.reject.apply(this,arguments)});m.always(j);return m});return k;function g(m){if(!d[l]){d[l]=[];var n=m();c[l]=n}else{d[l].push(m)}}function j(){if(!d[l]){return}var m=d[l].shift();if(m){var n=m();c[l]=n}else{delete d[l];delete c[l]}}};e.each(["getq","postq"],function(f,g){e[g]=function(l,h,j,k,i){if(e.isFunction(j)){i=i||k;k=j;j=undefined}return e.ajaxq(l,{type:g==="postq"?"post":"get",url:h,data:j,success:k,dataType:i})}});var a=function(f){return d.hasOwnProperty(f)};var b=function(){for(var f in d){if(a(f)){return true}}return false};e.ajaxq.isRunning=function(f){if(f){return a(f)}else{return b()}};e.ajaxq.getActiveRequest=function(f){if(!f){throw ("AjaxQ: queue name is required")}return c[f]};e.ajaxq.abort=function(g){if(!g){throw ("AjaxQ: queue name is required")}var f=e.ajaxq.getActiveRequest(g);delete d[g];delete c[g];if(f){f.abort()}};e.ajaxq.clear=function(g){if(!g){for(var f in d){if(d.hasOwnProperty(f)){d[f]=[]}}}else{if(d[g]){d[g]=[]}}}})(jQuery);
--------------------------------------------------------------------------------
/webapp/static/js/file_details.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2012 - 2015, Marian Steinbach, Ernesto Ruge
3 | All rights reserved.
4 |
5 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
6 |
7 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
8 |
9 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
10 |
11 | 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
12 |
13 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
14 | */
15 |
16 | $(document).ready(function(){
17 |
18 | var thumbs_data; // speichert Details zu den Thumbs aller Attachments
19 |
20 | /**
21 | * Zoomt die Thumbnail-Darstellung von Höhe 300 auf 800
22 | */
23 | function zoomThumbsClick(evt) {
24 | //console.log('zoomThumbs', evt.data);
25 | evt.preventDefault();
26 | // alle img src-Attribute umschreiben
27 | var full_width = 0;
28 | $('#filepreview-' + evt.data.file_id + ' img').each(function(index){
29 | var img = $(this);
30 | var target_height = 800;
31 | var target_width = img.data('width800');
32 | full_width += target_width + 10;
33 | img.animate({width: target_width, height: target_height}, {duration: 400, easing: 'swing'});
34 | img.attr('src', img.attr('src').replace('/300/', '/800/'));
35 | img.parent('a').replaceWith(img);
36 | });
37 | // Breite des Thumbs-Containers zuerst setzen, ohne Animation
38 | $('#filepreview-' + evt.data.file_id + ' .thumbsinner').css({width: full_width});
39 | // Animation zur Vergroesserung des Thumbnails-Containers
40 | $('#filepreview-' + evt.data.file_id + ' .thumbs').animate({height: '825px'}, {duration: 300, easing: 'swing'});
41 | $('#filepreview-' + evt.data.file_id + ' .thumbsinner').animate({height: '810px'}, {duration: 300, easing: 'swing'});
42 | }
43 |
44 | /**
45 | * Erweitert die Vorschaubilder-Anzeige, so dass bei Klick die nächst
46 | * groessere Stufe angezeigt wird.
47 | */
48 | function enhanceThumbnails() {
49 | $('img.thumb').each(function(i, item){
50 | var url_parts = $(item).attr('src').split('/');
51 | var filename = url_parts[(url_parts.length - 1)];
52 | var page = filename.split('.')[0];
53 | var height = url_parts[(url_parts.length - 2)];
54 | var file_id = url_parts[(url_parts.length - 3)];
55 | $(this).wrap(' ');
56 | $(this).parent().click({
57 | file_id: file_id,
58 | height: height,
59 | index: (page - 1)
60 | }, zoomThumbsClick);
61 | });
62 | }
63 |
64 | enhanceThumbnails();
65 | });
66 |
67 |
68 |
69 |
--------------------------------------------------------------------------------
/webapp/static/js/file_details.min.js:
--------------------------------------------------------------------------------
1 | $(document).ready(function(){var a;function b(d){d.preventDefault();var e=0;$("#filepreview-"+d.data.file_id+" img").each(function(h){var g=$(this);var i=800;var f=g.data("width800");e+=f+10;g.animate({width:f,height:i},{duration:400,easing:"swing"});g.attr("src",g.attr("src").replace("/300/","/800/"));g.parent("a").replaceWith(g)});$("#filepreview-"+d.data.file_id+" .thumbsinner").css({width:e});$("#filepreview-"+d.data.file_id+" .thumbs").animate({height:"825px"},{duration:300,easing:"swing"});$("#filepreview-"+d.data.file_id+" .thumbsinner").animate({height:"810px"},{duration:300,easing:"swing"})}function c(){$("img.thumb").each(function(f,h){var k=$(h).attr("src").split("/");var e=k[(k.length-1)];var j=e.split(".")[0];var d=k[(k.length-2)];var g=k[(k.length-3)];$(this).wrap(' ');$(this).parent().click({file_id:g,height:d,index:(j-1)},b)})}c()});
--------------------------------------------------------------------------------
/webapp/static/js/map.min.js:
--------------------------------------------------------------------------------
1 | $(document).ready(function(){OpenRIS.regionLoad();OpenRIS.post_region_change=function(){$.geosearchbox.settings.url="/api/locations?r="+OpenRIS.region.id;$.papersearchbox.settings.url="/api/papers-live?r="+OpenRIS.region.id;$("#search-form").attr({action:"/suche?r="+OpenRIS.region.id});b.setView(new L.LatLng(OpenRIS.region.lat,OpenRIS.region.lon),OpenRIS.region.zoom).addLayer(m);window.history.pushState(String(Date.now()),document.title,"/?r="+OpenRIS.region.id);if($("#search-examples")){$("#search-examples").html("");$("#search-examples").append(document.createTextNode("Beispiele: "));$.each(OpenRIS.region.keyword,function(p,o){$(" ").text(o).attr({href:"/suche?r="+OpenRIS.region.id+"&q="+encodeURI(o)}).appendTo("#search-examples");if(OpenRIS.region.keyword.length>p+1){$("#search-examples").append(document.createTextNode(", "))}})}$("#qinput-region").val(OpenRIS.region.id);f()};var b=new L.Map("map",{});var d=new L.LayerGroup();b.addLayer(d);var m=new L.TileLayer(CONF.mapTileUrlSchema,{maxZoom:CONF.mapTileMaxZoom,minZoom:CONF.mapTileMinZoom,attribution:CONF.mapTileAttribution});var j={};var a="";b.setView(new L.LatLng(OpenRIS.region.lat,OpenRIS.region.lon),OpenRIS.region.zoom).addLayer(m);if(search_data.address){$("#address").val(search_data.address);l()}OpenRIS.loadGeoLiveSearch();$("
").attr("id","address-live").css({top:$("#address").height(),width:$("#address").width()}).appendTo($("#address-box"));$("#address").geosearchbox({url:"/api/locations?r="+OpenRIS.region.id,param:"l",show_results:function(o){o=o.response;result_html="
";if(o.length){$("#address-live").css({display:"block"});for(i=0;i'+o[i]["name"]+", ";if(o[i].hasOwnProperty("postalcode")){result_html+=o[i]["postalcode"]+" "}result_html+=o[i]["bodyName"]+""}result_html+=" ";$("#address-live").html(result_html);$("#address-live li").click(function(){point=$(this).attr("data-point");point=point.split(",");search_data.lat=point[0];search_data.lon=point[1];$("#address").val($(this).text());$("#address-live").css({display:"none"});$("#position-prompt-submit").trigger("click")})}else{$("#address-live").css({display:"none"})}}});var e=$("#position-prompt");if(e.length>0){$("#address").focus()}$("#position-prompt-submit").click(function(o){o.preventDefault();l()});$("#position-prompt-form").submit(function(o){o.preventDefault();l()});$("#address").keydown(function(o){if(o.keyCode==13){o.preventDefault();if($("#address-live li.highlighted").length){$("#address-live li.highlighted").trigger("click")}else{$("#position-prompt-submit").trigger("click")}}if(o.keyCode==38){o.preventDefault();if($("#address-live li.highlighted").length){before=$("#address-live li.highlighted").prev();if(before.length){$("#address-live li.highlighted").removeClass("highlighted");before.addClass("highlighted")}}}if(o.keyCode==40){o.preventDefault();if($("#address-live li.highlighted").length){next=$("#address-live li.highlighted").next();if(next.length){$("#address-live li.highlighted").removeClass("highlighted");next.addClass("highlighted")}}else{$("#address-live li").first().addClass("highlighted")}}});$("#position-prompt-form").focusout(function(){$("#address-live").fadeOut(250)});function n(o){j=o.response}function l(){h();$("#position-prompt-submit");$("#position-prompt .error").remove();$("#location-prompt-resultchoice").remove();var o=$("#address").val();if(!search_data.lat||!search_data.lon){$.get("/api/locations?l="+o,function(q){if(q.response.length){var p=q.response[0]["point"].split(",");search_data.lat=p[0];search_data.lon=p[1];location_string=q.response[0]["name"]+", ";if(q.response[0]["postalcode"]){location_string+=q.response[0]["postalcode"]+" "}location_string+=q.response[0]["bodyName"]+" ";$("#address").val(location_string);search_data.address=location_string;g(parseFloat(search_data.lat),parseFloat(search_data.lon));sessionParams={address:o,lat:search_data.lat,lon:search_data.lon};OpenRIS.session(sessionParams,n)}else{}})}else{g(parseFloat(search_data.lat),parseFloat(search_data.lon));sessionParams={address:o,lat:search_data.lat,lon:search_data.lon};OpenRIS.session(sessionParams,n)}}function k(){d.clearLayers()}function h(){k();b.setView(new L.LatLng(OpenRIS.region.lat,OpenRIS.region.lon),OpenRIS.region.zoom)}function c(o){o.preventDefault();f()}function f(){window.history.pushState(String(Date.now()),document.title,"/?r="+OpenRIS.region.id);$("#map-claim").remove();$("#position-prompt").show();$("#address").focus();$("#address").select();search_data={address:null};sessionParams={address:null,lat:null,lon:null};OpenRIS.session(sessionParams,n);h()}function g(y,q){var v=$("#address").val();if(v===""){v=j.location_entry}window.history.pushState(String(Date.now()),document.title,"/?r="+OpenRIS.region.id+'&l="'+v+'"');var r=$(document.createElement("span")).text(v).attr({id:"map-claim-street"});var z=$(document.createElement("a")).text("Neue Suche").attr({href:"#","class":"awesome extrawide"}).css("margin-left","20px").click(c);var x="";if(OpenRIS.endsWith(v,"straße")||OpenRIS.endsWith(v,"gasse")){x="die"}var t='Das passiert rund um '+x+"
";$("#position-prompt").slideUp().after(t);$("#map-claim").append(r).append(z);k();var B=new L.LatLng(y,q),w=500;b.setView(B,14);var A={color:"#97c66b",opacity:0.7,fill:false,draggable:true};var p=new L.Circle(B,w,A);var s=new L.Circle(B,20,{fillOpacity:0.9,fillColor:"#97c66b",stroke:false,draggable:true});var o=L.popup().setLatLng(B).setContent("Dies ist der Suchmittelpunkt für die Umkreissuche.
");p.on("click",function(C){b.openPopup(o)});p.on("drag",function(C){console.log(C)});s.on("click",function(C){b.openPopup(o)});d.addLayer(p);d.addLayer(s);var u=[];OpenRIS.streetsForPosition(OpenRIS.region.id,y,q,w,function(C){$.each(C.response,function(D,E){if(E.paper_count){$.each(E.nodes,function(J,G){var H=[];$.each(G,function(M,K){H.push(new L.LatLng(K[1],K[0]))});var I=''+D+": "+E.paper_count+" Treffer ";if(E.paper_publishedDate&&E.paper_name){I+=" Der jüngste Treffer vom "+OpenRIS.formatIsoDate(E.paper_publishedDate)+" ("+E.paper_name+")"}I+="
";var F=L.polyline(H,{color:"#ff0909"});F.bindPopup(I);d.addLayer(F)})}})})}$("#qinput-submit").click(function(o){o.preventDefault();$("#search-form").trigger("submit")});OpenRIS.loadPaperLiveSearch();$("").attr("id","qinput-live").css({top:$("#qinput").height(),width:$("#qinput").width()}).appendTo($("#qinput-box"));$("#qinput").papersearchbox({url:"/api/papers-live?r="+OpenRIS.region.id,param:"p",show_results:function(o){o=o.response;result_html="
";if(o.length){$("#qinput-live").css({display:"block"});for(i=0;i'+o[i]["name"]+" ("+o[i]["count"]+")"}result_html+=" ";$("#qinput-live").html(result_html);$("#qinput-live li").click(function(){search_string=$(this).attr("data-q");$("#qinput").val(search_string);$("#qinput-submit").trigger("click")})}else{$("#qinput-live").css({display:"none"})}}});$("#qinput").keydown(function(o){if(o.keyCode==13){o.preventDefault();if($("#qinput-live li.highlighted").length){$("#qinput-live li.highlighted").trigger("click")}else{$("#qinput-submit").trigger("click")}}if(o.keyCode==38){o.preventDefault();if($("#qinput-live li.highlighted").length){before=$("#qinput-live li.highlighted").prev();if(before.length){$("#qinput-live li.highlighted").removeClass("highlighted");before.addClass("highlighted")}}}if(o.keyCode==40){o.preventDefault();if($("#qinput-live li.highlighted").length){next=$("#qinput-live li.highlighted").next();if(next.length){$("#qinput-live li.highlighted").removeClass("highlighted");next.addClass("highlighted")}}else{$("#qinput-live li").first().addClass("highlighted")}}})});
--------------------------------------------------------------------------------
/webapp/static/js/paper_details.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2012 - 2015, Marian Steinbach, Ernesto Ruge
3 | All rights reserved.
4 |
5 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
6 |
7 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
8 |
9 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
10 |
11 | 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
12 |
13 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
14 | */
15 |
16 | $(document).ready(function(){
17 |
18 | var thumbs_data; // speichert Details zu den Thumbs aller Attachments
19 |
20 | /**
21 | * Progressive enhancement zur Verkürzung der angezeigten texte
22 | */
23 | function truncateFulltext() {
24 | $('.attachment').each(function(n, attachment){
25 | var attachment_id = $(attachment).attr('id');
26 | $(attachment).find('.fulltext').each(function(n, fulltext){
27 | var fulltext_content = $('#' + attachment_id + ' .complete .text').html();
28 | var truncated_html = OpenRIS.truncateText(fulltext_content, 350);
29 | var truncated_div = $('');
30 | $(fulltext).append(truncated_div);
31 | $('#' + attachment_id + ' .complete').hide();
32 | if (fulltext_content.length > truncated_html.length) {
33 | var expand_text_link = $(document.createElement('a')).attr('href', '#').text('Gesamten Text anzeigen');
34 | expand_text_link.click({
35 | attachment_id: attachment_id,
36 | content: fulltext_content
37 | }, function(e){
38 | e.preventDefault();
39 | // hide truncated text div (for later re-use)
40 | $('#' + e.data.attachment_id + ' .truncated').hide();
41 | $('#' + e.data.attachment_id + ' .complete').slideDown();
42 | });
43 | $('#' + attachment_id + ' .truncated').append(expand_text_link);
44 | }
45 | });
46 | });
47 | }
48 |
49 | /**
50 | * Zoomt die Thumbnail-Darstellung von Höhe 300 auf 800
51 | */
52 | function zoomThumbsClick(evt) {
53 | //console.log('zoomThumbs', evt.data);
54 | evt.preventDefault();
55 | // alle img src-Attribute umschreiben
56 | var full_width = 0;
57 | $('#' + evt.data.file_id + ' img').each(function(index){
58 | var img = $(this);
59 | var target_height = 800;
60 | var target_width = img.data('width800');
61 | full_width += target_width + 10;
62 | img.animate({width: target_width, height: target_height}, {duration: 400, easing: 'swing'});
63 | img.attr('src', img.attr('src').replace('/300/', '/800/'));
64 | img.parent('a').replaceWith(img);
65 | });
66 | // Breite des Thumbs-Containers zuerst setzen, ohne Animation
67 | $('#' + evt.data.file_id + ' .thumbsinner').css({width: full_width});
68 | // Animation zur Vergroesserung des Thumbnails-Containers
69 | $('#' + evt.data.file_id + ' .thumbs').animate({height: '825px'}, {duration: 300, easing: 'swing'});
70 | $('#' + evt.data.file_id + ' .thumbsinner').animate({height: '810px'}, {duration: 300, easing: 'swing'});
71 | }
72 |
73 | /**
74 | * Liest Informationen über alle Thumbnails zu allen Attachments
75 | * und befüllt thumbs_data - inaktiv, spart einen Request.
76 | */
77 | function readThumbnailData(data) {
78 | thumbs_data = {};
79 | $.each(data.response.documents[0].attachments, function(i, attachment){
80 | thumbs_data[attachment._id] = {};
81 | $.each(attachment.thumbnails, function(height, heightthumbs){
82 | if (height == 300 || height == 800) {
83 | thumbs_data[attachment._id][height] = {
84 | num_thumbs: 0,
85 | width: 0,
86 | images: []
87 | };
88 | $.each(attachment.thumbnails[height], function(index, thumb){
89 | thumbs_data[attachment._id][height].num_thumbs += 1;
90 | thumbs_data[attachment._id][height].width += thumb.width + 11;
91 | thumbs_data[attachment._id][height].images.push({
92 | width: thumb.width,
93 | url: thumb.url
94 | });
95 | });
96 | }
97 | });
98 | });
99 | }
100 |
101 | /**
102 | * Erweitert die Vorschaubilder-Anzeige, so dass bei Klick die nächst
103 | * groessere Stufe angezeigt wird.
104 | */
105 | function enhanceThumbnails() {
106 | $('img.thumb').each(function(i, item){
107 | var url_parts = $(item).attr('src').split('/');
108 | var filename = url_parts[(url_parts.length - 1)];
109 | var page = filename.split('.')[0];
110 | var height = url_parts[(url_parts.length - 2)];
111 | var file_id = url_parts[(url_parts.length - 3)];
112 | $(this).wrap(' ');
113 | $(this).parent().click({
114 | file_id: file_id,
115 | height: height,
116 | index: (page - 1)
117 | }, zoomThumbsClick);
118 | });
119 | }
120 |
121 | // inaktiv, spart einen Request
122 | /*OpenRIS.paperDetails(ok_document_url, function(data){
123 | //console.log(data);
124 | readThumbnailData(data);
125 | enhanceThumbnails();
126 | });*/
127 | enhanceThumbnails();
128 | truncateFulltext();
129 | });
130 |
131 |
132 | /*
133 | // Volltextanzeige
134 | if (typeof attachment.content != 'undefined') {
135 | var fulltext_content = $.trim(attachment.content);
136 | if (fulltext_content !== '') {
137 | var truncated_html = OffenesKoeln.truncateText(fulltext_content, 200);
138 | var fulltext_div = $(document.createElement('div')).attr('class', 'fulltext');
139 | var truncated_div = $(document.createElement('div')).attr('class', 'truncated').html(truncated_html);
140 | fulltext_div.append(truncated_div);
141 | if (fulltext_content.length > truncated_html.length) {
142 | truncated_div.append(' ');
143 | var expand_text_link = $(document.createElement('a')).attr('href', '#').text('Gesamten Text anzeigen');
144 | expand_text_link.click({attachment: attachment}, function(e){
145 | e.preventDefault();
146 | console.log(e.data.attachment);
147 | $('.at' + e.data.attachment.id + ' .truncated').hide();
148 | var complete_fulltext_div = $(document.createElement('div')).attr('class', 'complete').html(e.data.attachment.content);
149 | complete_fulltext_div.hide();
150 | $('.at' + e.data.attachment.id + ' .fulltext').append(complete_fulltext_div);
151 | complete_fulltext_div.slideDown();
152 | });
153 | truncated_div.append(expand_text_link);
154 | }
155 | attachmentdiv.append(fulltext_div);
156 | }
157 | }
158 |
159 | */
160 |
161 |
--------------------------------------------------------------------------------
/webapp/static/js/paper_details.min.js:
--------------------------------------------------------------------------------
1 | $(document).ready(function(){var b;function e(){$(".attachment").each(function(h,g){var f=$(g).attr("id");$(g).find(".fulltext").each(function(o,m){var l=$("#"+f+" .complete .text").html();var j=OpenRIS.truncateText(l,350);var i=$('");$(m).append(i);$("#"+f+" .complete").hide();if(l.length>j.length){var k=$(document.createElement("a")).attr("href","#").text("Gesamten Text anzeigen");k.click({attachment_id:f,content:l},function(n){n.preventDefault();$("#"+n.data.attachment_id+" .truncated").hide();$("#"+n.data.attachment_id+" .complete").slideDown()});$("#"+f+" .truncated").append(k)}})})}function c(f){f.preventDefault();var g=0;$("#"+f.data.file_id+" img").each(function(j){var i=$(this);var k=800;var h=i.data("width800");g+=h+10;i.animate({width:h,height:k},{duration:400,easing:"swing"});i.attr("src",i.attr("src").replace("/300/","/800/"));i.parent("a").replaceWith(i)});$("#"+f.data.file_id+" .thumbsinner").css({width:g});$("#"+f.data.file_id+" .thumbs").animate({height:"825px"},{duration:300,easing:"swing"});$("#"+f.data.file_id+" .thumbsinner").animate({height:"810px"},{duration:300,easing:"swing"})}function a(f){b={};$.each(f.response.documents[0].attachments,function(g,h){b[h._id]={};$.each(h.thumbnails,function(i,j){if(i==300||i==800){b[h._id][i]={num_thumbs:0,width:0,images:[]};$.each(h.thumbnails[i],function(l,k){b[h._id][i].num_thumbs+=1;b[h._id][i].width+=k.width+11;b[h._id][i].images.push({width:k.width,url:k.url})})}})})}function d(){$("img.thumb").each(function(h,k){var m=$(k).attr("src").split("/");var g=m[(m.length-1)];var l=g.split(".")[0];var f=m[(m.length-2)];var j=m[(m.length-3)];$(this).wrap(' ');$(this).parent().click({file_id:j,height:f,index:(l-1)},c)})}d();e()});
--------------------------------------------------------------------------------
/webapp/static/js/pdfobject.js:
--------------------------------------------------------------------------------
1 | /* PDFObject, copyright (C) 2008 Philip Hutchison (pipwerks.com). Documentation and examples are at www.pdfobject.com. Version 1.2, April 2011. MIT style license */
2 | var PDFObject=function(y){if(!y||!y.url){return false;}var w="1.2",b=y.id||false,i=y.width||"100%",z=y.height||"100%",r=y.pdfOpenParams,a,x;var v=function(){var c=null;if(window.ActiveXObject){c=new ActiveXObject("AcroPDF.PDF");if(!c){c=new ActiveXObject("PDF.PdfCtrl");}if(c!==null){return true;}}return false;};var u=function(){var c,f=navigator.plugins,d=f.length,e=/Adobe Reader|Adobe PDF|Acrobat/gi;for(c=0;c';return c.getElementsByTagName("object")[0];};a=encodeURI(y.url)+"#"+p(r);x=s();this.get=function(c){return o(c);};this.embed=function(c){return n(c);};return this;};
--------------------------------------------------------------------------------
/webapp/static/js/script.min.js:
--------------------------------------------------------------------------------
1 | var OpenRIS={a:6378137,b:(6378137*297.257223563)/298.257223563,region:{},search_params:{},start_method_queue:new Array(),monthstr:{"01":"Januar","02":"Februar","03":"März","04":"April","05":"Mai","06":"Juni","07":"Juli","08":"August","09":"September","10":"Oktober","11":"November","12":"Dezember"},streetsForPosition:function(d,e,f,c,g){$.getJSON("/api/streets",{region:d,lat:e,lon:f,radius:c},g)},paperDetails:function(d,c){options={reference:d,output:"meetings,files,thumbnails"};$.getJSON("/api/paper",options,c)},regionLoad:function(){this.region=region_data;$("#change-region").click(function(){$.getJSON("/api/regions",function(c){$.each(c,function(d,e){$("#region-question").css({display:"none"});$(" ").text(e.name).attr({"class":"awesome extrawide"}).click({region:e},function(f){OpenRIS.region={id:f.data.region.id,name:f.data.region.name,lat:f.data.region.lat,lon:f.data.region.lon,zoom:f.data.region.zoom,type:f.data.region.type,keyword:f.data.region.keyword};$("#region-choice").html("");$("#region-question").css({display:"block"});$("#region-current").text(OpenRIS.region.name);sessionParams={region_id:OpenRIS.region.id};OpenRIS.session(sessionParams,function(){});if(typeof(OpenRIS.post_region_change)=="function"){OpenRIS.post_region_change()}}).appendTo("#region-choice")})})})},formatIsoDate:function(e){if(e!=null&&typeof e!="undefined"){var d=e.substr(0,4);var f=e.substr(5,2);var c=e.substr(8,2);return parseInt(c,10)+". "+this.monthstr[f]+" "+d}return e},truncateText:function(d,c){if(d.length<=c){return d}list=d.split(/\s+/);newtext="";while(newtext.lengthSuche...
');OpenRIS.search(OpenRIS.search_params,function(p){$("#search .result").empty();$("#facets").remove();if(p.status==0){if(typeof p.response.facets!="undefined"){$("#search-form").after('
');h(p.response.facets,p.request,"#facets")}e(p);c(p.response.numhits,openris_search_settings.ppp,p.response.start,"#search .result");if(p.response.numhits>1){d(p.request,"#search .result h3")}}else{g()}})}$("#search-submit").click(function(p){p.preventDefault();OpenRIS.search_params.start=0;OpenRIS.search_params.q=$("#qinput").val();b()});$("#searchform").submit(function(p){p.preventDefault();OpenRIS.search_params.start=0;OpenRIS.search_params.q=$("#qinput").val();b()});OpenRIS.post_region_change=function(){OpenRIS.search_params.r=OpenRIS.region.id;OpenRIS.search_params.start=0;OpenRIS.search_params.q=$("#qinput").val();b()};function a(q,s){var r=[];for(var p in q){r.push({key:p,value:q[p]})}if(s=="key"){r.sort(j)}else{if(s=="value"){r.sort(k)}}return r}function j(q,p){return p.key-q.key}function k(q,p){return p.value-q.value}function h(s,r,q){if(typeof s!="undefined"){fq=r.fq;var p=true;x=0;result=new Object();while(p){y=fq.indexOf(":",x);if(y==-1){break}temp=fq.substring(x,y);x=y+1;if(fq.substring(x,x+5)=="""){y=fq.indexOf(""",x+5);if(y==-1){break}result[temp]=fq.substring(x+5,y);x=y+6;if(x>fq.length){break}}else{y=fq.indexOf(";",x);if(y==-1){result[temp]=fq.substring(x,fq.length);break}else{result[temp]=fq.substring(x,y);x=y+1}}}paperType_facet=i("paperType",s.paperType,"Typ","value",result);$(q).append(paperType_facet);bodyName_facet=i("bodyName",s.bodyName,"Körperschaft","value",result);$(q).append(bodyName_facet);publishedDate_facet=i("publishedDate",s.publishedDate,"Erstellungsdatum","",result,true);$(q).append(publishedDate_facet)}}function i(p,t,r,A,v,C){var w=a(t,A);var q=$(document.createElement("div")).attr("class","facet "+p);var u=$(document.createElement("ul")).attr("class","facet");if(v[p]){var B=v[p];if(p=="publishedDate"){B=OpenRIS.monthstr[B.substr(5,7)]+" "+B.substr(0,4)}if(C==true){B=B.replace(/^[0-9]+\s+/,"")}var z="";for(var s in v){if(s!=p){if(z){z+=";"}z+=s+":"+o(v[s])}}if(!z){z=null}$("").attr("class","current").append($("").attr("href","/suche?"+m({fq:z})).attr("title","Diese Einschränkung aufheben").click({sqs:z},function(D){D.preventDefault();if(D.data.sqs){OpenRIS.search_params.fq=D.data.sqs.replace(/\"/g,""")}else{OpenRIS.search_params.fq=null}b()}).append($("").attr("class","facetdel").text("✕")).append($("").attr("class","facetlabel").text(B.replace(/"/g,"").replace(/\"/g,"")))).appendTo(u)}else{for(var s in w){var B=w[s].key;if(C==true){B=B.replace(/^[0-9]+\s+/,"")}if(p=="publishedDate"){B=OpenRIS.monthstr[B.substr(5,7)]+" "+B.substr(0,4)}if(!OpenRIS.search_params.fq){z=p+":"+o(w[s].key)}else{z=OpenRIS.search_params.fq+";"+p+":"+o(w[s].key)}list_element=$("").append($("").attr("href","/suche?"+m({fq:z})).attr("title","Auswahl einschränken").click({sqs:z},function(D){D.preventDefault();OpenRIS.search_params.fq=D.data.sqs.replace(/\"/g,""");b()}).append($("").attr("class","facetlabel").text(B.replace(/"/g,"").replace(/\"/g,""))).append(" ").append($("").attr("class","num").text(w[s].value)));if(p=="publishedDate"){list_element.prependTo(u)}else{list_element.appendTo(u)}}}q.append('");q.append(u);return q}function o(p){if(p.indexOf(" ")!=-1){p='"'+p+'"'}return p}function g(){$("#search .result").append('Fehler bei der Suche Es ist ein unerwarteter Fehler aufgetreten. Bitte probier es noch einmal.
Wenn das Problem weiterhin besteht, bitte kopiere den Inhalt der Adresszeile in eine E-Mail und sende sie an kontakt@politik-bei-uns.de . Vielen Dank!
')}function e(q){var A=$("#search .result");$("h1").text(q.response.numhits+" gefundene Dokumente");if(q.response.numhits>0){var t=$(document.createElement("h3"));t.text("Seite "+(Math.floor(q.response.start/openris_search_settings.ppp)+1)+" von "+(Math.ceil(q.response.numhits/openris_search_settings.ppp)));A.append(t)}var w=$(document.createElement("ol"));w.attr("start",q.response.start+1);A.append(w);for(var r in q.response.result){var z=$(document.createElement("li")).attr("class","resultitem");w.append(z);var u=$(document.createElement("a")).attr("href","/paper/"+q.response.result[r]["id"]);z.append(u);var v=$(document.createElement("span")).attr("class","title").html(n(q.response.result[r]));u.append(v);var s=$(document.createElement("span")).attr("class","metainfo");s.text(f(q.response.result[r]));u.append(s);if(q.response.result[r]["fileFulltext"]){var p=$(document.createElement("p")).attr("class","snippet");p.html(l(q.response.result[r]));z.append(p)}}}function n(p){if(p.name!==""){if(typeof p.highlighting!="undefined"&&typeof p.highlighting.title!="undefined"){return p.highlighting.title}return p.name}else{return"Dokument ohne Name"}}function f(p){return p.paperType+" aus "+p.bodyName+" vom "+OpenRIS.formatIsoDate(p.publishedDate)}function l(p){return"... "+p.fileFulltext+" ..."}function c(q,s,t,r){var p=$(document.createElement("div"));p.attr("class","pager");$(r).append(p);if(t>0){$("").attr("class","awesome extrawide paging back").attr("href","/suche?"+m({start:(t-OpenRIS.search_params.ppp)})).text("← Seite zurück").click(function(u){u.preventDefault();OpenRIS.search_params.start=t-OpenRIS.search_params.ppp;b()}).appendTo(p)}p.append(" ");if(q>(t+s)){$(" ").attr("class","awesome extrawide paging next").attr("href","/suche?"+m({start:(t+OpenRIS.search_params.ppp)})).text("Seite weiter →").click(function(u){u.preventDefault();OpenRIS.search_params.start=t+OpenRIS.search_params.ppp;b()}).appendTo(p)}}function d(r,p){var q=$(document.createElement("span"));q.attr("class","sort");$(p).append(q);q.append(" – sortiert nach ");var t=true;var u={"score:desc":"Relevanz","publishedDate:desc":"Datum: neuste zuerst","publishedDate:asc":"Datum: älteste zuerst"};for(var s in u){if(t){t=false}else{q.append(" | ")}if(r.sort==s){$("").text(u[s]).appendTo(q)}else{$("").attr("href","/suche?"+m({start:0,sort:s})).text(u[s]).click({o:s},function(v){v.preventDefault();OpenRIS.search_params.start=0;OpenRIS.search_params.sort=v.data.o;b()}).appendTo(q)}}}function m(p){var q=OpenRIS.deepCopy(OpenRIS.search_params);for(var r in p){if(p[r]==null||typeof p[r]=="undefined"){delete q[r]}else{q[r]=p[r]}}q=OpenRIS.processSearchParams(q);var s=[];for(var r in q){s.push(r+"="+encodeURI(q[r]))}return s.join("&")}});
--------------------------------------------------------------------------------
/webapp/templates/admin.html:
--------------------------------------------------------------------------------
1 | {% extends "layout.html" %}
2 | {% block title %}Disclaimer{% endblock %}
3 | {% block ogtitle %}Disclaimer{% endblock %}
4 | {% block meta_description %}Ein paar Worte zur Vorsicht{% endblock %}
5 |
6 | {% block content %}
7 |
8 |
9 |
Admin-Interface
10 |
11 |
12 | {% endblock %}
--------------------------------------------------------------------------------
/webapp/templates/admin_bodies.html:
--------------------------------------------------------------------------------
1 | {% extends "layout.html" %}
2 | {% import "bootstrap/wtf.html" as wtf %}
3 |
4 | {% block title %}Admin: Konfiguration{{super()}}{% endblock %}
5 |
6 | {% block riscontent %}
7 |
8 |
Admin: Bodies
9 |
Neuen Body hinzufügen
10 |
11 |
12 |
13 | UID
14 | Name
15 | Regionalschlüssel
16 | Funktionen
17 |
18 |
19 |
20 |
21 | UID
22 | Name
23 | Regionalschlüssel
24 | Funktionen
25 |
26 |
27 |
28 | {% for body in bodies %}
29 |
30 | {{ body._id }}
31 | {{ body.name }}
32 | {{ body['regionalschlüssel'] }}
33 | edit
34 |
35 | {% endfor %}
36 |
37 |
38 |
39 | {% endblock %}
--------------------------------------------------------------------------------
/webapp/templates/admin_body_edit.html:
--------------------------------------------------------------------------------
1 | {% extends "layout.html" %}
2 | {% import "bootstrap/wtf.html" as wtf %}
3 |
4 | {% block title %}Admin: Konfiguration{{super()}}{% endblock %}
5 |
6 | {% block riscontent %}
7 |
8 |
Admin: Body: Edit
9 | {{ wtf.quick_form(body_form) }}
10 |
11 | {% endblock %}
--------------------------------------------------------------------------------
/webapp/templates/admin_body_new.html:
--------------------------------------------------------------------------------
1 | {% extends "layout.html" %}
2 | {% import "bootstrap/wtf.html" as wtf %}
3 |
4 | {% block title %}Admin: Konfiguration{{super()}}{% endblock %}
5 |
6 | {% block riscontent %}
7 |
8 |
Admin: Body: Neu
9 | {{ wtf.quick_form(body_form) }}
10 |
11 | {% endblock %}
--------------------------------------------------------------------------------
/webapp/templates/admin_config.html:
--------------------------------------------------------------------------------
1 | {% extends "layout.html" %}
2 | {% import "bootstrap/wtf.html" as wtf %}
3 |
4 | {% block title %}Admin: Konfiguration{{super()}}{% endblock %}
5 |
6 | {% block riscontent %}
7 |
8 |
Admin: Konfiguration
9 | {{ wtf.quick_form(config_form) }}
10 |
11 | {% endblock %}
--------------------------------------------------------------------------------
/webapp/templates/admin_region_edit.html:
--------------------------------------------------------------------------------
1 | {% extends "layout.html" %}
2 | {% import "bootstrap/wtf.html" as wtf %}
3 |
4 | {% block title %}Admin: Konfiguration{{super()}}{% endblock %}
5 |
6 | {% block riscontent %}
7 |
8 |
Admin: Regien: Edit
9 | {{ wtf.quick_form(region_form) }}
10 |
11 | {% endblock %}
--------------------------------------------------------------------------------
/webapp/templates/admin_region_new.html:
--------------------------------------------------------------------------------
1 | {% extends "layout.html" %}
2 | {% import "bootstrap/wtf.html" as wtf %}
3 |
4 | {% block title %}Admin: Konfiguration{{super()}}{% endblock %}
5 |
6 | {% block riscontent %}
7 |
8 |
Admin: Region: Neu
9 | {{ wtf.quick_form(region_form) }}
10 |
11 | {% endblock %}
--------------------------------------------------------------------------------
/webapp/templates/admin_regions.html:
--------------------------------------------------------------------------------
1 | {% extends "layout.html" %}
2 | {% import "bootstrap/wtf.html" as wtf %}
3 |
4 | {% block title %}Admin: Konfiguration{{super()}}{% endblock %}
5 |
6 | {% block riscontent %}
7 |
8 |
Admin: Regionen
9 |
Neue Region hinzufügen
10 |
11 |
12 |
13 | UID
14 | Name
15 | Aktiv
16 | Funktionen
17 |
18 |
19 |
20 |
21 | UID
22 | Name
23 | Aktiv
24 | Funktionen
25 |
26 |
27 |
28 | {% for region in regions %}
29 |
30 | {{ region._id }}
31 | {{ region.name }}
32 | {{ region.active }}
33 | edit
34 |
35 | {% endfor %}
36 |
37 |
38 |
39 | {% endblock %}
--------------------------------------------------------------------------------
/webapp/templates/admin_response.html:
--------------------------------------------------------------------------------
1 | {% extends "layout.html" %}
2 | {% block title %}{{super()}}{% endblock %}
3 |
4 | {% block content %}
5 |
6 |
7 |
Admin-Interface: Response
8 |
9 |
10 |
11 | ID
12 | IP-Adresse
13 | Name
14 | Mail
15 | Gesendet auf
16 | Anhang ID
17 | Kategorie
18 | Nachricht
19 |
20 |
21 |
22 |
23 | ID
24 | IP-Adresse
25 | Name
26 | Mail
27 | Gesendet auf
28 | Anhang ID
29 | Kategorie
30 | Nachricht
31 |
32 |
33 |
34 | {% for response in responses %}
35 |
36 | {{ response._id }}
37 | {{ response.ip }}
38 | {{ response.name }}
39 | {{ response.email }}
40 | {{ response.sent_on }}
41 | {{ response.attachment_id }}
42 | {{ response.response_type }}
43 | {{ response.message }}
44 |
45 | {% endfor %}
46 |
47 |
48 |
49 |
50 | {% endblock %}
--------------------------------------------------------------------------------
/webapp/templates/api.html:
--------------------------------------------------------------------------------
1 | {% extends "layout.html" %}
2 | {% block title %}API | {{ config.site_name }}{% endblock %}
3 | {% block ogtitle %}API | {{ config.site_name }}{% endblock %}
4 | {% block meta_description %}Für echte Offenheit braucht es offene Schnittstellen. Hier gibt es Informationen über unsere Webservice API.{% endblock %}
5 |
6 | {% block riscontent %}
7 |
8 |
9 |
Die {{ config.site_name }} API
10 |
API = engl. Application Program Interface : Eine Programmierschnittstelle für den Zugriff auf ein System.
11 |
12 |
Das Ziel des offenen Ratsinformationssystems ist es, Daten und Informationen der Lokalpolitik so weit wie möglich für jede denkbare Nutzung zu öffnen. Dazu gehört auch die Öffnung für den Zugriff mit Hilfe von Programmen und Systemen.
13 |
14 |
15 |
16 |
Bereitstellung via OParl
17 |
18 |
Das Ziel von OParl ist die Schaffung einer Standard-API für den Zugang zu öffentlichen Inhalten in kommunalen Ratsinformationssystemen, damit die Inhalte daraus im Sinne von Open Data für möglichst viele verschiedene Zwecke eingesetzt werden können.
19 |
20 |
Alle hier präsentierten Daten sind über die OParl-Schnittstelle zu abrufbar. Die Dokumentation befindet sich auf GitHub , ebenso wie die Diskussion über die API . Mitarbeit ist erwünscht! Die Basis-URL der Schnittstelle lautet:
21 |
22 |
/oparl
23 |
Bislang ist bei der OParl-API-Ausgabe noch folgendes zu beachten:
24 |
25 | Die API auf {{ config.site_host }} ist nicht exakt OParl, einige Features fehlen noch.
26 | OParl selbst ist noch im Draft-Status, d.h. es können sich noch das eine oder andere ändern.
27 |
28 |
29 |
30 |
31 |
Zusatzfunktionen zu OParl
32 |
33 |
Um die OParl-Schnittstelle kennenzulernen, bieten wir eine speziellen HTML-Ausgabe an:
34 |
35 |
/oparl?html=1
36 |
37 |
38 | {% endblock %}
--------------------------------------------------------------------------------
/webapp/templates/daten.html:
--------------------------------------------------------------------------------
1 | {% extends "layout.html" %}
2 | {% block title %}Daten zum Download | {{ config.site_name }}{% endblock %}
3 | {% block ogtitle %}Daten zum Download | {{ config.site_name }}{% endblock %}
4 | {% block meta_description %}Hier können Sie die Daten hinter dem offenen Ratsinformationssystem herunter laden. Open Data First!{% endblock %}
5 |
6 | {% block riscontent %}
7 |
8 |
9 |
Daten
10 |
11 |
12 |
Die Datenbank hinter {{ config.site_host }} steht zum Download zur Verfügung. Bitte beachte, dass wir auch eine Programmierschnittstelle (API) anbieten, mit sich Daten gezielt abfragen lassen.
13 |
14 |
Bei den Inhalten handelt es sich größtenteils um amtliche Dokumente, die um einige Daten angereichert wurden.
15 |
16 |
Wenn Sie die Daten für eigene Projekte nutzen, freuen wir uns über eine Nachricht und einen Link zu {{ config.site_host }}!
17 |
18 |
19 |
20 |
21 |
22 |
Lizenz
23 |
24 |
Alle selbst erstellten Daten stehen unter der Open Data Commons Open Database License (ODbL) .
25 |
26 |
Die enthaltenen Geodaten sind Auszüge aus dem Datenbestand von OpenStreetMap . Urheber sind hier "OpenStreetMap und Mitwirkende".
27 |
28 |
Die Anhänge zu Dokumenten (PDF-Dateien etc.) stehen nicht unter der genannten Lizenz, bei etwaiger Weiterverwendung muss die Lizenz mit der jeweiligen Stadt geklärt werden.
29 |
30 |
Eine Ausnahme dazu ist die Stadt Moers, alle seit dem 1.7.2013 erstellten Daten unterliegen der Creative Commons Namensnennung 3.0 Deutschland (CC BY 3.0 DE) .
31 |
32 |
33 |
34 |
35 |
36 |
Datenbank-Dumps
37 |
38 |
Die Datenbank-Exporte enthalten alle strukturierten Daten zu Sitzungen, Dokumenten/Vorlagen, Anhängen sowie Geodaten.
39 |
40 |
Die Datei-Anhänge (PDF-Dateien etc.) sowie die Vorschaubilder zu diesen Dateien sind nicht im Export enthalten (siehe dazu der Abschnitt weiter unten). Weiterhin nicht enthalten sind Session-Daten, die zum Betrieb der Webapplikation benötigt werden und die nutzerbezogene Informationen enthalten.
41 |
42 |
Die Exporte geben die Inhalte der MongoDB Datenbank wieder und sind zur Verwendung mit den entsprechenden MongoDB-Werkzeugen (mongorestore oder mongoimport ) gedacht.
43 |
44 |
45 |
46 |
47 | #
48 | Stadt
49 | Größe
50 | Download
51 |
52 |
53 |
54 | {% for item in data_list %}
55 |
56 | {{ loop.index }}
57 | {{ item['name'] }}
58 | {{ item['size'] }} MB
59 | download
60 |
61 | {% endfor %}
62 |
63 |
64 |
65 |
66 |
67 |
68 |
Anlagen/Dateien zu Dokumenten
69 |
70 |
Die digitalen Anträge, Anfragen, Mitteilungen etc. liegen ebenfalls als Archiv vor. Zum größten Teil sind dies PDF-Dokumente, aber auch JPEG- und TIF-Bilder sowie andere Formate.
71 |
72 |
73 |
74 |
75 | #
76 | Stadt
77 | Größe
78 | Download
79 |
80 |
81 |
82 | {% for item in file_list %}
83 |
84 | {{ loop.index }}
85 | {{ item['name'] }}
86 | {{ item['size'] }} GB
87 | download
88 |
89 | {% endfor %}
90 |
91 |
92 |
93 |
94 |
95 |
96 |
Statistiken
97 |
98 |
Wie viele Dokumente befinden sich auf {{ config.site_host }}? Hier ein paar Statistiken.
99 |
100 |
101 |
102 |
103 | Stadt
104 | Organisationen
105 | Personen
106 | Sitzungen
107 | Tagesordnungspunkte
108 | Vorlagen
109 | Dateien
110 |
111 |
112 |
113 |
114 | Gesamt
115 | {{ statistics_all['organization']|dottify }}
116 | {{ statistics_all['person']|dottify }}
117 | {{ statistics_all['meeting']|dottify }}
118 | {{ statistics_all['agendaItem']|dottify }}
119 | {{ statistics_all['paper']|dottify }}
120 | {{ statistics_all['file']|dottify }}
121 |
122 |
123 |
124 | {% for item in statistics %}
125 |
126 | {{ item['name'] }}
127 | {{ item['organization']|dottify }}
128 | {{ item['person']|dottify }}
129 | {{ item['meeting']|dottify }}
130 | {{ item['agendaItem']|dottify }}
131 | {{ item['paper']|dottify }}
132 | {{ item['file']|dottify }}
133 |
134 | {% endfor %}
135 |
136 |
137 |
138 |
139 | {% endblock %}
--------------------------------------------------------------------------------
/webapp/templates/datenschutz.html:
--------------------------------------------------------------------------------
1 | {% extends "layout.html" %}
2 | {% block title %}Datenschutz | {{ config.site_name }}{% endblock %}
3 | {% block ogtitle %}Datenschutz | {{ config.site_name }}{% endblock %}
4 | {% block meta_description %}Impressum von {{ config.site_name }}{% endblock %}
5 |
6 | {% block riscontent %}
7 |
8 |
Datenschutzerklärung
9 |
Die Nutzung unserer Webseite ist in der Regel ohne Angabe personenbezogener Daten möglich. Soweit auf unseren Seiten personenbezogene Daten (beispielsweise Name, Anschrift oder eMail-Adressen) erhoben werden, erfolgt dies, soweit möglich, stets auf freiwilliger Basis. Diese Daten werden ohne Ihre ausdrückliche Zustimmung nicht an Dritte weitergegeben.
10 |
Wir weisen darauf hin, dass die Datenübertragung im Internet (z.B. bei der Kommunikation per E-Mail) Sicherheitslücken aufweisen kann. Ein lückenloser Schutz der Daten vor dem Zugriff durch Dritte ist nicht möglich.
11 |
Der Nutzung von im Rahmen der Impressumspflicht veröffentlichten Kontaktdaten durch Dritte zur Übersendung von nicht ausdrücklich angeforderter Werbung und Informationsmaterialien wird hiermit ausdrücklich widersprochen. Die Betreiber der Seiten behalten sich ausdrücklich rechtliche Schritte im Falle der unverlangten Zusendung von Werbeinformationen, etwa durch Spam-Mails, vor.
12 |
13 |
14 |
15 |
Webanalysedienst
16 |
Unsere Website verwendet Piwik, dabei handelt es sich um einen sogenannten Webanalysedienst. Piwik verwendet sog. "Cookies", das sind Textdateien, die auf Ihrem Computer gespeichert werden und die unsererseits eine Analyse der Benutzung der Webseite ermöglichen. Zu diesem Zweck werden die durch den Cookie erzeugten Nutzungsinformationen (einschließlich Ihrer gekürzten IP-Adresse) an unseren Server übertragen und zu Nutzungsanalysezwecken gespeichert, was der Webseitenoptimierung unsererseits dient. Ihre IP-Adresse wird bei diesem Vorgang umgehend anonymisiert, so dass Sie als Nutzer für uns anonym bleiben. Die durch den Cookie erzeugten Informationen über Ihre Benutzung dieser Webseite werden nicht an Dritte weitergegeben. Sie können die Verwendung der Cookies durch eine entsprechende Einstellung Ihrer Browser Software verhindern, es kann jedoch sein, dass Sie in diesem Fall gegebenenfalls nicht sämtliche Funktionen dieser Website voll umfänglich nutzen können.
17 |
18 |
19 |
Auskunft, Löschung, Sperrung
20 |
Sie haben jederzeit das Recht auf unentgeltliche Auskunft über Ihre gespeicherten personenbezogenen Daten, deren Herkunft und Empfänger und den Zweck der Datenverarbeitung sowie ein Recht auf Berichtigung, Sperrung oder Löschung dieser Daten. Hierzu sowie zu weiteren Fragen zum Thema personenbezogene Daten können Sie sich jederzeit über die im Impressum angegeben Adresse des Webseitenbetreibers an uns wenden.
21 |
22 | {% endblock %}
--------------------------------------------------------------------------------
/webapp/templates/disclaimer.html:
--------------------------------------------------------------------------------
1 | {% extends "layout.html" %}
2 | {% block title %}Disclaimer | {{ config.site_name }}{% endblock %}
3 | {% block ogtitle %}Disclaimer | {{ config.site_name }}{% endblock %}
4 | {% block meta_description %}Wichtige Hinweise zur Datenqualität und Datenherkunft{% endblock %}
5 |
6 | {% block riscontent %}
7 |
8 |
9 |
Wichtige Hinweise zur Datenqualität und Datenherkunft
10 |
11 |
12 |
13 |
Das offene Ratsinformationssystem ist keine offizielle Quelle für amtliche Dokumente und Informationen.
14 |
15 |
Trotz großer Anstrengungen, korrekte und vollständige Daten zu publizieren, kann es zu Fehlern und Lücken im Datenbestand kommen.
16 |
17 |
Für die Richtigkeit der Daten und Inhalte übernimmt der Betreiber des offenen Ratsinformationssystems keinerlei Gewährleistung oder Garantie.
18 |
19 |
Die Nutzung des offenen Ratsinformationssystems geschieht ausschließlich auf eigene Verantwortung der Nutzerinnen und Nutzer.
20 |
21 |
Solltesn Sie sich auf hier veröffentlichte amtliche Dokumente beziehen wollen, erkundigen Sie sich bitte bei den offiziellen Quellen (der Stadtverwaltung, dem Rat, den Gremien) nach der aktuellen und amtlichen Version.
22 |
23 |
Sollten Ihnen weitere Probleme am Datenbestand auffallen, kontaktieren Sie uns bitte und beschreiben Sie das Problem. Vielen Dank!
24 |
25 |
26 |
27 |
28 | {% endblock %}
--------------------------------------------------------------------------------
/webapp/templates/file_details.html:
--------------------------------------------------------------------------------
1 | {% extends "layout.html" %}
2 | {% block title %}{{ file.name }} | {{ config.site_name }}{% endblock %}
3 | {% block ogtitle %}{{ file.name }} {{ config.site_name }}{% endblock %}
4 | {% block meta_description %}Details einer Datei{% endblock %}
5 |
6 | {% block scripts %}
7 | {{ super() }}
8 |
9 | {% endblock %}
10 |
11 | {% block riscontent %}
12 | {% if file.thumbnails %}
13 | {% set twidth = (file.thumbnails['300']|sum(attribute='width') + (11 * file.thumbnails['300']|length)) %}
14 | {% set numpages = file.thumbnails['300']|length %}
15 | {% endif %}
16 |
17 |
18 |
Datei: {{ file.name }}
19 |
60 |
61 | {% if file.file %}
62 |
65 | {% endif %}
66 |
67 |
68 |
Vorschau der Datei
69 | {% if file.depublication %}
70 |
71 |
72 |
73 | {{ file.depublication.comment }}
74 |
75 |
76 | {% else %}
77 | {% if file.thumbnails %}
78 |
79 |
80 | {% for thumbnail in file.thumbnails['300'] %}
81 |
82 | {% endfor %}
83 |
84 |
85 | {% else %}
86 |
Zu diesem Anhang liegen keine Vorschaubilder vor.
87 | {% endif %}
88 |
89 |
90 |
Inhalt der Datei
91 | {% if file.fulltext %}
92 |
93 |
94 |
{{ file.fulltext|trim }}
95 |
96 |
97 | {% else %}
98 |
99 |
Zu diesem Anhang kann leider kein Text angezeigt und durchsucht werden. Evtl. handelt es sich um den Scan einer Papiervorlage.
100 |
101 | {% endif %}
102 | {% endif%}
103 |
104 |
105 |
106 | {% endblock %}
--------------------------------------------------------------------------------
/webapp/templates/hilfe.html:
--------------------------------------------------------------------------------
1 | {% extends "layout.html" %}
2 | {% block title %}Hilfe | {{ config.site_name }}{% endblock %}
3 | {% block ogtitle %}Hilfe | {{ config.site_name }}{% endblock %}
4 | {% block meta_description %}Eine kurze Anleitung, was man wie mit {{ config.site_name }} machen kann.{% endblock %}
5 |
6 | {% block riscontent %}
7 |
8 |
9 |
{{ config.site_name }}
10 |
11 |
Ziel von {{config.site_name}} ist es, Informationen, Dokumente und Daten aus der Lokalpolitik für jedermann offen zugänglich zu machen.
12 |
13 |
Dazu werden auf {{ config.site_host }} Dokumente und Daten, die in den jeweiligen Ratsinformationssystemen (RIS ) veröffentlicht werden, gesammelt, aufbereitet und in einer nutzerfreundlichen Art und Weise dargestellt.
14 |
15 |
16 |
{{ config.site_name }} richtet sich an alle, die sich dafür interessieren, wie die kommunale Politik ihr Leben direkt und indirekt beeinflusst. Wir vermuten, dass sich dieser Kreis der Interessierten durch eine Erleichterung des Zugangs zu Informationen vergrößern lässt. Außerdem glauben wir, dass wir viel voneinander lernen können, so dass der Blick in die Nachbarkommune ebenfalls möglich sein sollte.
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
Dinge in meiner Nähe : Über das obere Suchfeld der Startseite können Sie nach Straßen und Plätzen suchen, die in Dokumenten und Vorgängen erwähnt wurden. Geben Sie bitte zunächst die Straße und die Stadt an. Wenn Sie möchten, können Sie weiter oben die Suche auf eine bestimmte Region beschränken. Im Suchergebnis werden auf der Karte Straßen im Umkreis des gesuchten Ortes rot unterlegt. Ein Klick auf die Straße zeigt dann eine zugehörige Zahl an Treffern, über die Sie mit einem weiteren Klick zu den Dokumenten gelangen. Ausprobieren
25 |
Hierbei müssen Sie zunächst die Straße, Stadt angeben. Außerdem können Sie die Region einschränken, wenn Sie dies möchten. Auf der Karte werden dann Straßen mit Suchergebnissen rot unterlegt. Klicken Sie auf die Straße, um die Dokumente zu erhalten.
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
Flexible Suchfunktionen : Über das untere Suchfeld der Startseite können Sie nach allen Wörtern suchen, die in den Dokumenten vorkommen. Sie können das Suchergebnis auch auf bestimmte Gremien, wie z.B. die Bezirksvertretung Ihres Bezirks, oder nach Arten von Dokumenten beschränken. Es kann außerdem nach Satzteilen gesucht werden: Diese setzen Sie bitte in Anführungszeichen, also z.B. "Anlage Verwaltungsrat". Ausprobieren
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
Anlagen-Vorschau : Sie können Anlagen zu Dokumenten, bevor Sie diese zur detaillierten Einsicht herunter laden, in einer schnellen Voransicht ansehen. Damit können Sie schnell einen Eindruck bekommen, um welche Art von Dokument es sich handelt: Antragstext, Bericht, Präsentation etc. Damit fällt die Entscheidung, welches Dokument einen näheren Blick wert ist, leichter. Ausprobieren
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
Persistente URLs für Anlagen : Anders als im Ratsinformationssystem der jeweiligen Stadt können Sie alle Anlagen (z.B. PDF-Dokumente) über einen öffentlichen, langfristig bestehenden URL abrufen. Dies ist eine Grundvoraussetzung, damit Sie einen Favoriten/ein Lesezeichen auf die Datei setzen oder einen Link zum Dokument per E-Mail weiter senden können.
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
Daten-Download : Die Datenbank hinter "Was passiert bei mir?" steht zum Download zur Verfügung. Mehr erfahren
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
API : Unsere Daten sind nicht nur als Download verfügbar. Wir haben auch eine auf dem Standard OParl basierte API, also eine Schnittstelle zum gezielten Abruf bestimmter Daten mit Hilfe von Software. Mehr erfahren
76 |
77 |
78 |
79 |
80 |
81 |
Zum Weiterklicken
82 |
Niemand ist eine Insel, erst recht nicht im World Wide Web. Daher gibt es hier gesammelt wesentliche Links zu relevanten Ressourcen.
83 |
Das jeweilige lokale Ratsinformationssystem der Stadt ist die Quelle der Dokumente, dier hier zu finden sind. Die Quellen stehen bei den einzelnen Dokumenten dabei.
84 |
Sowas wie "Was passiert bei mir?" gibt es schon länger in Frankfurt unter dem Namen Frankfurt gestalten . Interessierte, die solche und ähnliche Plattformen in anderen Städten fördern wollen, diskutieren auf der OKF RIS . Überregionale Anlaufstellen, um sich Mitstreiter für ein solches Projekt zu suchen, ist die Open Knowledge Foundation Deutschland . Einige schöne Beispiele für andere Datenanwendungen findet man im Open Data Showroom .
85 |
86 | {% endblock %}
--------------------------------------------------------------------------------
/webapp/templates/impressum.html:
--------------------------------------------------------------------------------
1 | {% extends "layout.html" %}
2 | {% block title %}Impressum | {{ config.site_name }}"{% endblock %}
3 | {% block ogtitle %}Impressum | {{ config.site_name }}{% endblock %}
4 | {% block meta_description %}Impressum von {{ config.site_name }}{% endblock %}
5 |
6 | {% block riscontent %}
7 |
8 |
Impressum
9 |
10 |
Anbieter im Sinne des § 5 Telemediengesetzes
11 | Open Knowledge Foundation Deutschland e.V.
12 | Singerstraße 109
13 | 10179 Berlin
14 |
15 |
Kontakt
16 | E-Mail: {{ config.contact_mail }}
17 | Telefon: +49 30 57703666-0
18 | Fax: +49 30 57703666-9
19 |
20 |
Eintragung im Vereinsregister
21 | Vereinsregister-Nummer: VR 30468 B
22 | Vereinsregister-Gericht: Amtsgericht Charlottenburg (Berlin)
23 | Steuernummer: 27/674/52428
24 | Umsatzsteuer-Identifikationsnummer: DE278022128
25 |
26 |
27 |
28 |
29 |
Haftung für Inhalte
30 |
Als Diensteanbieter sind wir gemäß § 7 Abs.1 TMG für eigene Inhalte auf diesen Seiten nach den allgemeinen Gesetzen verantwortlich. Nach §§ 8 bis 10 TMG sind wir als Diensteanbieter jedoch nicht verpflichtet, übermittelte oder gespeicherte fremde Informationen zu überwachen oder nach Umständen zu forschen, die auf eine rechtswidrige Tätigkeit hinweisen. Verpflichtungen zur Entfernung oder Sperrung der Nutzung von Informationen nach den allgemeinen Gesetzen bleiben hiervon unberührt. Eine diesbezügliche Haftung ist jedoch erst ab dem Zeitpunkt der Kenntnis einer konkreten Rechtsverletzung möglich. Bei Bekanntwerden von entsprechenden Rechtsverletzungen werden wir diese Inhalte umgehend entfernen.
31 |
32 |
33 |
34 |
Haftung für Links
35 |
Unser Angebot enthält Links zu externen Webseiten Dritter, auf deren Inhalte wir keinen Einfluss haben. Deshalb können wir für diese fremden Inhalte auch keine Gewähr übernehmen. Für die Inhalte der verlinkten Seiten ist stets der jeweilige Anbieter oder Betreiber der Seiten verantwortlich. Die verlinkten Seiten wurden zum Zeitpunkt der Verlinkung auf mögliche Rechtsverstöße überprüft. Rechtswidrige Inhalte waren zum Zeitpunkt der Verlinkung nicht erkennbar. Eine permanente inhaltliche Kontrolle der verlinkten Seiten ist jedoch ohne konkrete Anhaltspunkte einer Rechtsverletzung nicht zumutbar. Bei Bekanntwerden von Rechtsverletzungen werden wir derartige Links umgehend entfernen.
36 |
37 |
38 |
39 |
Urheberrecht
40 |
Die durch die Seitenbetreiber erstellten Inhalte und Werke auf diesen Seiten unterliegen dem deutschen Urheberrecht. Die Vervielfältigung, Bearbeitung, Verbreitung und jede Art der Verwertung außerhalb der Grenzen des Urheberrechtes bedürfen der schriftlichen Zustimmung des jeweiligen Autors bzw. Erstellers. Downloads und Kopien dieser Seite sind nur für den privaten, nicht kommerziellen Gebrauch gestattet. Soweit die Inhalte auf dieser Seite nicht vom Betreiber erstellt wurden, werden die Urheberrechte Dritter beachtet. Insbesondere werden Inhalte Dritter als solche gekennzeichnet. Sollten Sie trotzdem auf eine Urheberrechtsverletzung aufmerksam werden, bitten wir um einen entsprechenden Hinweis. Bei Bekanntwerden von Rechtsverletzungen werden wir derartige Inhalte umgehend entfernen.
41 |
42 | {% endblock %}
43 |
--------------------------------------------------------------------------------
/webapp/templates/index.html:
--------------------------------------------------------------------------------
1 | {% extends "layout.html" %}
2 | {% block title %}Startseite | {{ config.site_name }}{% endblock %}
3 | {% block ogtitle %}Startseite | {{ config.site_name }}{% endblock %}
4 | {% block meta_description %}Informiere Dich auf {{ config.site_name }} über Deine lokale Politik, um mitreden zu können!{% endblock %}
5 |
6 | {% block scripts %}
7 | {{ super() }}
8 |
9 |
10 |
11 |
12 |
36 |
37 | {% endblock %}
38 |
39 | {% block riscontent %}
40 | {% if session['region_id'] %}{% set region_id = session['region_id'] %}{% else %}{% set region_id = config['region_default'] %}{% endif %}
41 |
42 |
43 |
44 |
Ausgewählte Region: {{ config['regions'][region_id]['name'] }}
45 |
46 |
47 |
48 |
59 |
60 |
61 |
62 |
69 |
70 | Beispiele: {% for example in config['regions'][region_id]['keyword'] %}
{{ example }} {% if not loop.last %}, {% endif %}{% endfor %}
71 |
72 |
73 |
74 | {% endblock %}
75 |
--------------------------------------------------------------------------------
/webapp/templates/layout.html:
--------------------------------------------------------------------------------
1 | {% extends "bootstrap/base.html" %}
2 |
3 | {% block title %} | {{ config.site_name }}{% endblock %}
4 |
5 | {% block head %}
6 | {{super()}}
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 | {% if config['google_site_verification'] %}
19 |
20 | {% endif %}
21 |
22 |
23 | {% endblock %}
24 |
25 | {% block styles %}
26 | {{super()}}
27 |
28 | {% endblock %}
29 |
30 | {% block scripts %}
31 | {{super()}}
32 |
33 |
34 | {% if config['tracking'] == 'analytics' %}
35 |
47 | {% elif config['tracking'] == 'piwik' %}
48 |
49 |
62 |
63 | {% endif %}
64 | {% endblock %}
65 |
66 | {% block content %}
67 |
75 |
76 |
77 | Sie müssen JavaScript aktivieren, um diese Site nutzen zu können.
78 |
79 | {% block riscontent %}{% endblock %}
80 |
81 |
115 | {% endblock %}
116 |
117 |
--------------------------------------------------------------------------------
/webapp/templates/oparl.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | OKF-DE OParl API
6 |
7 |
8 | {% if is_dict(data) %}
9 |
10 | {% for key, value in data.items() recursive %}
11 | {% set outer_loop = loop %}
12 | {{ key }}:
13 | {% if is_dict(value) %}
14 |
15 | {% elif is_list(value) %}
16 |
17 | {% for subvalue in value %}
18 | {% if is_dict(subvalue) %}
19 | {{ loop.index }}:
20 | {{ outer_loop(subvalue.items()) }}
21 | {% elif is_list(subvalue) %}
22 | no yet implemented
23 | {% elif is_link(subvalue) %}
24 | {{ subvalue }}
25 | {% else %}
26 | {{ subvalue }}
27 | {% endif %}
28 | {% endfor %}
29 |
30 | {% elif is_link(value) %}
31 | {{ value }}
32 | {% else %}
33 | {{ value }}
34 | {% endif %}
35 |
36 | {% endfor %}
37 |
38 | {% elif is_list(data) %}
39 | [
40 | {% for item in data %}
41 | {
42 | {% if is_dict(item) %}
43 |
44 | {% for key, value in item.items() recursive %}
45 | {{ key }}:
46 | {% if is_dict(value) %}
47 | no yet implemented
48 | {% elif is_list(value) %}
49 | no yet implemented
50 | {% elif is_link(value) %}
51 | {{ value }}
52 | {% else %}
53 | {{ value }}
54 | {% endif %}
55 |
56 | {% endfor %}
57 |
58 | {% elif is_list(item) %}
59 | no yet implemented
60 | {% elif is_link(item) %}
61 | {{ item }}
62 | {% else %}
63 | {{ item }}
64 | {% endif %}
65 | }
66 | {% endfor %}
67 | ]
68 | {% else %}
69 | {{ data }}
70 | {% endif %}
71 |
72 |
73 |
--------------------------------------------------------------------------------
/webapp/templates/robots.txt:
--------------------------------------------------------------------------------
1 | # Robots, Spider und Crawler abseits der Suchmaschinen bitte die OParl-API verwenden. Danke!
2 |
3 | Sitemap: {{ config.base_url }}/static/sitemap/sitemap.xml
4 |
5 | User-agent: *
6 | Disallow: /suche/
7 | Disallow: /api/
8 | Disallow: /admin/
9 | Disallow: /file/*/download
10 |
11 | User-agent: Googlebot
12 | Disallow: /suche/
13 | Disallow: /api/
14 | Disallow: /admin/
15 | Disallow: /file/*/download
16 | Disallow: /oparl/
17 |
18 | User-agent:Yahoo! Slurp
19 | Disallow: /suche/
20 | Disallow: /api/
21 | Disallow: /admin/
22 | Disallow: /file/*/download
23 | Disallow: /oparl/
24 |
25 | User-agent: bingbot
26 | Disallow: /suche/
27 | Disallow: /api/
28 | Disallow: /admin/
29 | Disallow: /file/*/download
30 | Disallow: /oparl/
31 |
--------------------------------------------------------------------------------
/webapp/templates/suche.html:
--------------------------------------------------------------------------------
1 | {% extends "layout.html" %}
2 | {% block title %}Suche | {{ config.site_name }}{% endblock %}
3 | {% block ogtitle %}Suche | {{ config.site_name }}{% endblock %}
4 | {% block meta_description %}Hier finden Sie alle Dokumente im Bestand{% endblock %}
5 |
6 | {% block head %}
7 | {{ super() }}
8 |
9 | {% endblock %}
10 |
11 | {% block scripts %}
12 | {{ super() }}
13 | {% if session['region_id'] %}{% set region_id = session['region_id'] %}{% else %}{% set region_id = config['region_default'] %}{% endif %}
14 |
34 |
35 | {% endblock %}
36 |
37 | {% block riscontent %}
38 | {% if session['region_id'] %}{% set region_id = session['region_id'] %}{% else %}{% set region_id = config['region_default'] %}{% endif %}
39 |
40 |
41 |
42 |
Ausgewählte Region: {{ config['regions'][region_id]['name'] }}
43 |
44 |
45 |
46 |
47 |
Suche
48 |
49 |
50 |
55 |
56 |
59 |
60 | {% endblock %}
61 |
62 | {% block footericons %} {% endblock %}
--------------------------------------------------------------------------------
/webapp/util.py:
--------------------------------------------------------------------------------
1 | # encoding: utf-8
2 |
3 | """
4 | Copyright (c) 2012 - 2015, Marian Steinbach, Ernesto Ruge
5 | All rights reserved.
6 |
7 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
8 |
9 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
10 |
11 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
12 |
13 | 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
14 |
15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
16 | """
17 |
18 | import datetime
19 | import email.utils
20 | import calendar
21 | import json
22 | import bson
23 | import re
24 | import urllib
25 | import urllib2
26 | import sys
27 | from flask import request
28 | from collections import OrderedDict
29 | import HTMLParser
30 |
31 | from webapp import app, mongo
32 |
33 | def verify_created_modified():
34 | result = []
35 | collections = ['body', 'organization', 'person', 'membership', 'meeting', 'consultation', 'agendaitem', 'paper', 'file', 'region']
36 | for collection in collections:
37 | print '########## now working at %s ##########' % collection
38 | mongo_collection = getattr(mongo.db, collection)
39 | for item in mongo_collection.find({},{'_id':1,'lastModified':1,'modified':1,'created':1}):
40 | state = ['ID: %s' % item['_id']]
41 | # modified
42 | if 'modified' in item:
43 | state.append('modified found')
44 | else:
45 | if 'lastModified' in item:
46 | state.append('modified insertet with lastModified')
47 | mongo_collection.update({'_id': item['_id']}, {'$set': {'modified': item['lastModified']}})
48 | else:
49 | state.append('modified insertet with datetime')
50 | mongo_collection.update({'_id': item['_id']}, {'$set': {'modified': datetime.datetime.now()}})
51 | # created
52 | if 'created' in item:
53 | state.append('created found')
54 | else:
55 | if 'createdAt' in item:
56 | state.append('created insertet with createdAt')
57 | mongo_collection.update({'_id': item['_id']}, {'$set': {'created': item['createdAt']}})
58 | elif 'modified' in item:
59 | state.append('created insertet with modified')
60 | mongo_collection.update({'_id': item['_id']}, {'$set': {'created': item['modified']}})
61 | elif 'lastModified' in item:
62 | state.append('created insertet with lastModified')
63 | mongo_collection.update({'_id': item['_id']}, {'$set': {'created': item['lastModified']}})
64 | else:
65 | state.append('created insertet with datetime')
66 | mongo_collection.update({'_id': item['_id']}, {'$set': {'created': datetime.datetime.now()}})
67 | # lastModified
68 | if 'lastModified' in item:
69 | state.append('lastModified deleted')
70 | mongo_collection.update({'_id': item['_id']}, {'$unset': {'lastModified':1}})
71 | else:
72 | state.append('no lastModified found')
73 | # createdAt
74 | if 'createdAt' in item:
75 | state.append('createdAt deleted')
76 | mongo_collection.update({'_id': item['_id']}, {'$unset': {'createdAt':1}})
77 | else:
78 | state.append('no createdAt found')
79 | print ', '.join(state)
80 |
81 | def rfc1123date(value):
82 | """
83 | Gibt ein Datum (datetime) im HTTP Head-tauglichen Format (RFC 1123) zurück
84 | """
85 | tpl = value.timetuple()
86 | stamp = calendar.timegm(tpl)
87 | return email.utils.formatdate(timeval=stamp, localtime=False, usegmt=True)
88 |
89 |
90 | def parse_rfc1123date(string):
91 | return datetime.datetime(*email.utils.parsedate(string)[:6])
92 |
93 |
94 | def expires_date(hours):
95 | """Date commonly used for Expires response header"""
96 | dt = datetime.datetime.now() + datetime.timedelta(hours=hours)
97 | return rfc1123date(dt)
98 |
99 |
100 | def cache_max_age(hours):
101 | """String commonly used for Cache-Control response headers"""
102 | seconds = hours * 60 * 60
103 | return 'max-age=' + str(seconds)
104 |
105 |
106 | def attachment_url(attachment_id, filename=None, extension=None):
107 | if filename is not None:
108 | extension = filename.split('.')[-1]
109 | return app.config['ATTACHMENT_DOWNLOAD_URL'] % (attachment_id, extension)
110 |
111 |
112 | def thumbnail_url(attachment_id, size, page):
113 | attachment_id = str(attachment_id)
114 | url = app.config['THUMBS_URL']
115 | url += attachment_id[-1] + '/' + attachment_id[-2] + '/' + attachment_id
116 | url += '/' + str(size)
117 | url += '/' + str(page) + '.' + app.config['THUMBNAILS_SUFFIX']
118 | return url
119 |
120 |
121 | def submission_url(identifier):
122 | url = app.config['BASE_URL']
123 | url += 'dokumente/' + urllib.quote_plus(identifier) + '/'
124 | return url
125 |
126 |
127 | def geocode(location_string, region):
128 | """
129 | Löst eine Straßen- und optional PLZ-Angabe zu einer Geo-Postion
130 | auf. Beispiel: "Straßenname (12345)"
131 | """
132 | if region != app.config['region_default']:
133 | location_string += ' ' + app.config['regions'][region]['name']
134 | address = location_string.encode('utf-8')
135 |
136 | # Filter Postalcode in Brackets from Selection
137 | postalre = re.compile(r'(.+), ([0-9]{5}) (.+)')
138 | postal_matching = re.match(postalre, address)
139 | postal = None
140 | if postal_matching is not None:
141 | postal = postal_matching.group(2)
142 | url = 'http://open.mapquestapi.com/nominatim/v1/search.php'
143 | params = {'format': 'json', # json
144 | 'q': address,
145 | 'addressdetails': 1,
146 | 'accept-language': 'de_DE',
147 | 'countrycodes': 'DE'}
148 | request = urllib2.urlopen(url + '?' + urllib.urlencode(params))
149 | response = request.read()
150 | addresses = json.loads(response)
151 | addresses_out = []
152 | for n in range(len(addresses)):
153 | for key in addresses[n].keys():
154 | if key in ['address', 'boundingbox', 'lat', 'lon', 'osm_id']:
155 | continue
156 | del addresses[n][key]
157 | # skip if no road contained
158 | if 'road' not in addresses[n]['address']:
159 | continue
160 | # skip if not in correct county
161 | if 'county' not in addresses[n]['address']:
162 | continue
163 |
164 | # TODO: Filter for County
165 | #if addresses[n]['address']['county'] != app.config['GEOCODING_FILTER_COUNTY']:
166 | # continue
167 | if postal is not None:
168 | if 'postcode' in addresses[n]['address'] and addresses[n]['address']['postcode'] == postal:
169 | addresses_out.append(addresses[n])
170 | else:
171 | addresses_out.append(addresses[n])
172 | return addresses_out
173 |
174 |
175 | class MyEncoder(json.JSONEncoder):
176 | def default(self, obj):
177 | if isinstance(obj, datetime.datetime):
178 | return obj.isoformat()
179 | elif isinstance(obj, bson.ObjectId):
180 | return str(obj)
181 | elif isinstance(obj, bson.DBRef):
182 | return {
183 | 'collection': obj.collection,
184 | '_id': obj.id
185 | }
186 | return obj.__dict__
187 |
188 |
189 | # Some simple Jinja2 Functions
190 | app.jinja_env.globals.update(is_dict=lambda value: type(value) == type({}) or type(value) == type(OrderedDict()))
191 | app.jinja_env.globals.update(is_list=lambda value: type(value) == type([]))
192 | app.jinja_env.globals.update(is_link=lambda value: value[0:7] == 'http://' or value[0:8] == 'https://' if isinstance(value, basestring) else False)
193 | app.jinja_env.globals.update(dir=dir)
194 |
195 | def dottify(value):
196 | if value:
197 | if value > 999:
198 | return str(value)[:-3] + '.' + str(value)[-3:]
199 | return value
200 |
201 | app.jinja_env.filters['dottify'] = dottify
202 |
203 | def utfunescape(value):
204 | h = HTMLParser.HTMLParser()
205 | return h.unescape(unicode(value))
206 |
207 | app.jinja_env.filters['utfunescape'] = utfunescape
208 |
--------------------------------------------------------------------------------